[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1005949: bullseye-pu: package glibc/2.31-13+deb11u3



Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian.org@packages.debian.org
Usertags: pu

[ Reason ]
There are multiple fixes in this upload:
- 4 security bugs
- a fix to avoid preinst script failure when running on kernel x.y.z
  with z > 255. 
- a fix to avoid changes to /etc/nsswitch.conf to be reverted on upgrade

[ Impact ]
Installation will be left vulnerable to security issues and upgrade
from buster will fail when running recent upstream stable kernels.

[ Tests ]
Those changes are all in testing for some time so have been tested by
many users already. In addition the security fixes come with additional
tests.

[ Risks ]
The risk can probably be considered low, as the changes have been tested
in testing/sid and upstream or on other distributions for the security
bugs.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]

Let me comment the changelog:

 * 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.

This fixes a security issue.

   - Remove PIE check on amd64 to fix FTBFS with binutils 2.37.

This is actually not something that is strictly needed in bullseye, as it runs
binutils 2.35. As it comes from the upstream stable branch and it is just about
removing code for an outdated check in a configure script (the version test on
binutils already ensures that), it has not impact on the binaries shipped in
the package. Therefore I didn't judged necessary to revert that change, it
makes my life easier when the upstream stable branch can be used.

   - Fix a buffer overflow in sunrpc svcunix_create (CVE-2022-23218).
   - Fix a buffer overflow in sunrpc clnt_create (CVE-2022-23219).

This fixes two similar security issues.

 * debian/debhelper.in/libc-bin.postinst: stop replacing older versions from
   /etc/nsswitch.conf.  Closes: #998008.

This is a forgotten leftover from the move of that file from base-files in Wheezy.

 * 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.

These two just drop the comparison for the z part in kernel version x.y.z, as z
is not relevant anymore since kernel 3.0, and the minimum supported kernel
version since buster is 3.2. This fixes cases where z > 255 as with recent
upstream stable kernels. Incidentally it also fixes the weird case where z is
not a numeric value.

 * 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.

This security fix does not come from the upstream stable branch, as a simple
backport would change the GLIBC_PRIVATE ABI and will cause issue with online
upgrades. Instead the corresponding code is included as a static function (see
the top of the patch for more details). Overall the code is the same as in
later glibc versions, just not ending up in the same library.
diff --git a/debian/changelog b/debian/changelog
index 7c23c790..36d87ef3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,25 @@
+glibc (2.31-13+deb11u3) UNRELEASED; 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>  Tue, 07 Dec 2021 23:51:16 +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 802a3ad0..6309f194 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 ff59ad9a..133ca478 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 00000000..1d91a5c4
--- /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 (&notify_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 e1cac4a1..a6898540 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 f315593c..02bd18e7 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

Reply to: