From 33c53a939f9f595ded355438208c9a002f8b4555 Mon Sep 17 00:00:00 2001 From: Aurelien Jarno <aurel32@debian.org> Date: Thu, 17 Mar 2022 22:37:00 +0100 Subject: [PATCH] Import Debian changes 2.31-13+deb11u3 --- debian/changelog | 22 + debian/debhelper.in/libc-bin.postinst | 15 - debian/debhelper.in/libc.preinst | 30 +- ...E-2021-33574-mq_notify-use-after-free.diff | 157 +++++ debian/patches/git-updates.diff | 589 +++++++++++++++++- debian/patches/series | 1 + 6 files changed, 752 insertions(+), 62 deletions(-) create mode 100644 debian/patches/any/local-CVE-2021-33574-mq_notify-use-after-free.diff diff --git a/debian/changelog b/debian/changelog index 7c23c790b..b1753afef 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,25 @@ +glibc (2.31-13+deb11u3) bullseye; urgency=medium + + [ Aurelien Jarno ] + * debian/patches/git-updates.diff: update from upstream stable branch: + - Fix bad conversion from ISO-2022-JP-3 with iconv (CVE-2021-43396). + Closes: #998622. + - Remove PIE check on amd64 to fix FTBFS with binutils 2.37. + - Fix a buffer overflow in sunrpc svcunix_create (CVE-2022-23218). + - Fix a buffer overflow in sunrpc clnt_create (CVE-2022-23219). + * debian/debhelper.in/libc-bin.postinst: stop replacing older versions from + /etc/nsswitch.conf. Closes: #998008. + * debian/debhelper.in/libc.preinst: simplify the version comparison by only + comparing the two first parts, now that kernel 2.X are not supported + anymore. Closes: #1004861. + * debian/debhelper.in/libc.preinst: drop the check for kernel release > 255 + now that glibc and preinstall script are fixed. Closes: #987266. + * debian/patches/local-CVE-2021-33574-mq_notify-use-after-free.diff: + fix a possible use-after-free in mq_notify (CVE-2021-33574). Closes: + #989147. + + -- Aurelien Jarno <aurel32@debian.org> Thu, 17 Mar 2022 22:37:00 +0100 + glibc (2.31-13+deb11u2) bullseye; urgency=medium [ Aurelien Jarno ] diff --git a/debian/debhelper.in/libc-bin.postinst b/debian/debhelper.in/libc-bin.postinst index 802a3ad05..6309f1946 100644 --- a/debian/debhelper.in/libc-bin.postinst +++ b/debian/debhelper.in/libc-bin.postinst @@ -12,21 +12,6 @@ update_to_current_default() { if [ -f $2 ]; then md5=`md5sum $2 | cut -f 1 -d " "` case "$md5" in - # base-files 3.0.0 to 3.1.15 - 109e33e2c91d1853b5bc56078a96aa18) - ;; - # base-files 3.1.8 and 3.1.9 - 3114ea9cf2f3bd8d120b4da96e3832d5) - ;; - # base-files 3.1.16 to 7.2 and libc-bin 2.19-18 to 2.22-11 - 295c15c4bdac80e50b37689ef08f359c) - ;; - # base-files 6.6 - 30b82cb1ce20d480703da2208a4607b4) - ;; - # base-files 7.3 and libc-bin 2.22-12 - f8e97bf611374634c7cb3a6085503ab5) - ;; # modified file *) return diff --git a/debian/debhelper.in/libc.preinst b/debian/debhelper.in/libc.preinst index ff59ad9a4..133ca4780 100644 --- a/debian/debhelper.in/libc.preinst +++ b/debian/debhelper.in/libc.preinst @@ -5,14 +5,7 @@ export LC_ALL=C type=$1 preversion=$2 -linux_compare_versions () { - verA=$(($(echo "$1" | sed 's/^\([0-9]*\.[0-9]*\)\([^.0-9]\|$\)/\1.0\2/; s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \* 10000 + \2 \* 100 + \3/'))) - verB=$(($(echo "$3" | sed 's/^\([0-9]*\.[0-9]*\)\([^.0-9]\|$\)/\1.0\2/; s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1 \* 10000 + \2 \* 100 + \3/'))) - - test $verA -$2 $verB -} - -kfreebsd_compare_versions () { +kernel_compare_versions () { verA=$(($(echo "$1" | sed 's/\([0-9]*\)\.\([0-9]*\).*/\1 \* 100 + \2/'))) verB=$(($(echo "$3" | sed 's/\([0-9]*\)\.\([0-9]*\).*/\1 \* 100 + \2/'))) @@ -99,21 +92,6 @@ then system=`uname -s` if [ "$system" = "Linux" ] then - # Test to make sure z < 255, in x.y.z-n form of kernel version - # Also make sure we don't trip on x.y.zFOO-n form - kernel_rev=$(uname -r | sed 's/\([0-9]*\.\)\{1,2\}\([0-9]*\)\(.*\)/\2/') - if [ "$kernel_rev" -ge 255 ] - then - echo "ERROR: Your kernel version indicates a revision number" - echo "of 255 or greater. Glibc has a number of built in" - echo "assumptions that this revision number is less than 255." - echo "If you\'ve built your own kernel, please make sure that any" - echo "custom version numbers are appended to the upstream" - echo "kernel number with a dash or some other delimiter." - echo - exit 1 - fi - # sanity checking for the appropriate kernel on each architecture. kernel_ver=`uname -r` case ${DPKG_MAINTSCRIPT_ARCH} in @@ -124,7 +102,7 @@ then ;; esac - if linux_compare_versions "$kernel_ver" lt $kernel_ver_min + if kernel_compare_versions "$kernel_ver" lt $kernel_ver_min then if [ "$USE_DEBCONF" ] then @@ -144,7 +122,7 @@ then exit 1 fi - if linux_compare_versions "$kernel_ver" lt $kernel_ver_rec + if kernel_compare_versions "$kernel_ver" lt $kernel_ver_rec then if [ "$USE_DEBCONF" ] then @@ -167,7 +145,7 @@ then then kernel_ver=`uname -r` kernel_ver_min=8.3 - if kfreebsd_compare_versions "$kernel_ver" lt $kernel_ver_min + if kernel_compare_versions "$kernel_ver" lt $kernel_ver_min then if [ "$USE_DEBCONF" ] then diff --git a/debian/patches/any/local-CVE-2021-33574-mq_notify-use-after-free.diff b/debian/patches/any/local-CVE-2021-33574-mq_notify-use-after-free.diff new file mode 100644 index 000000000..1d91a5c47 --- /dev/null +++ b/debian/patches/any/local-CVE-2021-33574-mq_notify-use-after-free.diff @@ -0,0 +1,157 @@ +This is basically a backport of the following upstream commits below with +__pthread_attr_copy implemented as a static function in mq_notify.c Indeed it +has been added upstream in glibc 2.32 and is exported as a GLIBC_PRIVATE symbol +from libpthread.so while __mq_notify is exported by librt.so. As Debian +supports online upgrades, We need to support the case where 1) a process is +started loading libpthread.so, 2) the glibc libraries are upgraded 3) librt.so +is dlopened. This scenario might happens for instance with OpenJDK. + +commit 331c6e8a184167dd21a9f0b3fc165aeefea6eeca +Author: Florian Weimer <fweimer@redhat.com> +Date: Tue May 19 12:32:39 2020 +0200 + + nptl: Add __pthread_attr_copy for copying pthread_attr_t objects + +commit 79474303223c5665bec75ffbdb2a86ee04a2514b +Author: Nikita Popov <npv1310@gmail.com> +Date: Mon Aug 9 20:17:34 2021 +0530 + + 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> + (cherry picked from commit b805aebd42364fe696e417808a700fdb9800c9e8) + +commit 42d359350510506b87101cf77202fefcbfc790cb +Author: Andreas Schwab <schwab@linux-m68k.org> +Date: Thu May 27 12:49:47 2021 +0200 + + 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. + +commit 217b6dc298156bdb0d6aea9ea93e7e394a5ff091 +Author: Florian Weimer <fweimer@redhat.com> +Date: Tue Jun 1 17:51:41 2021 +0200 + + 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> + +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index f288bac477..e78ae74f0b 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -134,9 +134,12 @@ 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) +- /* The only state we keep is the copy of the thread attributes. */ +- free (data.attr); ++ 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); ++ free (data.attr); ++ } + } + return NULL; + } +@@ -214,6 +217,42 @@ init_mq_netlink (void) + } + } + ++static int ++__pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source) ++{ ++ /* Avoid overwriting *TARGET until all allocations have ++ succeeded. */ ++ union ++ { ++ pthread_attr_t external; ++ struct pthread_attr internal; ++ } temp; ++ ++ ++ temp.external = *source; ++ ++ /* Force new allocation. This function has full ownership of temp. */ ++ temp.internal.cpuset = NULL; ++ temp.internal.cpusetsize = 0; ++ ++ struct pthread_attr *isource = (struct pthread_attr *) source; ++ ++ /* Propagate affinity mask information. */ ++ if (isource->cpuset != NULL && isource->cpusetsize > 0) ++ { ++ temp.internal.cpuset = (cpu_set_t *) malloc (isource->cpusetsize); ++ if (temp.internal.cpuset == NULL) ++ return ENOMEM; ++ ++ temp.internal.cpusetsize = isource->cpusetsize; ++ memcpy (temp.internal.cpuset, isource->cpuset, isource->cpusetsize); ++ } ++ ++ /* Transfer ownership. *target is not assumed to have been ++ initialized. */ ++ *target = temp.external; ++ return 0; ++} + + /* Register notification upon message arrival to an empty message queue + MQDES. */ +@@ -257,8 +296,14 @@ 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)); ++ 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,8 +316,11 @@ 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)) +- free (data.attr); ++ if (retval != 0 && data.attr != NULL) ++ { ++ pthread_attr_destroy (data.attr); ++ free (data.attr); ++ } + + return retval; + } diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff index e1cac4a1f..a68985405 100644 --- a/debian/patches/git-updates.diff +++ b/debian/patches/git-updates.diff @@ -1,10 +1,10 @@ GIT update of https://sourceware.org/git/glibc.git/release/2.31/master from glibc-2.31 diff --git a/NEWS b/NEWS -index 292fbc595a..98d4b24ab4 100644 +index 292fbc595a..4402867631 100644 --- a/NEWS +++ b/NEWS -@@ -5,6 +5,68 @@ See the end for copying conditions. +@@ -5,6 +5,78 @@ See the end for copying conditions. Please send GNU C library bug reports via <https://sourceware.org/bugzilla/> using `glibc' in the "product" field. @@ -15,6 +15,7 @@ index 292fbc595a..98d4b24ab4 100644 + (CVE-2016-10228) + [20019] NULL pointer dereference in libc.so.6 IFUNC due to uninitialized GOT + [20543] Please move from .gnu.linkonce to comdat ++ [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" + [23296] Data race in setting function descriptor during lazy binding + [24973] iconv encounters segmentation fault when converting 0x00 0xfe in + EUC-KR to UTF-8 (CVE-2019-25013) @@ -41,6 +42,8 @@ index 292fbc595a..98d4b24ab4 100644 + [26932] libc: sh: Multiple floating point functions defined as stubs only + [27130] "rep movsb" performance issue + [27177] GLIBC_TUNABLES=glibc.cpu.x86_ibt=on:glibc.cpu.x86_shstk=on doesn't work ++ [28524] Conversion from ISO-2022-JP-3 with iconv may emit spurious NULs ++ [28768] CVE-2022-23218: Buffer overflow in sunrpc svcunix_create + +Security related changes: + @@ -69,6 +72,13 @@ index 292fbc595a..98d4b24ab4 100644 + + CVE-2020-29562: An assertion failure has been fixed in the iconv function + when invoked with UCS4 input containing an invalid character. ++ ++ CVE-2022-23219: Passing an overlong file name to the clnt_create ++ legacy function could result in a stack-based buffer overflow when ++ using the "unix" protocol. Reported by Martin Sebor. ++ ++ CVE-2022-23218: Passing an overlong file name to the svcunix_create ++ legacy function could result in a stack-based buffer overflow. + Version 2.31 @@ -2200,23 +2210,32 @@ index 0000000000..d8db7b335c + check_errtest_result +done diff --git a/iconvdata/Makefile b/iconvdata/Makefile -index c83962f351..72a91416d3 100644 +index c83962f351..8fbb67a52b 100644 --- a/iconvdata/Makefile +++ b/iconvdata/Makefile -@@ -73,7 +73,7 @@ modules.so := $(addsuffix .so, $(modules)) +@@ -1,4 +1,5 @@ + # Copyright (C) 1997-2020 Free Software Foundation, Inc. ++# Copyright (C) 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 +@@ -73,7 +74,8 @@ modules.so := $(addsuffix .so, $(modules)) ifeq (yes,$(build-shared)) 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 -+ bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 ++ bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 \ ++ bug-iconv15 ifeq ($(have-thread-library),yes) tests += bug-iconv3 endif -@@ -316,6 +316,8 @@ $(objpfx)bug-iconv10.out: $(objpfx)gconv-modules \ +@@ -316,6 +318,10 @@ $(objpfx)bug-iconv10.out: $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) $(objpfx)bug-iconv12.out: $(objpfx)gconv-modules \ $(addprefix $(objpfx),$(modules.so)) +$(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \ ++ $(addprefix $(objpfx),$(modules.so)) ++$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \ + $(addprefix $(objpfx),$(modules.so)) $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ @@ -2413,6 +2432,72 @@ index 0000000000..902f140fa9 +} + +#include <support/test-driver.c> +diff --git a/iconvdata/bug-iconv15.c b/iconvdata/bug-iconv15.c +new file mode 100644 +index 0000000000..cc04bd0313 +--- /dev/null ++++ b/iconvdata/bug-iconv15.c +@@ -0,0 +1,60 @@ ++/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv ++ may emit spurious NUL character on state reset. ++ Copyright (C) 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 <stddef.h> ++#include <iconv.h> ++#include <support/check.h> ++ ++static int ++do_test (void) ++{ ++ char in[] = "\x1b(I"; ++ char *inbuf = in; ++ size_t inleft = sizeof (in) - 1; ++ char out[1]; ++ char *outbuf = out; ++ size_t outleft = sizeof (out); ++ iconv_t cd; ++ ++ cd = iconv_open ("UTF8", "ISO-2022-JP-3"); ++ TEST_VERIFY_EXIT (cd != (iconv_t) -1); ++ ++ /* First call to iconv should alter internal state. ++ Now, JISX0201_Kana_set is selected and ++ state value != ASCII_set. */ ++ TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1); ++ ++ /* No bytes should have been added to ++ the output buffer at this point. */ ++ TEST_VERIFY (outbuf == out); ++ TEST_VERIFY (outleft == sizeof (out)); ++ ++ /* Second call shall emit spurious NUL character in unpatched glibc. */ ++ TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1); ++ ++ /* No characters are expected to be produced. */ ++ TEST_VERIFY (outbuf == out); ++ TEST_VERIFY (outleft == sizeof (out)); ++ ++ TEST_VERIFY_EXIT (iconv_close (cd) != -1); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/iconvdata/euc-kr.c b/iconvdata/euc-kr.c index b0d56cf3ee..1045bae926 100644 --- a/iconvdata/euc-kr.c @@ -2462,10 +2547,17 @@ index 49e7267ab4..521f0825b7 100644 ++inptr; \ continue; \ diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c -index 8c3b7e627e..62cbc54a11 100644 +index 8c3b7e627e..c7b470db61 100644 --- a/iconvdata/iso-2022-jp-3.c +++ b/iconvdata/iso-2022-jp-3.c -@@ -67,23 +67,34 @@ enum +@@ -1,5 +1,6 @@ + /* Conversion module for ISO-2022-JP-3. + Copyright (C) 1998-2020 Free Software Foundation, Inc. ++ Copyright (C) The GNU Toolchain Authors. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998, + and Bruno Haible <bruno@clisp.org>, 2002. +@@ -67,10 +68,15 @@ enum CURRENT_SEL_MASK = 7 << 3 }; @@ -2485,10 +2577,7 @@ index 8c3b7e627e..62cbc54a11 100644 /* Since this is a stateful encoding we have to provide code which resets the output state to the initial state. This has to be done during the - flushing. */ - #define EMIT_SHIFT_TO_INIT \ -- if ((data->__statep->__count & ~7) != ASCII_set) \ -+ if (data->__statep->__count != ASCII_set) \ +@@ -80,10 +86,27 @@ enum { \ if (FROM_DIRECTION) \ { \ @@ -2496,20 +2585,31 @@ index 8c3b7e627e..62cbc54a11 100644 - state for the input. */ \ - data->__statep->__count &= 7; \ - data->__statep->__count |= ASCII_set; \ -+ if (__glibc_likely (outbuf + 4 <= outend)) \ ++ uint32_t ch = data->__statep->__count >> 6; \ ++ \ ++ if (__glibc_unlikely (ch != 0)) \ + { \ -+ /* Write out the last character. */ \ -+ *((uint32_t *) outbuf) = data->__statep->__count >> 6; \ -+ outbuf += sizeof (uint32_t); \ -+ data->__statep->__count = ASCII_set; \ ++ if (__glibc_likely (outbuf + 4 <= outend)) \ ++ { \ ++ /* Write out the last character. */ \ ++ put32u (outbuf, ch); \ ++ outbuf += 4; \ ++ data->__statep->__count &= 7; \ ++ data->__statep->__count |= ASCII_set; \ ++ } \ ++ else \ ++ /* We don't have enough room in the output buffer. */ \ ++ status = __GCONV_FULL_OUTPUT; \ + } \ + else \ -+ /* We don't have enough room in the output buffer. */ \ -+ status = __GCONV_FULL_OUTPUT; \ ++ { \ ++ data->__statep->__count &= 7; \ ++ data->__statep->__count |= ASCII_set; \ ++ } \ } \ else \ { \ -@@ -151,7 +162,21 @@ enum +@@ -151,7 +174,21 @@ enum #define LOOPFCT FROM_LOOP #define BODY \ { \ @@ -2532,7 +2632,7 @@ index 8c3b7e627e..62cbc54a11 100644 \ /* Recognize escape sequences. */ \ if (__glibc_unlikely (ch == ESC)) \ -@@ -297,21 +322,25 @@ enum +@@ -297,21 +334,25 @@ enum uint32_t u1 = __jisx0213_to_ucs_combining[ch - 1][0]; \ uint32_t u2 = __jisx0213_to_ucs_combining[ch - 1][1]; \ \ @@ -2590,6 +2690,50 @@ index d3eb3a4ff8..f5cdc72797 100644 ch2 = (*s)[1]; if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f) return __UNKNOWN_10646_CHAR; +diff --git a/include/libc-symbols.h b/include/libc-symbols.h +index 685e20fdc0..68fc798051 100644 +--- a/include/libc-symbols.h ++++ b/include/libc-symbols.h +@@ -59,6 +59,19 @@ + # define IN_MODULE (-1) + #endif + ++/* Use symbol_version_reference to specify the version a symbol ++ reference should link to. Use symbol_version or ++ default_symbol_version for the definition of a versioned symbol. ++ The difference is that the latter is a no-op in non-shared ++ builds. */ ++#ifdef __ASSEMBLER__ ++# define symbol_version_reference(real, name, version) \ ++ .symver real, name##@##version ++#else /* !__ASSEMBLER__ */ ++# define symbol_version_reference(real, name, version) \ ++ __asm__ (".symver " #real "," #name "@" #version) ++#endif ++ + #ifndef _ISOMAC + + /* This is defined for the compilation of all C library code. features.h +@@ -396,19 +409,6 @@ for linking") + past the last element in SET. */ + #define symbol_set_end_p(set, ptr) ((ptr) >= (void *const *) &__stop_##set) + +-/* Use symbol_version_reference to specify the version a symbol +- reference should link to. Use symbol_version or +- default_symbol_version for the definition of a versioned symbol. +- The difference is that the latter is a no-op in non-shared +- builds. */ +-#ifdef __ASSEMBLER__ +-# define symbol_version_reference(real, name, version) \ +- .symver real, name##@##version +-#else /* !__ASSEMBLER__ */ +-# define symbol_version_reference(real, name, version) \ +- __asm__ (".symver " #real "," #name "@" #version) +-#endif +- + #ifdef SHARED + # define symbol_version(real, name, version) \ + symbol_version_reference(real, name, version) diff --git a/include/sys/prctl.h b/include/sys/prctl.h index 0920ed642b..d33f3a290e 100644 --- a/include/sys/prctl.h @@ -2602,6 +2746,24 @@ index 0920ed642b..d33f3a290e 100644 # endif /* !_ISOMAC */ #endif +diff --git a/include/sys/un.h b/include/sys/un.h +index bdbee99980..152afd9fc7 100644 +--- a/include/sys/un.h ++++ b/include/sys/un.h +@@ -1 +1,13 @@ + #include <socket/sys/un.h> ++ ++#ifndef _ISOMAC ++ ++/* Set ADDR->sun_family to AF_UNIX and ADDR->sun_path to PATHNAME. ++ Return 0 on success or -1 on failure (due to overlong PATHNAME). ++ The caller should always use sizeof (struct sockaddr_un) as the ++ socket address length, disregaring the length of PATHNAME. ++ Only concrete (non-abstract) pathnames are supported. */ ++int __sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) ++ attribute_hidden; ++ ++#endif /* _ISOMAC */ diff --git a/intl/dcigettext.c b/intl/dcigettext.c index 465c8df34c..bd332e71da 100644 --- a/intl/dcigettext.c @@ -3672,6 +3834,141 @@ index e082d94895..56289503a1 100644 if (n >= __libc_argc) /* Substitute NULL. */ +diff --git a/socket/Makefile b/socket/Makefile +index 125c042cab..19fc6ab41d 100644 +--- a/socket/Makefile ++++ b/socket/Makefile +@@ -29,10 +29,14 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \ + routines := accept bind connect getpeername getsockname getsockopt \ + listen recv recvfrom recvmsg send sendmsg sendto \ + setsockopt shutdown socket socketpair isfdtype opensock \ +- sockatmark accept4 recvmmsg sendmmsg ++ sockatmark accept4 recvmmsg sendmmsg sockaddr_un_set + + tests := tst-accept4 + ++tests-internal := \ ++ tst-sockaddr_un_set \ ++ # tests-internal ++ + aux := sa_len + + include ../Rules +diff --git a/socket/sockaddr_un_set.c b/socket/sockaddr_un_set.c +new file mode 100644 +index 0000000000..0bd40dc34e +--- /dev/null ++++ b/socket/sockaddr_un_set.c +@@ -0,0 +1,41 @@ ++/* Set the sun_path member of struct sockaddr_un. ++ Copyright (C) 2022 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 <errno.h> ++#include <string.h> ++#include <sys/socket.h> ++#include <sys/un.h> ++ ++int ++__sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) ++{ ++ size_t name_length = strlen (pathname); ++ ++ /* The kernel supports names of exactly sizeof (addr->sun_path) ++ bytes, without a null terminator, but userspace does not; see the ++ SUN_LEN macro. */ ++ if (name_length >= sizeof (addr->sun_path)) ++ { ++ __set_errno (EINVAL); /* Error code used by the kernel. */ ++ return -1; ++ } ++ ++ addr->sun_family = AF_UNIX; ++ memcpy (addr->sun_path, pathname, name_length + 1); ++ return 0; ++} +diff --git a/socket/tst-sockaddr_un_set.c b/socket/tst-sockaddr_un_set.c +new file mode 100644 +index 0000000000..29c2a81afd +--- /dev/null ++++ b/socket/tst-sockaddr_un_set.c +@@ -0,0 +1,62 @@ ++/* Test the __sockaddr_un_set function. ++ Copyright (C) 2022 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/>. */ ++ ++/* Re-compile the function because the version in libc is not ++ exported. */ ++#include "sockaddr_un_set.c" ++ ++#include <support/check.h> ++ ++static int ++do_test (void) ++{ ++ struct sockaddr_un sun; ++ ++ memset (&sun, 0xcc, sizeof (sun)); ++ __sockaddr_un_set (&sun, ""); ++ TEST_COMPARE (sun.sun_family, AF_UNIX); ++ TEST_COMPARE (__sockaddr_un_set (&sun, ""), 0); ++ ++ memset (&sun, 0xcc, sizeof (sun)); ++ TEST_COMPARE (__sockaddr_un_set (&sun, "/example"), 0); ++ TEST_COMPARE_STRING (sun.sun_path, "/example"); ++ ++ { ++ char pathname[108]; /* Length of sun_path (ABI constant). */ ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ memset (&sun, 0xcc, sizeof (sun)); ++ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), 0); ++ TEST_COMPARE (sun.sun_family, AF_UNIX); ++ TEST_COMPARE_STRING (sun.sun_path, pathname); ++ } ++ ++ { ++ char pathname[109]; ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ memset (&sun, 0xcc, sizeof (sun)); ++ errno = 0; ++ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), -1); ++ TEST_COMPARE (errno, EINVAL); ++ } ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/stdlib/Makefile b/stdlib/Makefile index 45214b59e4..4615f6dfe7 100644 --- a/stdlib/Makefile @@ -4062,6 +4359,174 @@ index b6c5aea08f..eddea33f4c 100644 -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" +#include <support/test-driver.c> +diff --git a/sunrpc/Makefile b/sunrpc/Makefile +index d5840d0770..162a5cef53 100644 +--- a/sunrpc/Makefile ++++ b/sunrpc/Makefile +@@ -95,7 +95,8 @@ others += rpcgen + endif + + tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \ +- tst-udp-nonblocking ++ tst-udp-nonblocking tst-bug22542 tst-bug28768 ++ + xtests := tst-getmyaddr + + ifeq ($(have-thread-library),yes) +@@ -246,3 +247,5 @@ $(objpfx)tst-udp-timeout: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-udp-garbage: \ + $(common-objpfx)linkobj/libc.so $(shared-thread-library) ++ ++$(objpfx)tst-bug22542: $(common-objpfx)linkobj/libc.so +diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c +index 13ced8994e..b44357cd88 100644 +--- a/sunrpc/clnt_gen.c ++++ b/sunrpc/clnt_gen.c +@@ -57,9 +57,13 @@ clnt_create (const char *hostname, u_long prog, u_long vers, + + if (strcmp (proto, "unix") == 0) + { +- memset ((char *)&sun, 0, sizeof (sun)); +- sun.sun_family = AF_UNIX; +- strcpy (sun.sun_path, hostname); ++ if (__sockaddr_un_set (&sun, hostname) < 0) ++ { ++ struct rpc_createerr *ce = &get_rpc_createerr (); ++ ce->cf_stat = RPC_SYSTEMERROR; ++ ce->cf_error.re_errno = errno; ++ return NULL; ++ } + sock = RPC_ANYSOCK; + client = clntunix_create (&sun, prog, vers, &sock, 0, 0); + if (client == NULL) +diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c +index e01afeabe6..b065d6063a 100644 +--- a/sunrpc/svc_unix.c ++++ b/sunrpc/svc_unix.c +@@ -154,7 +154,10 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) + SVCXPRT *xprt; + struct unix_rendezvous *r; + struct sockaddr_un addr; +- socklen_t len = sizeof (struct sockaddr_in); ++ socklen_t len = sizeof (addr); ++ ++ if (__sockaddr_un_set (&addr, path) < 0) ++ return NULL; + + if (sock == RPC_ANYSOCK) + { +@@ -165,12 +168,6 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) + } + madesock = TRUE; + } +- memset (&addr, '\0', sizeof (addr)); +- addr.sun_family = AF_UNIX; +- len = strlen (path) + 1; +- memcpy (addr.sun_path, path, len); +- len += sizeof (addr.sun_family); +- + __bind (sock, (struct sockaddr *) &addr, len); + + if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0 +diff --git a/sunrpc/tst-bug22542.c b/sunrpc/tst-bug22542.c +new file mode 100644 +index 0000000000..d6cd79787b +--- /dev/null ++++ b/sunrpc/tst-bug22542.c +@@ -0,0 +1,44 @@ ++/* Test to verify that overlong hostname is rejected by clnt_create ++ and doesn't cause a buffer overflow (bug 22542). ++ ++ Copyright (C) 2022 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <rpc/clnt.h> ++#include <string.h> ++#include <support/check.h> ++#include <sys/socket.h> ++#include <sys/un.h> ++ ++static int ++do_test (void) ++{ ++ /* Create an arbitrary hostname that's longer than fits in sun_path. */ ++ char name [sizeof ((struct sockaddr_un*)0)->sun_path * 2]; ++ memset (name, 'x', sizeof name - 1); ++ name [sizeof name - 1] = '\0'; ++ ++ errno = 0; ++ CLIENT *clnt = clnt_create (name, 0, 0, "unix"); ++ ++ TEST_VERIFY (clnt == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ return 0; ++} ++ ++#include <support/test-driver.c> +diff --git a/sunrpc/tst-bug28768.c b/sunrpc/tst-bug28768.c +new file mode 100644 +index 0000000000..35a4b7b0b3 +--- /dev/null ++++ b/sunrpc/tst-bug28768.c +@@ -0,0 +1,42 @@ ++/* Test to verify that long path is rejected by svcunix_create (bug 28768). ++ Copyright (C) 2022 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 ++ <http://www.gnu.org/licenses/>. */ ++ ++#include <errno.h> ++#include <rpc/svc.h> ++#include <shlib-compat.h> ++#include <string.h> ++#include <support/check.h> ++ ++/* svcunix_create does not have a default version in linkobj/libc.so. */ ++compat_symbol_reference (libc, svcunix_create, svcunix_create, GLIBC_2_1); ++ ++static int ++do_test (void) ++{ ++ char pathname[109]; ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ ++ errno = 0; ++ TEST_VERIFY (svcunix_create (RPC_ANYSOCK, 4096, 4096, pathname) == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ ++ return 0; ++} ++ ++#include <support/test-driver.c> diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h index 9808750f80..421f657678 100644 --- a/support/capture_subprocess.h @@ -8668,6 +9133,88 @@ index 0000000000..42c795d2a8 +++ b/sysdeps/x86/tst-setjmp-cet.c @@ -0,0 +1 @@ +#include <setjmp/tst-setjmp.c> +diff --git a/sysdeps/x86_64/configure b/sysdeps/x86_64/configure +old mode 100644 +new mode 100755 +index 84f82c2406..fc1840e23f +--- a/sysdeps/x86_64/configure ++++ b/sysdeps/x86_64/configure +@@ -107,39 +107,6 @@ if test x"$build_mathvec" = xnotset; then + build_mathvec=yes + fi + +-if test "$static_pie" = yes; then +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker static PIE support" >&5 +-$as_echo_n "checking for linker static PIE support... " >&6; } +-if ${libc_cv_ld_static_pie+:} false; then : +- $as_echo_n "(cached) " >&6 +-else +- cat > conftest.s <<\EOF +- .text +- .global _start +- .weak foo +-_start: +- leaq foo(%rip), %rax +-EOF +- libc_cv_pie_option="-Wl,-pie" +- if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&5' +- { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 +- (eval $ac_try) 2>&5 +- ac_status=$? +- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 +- test $ac_status = 0; }; }; then +- libc_cv_ld_static_pie=yes +- else +- libc_cv_ld_static_pie=no +- fi +-rm -f conftest* +-fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ld_static_pie" >&5 +-$as_echo "$libc_cv_ld_static_pie" >&6; } +- if test "$libc_cv_ld_static_pie" != yes; then +- as_fn_error $? "linker support for static PIE needed" "$LINENO" 5 +- fi +-fi +- + $as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h + + +diff --git a/sysdeps/x86_64/configure.ac b/sysdeps/x86_64/configure.ac +index cdaba0c075..611a7d9ba3 100644 +--- a/sysdeps/x86_64/configure.ac ++++ b/sysdeps/x86_64/configure.ac +@@ -53,31 +53,6 @@ if test x"$build_mathvec" = xnotset; then + build_mathvec=yes + fi + +-dnl Check if linker supports static PIE with the fix for +-dnl +-dnl https://sourceware.org/bugzilla/show_bug.cgi?id=21782 +-dnl +-if test "$static_pie" = yes; then +- AC_CACHE_CHECK(for linker static PIE support, libc_cv_ld_static_pie, [dnl +-cat > conftest.s <<\EOF +- .text +- .global _start +- .weak foo +-_start: +- leaq foo(%rip), %rax +-EOF +- libc_cv_pie_option="-Wl,-pie" +- if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -nostartfiles -nostdlib $no_ssp $libc_cv_pie_option -o conftest conftest.s 1>&AS_MESSAGE_LOG_FD); then +- libc_cv_ld_static_pie=yes +- else +- libc_cv_ld_static_pie=no +- fi +-rm -f conftest*]) +- if test "$libc_cv_ld_static_pie" != yes; then +- AC_MSG_ERROR([linker support for static PIE needed]) +- fi +-fi +- + dnl It is always possible to access static and hidden symbols in an + dnl position independent way. + AC_DEFINE(PI_STATIC_AND_HIDDEN) diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index 8e9baffeb4..74029871d8 100644 --- a/sysdeps/x86_64/dl-machine.h diff --git a/debian/patches/series b/debian/patches/series index f315593cc..02bd18e7c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -168,3 +168,4 @@ any/submitted-ld.so-cache-new-format.diff any/local-test-install.diff any/git-surplus-tls-accounting.diff any/git-ld.so-cache-endianness-markup.diff +any/local-CVE-2021-33574-mq_notify-use-after-free.diff -- GitLab