From patchwork Wed Apr 7 15:10:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Michal Nazarewicz X-Patchwork-Id: 42927 X-Patchwork-Delegate: azanella@linux.vnet.ibm.com Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B060C3938C17; Wed, 7 Apr 2021 15:15:58 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) by sourceware.org (Postfix) with ESMTPS id 8289F3938C25 for ; Wed, 7 Apr 2021 15:15:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8289F3938C25 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=mina86.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mnazarewicz@gmail.com Received: by mail-ed1-x532.google.com with SMTP id h10so21298825edt.13 for ; Wed, 07 Apr 2021 08:15:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=nRq8vyIEwjkXqo1jJKYVFL21iS+novZbtWCTFby+j78=; b=QX8RZzbwTTUbeElwoqHl7U3ewlIomJvaQNYY/QVXU4nNnyg61xorYkYX3xk7M+o49J fUPpRnv7ivBIu9aA+bUKm7kiAE8CetdWnyVF3bvdGMdUHcCE9J/bGFnxUe0kfuhYFCqq LiYt1Ij148vQQYQi2t9N5MI0/UoZSzCeFlfsmWsp55898cnHAq0LD+NGCQ0Rhu0A/zfG QZUEp2RVJdTaZX/vhoVeqh1GaCWtu+qjwGrKSTfSCcCn1NJncL/o6KYOInrDYIowgc+w w3LkFWBnayENAwpAiIUkLS66tG9NQBr4iXyIljuOjpMXa6l6XCa6NLWE5QsXZq7uN2l2 FCtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :mime-version:content-transfer-encoding; bh=nRq8vyIEwjkXqo1jJKYVFL21iS+novZbtWCTFby+j78=; b=IFHTZBIN+m6Ond5oiPkbPMPRwjjVMTqQlutN4Dk6BE4aLuqY3Zz1uUtDqNLlCrRffv h/mAhWhAfd60s49qXsDZq/KDXM5N+o6fTWxtxLHNG6TZelj7j2Opj9IRcXooUAq3NMFu M/pVlbJTs1ujIDGkSPpx0t4E9WMeexTyn5Y6U/uol09ieveaezQditAp9LW/5O+8qO8I Vr3zW6DVaa+kBdK4hFLJe4Hbl7UzTFt8Wzh1xufjZo3sUSCT1JDxW+TbjE+V/4vOddT3 we2uFvYrBCuaZNrvHQcm2EA3KLtR4Zn39BGp/GCBie3bNhq5deRZBxUjKeXfsCy6pxVv ofVg== X-Gm-Message-State: AOAM533m1e55UpzPtLSz5m/vYr98yUFYowhi3ZQru+EtFKVd26TqVIN2 AJbeO8ogEZpemEaahyu82YBkw+3Ovv/cYg== X-Google-Smtp-Source: ABdhPJy7AMNFZRIerEerdjjLAQcvz6b62u5dS1N3ClKME0kw3VU8V/arPZhl37g8Qp34lHJj88RChw== X-Received: by 2002:a05:6402:5255:: with SMTP id t21mr5075582edd.91.1617808554355; Wed, 07 Apr 2021 08:15:54 -0700 (PDT) Received: from erwin.mina86.com (77-253-94-61.adsl.inetia.pl. [77.253.94.61]) by smtp.gmail.com with ESMTPSA id k8sm487008edr.75.2021.04.07.08.15.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Apr 2021 08:15:53 -0700 (PDT) From: Michal Nazarewicz To: libc-alpha@sourceware.org Subject: [PATCH] linux: sysconf: limit _SC_MAX_ARG to 6 MiB [BZ #25305] Date: Wed, 7 Apr 2021 17:10:58 +0200 Message-Id: <20210407151058.1176364-1-mina86@mina86.com> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Since Linux 4.13, kernel limits the maximum command line arguments length to 6 MiB.¹ Normally the limit is still quarter of the maximum stack size but if that limit exceeds 6 MiB it’s clamped down. glibc’s __sysconf implementation for Linux platform is not aware of this limitation and for stack sizes of over 24 MiB it returns higher ARG_MAX than Linux will actually accept. This can be verified by executing the following application on Linux 4.13 or newer: #include #include #include #include #include int main(void) { const struct rlimit rlim = { 40 * 1024 * 1024, 40 * 1024 * 1024 }; if (setrlimit(RLIMIT_STACK, &rlim) < 0) { perror("setrlimit: RLIMIT_STACK"); return 1; } printf("ARG_MAX : %8ld\n", sysconf(_SC_ARG_MAX)); printf("63 * 100 KiB: %8ld\n", 63L * 100 * 1024); printf("6 MiB : %8ld\n", 6L * 1024 * 1024); char str[100 * 1024], *argv[64], *envp[1]; memset(&str, 'A', sizeof str); str[sizeof str - 1] = '\0'; for (size_t i = 0; i < sizeof argv / sizeof *argv - 1; ++i) { argv[i] = str; } argv[sizeof argv / sizeof *argv - 1] = envp[0] = 0; execve("/bin/true", argv, envp); perror("execve"); return 1; } On affected systems the program will report ARG_MAX as 10 MiB but despite that executing /bin/true with a bit over 6 MiB of command line arguments will fail with E2BIG error. Expected result is that ARG_MAX is reported as 6 MiB. Update the __sysconf function to clamp ARG_MAX value to 6 MiB if it would otherwise exceed it. This resolves bug #25305 which was market WONTFIX as suggested solution was to cap ARG_MAX at 128 KiB. As an aside and point of comparison, bionic (a libc implementation for Android systems) decided to resolve this issue by always returning 128 KiB ignoring any potential xargs regressions.² On older kernels this results in returning overly conservative value but that’s a safer option than being aggressive and returning invalid value on recent systems. It’s also worth noting that at this point all supported Linux releases have the 6 MiB barrier so only someone running an unsupported kernel version would get incorrectly truncated result. ¹ See https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=da029c11e6b12f321f36dac8771e833b65cec962 ² See https://android.googlesource.com/platform/bionic/+/baed51ee3a13dae4b87b11870bdf7f10bdc9efc1 --- sysdeps/unix/sysv/linux/sysconf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sysdeps/unix/sysv/linux/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c index 366fcef01e..bd711795c7 100644 --- a/sysdeps/unix/sysv/linux/sysconf.c +++ b/sysdeps/unix/sysv/linux/sysconf.c @@ -55,7 +55,10 @@ __sysconf (int name) struct rlimit rlimit; /* Use getrlimit to get the stack limit. */ if (__getrlimit (RLIMIT_STACK, &rlimit) == 0) - return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4); + { + const long int limit = MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4); + return MIN (limit, 6 << 10 << 10); + } return legacy_ARG_MAX; }