diff options
Diffstat (limited to 'patches/source/glibc/patches')
10 files changed, 1193 insertions, 0 deletions
diff --git a/patches/source/glibc/patches/0001-nsswitch-return-result-when-nss-database-is-locked.patch b/patches/source/glibc/patches/0001-nsswitch-return-result-when-nss-database-is-locked.patch new file mode 100644 index 000000000..458369251 --- /dev/null +++ b/patches/source/glibc/patches/0001-nsswitch-return-result-when-nss-database-is-locked.patch @@ -0,0 +1,47 @@ +From c3479fb7939898ec22c655c383454d6e8b982a67 Mon Sep 17 00:00:00 2001 +From: Sergei Trofimovich <slyfox@gentoo.org> +Date: Fri, 5 Feb 2021 07:32:18 +0000 +Subject: [PATCH] nsswitch: return result when nss database is locked [BZ + #27343] + +Before the change nss_database_check_reload_and_get() did not populate +the '*result' value when it returned success in a case of chroot +detection. This caused initgroups() to use garage pointer in the +following test (extracted from unbound): + +``` + +int main() { + // load some NSS modules + struct passwd * pw = getpwnam("root"); + + chdir("/tmp"); + chroot("/tmp"); + chdir("/"); + // access nsswitch.conf in a chroot + initgroups("root", 0); +} +``` + +Reviewed-by: DJ Delorie <dj@redhat.com> +--- + nss/nss_database.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/nss/nss_database.c b/nss/nss_database.c +index cf0306adc4..e1bef6bd75 100644 +--- a/nss/nss_database.c ++++ b/nss/nss_database.c +@@ -398,8 +398,9 @@ nss_database_check_reload_and_get (struct nss_database_state *local, + && (str.st_ino != local->root_ino + || str.st_dev != local->root_dev))) + { +- /* Change detected; disable reloading. */ ++ /* Change detected; disable reloading and return current state. */ + atomic_store_release (&local->data.reload_disabled, 1); ++ *result = local->data.services[database_index]; + __libc_lock_unlock (local->lock); + __nss_module_disable_loading (); + return true; +-- +2.27.0 diff --git a/patches/source/glibc/patches/CVE-2021-27645.patch b/patches/source/glibc/patches/CVE-2021-27645.patch new file mode 100644 index 000000000..c568dd16b --- /dev/null +++ b/patches/source/glibc/patches/CVE-2021-27645.patch @@ -0,0 +1,20 @@ +--- ./nscd/netgroupcache.c.orig 2021-08-07 13:20:02.459057859 -0500 ++++ ./nscd/netgroupcache.c 2021-08-07 13:22:08.983060689 -0500 +@@ -248,7 +248,7 @@ + : NULL); + ndomain = (ndomain ? newbuf + ndomaindiff + : NULL); +- buffer = newbuf; ++ *tofreep = buffer = newbuf; + } + + nhost = memcpy (buffer + bufused, +@@ -319,7 +319,7 @@ + else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) + { + buflen *= 2; +- buffer = xrealloc (buffer, buflen); ++ *tofreep = buffer = xrealloc (buffer, buflen); + } + else if (status == NSS_STATUS_RETURN + || status == NSS_STATUS_NOTFOUND diff --git a/patches/source/glibc/patches/CVE-2021-33574_1.patch b/patches/source/glibc/patches/CVE-2021-33574_1.patch new file mode 100644 index 000000000..20f1889ce --- /dev/null +++ b/patches/source/glibc/patches/CVE-2021-33574_1.patch @@ -0,0 +1,71 @@ +From 42d359350510506b87101cf77202fefcbfc790cb Mon Sep 17 00:00:00 2001 +From: Andreas Schwab <schwab@linux-m68k.org> +Date: Thu, 27 May 2021 12:49:47 +0200 +Subject: [PATCH] Use __pthread_attr_copy in mq_notify (bug 27896) + +Make a deep copy of the pthread attribute object to remove a potential +use-after-free issue. +--- + NEWS | 4 ++++ + sysdeps/unix/sysv/linux/mq_notify.c | 15 ++++++++++----- + 2 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/NEWS b/NEWS +index 6f4d325d55..1bf3daa502 100644 +--- a/NEWS ++++ b/NEWS +@@ -62,6 +62,10 @@ Security related changes: + potentially resulting in degraded service or Denial of Service on the + local system. Reported by Chris Schanzle. + ++ CVE-2021-33574: The mq_notify function has a potential use-after-free ++ issue when using a notification type of SIGEV_THREAD and a thread ++ attribute with a non-default affinity mask. ++ + The following bugs are resolved with this release: + + [The release manager will add the list generated by +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index cc575a0cdd..f7ddfe5a6c 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -133,8 +133,11 @@ helper_thread (void *arg) + (void) __pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) +- /* The only state we keep is the copy of the thread attributes. */ +- free (data.attr); ++ { ++ /* The only state we keep is the copy of the thread attributes. */ ++ pthread_attr_destroy (data.attr); ++ free (data.attr); ++ } + } + return NULL; + } +@@ -255,8 +258,7 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + if (data.attr == NULL) + return -1; + +- memcpy (data.attr, notification->sigev_notify_attributes, +- sizeof (pthread_attr_t)); ++ __pthread_attr_copy (data.attr, notification->sigev_notify_attributes); + } + + /* Construct the new request. */ +@@ -270,7 +272,10 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + + /* If it failed, free the allocated memory. */ + if (__glibc_unlikely (retval != 0)) +- free (data.attr); ++ { ++ pthread_attr_destroy (data.attr); ++ free (data.attr); ++ } + + return retval; + } +-- +2.27.0 + + diff --git a/patches/source/glibc/patches/CVE-2021-33574_2.patch b/patches/source/glibc/patches/CVE-2021-33574_2.patch new file mode 100644 index 000000000..608dbfdc5 --- /dev/null +++ b/patches/source/glibc/patches/CVE-2021-33574_2.patch @@ -0,0 +1,53 @@ +From 217b6dc298156bdb0d6aea9ea93e7e394a5ff091 Mon Sep 17 00:00:00 2001 +From: Florian Weimer <fweimer@redhat.com> +Date: Tue, 1 Jun 2021 17:51:41 +0200 +Subject: [PATCH] Fix use of __pthread_attr_copy in mq_notify (bug 27896) + +__pthread_attr_copy can fail and does not initialize the attribute +structure in that case. + +If __pthread_attr_copy is never called and there is no allocated +attribute, pthread_attr_destroy should not be called, otherwise +there is a null pointer dereference in rt/tst-mqueue6. + +Fixes commit 42d359350510506b87101cf77202fefcbfc790cb +("Use __pthread_attr_copy in mq_notify (bug 27896)"). + +Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> +--- + sysdeps/unix/sysv/linux/mq_notify.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index f7ddfe5a6c..6f46d29d1d 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -258,7 +258,14 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + if (data.attr == NULL) + return -1; + +- __pthread_attr_copy (data.attr, notification->sigev_notify_attributes); ++ int ret = __pthread_attr_copy (data.attr, ++ notification->sigev_notify_attributes); ++ if (ret != 0) ++ { ++ free (data.attr); ++ __set_errno (ret); ++ return -1; ++ } + } + + /* Construct the new request. */ +@@ -271,7 +278,7 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ +- if (__glibc_unlikely (retval != 0)) ++ if (retval != 0 && data.attr != NULL) + { + pthread_attr_destroy (data.attr); + free (data.attr); +-- +2.27.0 + + diff --git a/patches/source/glibc/patches/CVE-2021-35942.patch b/patches/source/glibc/patches/CVE-2021-35942.patch new file mode 100644 index 000000000..fde0fbdb3 --- /dev/null +++ b/patches/source/glibc/patches/CVE-2021-35942.patch @@ -0,0 +1,41 @@ +From 5adda61f62b77384718b4c0d8336ade8f2b4b35c Mon Sep 17 00:00:00 2001 +From: Andreas Schwab <schwab@linux-m68k.org> +Date: Fri, 25 Jun 2021 15:02:47 +0200 +Subject: [PATCH] wordexp: handle overflow in positional parameter number (bug + 28011) + +Use strtoul instead of atoi so that overflow can be detected. +--- + posix/wordexp-test.c | 1 + + posix/wordexp.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c +index f93a546d7e..9df02dbbb3 100644 +--- a/posix/wordexp-test.c ++++ b/posix/wordexp-test.c +@@ -183,6 +183,7 @@ struct test_case_struct + { 0, NULL, "$var", 0, 0, { NULL, }, IFS }, + { 0, NULL, "\"\\n\"", 0, 1, { "\\n", }, IFS }, + { 0, NULL, "", 0, 0, { NULL, }, IFS }, ++ { 0, NULL, "${1234567890123456789012}", 0, 0, { NULL, }, IFS }, + + /* Flags not already covered (testit() has special handling for these) */ + { 0, NULL, "one two", WRDE_DOOFFS, 2, { "one", "two", }, IFS }, +diff --git a/posix/wordexp.c b/posix/wordexp.c +index bcbe96e48d..1f3b09f721 100644 +--- a/posix/wordexp.c ++++ b/posix/wordexp.c +@@ -1399,7 +1399,7 @@ envsubst: + /* Is it a numeric parameter? */ + else if (isdigit (env[0])) + { +- int n = atoi (env); ++ unsigned long n = strtoul (env, NULL, 10); + + if (n >= __libc_argc) + /* Substitute NULL. */ +-- +2.27.0 + + diff --git a/patches/source/glibc/patches/CVE-2021-38604.patch b/patches/source/glibc/patches/CVE-2021-38604.patch new file mode 100644 index 000000000..ad0a81588 --- /dev/null +++ b/patches/source/glibc/patches/CVE-2021-38604.patch @@ -0,0 +1,40 @@ +From b805aebd42364fe696e417808a700fdb9800c9e8 Mon Sep 17 00:00:00 2001 +From: Nikita Popov <npv1310@gmail.com> +Date: Mon, 9 Aug 2021 20:17:34 +0530 +Subject: [PATCH] librt: fix NULL pointer dereference (bug 28213) + +Helper thread frees copied attribute on NOTIFY_REMOVED message +received from the OS kernel. Unfortunately, it fails to check whether +copied attribute actually exists (data.attr != NULL). This worked +earlier because free() checks passed pointer before actually +attempting to release corresponding memory. But +__pthread_attr_destroy assumes pointer is not NULL. + +So passing NULL pointer to __pthread_attr_destroy will result in +segmentation fault. This scenario is possible if +notification->sigev_notify_attributes == NULL (which means default +thread attributes should be used). + +Signed-off-by: Nikita Popov <npv1310@gmail.com> +Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org> +--- + sysdeps/unix/sysv/linux/mq_notify.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index 9799dcdaa4..eccae2e4c6 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -131,7 +131,7 @@ helper_thread (void *arg) + to wait until it is done with it. */ + (void) __pthread_barrier_wait (¬ify_barrier); + } +- else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) ++ else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL) + { + /* The only state we keep is the copy of the thread attributes. */ + __pthread_attr_destroy (data.attr); +-- +2.27.0 + + diff --git a/patches/source/glibc/patches/CVE-2024-2961_glibc2.33.patch b/patches/source/glibc/patches/CVE-2024-2961_glibc2.33.patch new file mode 100644 index 000000000..211bd38c7 --- /dev/null +++ b/patches/source/glibc/patches/CVE-2024-2961_glibc2.33.patch @@ -0,0 +1,205 @@ +From ed4f16ff6bed3037266f1fa682ebd32a18fce29c Mon Sep 17 00:00:00 2001 +From: Charles Fol <folcharles@gmail.com> +Date: Thu, 28 Mar 2024 12:25:38 -0300 +Subject: [PATCH] iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing + escape sequence (CVE-2024-2961) + +ISO-2022-CN-EXT uses escape sequences to indicate character set changes +(as specified by RFC 1922). While the SOdesignation has the expected +bounds checks, neither SS2designation nor SS3designation have its; +allowing a write overflow of 1, 2, or 3 bytes with fixed values: +'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'. + +Checked on aarch64-linux-gnu. + +Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Reviewed-by: Carlos O'Donell <carlos@redhat.com> +Tested-by: Carlos O'Donell <carlos@redhat.com> + +(cherry picked from commit f9dc609e06b1136bb0408be9605ce7973a767ada) +--- + iconvdata/Makefile | 5 +- + iconvdata/iso-2022-cn-ext.c | 12 +++ + iconvdata/tst-iconv-iso-2022-cn-ext.c | 128 ++++++++++++++++++++++++++ + 3 files changed, 144 insertions(+), 1 deletion(-) + create mode 100644 iconvdata/tst-iconv-iso-2022-cn-ext.c + +--- ./iconvdata/iso-2022-cn-ext.c.orig 2021-02-01 11:15:33.000000000 -0600 ++++ ./iconvdata/iso-2022-cn-ext.c 2024-04-18 13:10:47.597086361 -0500 +@@ -575,6 +575,12 @@ + { \ + const char *escseq; \ + \ ++ if (outptr + 4 > outend) \ ++ { \ ++ result = __GCONV_FULL_OUTPUT; \ ++ break; \ ++ } \ ++ \ + assert (used == CNS11643_2_set); /* XXX */ \ + escseq = "*H"; \ + *outptr++ = ESC; \ +@@ -588,6 +594,12 @@ + { \ + const char *escseq; \ + \ ++ if (outptr + 4 > outend) \ ++ { \ ++ result = __GCONV_FULL_OUTPUT; \ ++ break; \ ++ } \ ++ \ + assert ((used >> 5) >= 3 && (used >> 5) <= 7); \ + escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \ + *outptr++ = ESC; \ +--- ./iconvdata/tst-iconv-iso-2022-cn-ext.c.orig 2024-04-18 13:10:47.597086361 -0500 ++++ ./iconvdata/tst-iconv-iso-2022-cn-ext.c 2024-04-18 13:10:47.597086361 -0500 +@@ -0,0 +1,128 @@ ++/* Verify ISO-2022-CN-EXT does not write out of the bounds. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdio.h> ++#include <string.h> ++ ++#include <errno.h> ++#include <iconv.h> ++#include <sys/mman.h> ++ ++#include <support/xunistd.h> ++#include <support/check.h> ++#include <support/support.h> ++ ++/* The test sets up a two memory page buffer with the second page marked ++ PROT_NONE to trigger a fault if the conversion writes beyond the exact ++ expected amount. Then we carry out various conversions and precisely ++ place the start of the output buffer in order to trigger a SIGSEGV if the ++ process writes anywhere between 1 and page sized bytes more (only one ++ PROT_NONE page is setup as a canary) than expected. These tests exercise ++ all three of the cases in ISO-2022-CN-EXT where the converter must switch ++ character sets and may run out of buffer space while doing the ++ operation. */ ++ ++static int ++do_test (void) ++{ ++ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8"); ++ TEST_VERIFY_EXIT (cd != (iconv_t) -1); ++ ++ char *ntf; ++ size_t ntfsize; ++ char *outbufbase; ++ { ++ int pgz = getpagesize (); ++ TEST_VERIFY_EXIT (pgz > 0); ++ ntfsize = 2 * pgz; ++ ++ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE ++ | MAP_ANONYMOUS, -1); ++ xmprotect (ntf + pgz, pgz, PROT_NONE); ++ ++ outbufbase = ntf + pgz; ++ } ++ ++ /* Check if SOdesignation escape sequence does not trigger an OOB write. */ ++ { ++ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2"; ++ ++ for (int i = 0; i < 9; i++) ++ { ++ char *inp = inbuf; ++ size_t inleft = sizeof (inbuf) - 1; ++ ++ char *outp = outbufbase - i; ++ size_t outleft = i; ++ ++ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) ++ == (size_t) -1); ++ TEST_COMPARE (errno, E2BIG); ++ ++ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); ++ } ++ } ++ ++ /* Same as before for SS2designation. */ ++ { ++ char inbuf[] = "ã´½ \xe3\xb4\xbd"; ++ ++ for (int i = 0; i < 14; i++) ++ { ++ char *inp = inbuf; ++ size_t inleft = sizeof (inbuf) - 1; ++ ++ char *outp = outbufbase - i; ++ size_t outleft = i; ++ ++ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) ++ == (size_t) -1); ++ TEST_COMPARE (errno, E2BIG); ++ ++ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); ++ } ++ } ++ ++ /* Same as before for SS3designation. */ ++ { ++ char inbuf[] = "å \xe5\x8a\x84"; ++ ++ for (int i = 0; i < 14; i++) ++ { ++ char *inp = inbuf; ++ size_t inleft = sizeof (inbuf) - 1; ++ ++ char *outp = outbufbase - i; ++ size_t outleft = i; ++ ++ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) ++ == (size_t) -1); ++ TEST_COMPARE (errno, E2BIG); ++ ++ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); ++ } ++ } ++ ++ TEST_VERIFY_EXIT (iconv_close (cd) != -1); ++ ++ xmunmap (ntf, ntfsize); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> +--- ./iconvdata/Makefile.orig 2021-02-01 11:15:33.000000000 -0600 ++++ ./iconvdata/Makefile 2024-04-18 13:12:59.503089312 -0500 +@@ -74,7 +74,7 @@ + tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ + tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ + bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \ +- bug-iconv13 bug-iconv14 ++ bug-iconv13 bug-iconv14 tst-iconv-iso-2022-cn-ext + ifeq ($(have-thread-library),yes) + tests += bug-iconv3 + endif +@@ -324,6 +324,8 @@ + $(addprefix $(objpfx),$(modules.so)) + $(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) ++$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \ ++ $(addprefix $(objpfx),$(modules.so)) + + $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) \ diff --git a/patches/source/glibc/patches/cdc31409bd4f878577059e70dbd52a28643ec609.patch b/patches/source/glibc/patches/cdc31409bd4f878577059e70dbd52a28643ec609.patch new file mode 100644 index 000000000..96f56ce73 --- /dev/null +++ b/patches/source/glibc/patches/cdc31409bd4f878577059e70dbd52a28643ec609.patch @@ -0,0 +1,237 @@ +From cdc31409bd4f878577059e70dbd52a28643ec609 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Date: Wed, 31 Mar 2021 13:53:34 -0300 +Subject: [PATCH] linux: Normalize and return timeout on select (BZ #27651) + +The commit 2433d39b697, which added time64 support to select, changed +the function to use __NR_pselect6 (or __NR_pelect6_time64) on all +architectures. However, on architectures where the symbol was +implemented with __NR_select the kernel normalizes the passed timeout +instead of return EINVAL. For instance, the input timeval +{ 0, 5000000 } is interpreted as { 5, 0 }. + +And as indicated by BZ #27651, this semantic seems to be expected +and changing it results in some performance issues (most likely +the program does not check the return code and keeps issuing +select with unormalized tv_usec argument). + +To avoid a different semantic depending whether which syscall the +architecture used to issue, select now always normalize the timeout +input. This is a slight change for some ABIs (for instance aarch64). + +Checked on x86_64-linux-gnu and i686-linux-gnu. +--- + include/time.h | 5 +++ + sunrpc/svcauth_des.c | 1 - + support/Makefile | 2 ++ + support/support.h | 8 +++++ + support/support_select_modify_timeout.c | 29 ++++++++++++++++ + support/support_select_normalize_timeout.c | 29 ++++++++++++++++ + sysdeps/unix/sysv/linux/select.c | 40 ++++++++++++++++++---- + 8 files changed, 123 insertions(+), 8 deletions(-) + create mode 100644 support/support_select_modify_timeout.c + create mode 100644 support/support_select_normalize_timeout.c + +diff --git a/include/time.h b/include/time.h +index caf2af5e74..e0636132a6 100644 +--- a/include/time.h ++++ b/include/time.h +@@ -502,6 +502,11 @@ time_now (void) + __clock_gettime (TIME_CLOCK_GETTIME_CLOCKID, &ts); + return ts.tv_sec; + } ++ ++#define NSEC_PER_SEC 1000000000L /* Nanoseconds per second. */ ++#define USEC_PER_SEC 1000000L /* Microseconds per second. */ ++#define NSEC_PER_USEC 1000L /* Nanoseconds per microsecond. */ ++ + #endif + + #endif +diff --git a/sunrpc/svcauth_des.c b/sunrpc/svcauth_des.c +index 7607abc818..25a85c9097 100644 +--- a/sunrpc/svcauth_des.c ++++ b/sunrpc/svcauth_des.c +@@ -58,7 +58,6 @@ + + #define debug(msg) /*printf("svcauth_des: %s\n", msg) */ + +-#define USEC_PER_SEC ((uint32_t) 1000000L) + #define BEFORE(t1, t2) timercmp(t1, t2, <) + + /* +diff --git a/support/Makefile b/support/Makefile +index 900e17f94f..1e2fc97ee6 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -68,6 +68,8 @@ libsupport-routines = \ + support_quote_string \ + support_record_failure \ + support_run_diff \ ++ support_select_modify_timeout \ ++ support_select_normalize_timeout \ + support_set_small_thread_stack_size \ + support_shared_allocate \ + support_small_stack_thread_attribute \ +diff --git a/support/support.h b/support/support.h +index e023d00857..f983783d64 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -144,6 +144,14 @@ static __inline bool support_path_support_time64 (const char *path) + /* Return true if stat supports nanoseconds resolution. */ + extern bool support_stat_nanoseconds (const char *path); + ++/* Return true if select modify the timeout to reflect the amount of time ++ no slept. */ ++extern bool support_select_modify_timeout (void); ++ ++/* Return true if select normalize the timeout input by taking in account ++ tv_usec larger than 1000000. */ ++extern bool support_select_normalize_timeout (void); ++ + __END_DECLS + + #endif /* SUPPORT_H */ +diff --git a/support/support_select_modify_timeout.c b/support/support_select_modify_timeout.c +new file mode 100644 +index 0000000000..d70a5a5068 +--- /dev/null ++++ b/support/support_select_modify_timeout.c +@@ -0,0 +1,29 @@ ++/* Return whether select modify the timeout. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdbool.h> ++ ++bool ++support_select_modify_timeout (void) ++{ ++#ifdef __linux__ ++ return true; ++#else ++ return false; ++#endif ++} +diff --git a/support/support_select_normalize_timeout.c b/support/support_select_normalize_timeout.c +new file mode 100644 +index 0000000000..447e3ec3e3 +--- /dev/null ++++ b/support/support_select_normalize_timeout.c +@@ -0,0 +1,29 @@ ++/* Return whether select normalize the timeout. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <stdbool.h> ++ ++bool ++support_select_normalize_timeout (void) ++{ ++#ifdef __linux__ ++ return true; ++#else ++ return false; ++#endif ++} +diff --git a/sysdeps/unix/sysv/linux/select.c b/sysdeps/unix/sysv/linux/select.c +index 415aa87d3c..d075270ff4 100644 +--- a/sysdeps/unix/sysv/linux/select.c ++++ b/sysdeps/unix/sysv/linux/select.c +@@ -33,12 +33,34 @@ int + __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct __timeval64 *timeout) + { +- struct __timespec64 ts64, *pts64 = NULL; +- if (timeout != NULL) ++ __time64_t s = timeout != NULL ? timeout->tv_sec : 0; ++ int32_t us = timeout != NULL ? timeout->tv_usec : 0; ++ int32_t ns; ++ ++ if (s < 0 || us < 0) ++ return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL); ++ ++ /* Normalize the timeout, as legacy Linux __NR_select and __NR__newselect. ++ Different than syscall, it also handle possible overflow. */ ++ if (us / USEC_PER_SEC > INT64_MAX - s) + { +- ts64 = timeval64_to_timespec64 (*timeout); +- pts64 = &ts64; ++ s = INT64_MAX; ++ ns = NSEC_PER_SEC - 1; + } ++ else ++ { ++ s += us / USEC_PER_SEC; ++ us = us % USEC_PER_SEC; ++ ns = us * NSEC_PER_USEC; ++ } ++ ++ struct __timespec64 ts64, *pts64 = NULL; ++ if (timeout != NULL) ++ { ++ ts64.tv_sec = s; ++ ts64.tv_nsec = ns; ++ pts64 = &ts64; ++ } + + #ifndef __NR_pselect6_time64 + # define __NR_pselect6_time64 __NR_pselect6 +@@ -52,10 +74,13 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + (though the pselect() glibc call suppresses this behavior). + Since select() on Linux has the same behavior as the pselect6 + syscall, we update the timeout here. */ +- if (r == 0 || errno != ENOSYS) ++ if (r >= 0 || errno != ENOSYS) + { + if (timeout != NULL) +- TIMEVAL_TO_TIMESPEC (timeout, &ts64); ++ { ++ timeout->tv_sec = ts64.tv_sec; ++ timeout->tv_usec = ts64.tv_nsec / NSEC_PER_USEC; ++ } + return r; + } + +@@ -71,7 +96,8 @@ __select64 (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + __set_errno (EINVAL); + return -1; + } +- ts32 = valid_timespec64_to_timespec (ts64); ++ ts32.tv_sec = s; ++ ts32.tv_nsec = ns; + pts32 = &ts32; + } + # ifndef __ASSUME_PSELECT +-- +2.27.0 + + diff --git a/patches/source/glibc/patches/glibc.CVE-2021-3998.patch b/patches/source/glibc/patches/glibc.CVE-2021-3998.patch new file mode 100644 index 000000000..45602d050 --- /dev/null +++ b/patches/source/glibc/patches/glibc.CVE-2021-3998.patch @@ -0,0 +1,123 @@ +From f7a79879c0b2bef0dadd6caaaeeb0d26423e04e5 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar <siddhesh@sourceware.org> +Date: Thu, 13 Jan 2022 11:28:36 +0530 +Subject: [PATCH] realpath: Set errno to ENAMETOOLONG for result larger than + PATH_MAX [BZ #28770] + +realpath returns an allocated string when the result exceeds PATH_MAX, +which is unexpected when its second argument is not NULL. This results +in the second argument (resolved) being uninitialized and also results +in a memory leak since the caller expects resolved to be the same as the +returned value. + +Return NULL and set errno to ENAMETOOLONG if the result exceeds +PATH_MAX. This fixes [BZ #28770], which is CVE-2021-3998. + +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> +(cherry picked from commit ee8d5e33adb284601c00c94687bc907e10aec9bb) +--- + NEWS | 4 +++ + stdlib/Makefile | 1 + + stdlib/canonicalize.c | 12 +++++++-- + stdlib/tst-realpath-toolong.c | 49 +++++++++++++++++++++++++++++++++++ + 4 files changed, 64 insertions(+), 2 deletions(-) + create mode 100644 stdlib/tst-realpath-toolong.c + +--- ./NEWS.orig 2021-02-01 11:15:33.000000000 -0600 ++++ ./NEWS 2022-01-24 13:32:24.268678228 -0600 +@@ -118,6 +118,10 @@ + CVE-2019-25013: A buffer overflow has been fixed in the iconv function when + invoked with EUC-KR input containing invalid multibyte input sequences. + ++ CVE-2021-3998: Passing a path longer than PATH_MAX to the realpath ++ function could result in a memory leak and potential access of ++ uninitialized memory. Reported by Qualys. ++ + The following bugs are resolved with this release: + + [10635] libc: realpath portability patches +--- ./stdlib/canonicalize.c.orig 2021-02-01 11:15:33.000000000 -0600 ++++ ./stdlib/canonicalize.c 2022-01-24 13:32:24.268678228 -0600 +@@ -400,8 +400,16 @@ + + error: + *dest++ = '\0'; +- if (resolved != NULL && dest - rname <= get_path_max ()) +- rname = strcpy (resolved, rname); ++ if (resolved != NULL) ++ { ++ if (dest - rname <= get_path_max ()) ++ rname = strcpy (resolved, rname); ++ else ++ { ++ failed = true; ++ __set_errno (ENAMETOOLONG); ++ } ++ } + + error_nomem: + scratch_buffer_free (&extra_buffer); +--- ./stdlib/Makefile.orig 2022-01-24 13:32:24.268678228 -0600 ++++ ./stdlib/Makefile 2022-01-24 13:32:59.968676254 -0600 +@@ -86,7 +86,7 @@ + tst-makecontext-align test-bz22786 tst-strtod-nan-sign \ + tst-swapcontext1 tst-setcontext4 tst-setcontext5 \ + tst-setcontext6 tst-setcontext7 tst-setcontext8 \ +- tst-setcontext9 tst-bz20544 tst-canon-bz26341 ++ tst-setcontext9 tst-bz20544 tst-canon-bz26341 tst-realpath-toolong + + tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ + tst-tls-atexit tst-tls-atexit-nodelete +--- ./stdlib/tst-realpath-toolong.c.orig 2022-01-24 13:32:24.268678228 -0600 ++++ ./stdlib/tst-realpath-toolong.c 2022-01-24 13:32:24.268678228 -0600 +@@ -0,0 +1,49 @@ ++/* Verify that realpath returns NULL with ENAMETOOLONG if the result exceeds ++ NAME_MAX. ++ Copyright The GNU Toolchain Authors. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <limits.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++#include <support/check.h> ++#include <support/temp_file.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++ ++#define BASENAME "tst-realpath-toolong." ++ ++int ++do_test (void) ++{ ++ char *base = support_create_and_chdir_toolong_temp_directory (BASENAME); ++ ++ char buf[PATH_MAX + 1]; ++ const char *res = realpath (".", buf); ++ ++ /* canonicalize.c states that if the real path is >= PATH_MAX, then ++ realpath returns NULL and sets ENAMETOOLONG. */ ++ TEST_VERIFY (res == NULL); ++ TEST_VERIFY (errno == ENAMETOOLONG); ++ ++ free (base); ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/patches/source/glibc/patches/glibc.CVE-2021-3999.patch b/patches/source/glibc/patches/glibc.CVE-2021-3999.patch new file mode 100644 index 000000000..0644f798a --- /dev/null +++ b/patches/source/glibc/patches/glibc.CVE-2021-3999.patch @@ -0,0 +1,356 @@ +From 472e799a5f2102bc0c3206dbd5a801765fceb39c Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar <siddhesh@sourceware.org> +Date: Fri, 21 Jan 2022 23:32:56 +0530 +Subject: [PATCH] getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999) + +No valid path returned by getcwd would fit into 1 byte, so reject the +size early and return NULL with errno set to ERANGE. This change is +prompted by CVE-2021-3999, which describes a single byte buffer +underflow and overflow when all of the following conditions are met: + +- The buffer size (i.e. the second argument of getcwd) is 1 byte +- The current working directory is too long +- '/' is also mounted on the current working directory + +Sequence of events: + +- In sysdeps/unix/sysv/linux/getcwd.c, the syscall returns ENAMETOOLONG + because the linux kernel checks for name length before it checks + buffer size + +- The code falls back to the generic getcwd in sysdeps/posix + +- In the generic func, the buf[0] is set to '\0' on line 250 + +- this while loop on line 262 is bypassed: + + while (!(thisdev == rootdev && thisino == rootino)) + + since the rootfs (/) is bind mounted onto the directory and the flow + goes on to line 449, where it puts a '/' in the byte before the + buffer. + +- Finally on line 458, it moves 2 bytes (the underflowed byte and the + '\0') to the buf[0] and buf[1], resulting in a 1 byte buffer overflow. + +- buf is returned on line 469 and errno is not set. + +This resolves BZ #28769. + +Reviewed-by: Andreas Schwab <schwab@linux-m68k.org> +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +Signed-off-by: Qualys Security Advisory <qsa@qualys.com> +Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org> +(cherry picked from commit 23e0e8f5f1fb5ed150253d986ecccdc90c2dcd5e) +--- + NEWS | 6 + + sysdeps/posix/getcwd.c | 7 + + sysdeps/unix/sysv/linux/Makefile | 7 +- + .../unix/sysv/linux/tst-getcwd-smallbuff.c | 241 ++++++++++++++++++ + 4 files changed, 260 insertions(+), 1 deletion(-) + create mode 100644 sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c + +diff --git a/NEWS b/NEWS +index b4f81c2668..8d7467d2c1 100644 +--- a/NEWS ++++ b/NEWS +@@ -20,6 +20,12 @@ Security related changes: + function could result in a memory leak and potential access of + uninitialized memory. Reported by Qualys. + ++ CVE-2021-3999: Passing a buffer of size exactly 1 byte to the getcwd ++ function may result in an off-by-one buffer underflow and overflow ++ when the current working directory is longer than PATH_MAX and also ++ corresponds to the / directory through an unprivileged mount ++ namespace. Reported by Qualys. ++ + The following bugs are resolved with this release: + + [12889] nptl: Fix race between pthread_kill and thread exit +diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c +index 13680026ff..b6984a382c 100644 +--- a/sysdeps/posix/getcwd.c ++++ b/sysdeps/posix/getcwd.c +@@ -187,6 +187,13 @@ __getcwd_generic (char *buf, size_t size) + size_t allocated = size; + size_t used; + ++ /* A size of 1 byte is never useful. */ ++ if (allocated == 1) ++ { ++ __set_errno (ERANGE); ++ return NULL; ++ } ++ + #if HAVE_MINIMALLY_WORKING_GETCWD + /* If AT_FDCWD is not defined, the algorithm below is O(N**2) and + this is much slower than the system getcwd (at least on +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 76ad06361c..9380d3848d 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -331,7 +331,12 @@ sysdep_routines += xstatconv internal_statvfs \ + + sysdep_headers += bits/fcntl-linux.h + +-tests += tst-fallocate tst-fallocate64 tst-o_path-locks ++tests += \ ++ tst-fallocate \ ++ tst-fallocate64 \ ++ tst-getcwd-smallbuff \ ++ tst-o_path-locks \ ++# tests + endif + + ifeq ($(subdir),elf) +diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +new file mode 100644 +index 0000000000..d460d6e766 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +@@ -0,0 +1,241 @@ ++/* Verify that getcwd returns ERANGE for size 1 byte and does not underflow ++ buffer when the CWD is too long and is also a mount target of /. See bug ++ #28769 or CVE-2021-3999 for more context. ++ Copyright The GNU Toolchain Authors. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <fcntl.h> ++#include <intprops.h> ++#include <limits.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <sys/mount.h> ++#include <sys/stat.h> ++#include <sys/types.h> ++#include <sys/wait.h> ++ ++#include <sys/socket.h> ++#include <sys/un.h> ++#include <support/check.h> ++#include <support/temp_file.h> ++#include <support/xsched.h> ++#include <support/xunistd.h> ++ ++static char *base; ++#define BASENAME "tst-getcwd-smallbuff" ++#define MOUNT_NAME "mpoint" ++static int sockfd[2]; ++ ++static void ++do_cleanup (void) ++{ ++ support_chdir_toolong_temp_directory (base); ++ TEST_VERIFY_EXIT (rmdir (MOUNT_NAME) == 0); ++ free (base); ++} ++ ++static void ++send_fd (const int sock, const int fd) ++{ ++ struct msghdr msg = {0}; ++ union ++ { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE (sizeof (int))]; ++ } cmsgbuf = {0}; ++ struct cmsghdr *cmsg; ++ struct iovec vec; ++ char ch = 'A'; ++ ssize_t n; ++ ++ msg.msg_control = &cmsgbuf.buf; ++ msg.msg_controllen = sizeof (cmsgbuf.buf); ++ ++ cmsg = CMSG_FIRSTHDR (&msg); ++ cmsg->cmsg_len = CMSG_LEN (sizeof (int)); ++ cmsg->cmsg_level = SOL_SOCKET; ++ cmsg->cmsg_type = SCM_RIGHTS; ++ memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd)); ++ ++ vec.iov_base = &ch; ++ vec.iov_len = 1; ++ msg.msg_iov = &vec; ++ msg.msg_iovlen = 1; ++ ++ while ((n = sendmsg (sock, &msg, 0)) == -1 && errno == EINTR); ++ ++ TEST_VERIFY_EXIT (n == 1); ++} ++ ++static int ++recv_fd (const int sock) ++{ ++ struct msghdr msg = {0}; ++ union ++ { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE(sizeof(int))]; ++ } cmsgbuf = {0}; ++ struct cmsghdr *cmsg; ++ struct iovec vec; ++ ssize_t n; ++ char ch = '\0'; ++ int fd = -1; ++ ++ vec.iov_base = &ch; ++ vec.iov_len = 1; ++ msg.msg_iov = &vec; ++ msg.msg_iovlen = 1; ++ ++ msg.msg_control = &cmsgbuf.buf; ++ msg.msg_controllen = sizeof (cmsgbuf.buf); ++ ++ while ((n = recvmsg (sock, &msg, 0)) == -1 && errno == EINTR); ++ if (n != 1 || ch != 'A') ++ return -1; ++ ++ cmsg = CMSG_FIRSTHDR (&msg); ++ if (cmsg == NULL) ++ return -1; ++ if (cmsg->cmsg_type != SCM_RIGHTS) ++ return -1; ++ memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd)); ++ if (fd < 0) ++ return -1; ++ return fd; ++} ++ ++static int ++child_func (void * const arg) ++{ ++ xclose (sockfd[0]); ++ const int sock = sockfd[1]; ++ char ch; ++ ++ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1); ++ TEST_VERIFY_EXIT (ch == '1'); ++ ++ if (mount ("/", MOUNT_NAME, NULL, MS_BIND | MS_REC, NULL)) ++ FAIL_EXIT1 ("mount failed: %m\n"); ++ const int fd = xopen ("mpoint", ++ O_RDONLY | O_PATH | O_DIRECTORY | O_NOFOLLOW, 0); ++ ++ send_fd (sock, fd); ++ xclose (fd); ++ ++ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1); ++ TEST_VERIFY_EXIT (ch == 'a'); ++ ++ xclose (sock); ++ return 0; ++} ++ ++static void ++update_map (char * const mapping, const char * const map_file) ++{ ++ const size_t map_len = strlen (mapping); ++ ++ const int fd = xopen (map_file, O_WRONLY, 0); ++ xwrite (fd, mapping, map_len); ++ xclose (fd); ++} ++ ++static void ++proc_setgroups_write (const long child_pid, const char * const str) ++{ ++ const size_t str_len = strlen(str); ++ ++ char setgroups_path[sizeof ("/proc//setgroups") + INT_STRLEN_BOUND (long)]; ++ ++ snprintf (setgroups_path, sizeof (setgroups_path), ++ "/proc/%ld/setgroups", child_pid); ++ ++ const int fd = open (setgroups_path, O_WRONLY); ++ ++ if (fd < 0) ++ { ++ TEST_VERIFY_EXIT (errno == ENOENT); ++ FAIL_UNSUPPORTED ("/proc/%ld/setgroups not found\n", child_pid); ++ } ++ ++ xwrite (fd, str, str_len); ++ xclose(fd); ++} ++ ++static char child_stack[1024 * 1024]; ++ ++int ++do_test (void) ++{ ++ base = support_create_and_chdir_toolong_temp_directory (BASENAME); ++ ++ xmkdir (MOUNT_NAME, S_IRWXU); ++ atexit (do_cleanup); ++ ++ TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0); ++ pid_t child_pid = xclone (child_func, NULL, child_stack, ++ sizeof (child_stack), ++ CLONE_NEWUSER | CLONE_NEWNS | SIGCHLD); ++ ++ xclose (sockfd[1]); ++ const int sock = sockfd[0]; ++ ++ char map_path[sizeof ("/proc//uid_map") + INT_STRLEN_BOUND (long)]; ++ char map_buf[sizeof ("0 1") + INT_STRLEN_BOUND (long)]; ++ ++ snprintf (map_path, sizeof (map_path), "/proc/%ld/uid_map", ++ (long) child_pid); ++ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getuid()); ++ update_map (map_buf, map_path); ++ ++ proc_setgroups_write ((long) child_pid, "deny"); ++ snprintf (map_path, sizeof (map_path), "/proc/%ld/gid_map", ++ (long) child_pid); ++ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getgid()); ++ update_map (map_buf, map_path); ++ ++ TEST_VERIFY_EXIT (send (sock, "1", 1, MSG_NOSIGNAL) == 1); ++ const int fd = recv_fd (sock); ++ TEST_VERIFY_EXIT (fd >= 0); ++ TEST_VERIFY_EXIT (fchdir (fd) == 0); ++ ++ static char buf[2 * 10 + 1]; ++ memset (buf, 'A', sizeof (buf)); ++ ++ /* Finally, call getcwd and check if it resulted in a buffer underflow. */ ++ char * cwd = getcwd (buf + sizeof (buf) / 2, 1); ++ TEST_VERIFY (cwd == NULL); ++ TEST_VERIFY (errno == ERANGE); ++ ++ for (int i = 0; i < sizeof (buf); i++) ++ if (buf[i] != 'A') ++ { ++ printf ("buf[%d] = %02x\n", i, (unsigned int) buf[i]); ++ support_record_failure (); ++ } ++ ++ TEST_VERIFY_EXIT (send (sock, "a", 1, MSG_NOSIGNAL) == 1); ++ xclose (sock); ++ TEST_VERIFY_EXIT (xwaitpid (child_pid, NULL, 0) == child_pid); ++ ++ return 0; ++} ++ ++#define CLEANUP_HANDLER do_cleanup ++#include <support/test-driver.c> +-- +2.27.0 + + |