diff --git a/check-pf-cancel-handler.patch b/check-pf-cancel-handler.patch new file mode 100644 index 0000000..af55725 --- /dev/null +++ b/check-pf-cancel-handler.patch @@ -0,0 +1,85 @@ +From f5d377c896b95fefc712b0fd5e5804ae3f48d392 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Thu, 27 Apr 2023 13:06:15 -0700 +Subject: [PATCH] __check_pf: Add a cancellation cleanup handler [BZ #20975] + +There are reports for hang in __check_pf: + +https://github.com/JoeDog/siege/issues/4 + +It is reproducible only under specific configurations: + +1. Large number of cores (>= 64) and large number of threads (> 3X of +the number of cores) with long lived socket connection. +2. Low power (frequency) mode. +3. Power management is enabled. + +While holding lock, __check_pf calls make_request which calls __sendto +and __recvmsg. Since __sendto and __recvmsg are cancellation points, +lock held by __check_pf won't be released and can cause deadlock when +thread cancellation happens in __sendto or __recvmsg. Add a cancellation +cleanup handler for __check_pf to unlock the lock when cancelled by +another thread. This fixes BZ #20975 and the siege hang issue. + +(cherry picked from commit a443bd3fb233186038b8b483959ecb7978d1abea) +--- + sysdeps/unix/sysv/linux/Makefile | 2 ++ + sysdeps/unix/sysv/linux/check_pf.c | 15 +++++++++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index f298878e8f..94747b37a6 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -456,6 +456,8 @@ sysdep_headers += netinet/if_fddi.h netinet/if_tr.h \ + netrom/netrom.h netpacket/packet.h netrose/rose.h \ + neteconet/ec.h netiucv/iucv.h + sysdep_routines += netlink_assert_response ++ ++CFLAGS-check_pf.c += -fexceptions + endif + + # Don't compile the ctype glue code, since there is no old non-GNU C library. +diff --git a/sysdeps/unix/sysv/linux/check_pf.c b/sysdeps/unix/sysv/linux/check_pf.c +index de207122b0..50654cb28d 100644 +--- a/sysdeps/unix/sysv/linux/check_pf.c ++++ b/sysdeps/unix/sysv/linux/check_pf.c +@@ -292,6 +292,14 @@ make_request (int fd, pid_t pid) + return NULL; + } + ++#ifdef __EXCEPTIONS ++static void ++cancel_handler (void *arg __attribute__((unused))) ++{ ++ /* Release the lock. */ ++ __libc_lock_unlock (lock); ++} ++#endif + + void + attribute_hidden +@@ -304,6 +312,10 @@ __check_pf (bool *seen_ipv4, bool *seen_ipv6, + struct cached_data *olddata = NULL; + struct cached_data *data = NULL; + ++#ifdef __EXCEPTIONS ++ /* Make sure that lock is released when the thread is cancelled. */ ++ __libc_cleanup_push (cancel_handler, NULL); ++#endif + __libc_lock_lock (lock); + + if (cache_valid_p ()) +@@ -338,6 +350,9 @@ __check_pf (bool *seen_ipv4, bool *seen_ipv6, + } + } + ++#ifdef __EXCEPTIONS ++ __libc_cleanup_pop (0); ++#endif + __libc_lock_unlock (lock); + + if (data != NULL) +-- +2.41.0 + diff --git a/dl-find-object-return.patch b/dl-find-object-return.patch new file mode 100644 index 0000000..75ce9db --- /dev/null +++ b/dl-find-object-return.patch @@ -0,0 +1,60 @@ +From 3f4b4e2cdd529266ea5a2c6c5e0c66bab81bfd0e Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Fri, 7 Jul 2023 10:11:26 +0200 +Subject: [PATCH] elf: _dl_find_object may return 1 during early startup (bug + 30515) + +Success is reported with a 0 return value, and failure is -1. +Enhance the kitchen sink test elf/tst-audit28 to cover +_dl_find_object as well. + +Fixes commit 5d28a8962dcb ("elf: Add _dl_find_object function") +and bug 30515. + +Reviewed-by: Carlos O'Donell +Tested-by: Carlos O'Donell +(cherry picked from commit 1bcfe0f732066ae5336b252295591ebe7e51c301) +--- + NEWS | 1 + + elf/dl-find_object.c | 2 +- + elf/tst-auditmod28.c | 11 +++++++++++ + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/elf/dl-find_object.c b/elf/dl-find_object.c +index 2ced2f3510..934e77e11f 100644 +--- a/elf/dl-find_object.c ++++ b/elf/dl-find_object.c +@@ -46,7 +46,7 @@ _dl_find_object_slow (void *pc, struct dl_find_object *result) + struct dl_find_object_internal internal; + _dl_find_object_from_map (l, &internal); + _dl_find_object_to_external (&internal, result); +- return 1; ++ return 0; + } + + /* Object not found. */ +diff --git a/elf/tst-auditmod28.c b/elf/tst-auditmod28.c +index f6ab991398..f6dfbbe202 100644 +--- a/elf/tst-auditmod28.c ++++ b/elf/tst-auditmod28.c +@@ -71,6 +71,17 @@ la_version (unsigned int current) + TEST_VERIFY (dladdr1 (&_exit, &info, &extra_info, RTLD_DL_LINKMAP) != 0); + TEST_VERIFY (extra_info == handle); + ++ /* Check _dl_find_object. */ ++ struct dl_find_object dlfo; ++ TEST_COMPARE (_dl_find_object (__builtin_return_address (0), &dlfo), 0); ++ /* "ld.so" is seen with --enable-hardcoded-path-in-tests. */ ++ if (strcmp (basename (dlfo.dlfo_link_map->l_name), "ld.so") != 0) ++ TEST_COMPARE_STRING (basename (dlfo.dlfo_link_map->l_name), LD_SO); ++ TEST_COMPARE (_dl_find_object (dlsym (handle, "environ"), &dlfo), 0); ++ TEST_COMPARE_STRING (basename (dlfo.dlfo_link_map->l_name), LIBC_SO); ++ TEST_COMPARE (_dl_find_object ((void *) 1, &dlfo), -1); ++ TEST_COMPARE (_dl_find_object ((void *) -1, &dlfo), -1); ++ + /* Verify that dlmopen creates a new namespace. */ + void *dlmopen_handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); + TEST_VERIFY (dlmopen_handle != handle); +-- +2.41.0 + diff --git a/fix-locking-in-_IO_cleanup.patch b/fix-locking-in-_IO_cleanup.patch index 071853a..03cc926 100644 --- a/fix-locking-in-_IO_cleanup.patch +++ b/fix-locking-in-_IO_cleanup.patch @@ -2,13 +2,12 @@ Always do locking when accessing streams (bug 15142, bug 14697) Now that abort no longer calls fflush there is no reason to avoid locking the stdio streams anywhere. This fixes a conformance issue and potential -heap corruption during exit. The test nptl/tst-stdio1 is removed as that -was expecting the problematic behaviour. +heap corruption during exit. -Index: glibc-2.32/libio/genops.c +Index: glibc-2.37/libio/genops.c =================================================================== ---- glibc-2.32.orig/libio/genops.c -+++ glibc-2.32/libio/genops.c +--- glibc-2.37.orig/libio/genops.c ++++ glibc-2.37/libio/genops.c @@ -682,7 +682,7 @@ _IO_adjust_column (unsigned start, const libc_hidden_def (_IO_adjust_column) @@ -114,11 +113,11 @@ Index: glibc-2.32/libio/genops.c /* We currently don't have a reliable mechanism for making sure that C++ static destructors are executed in the correct order. -Index: glibc-2.32/libio/libioP.h +Index: glibc-2.37/libio/libioP.h =================================================================== ---- glibc-2.32.orig/libio/libioP.h -+++ glibc-2.32/libio/libioP.h -@@ -487,7 +487,6 @@ extern int _IO_new_do_write (FILE *, con +--- glibc-2.37.orig/libio/libioP.h ++++ glibc-2.37/libio/libioP.h +@@ -488,7 +488,6 @@ extern int _IO_new_do_write (FILE *, con extern int _IO_old_do_write (FILE *, const char *, size_t); extern int _IO_wdo_write (FILE *, const wchar_t *, size_t); libc_hidden_proto (_IO_wdo_write) @@ -126,76 +125,109 @@ Index: glibc-2.32/libio/libioP.h extern int _IO_flush_all (void); libc_hidden_proto (_IO_flush_all) extern int _IO_cleanup (void); -Index: glibc-2.32/sysdeps/pthread/Makefile +Index: glibc-2.37/support/delayed_exit.c =================================================================== ---- glibc-2.32.orig/sysdeps/pthread/Makefile -+++ glibc-2.32/sysdeps/pthread/Makefile -@@ -99,7 +99,7 @@ tests += tst-cnd-basic tst-mtx-trylock t - tst-signal4 tst-signal5 tst-signal6 tst-signal8 \ - tst-spin1 tst-spin2 tst-spin3 tst-spin4 \ - tst-stack1 \ -- tst-stdio1 tst-stdio2 \ -+ tst-stdio2 \ - tst-pt-sysconf \ - tst-pt-tls1 tst-pt-tls2 \ - tst-tsd1 tst-tsd2 tst-tsd5 tst-tsd6 \ -Index: glibc-2.32/sysdeps/pthread/tst-stdio1.c +--- glibc-2.37.orig/support/delayed_exit.c ++++ glibc-2.37/support/delayed_exit.c +@@ -23,33 +23,58 @@ + #include + #include + #include ++#include + #include ++#include ++ ++struct delayed_exit_request ++{ ++ void (*exitfunc) (int); ++ int seconds; ++}; + + static void * +-delayed_exit_thread (void *seconds_as_ptr) ++delayed_exit_thread (void *closure) + { +- int seconds = (uintptr_t) seconds_as_ptr; +- struct timespec delay = { seconds, 0 }; ++ struct delayed_exit_request *request = closure; ++ void (*exitfunc) (int) = request->exitfunc; ++ struct timespec delay = { request->seconds, 0 }; + struct timespec remaining = { 0 }; ++ free (request); ++ + if (nanosleep (&delay, &remaining) != 0) + FAIL_EXIT1 ("nanosleep: %m"); + /* Exit the process sucessfully. */ +- exit (0); ++ exitfunc (0); + return NULL; + } + +-void +-delayed_exit (int seconds) ++static void ++delayed_exit_1 (int seconds, void (*exitfunc) (int)) + { + /* Create the new thread with all signals blocked. */ + sigset_t all_blocked; + sigfillset (&all_blocked); + sigset_t old_set; + xpthread_sigmask (SIG_SETMASK, &all_blocked, &old_set); ++ struct delayed_exit_request *request = xmalloc (sizeof (*request)); ++ request->seconds = seconds; ++ request->exitfunc = exitfunc; + /* Create a detached thread. */ +- pthread_t thr = xpthread_create +- (NULL, delayed_exit_thread, (void *) (uintptr_t) seconds); ++ pthread_t thr = xpthread_create (NULL, delayed_exit_thread, request); + xpthread_detach (thr); + /* Restore the original signal mask. */ + xpthread_sigmask (SIG_SETMASK, &old_set, NULL); + } ++ ++void ++delayed_exit (int seconds) ++{ ++ delayed_exit_1 (seconds, exit); ++} ++ ++void ++delayed__exit (int seconds) ++{ ++ delayed_exit_1 (seconds, _exit); ++} +Index: glibc-2.37/support/xthread.h =================================================================== ---- glibc-2.32.orig/sysdeps/pthread/tst-stdio1.c -+++ /dev/null -@@ -1,55 +0,0 @@ --/* Copyright (C) 2002-2023 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 -- . */ -- --#include --#include --#include --#include -- --static int do_test (void); -- --#define TEST_FUNCTION do_test () --#include "../test-skeleton.c" -- --static void *tf (void *a) --{ -- flockfile (stdout); -- /* This call should never return. */ -- return a; --} -- -- --int --do_test (void) --{ -- pthread_t th; -- -- flockfile (stdout); -- -- if (pthread_create (&th, NULL, tf, NULL) != 0) -- { -- write_message ("create failed\n"); -- _exit (1); -- } -- +--- glibc-2.37.orig/support/xthread.h ++++ glibc-2.37/support/xthread.h +@@ -25,11 +25,14 @@ + + __BEGIN_DECLS + +-/* Terminate the process (with exit status 0) after SECONDS have +- elapsed, from a helper thread. The process is terminated with the +- exit function, so atexit handlers are executed. */ ++/* Terminate the process (with exit (0)) after SECONDS have elapsed, ++ from a helper thread. The process is terminated with the exit ++ function, so atexit handlers are executed. */ + void delayed_exit (int seconds); + ++/* Like delayed_exit, but use _exit (0). */ ++void delayed__exit (int seconds); ++ + /* Returns true if Priority Inheritance support CLOCK_MONOTONIC. */ + bool support_mutex_pi_monotonic (void); + +Index: glibc-2.37/sysdeps/pthread/tst-stdio1.c +=================================================================== +--- glibc-2.37.orig/sysdeps/pthread/tst-stdio1.c ++++ glibc-2.37/sysdeps/pthread/tst-stdio1.c +@@ -46,7 +46,7 @@ do_test (void) + _exit (1); + } + - delayed_exit (1); -- xpthread_join (th); -- -- puts ("join returned"); -- -- return 1; --} ++ delayed__exit (1); + xpthread_join (th); + + puts ("join returned"); diff --git a/glibc.changes b/glibc.changes index 0bf6ec3..c2f5300 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,30 @@ +------------------------------------------------------------------- +Mon Jul 10 08:46:18 UTC 2023 - Andreas Schwab + +- gshadow-erange-rhandling.patch: gshadow: Matching sgetsgent, sgetsgent_r + ERANGE handling (BZ #30151) +- system-sigchld-block.patch: posix: Fix system blocks SIGCHLD erroneously + (BZ #30163) +- gmon-buffer-alloc.patch: gmon: Fix allocated buffer overflow (BZ #29444) +- check-pf-cancel-handler.patch: __check_pf: Add a cancellation cleanup + handler (BZ #20975) +- powerpc64-fcntl-lock.patch: io: Fix F_GETLK, F_SETLK, and F_SETLKW for + powerpc64 +- realloc-limit-chunk-reuse.patch: realloc: Limit chunk reuse to only + growing requests (BZ #30579) +- dl-find-object-return.patch: elf: _dl_find_object may return 1 during + early startup (BZ #30515) + +------------------------------------------------------------------- +Mon Jul 3 16:31:17 UTC 2023 - Andreas Schwab + +- Need to build with GCC 12 as minimum + +------------------------------------------------------------------- +Thu Jun 29 13:05:55 UTC 2023 - Andreas Schwab + +- fix-locking-in-_IO_cleanup.patch: Update to final version + ------------------------------------------------------------------- Fri Apr 28 23:42:47 UTC 2023 - Giuliano Belinassi diff --git a/glibc.spec b/glibc.spec index 4049ca6..fbdf16d 100644 --- a/glibc.spec +++ b/glibc.spec @@ -49,6 +49,10 @@ %bcond_with usrmerged %endif +%if %{gcc_version} < 12 +%define with_gcc 12 +%endif + # Enable support for livepatching. %ifarch x86_64 %bcond_without livepatching @@ -205,8 +209,11 @@ BuildRequires: systemd-rpm-macros BuildRequires: systemtap-headers BuildRequires: sysuser-tools BuildRequires: xz +%if 0%{?with_gcc:1} +BuildRequires: gcc%{with_gcc} +%endif %if %{build_testsuite} -BuildRequires: gcc-c++ +BuildRequires: gcc%{?with_gcc}-c++ BuildRequires: gdb BuildRequires: glibc-devel-static BuildRequires: libidn2-0 @@ -219,7 +226,7 @@ BuildRequires: libpng-devel BuildRequires: zlib-devel %endif %if %{build_cross} -BuildRequires: cross-%{cross_arch}-gcc%{gcc_version}-bootstrap +BuildRequires: cross-%{cross_arch}-gcc%{!?with_gcc:%{gcc_version}}%{?with_gcc}-bootstrap BuildRequires: cross-%{cross_arch}-linux-glibc-devel %endif %if "%flavor" == "i686" @@ -288,14 +295,28 @@ Patch1000: printf-grouping.patch Patch1001: strftime-time64.patch # PATCH-FIX-UPSTREAM getlogin_r: fix missing fallback if loginuid is unset (BZ #30235) Patch1002: getlogin-no-loginuid.patch +# PATCH-FIX-UPSTREAM Always to locking when accessing streams (BZ #15142) +Patch1003: fix-locking-in-_IO_cleanup.patch +# PATCH-FIX-UPSTREAM gshadow: Matching sgetsgent, sgetsgent_r ERANGE handling (BZ #30151) +Patch1004: gshadow-erange-rhandling.patch +# PATCH-FIX-UPSTREAM posix: Fix system blocks SIGCHLD erroneously (BZ #30163) +Patch1005: system-sigchld-block.patch +# PATCH-FIX-UPSTREAM gmon: Fix allocated buffer overflow (BZ #29444) +Patch1006: gmon-buffer-alloc.patch +# PATCH-FIX-UPSTREAM __check_pf: Add a cancellation cleanup handler (BZ #20975) +Patch1007: check-pf-cancel-handler.patch +# PATCH-FIX-UPSTREAM io: Fix F_GETLK, F_SETLK, and F_SETLKW for powerpc64 +Patch1008: powerpc64-fcntl-lock.patch +# PATCH-FIX-UPSTREAM realloc: Limit chunk reuse to only growing requests (BZ #30579) +Patch1009: realloc-limit-chunk-reuse.patch +# PATCH-FIX-UPSTREAM elf: _dl_find_object may return 1 during early startup (BZ #30515) +Patch1010: dl-find-object-return.patch ### # Patches awaiting upstream approval ### -# PATCH-FIX-UPSTREAM Always to locking when accessing streams (BZ #15142) -Patch2000: fix-locking-in-_IO_cleanup.patch # PATCH-FIX-UPSTREAM Avoid concurrency problem in ldconfig (BZ #23973) -Patch2001: ldconfig-concurrency.patch +Patch2000: ldconfig-concurrency.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -516,10 +537,17 @@ library in a cross compilation setting. %patch1000 -p1 %patch1001 -p1 %patch1002 -p1 +%patch1003 -p1 +%patch1004 -p1 +%patch1005 -p1 +%patch1006 -p1 +%patch1007 -p1 +%patch1008 -p1 +%patch1009 -p1 +%patch1010 -p1 %endif %patch2000 -p1 -%patch2001 -p1 %patch3000 rm -f manpages/catchsegv.1 @@ -579,8 +607,13 @@ done %if "%flavor" == "i686" BuildFlags+=" -march=i686 -mtune=generic" %endif +%if 0%{?with_gcc:1} +BuildCC="gcc-%{with_gcc}" +BuildCCplus="g++-%{with_gcc}" +%else BuildCC="%__cc" BuildCCplus="%__cxx" +%endif # #now overwrite for some architectures diff --git a/gmon-buffer-alloc.patch b/gmon-buffer-alloc.patch new file mode 100644 index 0000000..726eafa --- /dev/null +++ b/gmon-buffer-alloc.patch @@ -0,0 +1,79 @@ +From 801af9fafd4689337ebf27260aa115335a0cb2bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= + =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= +Date: Sat, 4 Feb 2023 14:41:38 +0300 +Subject: [PATCH] gmon: Fix allocated buffer overflow (bug 29444) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The `__monstartup()` allocates a buffer used to store all the data +accumulated by the monitor. + +The size of this buffer depends on the size of the internal structures +used and the address range for which the monitor is activated, as well +as on the maximum density of call instructions and/or callable functions +that could be potentially on a segment of executable code. + +In particular a hash table of arcs is placed at the end of this buffer. +The size of this hash table is calculated in bytes as + p->fromssize = p->textsize / HASHFRACTION; + +but actually should be + p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); + +This results in writing beyond the end of the allocated buffer when an +added arc corresponds to a call near from the end of the monitored +address range, since `_mcount()` check the incoming caller address for +monitored range but not the intermediate result hash-like index that +uses to write into the table. + +It should be noted that when the results are output to `gmon.out`, the +table is read to the last element calculated from the allocated size in +bytes, so the arcs stored outside the buffer boundary did not fall into +`gprof` for analysis. Thus this "feature" help me to found this bug +during working with https://sourceware.org/bugzilla/show_bug.cgi?id=29438 + +Just in case, I will explicitly note that the problem breaks the +`make test t=gmon/tst-gmon-dso` added for Bug 29438. +There, the arc of the `f3()` call disappears from the output, since in +the DSO case, the call to `f3` is located close to the end of the +monitored range. + +Signed-off-by: Леонид Юрьев (Leonid Yuriev) + +Another minor error seems a related typo in the calculation of +`kcountsize`, but since kcounts are smaller than froms, this is +actually to align the p->froms data. + +Co-authored-by: DJ Delorie +Reviewed-by: Carlos O'Donell +--- + gmon/gmon.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/gmon/gmon.c b/gmon/gmon.c +index dee64803ad..bf76358d5b 100644 +--- a/gmon/gmon.c ++++ b/gmon/gmon.c +@@ -132,6 +132,8 @@ __monstartup (u_long lowpc, u_long highpc) + p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); + p->textsize = p->highpc - p->lowpc; ++ /* This looks like a typo, but it's here to align the p->froms ++ section. */ + p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms)); + p->hashfraction = HASHFRACTION; + p->log_hashfraction = -1; +@@ -142,7 +144,7 @@ __monstartup (u_long lowpc, u_long highpc) + instead of integer division. Precompute shift amount. */ + p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1; + } +- p->fromssize = p->textsize / HASHFRACTION; ++ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms)); + p->tolimit = p->textsize * ARCDENSITY / 100; + if (p->tolimit < MINARCS) + p->tolimit = MINARCS; +-- +2.41.0 + diff --git a/gshadow-erange-rhandling.patch b/gshadow-erange-rhandling.patch new file mode 100644 index 0000000..81f5261 --- /dev/null +++ b/gshadow-erange-rhandling.patch @@ -0,0 +1,130 @@ +From 969e9733c7d17edf1e239a73fa172f357561f440 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Tue, 21 Feb 2023 09:20:28 +0100 +Subject: [PATCH] gshadow: Matching sgetsgent, sgetsgent_r ERANGE handling (bug + 30151) + +Before this change, sgetsgent_r did not set errno to ERANGE, but +sgetsgent only check errno, not the return value from sgetsgent_r. +Consequently, sgetsgent did not detect any error, and reported +success to the caller, without initializing the struct sgrp object +whose address was returned. + +This commit changes sgetsgent_r to set errno as well. This avoids +similar issues in applications which only change errno. + +Reviewed-by: Siddhesh Poyarekar +--- + gshadow/Makefile | 2 +- + gshadow/sgetsgent_r.c | 5 ++- + gshadow/tst-sgetsgent.c | 69 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 74 insertions(+), 2 deletions(-) + create mode 100644 gshadow/tst-sgetsgent.c + +diff --git a/gshadow/Makefile b/gshadow/Makefile +index 796fbbf473..a95524593a 100644 +--- a/gshadow/Makefile ++++ b/gshadow/Makefile +@@ -26,7 +26,7 @@ headers = gshadow.h + routines = getsgent getsgnam sgetsgent fgetsgent putsgent \ + getsgent_r getsgnam_r sgetsgent_r fgetsgent_r + +-tests = tst-gshadow tst-putsgent tst-fgetsgent_r ++tests = tst-gshadow tst-putsgent tst-fgetsgent_r tst-sgetsgent + + CFLAGS-getsgent_r.c += -fexceptions + CFLAGS-getsgent.c += -fexceptions +diff --git a/gshadow/sgetsgent_r.c b/gshadow/sgetsgent_r.c +index ea085e91d7..c75624e1f7 100644 +--- a/gshadow/sgetsgent_r.c ++++ b/gshadow/sgetsgent_r.c +@@ -61,7 +61,10 @@ __sgetsgent_r (const char *string, struct sgrp *resbuf, char *buffer, + buffer[buflen - 1] = '\0'; + sp = strncpy (buffer, string, buflen); + if (buffer[buflen - 1] != '\0') +- return ERANGE; ++ { ++ __set_errno (ERANGE); ++ return ERANGE; ++ } + } + else + sp = (char *) string; +diff --git a/gshadow/tst-sgetsgent.c b/gshadow/tst-sgetsgent.c +new file mode 100644 +index 0000000000..0370c10fd0 +--- /dev/null ++++ b/gshadow/tst-sgetsgent.c +@@ -0,0 +1,69 @@ ++/* Test large input for sgetsgent (bug 30151). ++ Copyright (C) 2023 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Create a shadow group with 1000 members. */ ++ struct xmemstream mem; ++ xopen_memstream (&mem); ++ const char *passwd = "k+zD0nucwfxAo3sw1NXUj6K5vt5M16+X0TVGdE1uFvq5R8V7efJ"; ++ fprintf (mem.out, "group-name:%s::m0", passwd); ++ for (int i = 1; i < 1000; ++i) ++ fprintf (mem.out, ",m%d", i); ++ xfclose_memstream (&mem); ++ ++ /* Call sgetsgent. */ ++ char *input = mem.buffer; ++ struct sgrp *e = sgetsgent (input); ++ TEST_VERIFY_EXIT (e != NULL); ++ TEST_COMPARE_STRING (e->sg_namp, "group-name"); ++ TEST_COMPARE_STRING (e->sg_passwd, passwd); ++ /* No administrators. */ ++ TEST_COMPARE_STRING (e->sg_adm[0], NULL); ++ /* Check the members list. */ ++ for (int i = 0; i < 1000; ++i) ++ { ++ char *member = xasprintf ("m%d", i); ++ TEST_COMPARE_STRING (e->sg_mem[i], member); ++ free (member); ++ } ++ TEST_COMPARE_STRING (e->sg_mem[1000], NULL); ++ ++ /* Check that putsgent brings back the input string. */ ++ xopen_memstream (&mem); ++ TEST_COMPARE (putsgent (e, mem.out), 0); ++ xfclose_memstream (&mem); ++ /* Compare without the trailing '\n' that putsgent added. */ ++ TEST_COMPARE (mem.buffer[mem.length - 1], '\n'); ++ mem.buffer[mem.length - 1] = '\0'; ++ TEST_COMPARE_STRING (mem.buffer, input); ++ ++ free (mem.buffer); ++ free (input); ++ return 0; ++} ++ ++#include +-- +2.41.0 + diff --git a/powerpc64-fcntl-lock.patch b/powerpc64-fcntl-lock.patch new file mode 100644 index 0000000..bbe6a80 --- /dev/null +++ b/powerpc64-fcntl-lock.patch @@ -0,0 +1,44 @@ +From 5f828ff824e3b7cd133ef905b8ae25ab8a8f3d66 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Tue, 30 May 2023 16:40:38 -0300 +Subject: [PATCH] io: Fix F_GETLK, F_SETLK, and F_SETLKW for powerpc64 + +Different than other 64 bit architectures, powerpc64 defines the +LFS POSIX lock constants with values similar to 32 ABI, which +are meant to be used with fcntl64 syscall. Since powerpc64 kABI +does not have fcntl, the constants are adjusted with the +FCNTL_ADJUST_CMD macro. + +The 4d0fe291aed3a476a changed the logic of generic constants +LFS value are equal to the default values; which is now wrong +for powerpc64. + +Fix the value by explicit define the previous glibc constants +(powerpc64 does not need to use the 32 kABI value, but it simplifies +the FCNTL_ADJUST_CMD which should be kept as compatibility). + +Checked on powerpc64-linux-gnu and powerpc-linux-gnu. +--- + sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h b/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h +index 0905cd833c..f7615a447e 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h ++++ b/sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h +@@ -33,6 +33,12 @@ + # define __O_LARGEFILE 0200000 + #endif + ++#if __WORDSIZE == 64 ++# define F_GETLK 5 ++# define F_SETLK 6 ++# define F_SETLKW 7 ++#endif ++ + struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ +-- +2.41.0 + diff --git a/realloc-limit-chunk-reuse.patch b/realloc-limit-chunk-reuse.patch new file mode 100644 index 0000000..dbeaadc --- /dev/null +++ b/realloc-limit-chunk-reuse.patch @@ -0,0 +1,68 @@ +From 0930ff8eb35cb493c945f176c3c9ab320f4d1b86 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Thu, 6 Jul 2023 11:09:44 -0400 +Subject: [PATCH] realloc: Limit chunk reuse to only growing requests [BZ + #30579] + +The trim_threshold is too aggressive a heuristic to decide if chunk +reuse is OK for reallocated memory; for repeated small, shrinking +allocations it leads to internal fragmentation and for repeated larger +allocations that fragmentation may blow up even worse due to the dynamic +nature of the threshold. + +Limit reuse only when it is within the alignment padding, which is 2 * +size_t for heap allocations and a page size for mmapped allocations. +There's the added wrinkle of THP, but this fix ignores it for now, +pessimizing that case in favor of keeping fragmentation low. + +This resolves BZ #30579. + +Signed-off-by: Siddhesh Poyarekar +Reported-by: Nicolas Dusart +Reported-by: Aurelien Jarno +Reviewed-by: Aurelien Jarno +Tested-by: Aurelien Jarno +(cherry picked from commit 2fb12bbd092b0c10f1f2083216e723d2406e21c4) +--- + malloc/malloc.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index fd8b52bfac..67df9f8c51 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3398,16 +3398,23 @@ __libc_realloc (void *oldmem, size_t bytes) + if (__glibc_unlikely (mtag_enabled)) + *(volatile char*) oldmem; + +- /* Return the chunk as is whenever possible, i.e. there's enough usable space +- but not so much that we end up fragmenting the block. We use the trim +- threshold as the heuristic to decide the latter. */ +- size_t usable = musable (oldmem); +- if (bytes <= usable +- && (unsigned long) (usable - bytes) <= mp_.trim_threshold) +- return oldmem; +- + /* chunk corresponding to oldmem */ + const mchunkptr oldp = mem2chunk (oldmem); ++ ++ /* Return the chunk as is if the request grows within usable bytes, typically ++ into the alignment padding. We want to avoid reusing the block for ++ shrinkages because it ends up unnecessarily fragmenting the address space. ++ This is also why the heuristic misses alignment padding for THP for ++ now. */ ++ size_t usable = musable (oldmem); ++ if (bytes <= usable) ++ { ++ size_t difference = usable - bytes; ++ if ((unsigned long) difference < 2 * sizeof (INTERNAL_SIZE_T) ++ || (chunk_is_mmapped (oldp) && difference <= GLRO (dl_pagesize))) ++ return oldmem; ++ } ++ + /* its size */ + const INTERNAL_SIZE_T oldsize = chunksize (oldp); + +-- +2.41.0 + diff --git a/system-sigchld-block.patch b/system-sigchld-block.patch new file mode 100644 index 0000000..bda7f96 --- /dev/null +++ b/system-sigchld-block.patch @@ -0,0 +1,290 @@ +From 436a604b7dc741fc76b5a6704c6cd8bb178518e7 Mon Sep 17 00:00:00 2001 +From: Adam Yi +Date: Tue, 7 Mar 2023 07:30:02 -0500 +Subject: [PATCH] posix: Fix system blocks SIGCHLD erroneously [BZ #30163] + +Fix bug that SIGCHLD is erroneously blocked forever in the following +scenario: + +1. Thread A calls system but hasn't returned yet +2. Thread B calls another system but returns + +SIGCHLD would be blocked forever in thread B after its system() returns, +even after the system() in thread A returns. + +Although POSIX does not require, glibc system implementation aims to be +thread and cancellation safe. This bug was introduced in +5fb7fc96350575c9adb1316833e48ca11553be49 when we moved reverting signal +mask to happen when the last concurrently running system returns, +despite that signal mask is per thread. This commit reverts this logic +and adds a test. + +Signed-off-by: Adam Yi +Reviewed-by: Adhemerval Zanella +--- + stdlib/tst-system.c | 26 +++++++++++++++++++ + support/Makefile | 2 ++ + support/dtotimespec-time64.c | 27 +++++++++++++++++++ + support/dtotimespec.c | 50 ++++++++++++++++++++++++++++++++++++ + support/shell-container.c | 28 ++++++++++++++++++++ + support/timespec.h | 4 +++ + sysdeps/posix/system.c | 6 ++--- + 7 files changed, 140 insertions(+), 3 deletions(-) + create mode 100644 support/dtotimespec-time64.c + create mode 100644 support/dtotimespec.c + +diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c +index 634acfe264..47a0afe6bf 100644 +--- a/stdlib/tst-system.c ++++ b/stdlib/tst-system.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + + static char *tmpdir; +@@ -71,6 +72,20 @@ call_system (void *closure) + } + } + ++static void * ++sleep_and_check_sigchld (void *closure) ++{ ++ double *seconds = (double *) closure; ++ char cmd[namemax]; ++ sprintf (cmd, "sleep %lf" , *seconds); ++ TEST_COMPARE (system (cmd), 0); ++ ++ sigset_t blocked = {0}; ++ TEST_COMPARE (sigprocmask (SIG_BLOCK, NULL, &blocked), 0); ++ TEST_COMPARE (sigismember (&blocked, SIGCHLD), 0); ++ return NULL; ++} ++ + static int + do_test (void) + { +@@ -154,6 +169,17 @@ do_test (void) + xchmod (_PATH_BSHELL, st.st_mode); + } + ++ { ++ pthread_t long_sleep_thread = xpthread_create (NULL, ++ sleep_and_check_sigchld, ++ &(double) { 0.2 }); ++ pthread_t short_sleep_thread = xpthread_create (NULL, ++ sleep_and_check_sigchld, ++ &(double) { 0.1 }); ++ xpthread_join (short_sleep_thread); ++ xpthread_join (long_sleep_thread); ++ } ++ + TEST_COMPARE (system (""), 0); + + return 0; +diff --git a/support/Makefile b/support/Makefile +index d52c472755..05b31159ea 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -32,6 +32,8 @@ libsupport-routines = \ + check_hostent \ + check_netent \ + delayed_exit \ ++ dtotimespec \ ++ dtotimespec-time64 \ + ignore_stderr \ + next_to_fault \ + oom_error \ +diff --git a/support/dtotimespec-time64.c b/support/dtotimespec-time64.c +new file mode 100644 +index 0000000000..b3d5e351e3 +--- /dev/null ++++ b/support/dtotimespec-time64.c +@@ -0,0 +1,27 @@ ++/* Convert double to timespec. 64-bit time support. ++ Copyright (C) 2011-2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library and is also part of gnulib. ++ Patches to this file should be submitted to both projects. ++ ++ 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 ++ . */ ++ ++#include ++ ++#if __TIMESIZE != 64 ++# define timespec __timespec64 ++# define time_t __time64_t ++# define dtotimespec dtotimespec_time64 ++# include "dtotimespec.c" ++#endif +diff --git a/support/dtotimespec.c b/support/dtotimespec.c +new file mode 100644 +index 0000000000..cde5b4d74c +--- /dev/null ++++ b/support/dtotimespec.c +@@ -0,0 +1,50 @@ ++/* Convert double to timespec. ++ Copyright (C) 2011-2023 Free Software Foundation, Inc. ++ This file is part of the GNU C Library and is also part of gnulib. ++ Patches to this file should be submitted to both projects. ++ ++ 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 ++ . */ ++ ++/* Convert the double value SEC to a struct timespec. Round toward ++ positive infinity. On overflow, return an extremal value. */ ++ ++#include ++#include ++ ++struct timespec ++dtotimespec (double sec) ++{ ++ if (sec <= TYPE_MINIMUM (time_t)) ++ return make_timespec (TYPE_MINIMUM (time_t), 0); ++ else if (sec >= 1.0 + TYPE_MAXIMUM (time_t)) ++ return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1); ++ else ++ { ++ time_t s = sec; ++ double frac = TIMESPEC_HZ * (sec - s); ++ long ns = frac; ++ ns += ns < frac; ++ s += ns / TIMESPEC_HZ; ++ ns %= TIMESPEC_HZ; ++ ++ if (ns < 0) ++ { ++ s--; ++ ns += TIMESPEC_HZ; ++ } ++ ++ return make_timespec (s, ns); ++ } ++} +diff --git a/support/shell-container.c b/support/shell-container.c +index ffa3378b5e..b1f9e793c1 100644 +--- a/support/shell-container.c ++++ b/support/shell-container.c +@@ -37,6 +37,7 @@ + #include + + #include ++#include + + /* Design considerations + +@@ -169,6 +170,32 @@ kill_func (char **argv) + return 0; + } + ++/* Emulate the "/bin/sleep" command. No suffix support. Options are ++ ignored. */ ++static int ++sleep_func (char **argv) ++{ ++ if (argv[0] == NULL) ++ { ++ fprintf (stderr, "sleep: missing operand\n"); ++ return 1; ++ } ++ char *endptr = NULL; ++ double sec = strtod (argv[0], &endptr); ++ if (endptr == argv[0] || errno == ERANGE || sec < 0) ++ { ++ fprintf (stderr, "sleep: invalid time interval '%s'\n", argv[0]); ++ return 1; ++ } ++ struct timespec ts = dtotimespec (sec); ++ if (nanosleep (&ts, NULL) < 0) ++ { ++ fprintf (stderr, "sleep: failed to nanosleep: %s\n", strerror (errno)); ++ return 1; ++ } ++ return 0; ++} ++ + /* This is a list of all the built-in commands we understand. */ + static struct { + const char *name; +@@ -179,6 +206,7 @@ static struct { + { "cp", copy_func }, + { "exit", exit_func }, + { "kill", kill_func }, ++ { "sleep", sleep_func }, + { NULL, NULL } + }; + +diff --git a/support/timespec.h b/support/timespec.h +index 77b1e4e8d6..9559836d4c 100644 +--- a/support/timespec.h ++++ b/support/timespec.h +@@ -57,6 +57,8 @@ int support_timespec_check_in_range (struct timespec expected, + struct timespec observed, + double lower_bound, double upper_bound); + ++struct timespec dtotimespec (double sec) __attribute__((const)); ++ + #else + struct timespec __REDIRECT (timespec_add, (struct timespec, struct timespec), + timespec_add_time64); +@@ -82,6 +84,8 @@ int __REDIRECT (support_timespec_check_in_range, (struct timespec expected, + double lower_bound, + double upper_bound), + support_timespec_check_in_range_time64); ++ ++struct timespec __REDIRECT (dtotimespec, (double sec), dtotimespec_time64); + #endif + + /* Check that the timespec on the left represents a time before the +diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c +index 2335a99184..d77720a625 100644 +--- a/sysdeps/posix/system.c ++++ b/sysdeps/posix/system.c +@@ -179,16 +179,16 @@ do_system (const char *line) + as if the shell had terminated using _exit(127). */ + status = W_EXITCODE (127, 0); + ++ /* sigaction can not fail with SIGINT/SIGQUIT used with old ++ disposition. Same applies for sigprocmask. */ + DO_LOCK (); + if (SUB_REF () == 0) + { +- /* sigaction can not fail with SIGINT/SIGQUIT used with old +- disposition. Same applies for sigprocmask. */ + __sigaction (SIGINT, &intr, NULL); + __sigaction (SIGQUIT, &quit, NULL); +- __sigprocmask (SIG_SETMASK, &omask, NULL); + } + DO_UNLOCK (); ++ __sigprocmask (SIG_SETMASK, &omask, NULL); + + if (ret != 0) + __set_errno (ret); +-- +2.41.0 +