From 026f78f16f9ad6db2cb97a03423d937e52926149 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 23 Sep 2021 12:24:44 +0200 Subject: [PATCH] Import glibc-2.34-6.fc35 from f35 (#2003135) Related: #2003135 --- glibc-upstream-2.34-21.patch | 44 +++++ glibc-upstream-2.34-22.patch | 137 ++++++++++++++ glibc-upstream-2.34-23.patch | 32 ++++ glibc-upstream-2.34-24.patch | 355 +++++++++++++++++++++++++++++++++++ glibc-upstream-2.34-25.patch | 204 ++++++++++++++++++++ glibc-upstream-2.34-26.patch | 129 +++++++++++++ glibc.spec | 25 ++- 7 files changed, 922 insertions(+), 4 deletions(-) create mode 100644 glibc-upstream-2.34-21.patch create mode 100644 glibc-upstream-2.34-22.patch create mode 100644 glibc-upstream-2.34-23.patch create mode 100644 glibc-upstream-2.34-24.patch create mode 100644 glibc-upstream-2.34-25.patch create mode 100644 glibc-upstream-2.34-26.patch diff --git a/glibc-upstream-2.34-21.patch b/glibc-upstream-2.34-21.patch new file mode 100644 index 0000000..16ddaef --- /dev/null +++ b/glibc-upstream-2.34-21.patch @@ -0,0 +1,44 @@ +commit 433ec4f14a5753c7689c83c20c9972915c53c204 +Author: Aurelien Jarno +Date: Fri Sep 10 19:39:35 2021 +0200 + + posix: Fix attribute access mode on getcwd [BZ #27476] + + There is a GNU extension that allows to call getcwd(NULL, >0). It is + described in the documentation, but also directly in the unistd.h + header, just above the declaration. + + Therefore the attribute access mode added in commit 06febd8c6705 + is not correct. Drop it. + +diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h +index f0831386c7ddb574..622adeb2b28ed298 100644 +--- a/posix/bits/unistd.h ++++ b/posix/bits/unistd.h +@@ -199,10 +199,9 @@ __NTH (readlinkat (int __fd, const char *__restrict __path, + #endif + + extern char *__getcwd_chk (char *__buf, size_t __size, size_t __buflen) +- __THROW __wur __attr_access ((__write_only__, 1, 2)); ++ __THROW __wur; + extern char *__REDIRECT_NTH (__getcwd_alias, +- (char *__buf, size_t __size), getcwd) +- __wur __attr_access ((__write_only__, 1, 2)); ++ (char *__buf, size_t __size), getcwd) __wur; + extern char *__REDIRECT_NTH (__getcwd_chk_warn, + (char *__buf, size_t __size, size_t __buflen), + __getcwd_chk) +diff --git a/posix/unistd.h b/posix/unistd.h +index 3dca65732fdde52f..8224c5fbc956306f 100644 +--- a/posix/unistd.h ++++ b/posix/unistd.h +@@ -528,8 +528,7 @@ extern int fchdir (int __fd) __THROW __wur; + an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE == 0, in which case it is as + big as necessary. */ +-extern char *getcwd (char *__buf, size_t __size) __THROW __wur +- __attr_access ((__write_only__, 1, 2)); ++extern char *getcwd (char *__buf, size_t __size) __THROW __wur; + + #ifdef __USE_GNU + /* Return a malloc'd string containing the current directory name. diff --git a/glibc-upstream-2.34-22.patch b/glibc-upstream-2.34-22.patch new file mode 100644 index 0000000..bdcd19c --- /dev/null +++ b/glibc-upstream-2.34-22.patch @@ -0,0 +1,137 @@ +commit 73c7f5a87971de2797f261e1a447f68dce09284b +Author: Florian Weimer +Date: Mon Sep 20 14:56:08 2021 +0200 + + nptl: pthread_kill needs to return ESRCH for old programs (bug 19193) + + The fix for bug 19193 breaks some old applications which appear + to use pthread_kill to probe if a thread is still running, something + that is not supported by POSIX. + + (cherry picked from commit 95dba35bf05e4a5d69dfae5e9c9d4df3646a7f93) + +diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c +index fb7862eff787a94f..a44dc8f2d9baa925 100644 +--- a/nptl/pthread_kill.c ++++ b/nptl/pthread_kill.c +@@ -21,8 +21,11 @@ + #include + #include + +-int +-__pthread_kill_internal (pthread_t threadid, int signo) ++/* Sends SIGNO to THREADID. If the thread is about to exit or has ++ already exited on the kernel side, return NO_TID. Otherwise return ++ 0 or an error code. */ ++static int ++__pthread_kill_implementation (pthread_t threadid, int signo, int no_tid) + { + struct pthread *pd = (struct pthread *) threadid; + if (pd == THREAD_SELF) +@@ -52,11 +55,8 @@ __pthread_kill_internal (pthread_t threadid, int signo) + signal is either not observable (the target thread has already + blocked signals at this point), or it will fail, or it might be + delivered to a new, unrelated thread that has reused the TID. +- So do not actually send the signal. Do not report an error +- because the threadid argument is still valid (the thread ID +- lifetime has not ended), and ESRCH (for example) would be +- misleading. */ +- ret = 0; ++ So do not actually send the signal. */ ++ ret = no_tid; + else + { + /* Using tgkill is a safety measure. pd->exit_lock ensures that +@@ -71,6 +71,15 @@ __pthread_kill_internal (pthread_t threadid, int signo) + return ret; + } + ++int ++__pthread_kill_internal (pthread_t threadid, int signo) ++{ ++ /* Do not report an error in the no-tid case because the threadid ++ argument is still valid (the thread ID lifetime has not ended), ++ and ESRCH (for example) would be misleading. */ ++ return __pthread_kill_implementation (threadid, signo, 0); ++} ++ + int + __pthread_kill (pthread_t threadid, int signo) + { +@@ -81,6 +90,7 @@ __pthread_kill (pthread_t threadid, int signo) + + return __pthread_kill_internal (threadid, signo); + } ++ + /* Some architectures (for instance arm) might pull raise through libgcc, so + avoid the symbol version if it ends up being used on ld.so. */ + #if !IS_IN(rtld) +@@ -88,6 +98,17 @@ libc_hidden_def (__pthread_kill) + versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34); + + # if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) +-compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0); ++/* Variant which returns ESRCH in the no-TID case, for backwards ++ compatibility. */ ++int ++attribute_compat_text_section ++__pthread_kill_esrch (pthread_t threadid, int signo) ++{ ++ if (__is_internal_signal (signo)) ++ return EINVAL; ++ ++ return __pthread_kill_implementation (threadid, signo, ESRCH); ++} ++compat_symbol (libc, __pthread_kill_esrch, pthread_kill, GLIBC_2_0); + # endif + #endif +diff --git a/sysdeps/pthread/tst-pthread_kill-exited.c b/sysdeps/pthread/tst-pthread_kill-exited.c +index 7575fb6d58cae99c..a2fddad526666c8c 100644 +--- a/sysdeps/pthread/tst-pthread_kill-exited.c ++++ b/sysdeps/pthread/tst-pthread_kill-exited.c +@@ -16,11 +16,15 @@ + License along with the GNU C Library; if not, see + . */ + +-/* This test verifies that pthread_kill returns 0 (and not ESRCH) for +- a thread that has exited on the kernel side. */ ++/* This test verifies that the default pthread_kill returns 0 (and not ++ ESRCH) for a thread that has exited on the kernel side. */ + ++#include ++#include ++#include + #include + #include ++#include + #include + #include + +@@ -30,6 +34,12 @@ noop_thread (void *closure) + return NULL; + } + ++#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC ++extern __typeof (pthread_kill) compat_pthread_kill; ++compat_symbol_reference (libpthread, compat_pthread_kill, pthread_kill, ++ GLIBC_2_0); ++#endif ++ + static int + do_test (void) + { +@@ -37,7 +47,14 @@ do_test (void) + + support_wait_for_thread_exit (); + ++ /* NB: Always uses the default symbol due to separate compilation. */ + xpthread_kill (thr, SIGUSR1); ++ ++#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC ++ /* Old binaries need the non-conforming ESRCH error code. */ ++ TEST_COMPARE (compat_pthread_kill (thr, SIGUSR1), ESRCH); ++#endif ++ + xpthread_join (thr); + + return 0; diff --git a/glibc-upstream-2.34-23.patch b/glibc-upstream-2.34-23.patch new file mode 100644 index 0000000..67d7d88 --- /dev/null +++ b/glibc-upstream-2.34-23.patch @@ -0,0 +1,32 @@ +commit 8b8a1d0b7375c547ae905917a03743ed6759c5bc +Author: Florian Weimer +Date: Tue Sep 21 07:12:56 2021 +0200 + + nptl: Fix type of pthread_mutexattr_getrobust_np, pthread_mutexattr_setrobust_np (bug 28036) + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + (cherry picked from commit f3e664563361dc17530113b3205998d1f19dc4d9) + +diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h +index f1b7f2bdc6062c3e..43146e91c9d9579b 100644 +--- a/sysdeps/nptl/pthread.h ++++ b/sysdeps/nptl/pthread.h +@@ -933,7 +933,7 @@ extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr, + # ifdef __USE_GNU + # ifdef __REDIRECT_NTH + extern int __REDIRECT_NTH (pthread_mutexattr_getrobust_np, +- (pthread_mutex_t *, int *), ++ (pthread_mutexattr_t *, int *), + pthread_mutexattr_getrobust) __nonnull ((1)) + __attribute_deprecated_msg__ ("\ + pthread_mutexattr_getrobust_np is deprecated, use pthread_mutexattr_getrobust"); +@@ -949,7 +949,7 @@ extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr, + # ifdef __USE_GNU + # ifdef __REDIRECT_NTH + extern int __REDIRECT_NTH (pthread_mutexattr_setrobust_np, +- (pthread_mutex_t *, int), ++ (pthread_mutexattr_t *, int), + pthread_mutexattr_setrobust) __nonnull ((1)) + __attribute_deprecated_msg__ ("\ + pthread_mutexattr_setrobust_np is deprecated, use pthread_mutexattr_setrobust"); diff --git a/glibc-upstream-2.34-24.patch b/glibc-upstream-2.34-24.patch new file mode 100644 index 0000000..4c4a4c0 --- /dev/null +++ b/glibc-upstream-2.34-24.patch @@ -0,0 +1,355 @@ +commit 5ad589d63bc2d9b1fc3d9f32144acaebb85e0803 +Author: Adhemerval Zanella +Date: Tue Aug 24 16:12:24 2021 -0300 + + support: Add support_open_dev_null_range + + It returns a range of file descriptor referring to the '/dev/null' + pathname. The function takes care of restarting the open range + if a file descriptor is found within the specified range and + also increases RLIMIT_NOFILE if required. + + Checked on x86_64-linux-gnu. + + (cherry picked from commit e814f4b04ee413a7bb3dfa43e74c8fb4abf58359) + +diff --git a/support/Makefile b/support/Makefile +index ef2b1a980a407f8f..2a0731796fdb3f2d 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -66,6 +66,7 @@ libsupport-routines = \ + support_path_support_time64 \ + support_process_state \ + support_ptrace \ ++ support-open-dev-null-range \ + support_openpty \ + support_paths \ + support_quote_blob \ +@@ -265,6 +266,7 @@ tests = \ + tst-support_capture_subprocess \ + tst-support_descriptors \ + tst-support_format_dns_packet \ ++ tst-support-open-dev-null-range \ + tst-support-process_state \ + tst-support_quote_blob \ + tst-support_quote_string \ +diff --git a/support/support-open-dev-null-range.c b/support/support-open-dev-null-range.c +new file mode 100644 +index 0000000000000000..80d9dba50402ce12 +--- /dev/null ++++ b/support/support-open-dev-null-range.c +@@ -0,0 +1,134 @@ ++/* Return a range of open file descriptors. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++increase_nofile (void) ++{ ++ struct rlimit rl; ++ if (getrlimit (RLIMIT_NOFILE, &rl) == -1) ++ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m"); ++ ++ rl.rlim_cur += 128; ++ ++ if (setrlimit (RLIMIT_NOFILE, &rl) == 1) ++ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m"); ++} ++ ++static int ++open_dev_null (int flags, mode_t mode) ++{ ++ int fd = open64 ("/dev/null", flags, mode); ++ if (fd > 0) ++ return fd; ++ ++ if (fd < 0 && errno != EMFILE) ++ FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode); ++ ++ increase_nofile (); ++ ++ return xopen ("/dev/null", flags, mode); ++} ++ ++struct range ++{ ++ int lowfd; ++ size_t len; ++}; ++ ++struct range_list ++{ ++ size_t total; ++ size_t used; ++ struct range *ranges; ++}; ++ ++static void ++range_init (struct range_list *r) ++{ ++ r->total = 8; ++ r->used = 0; ++ r->ranges = xmalloc (r->total * sizeof (struct range)); ++} ++ ++static void ++range_add (struct range_list *r, int lowfd, size_t len) ++{ ++ if (r->used == r->total) ++ { ++ r->total *= 2; ++ r->ranges = xrealloc (r->ranges, r->total * sizeof (struct range)); ++ } ++ r->ranges[r->used].lowfd = lowfd; ++ r->ranges[r->used].len = len; ++ r->used++; ++} ++ ++static void ++range_close (struct range_list *r) ++{ ++ for (size_t i = 0; i < r->used; i++) ++ { ++ int minfd = r->ranges[i].lowfd; ++ int maxfd = r->ranges[i].lowfd + r->ranges[i].len; ++ for (int fd = minfd; fd < maxfd; fd++) ++ xclose (fd); ++ } ++ free (r->ranges); ++} ++ ++int ++support_open_dev_null_range (int num, int flags, mode_t mode) ++{ ++ /* We keep track of the ranges that hit an already opened descriptor, so ++ we close them after we get a working range. */ ++ struct range_list rl; ++ range_init (&rl); ++ ++ int lowfd = open_dev_null (flags, mode); ++ int prevfd = lowfd; ++ while (true) ++ { ++ int i = 1; ++ for (; i < num; i++) ++ { ++ int fd = open_dev_null (flags, mode); ++ if (fd != lowfd + i) ++ { ++ range_add (&rl, lowfd, prevfd - lowfd + 1); ++ ++ prevfd = lowfd = fd; ++ break; ++ } ++ prevfd = fd; ++ } ++ if (i == num) ++ break; ++ } ++ ++ range_close (&rl); ++ ++ return lowfd; ++} +diff --git a/support/support.h b/support/support.h +index a5978b939af2fb41..c219e0d9d1aef046 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -197,6 +197,14 @@ struct support_stack support_stack_alloc (size_t size); + /* Deallocate the STACK. */ + void support_stack_free (struct support_stack *stack); + ++ ++/* Create a range of NUM opened '/dev/null' file descriptors using FLAGS and ++ MODE. The function takes care of restarting the open range if a file ++ descriptor is found within the specified range and also increases ++ RLIMIT_NOFILE if required. ++ The returned value is the lowest file descriptor number. */ ++int support_open_dev_null_range (int num, int flags, mode_t mode); ++ + __END_DECLS + + #endif /* SUPPORT_H */ +diff --git a/support/tst-support-open-dev-null-range.c b/support/tst-support-open-dev-null-range.c +new file mode 100644 +index 0000000000000000..8e29def1ce780629 +--- /dev/null ++++ b/support/tst-support-open-dev-null-range.c +@@ -0,0 +1,155 @@ ++/* Tests for support_open_dev_null_range. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef PATH_MAX ++# define PATH_MAX 1024 ++#endif ++ ++#include ++ ++static void ++check_path (int fd) ++{ ++ char *proc_fd_path = xasprintf ("/proc/self/fd/%d", fd); ++ char file_path[PATH_MAX]; ++ ssize_t file_path_length ++ = readlink (proc_fd_path, file_path, sizeof (file_path)); ++ free (proc_fd_path); ++ if (file_path_length < 0) ++ FAIL_EXIT1 ("readlink (%s, %p, %zu)", proc_fd_path, file_path, ++ sizeof (file_path)); ++ file_path[file_path_length] = '\0'; ++ TEST_COMPARE_STRING (file_path, "/dev/null"); ++} ++ ++static int ++number_of_opened_files (void) ++{ ++ DIR *fds = opendir ("/proc/self/fd"); ++ if (fds == NULL) ++ FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m"); ++ ++ int r = 0; ++ while (true) ++ { ++ errno = 0; ++ struct dirent64 *e = readdir64 (fds); ++ if (e == NULL) ++ { ++ if (errno != 0) ++ FAIL_EXIT1 ("readdir: %m"); ++ break; ++ } ++ ++ if (e->d_name[0] == '.') ++ continue; ++ ++ char *endptr; ++ long int fd = strtol (e->d_name, &endptr, 10); ++ if (*endptr != '\0' || fd < 0 || fd > INT_MAX) ++ FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s", ++ e->d_name); ++ ++ /* Skip the descriptor which is used to enumerate the ++ descriptors. */ ++ if (fd == dirfd (fds)) ++ continue; ++ ++ r = r + 1; ++ } ++ ++ closedir (fds); ++ ++ return r; ++} ++ ++static int ++do_test (void) ++{ ++ const int nfds1 = 8; ++ int lowfd = support_open_dev_null_range (nfds1, O_RDONLY, 0600); ++ for (int i = 0; i < nfds1; i++) ++ { ++ TEST_VERIFY (fcntl (lowfd + i, F_GETFL) > -1); ++ check_path (lowfd + i); ++ } ++ ++ /* create some gaps. */ ++ xclose (lowfd + 1); ++ xclose (lowfd + 5); ++ xclose (lowfd + 6); ++ ++ const int nfds2 = 16; ++ int lowfd2 = support_open_dev_null_range (nfds2, O_RDONLY, 0600); ++ for (int i = 0; i < nfds2; i++) ++ { ++ TEST_VERIFY (fcntl (lowfd2 + i, F_GETFL) > -1); ++ check_path (lowfd2 + i); ++ } ++ ++ /* Decrease the maximum number of files. */ ++ { ++ struct rlimit rl; ++ if (getrlimit (RLIMIT_NOFILE, &rl) == -1) ++ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m"); ++ ++ rl.rlim_cur = number_of_opened_files (); ++ ++ if (setrlimit (RLIMIT_NOFILE, &rl) == 1) ++ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m"); ++ } ++ ++ const int nfds3 = 16; ++ int lowfd3 = support_open_dev_null_range (nfds3, O_RDONLY, 0600); ++ for (int i = 0; i < nfds3; i++) ++ { ++ TEST_VERIFY (fcntl (lowfd3 + i, F_GETFL) > -1); ++ check_path (lowfd3 + i); ++ } ++ ++ /* create a lot of gaps to trigger the range extension. */ ++ xclose (lowfd3 + 1); ++ xclose (lowfd3 + 3); ++ xclose (lowfd3 + 5); ++ xclose (lowfd3 + 7); ++ xclose (lowfd3 + 9); ++ xclose (lowfd3 + 11); ++ xclose (lowfd3 + 13); ++ ++ const int nfds4 = 16; ++ int lowfd4 = support_open_dev_null_range (nfds4, O_RDONLY, 0600); ++ for (int i = 0; i < nfds4; i++) ++ { ++ TEST_VERIFY (fcntl (lowfd4 + i, F_GETFL) > -1); ++ check_path (lowfd4 + i); ++ } ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-upstream-2.34-25.patch b/glibc-upstream-2.34-25.patch new file mode 100644 index 0000000..8899335 --- /dev/null +++ b/glibc-upstream-2.34-25.patch @@ -0,0 +1,204 @@ +commit 772e33411bc730f832f415f93eb3e7c67e4d5488 +Author: Adhemerval Zanella +Date: Tue Aug 24 16:15:50 2021 -0300 + + Use support_open_dev_null_range io/tst-closefrom, misc/tst-close_range, and posix/tst-spawn5 (BZ #28260) + + It ensures a continuous range of file descriptor and avoid hitting + the RLIMIT_NOFILE. + + Checked on x86_64-linux-gnu. + + (cherry picked from commit 6b20880b22d1d0fce7e9f506baa6fe2d5c7fcfdc) + +diff --git a/io/tst-closefrom.c b/io/tst-closefrom.c +index d4c187073c7280e9..395ec0d894101a47 100644 +--- a/io/tst-closefrom.c ++++ b/io/tst-closefrom.c +@@ -24,31 +24,22 @@ + #include + #include + #include ++#include + + #include + + #define NFDS 100 + +-static int +-open_multiple_temp_files (void) +-{ +- /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); +- for (int i = 1; i <= NFDS; i++) +- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), lowfd + i); +- return lowfd; +-} +- + static int + closefrom_test (void) + { + struct support_descriptors *descrs = support_descriptors_list (); + +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + +- const int maximum_fd = lowfd + NFDS; ++ const int maximum_fd = lowfd + NFDS - 1; + const int half_fd = lowfd + NFDS / 2; +- const int gap = maximum_fd / 4; ++ const int gap = lowfd + NFDS / 4; + + /* Close half of the descriptors and check result. */ + closefrom (half_fd); +@@ -58,7 +49,7 @@ closefrom_test (void) + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } +- for (int i = 0; i < half_fd; i++) ++ for (int i = lowfd; i < half_fd; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Create some gaps, close up to a threshold, and check result. */ +@@ -74,7 +65,7 @@ closefrom_test (void) + TEST_COMPARE (fcntl (i, F_GETFL), -1); + TEST_COMPARE (errno, EBADF); + } +- for (int i = 0; i < gap; i++) ++ for (int i = lowfd; i < gap; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + /* Close the remmaining but the last one. */ +diff --git a/posix/tst-spawn5.c b/posix/tst-spawn5.c +index ac6673800464ce72..a95199af6b3b7c9a 100644 +--- a/posix/tst-spawn5.c ++++ b/posix/tst-spawn5.c +@@ -47,17 +47,6 @@ static int initial_argv_count; + + #define NFDS 100 + +-static int +-open_multiple_temp_files (void) +-{ +- /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); +- for (int i = 1; i <= NFDS; i++) +- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), +- lowfd + i); +- return lowfd; +-} +- + static int + parse_fd (const char *str) + { +@@ -185,7 +174,7 @@ spawn_closefrom_test (posix_spawn_file_actions_t *fa, int lowfd, int highfd, + static void + do_test_closefrom (void) + { +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + const int half_fd = lowfd + NFDS / 2; + + /* Close half of the descriptors and check result. */ +diff --git a/sysdeps/unix/sysv/linux/tst-close_range.c b/sysdeps/unix/sysv/linux/tst-close_range.c +index dccb6189c53fcb90..f5069d1b8a067241 100644 +--- a/sysdeps/unix/sysv/linux/tst-close_range.c ++++ b/sysdeps/unix/sysv/linux/tst-close_range.c +@@ -36,23 +36,12 @@ + + #define NFDS 100 + +-static int +-open_multiple_temp_files (void) +-{ +- /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = xopen ("/dev/null", O_RDONLY, 0600); +- for (int i = 1; i <= NFDS; i++) +- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), +- lowfd + i); +- return lowfd; +-} +- + static void + close_range_test_max_upper_limit (void) + { + struct support_descriptors *descrs = support_descriptors_list (); + +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + + { + int r = close_range (lowfd, ~0U, 0); +@@ -68,7 +57,7 @@ close_range_test_max_upper_limit (void) + static void + close_range_test_common (int lowfd, unsigned int flags) + { +- const int maximum_fd = lowfd + NFDS; ++ const int maximum_fd = lowfd + NFDS - 1; + const int half_fd = lowfd + NFDS / 2; + const int gap_1 = maximum_fd - 8; + +@@ -121,7 +110,7 @@ close_range_test (void) + struct support_descriptors *descrs = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + + close_range_test_common (lowfd, 0); + +@@ -146,7 +135,7 @@ close_range_test_subprocess (void) + struct support_descriptors *descrs = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + + struct support_stack stack = support_stack_alloc (4096); + +@@ -184,7 +173,7 @@ close_range_unshare_test (void) + struct support_descriptors *descrs1 = support_descriptors_list (); + + /* Check if the temporary file descriptor has no no gaps. */ +- int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + + struct support_descriptors *descrs2 = support_descriptors_list (); + +@@ -200,7 +189,7 @@ close_range_unshare_test (void) + + support_stack_free (&stack); + +- for (int i = 0; i < NFDS; i++) ++ for (int i = lowfd; i < lowfd + NFDS; i++) + TEST_VERIFY (fcntl (i, F_GETFL) > -1); + + support_descriptors_check (descrs2); +@@ -226,9 +215,9 @@ static void + close_range_cloexec_test (void) + { + /* Check if the temporary file descriptor has no no gaps. */ +- const int lowfd = open_multiple_temp_files (); ++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600); + +- const int maximum_fd = lowfd + NFDS; ++ const int maximum_fd = lowfd + NFDS - 1; + const int half_fd = lowfd + NFDS / 2; + const int gap_1 = maximum_fd - 8; + +@@ -251,13 +240,13 @@ close_range_cloexec_test (void) + /* Create some gaps, close up to a threshold, and check result. */ + static int gap_close[] = { 57, 78, 81, 82, 84, 90 }; + for (int i = 0; i < array_length (gap_close); i++) +- xclose (gap_close[i]); ++ xclose (lowfd + gap_close[i]); + + TEST_COMPARE (close_range (half_fd + 1, gap_1, CLOSE_RANGE_CLOEXEC), 0); + for (int i = half_fd + 1; i < gap_1; i++) + { + int flags = fcntl (i, F_GETFD); +- if (is_in_array (gap_close, array_length (gap_close), i)) ++ if (is_in_array (gap_close, array_length (gap_close), i - lowfd)) + TEST_COMPARE (flags, -1); + else + { diff --git a/glibc-upstream-2.34-26.patch b/glibc-upstream-2.34-26.patch new file mode 100644 index 0000000..4366808 --- /dev/null +++ b/glibc-upstream-2.34-26.patch @@ -0,0 +1,129 @@ +commit 33adeaa3e2b9143c38884bc5aa65ded222ed274e +Author: Florian Weimer +Date: Thu Sep 23 09:55:54 2021 +0200 + + nptl: Avoid setxid deadlock with blocked signals in thread exit [BZ #28361] + + As part of the fix for bug 12889, signals are blocked during + thread exit, so that application code cannot run on the thread that + is about to exit. This would cause problems if the application + expected signals to be delivered after the signal handler revealed + the thread to still exist, despite pthread_kill can no longer be used + to send signals to it. However, glibc internally uses the SIGSETXID + signal in a way that is incompatible with signal blocking, due to the + way the setxid handshake delays thread exit until the setxid operation + has completed. With a blocked SIGSETXID, the handshake can never + complete, causing a deadlock. + + As a band-aid, restore the previous handshake protocol by not blocking + SIGSETXID during thread exit. + + The new test sysdeps/pthread/tst-pthread-setuid-loop.c is based on + a downstream test by Martin Osvald. + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + (cherry picked from commit 2849e2f53311b66853cb5159b64cba2bddbfb854) + +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index 33b426fc682300dc..bc213f0bc4e948bd 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -488,8 +488,16 @@ start_thread (void *arg) + + /* This prevents sending a signal from this thread to itself during + its final stages. This must come after the exit call above +- because atexit handlers must not run with signals blocked. */ +- __libc_signal_block_all (NULL); ++ because atexit handlers must not run with signals blocked. ++ ++ Do not block SIGSETXID. The setxid handshake below expects the ++ signal to be delivered. (SIGSETXID cannot run application code, ++ nor does it use pthread_kill.) Reuse the pd->sigmask space for ++ computing the signal mask, to save stack space. */ ++ __sigfillset (&pd->sigmask); ++ __sigdelset (&pd->sigmask, SIGSETXID); ++ INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &pd->sigmask, NULL, ++ __NSIG_BYTES); + + /* Tell __pthread_kill_internal that this thread is about to exit. + If there is a __pthread_kill_internal in progress, this delays +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index 48dba717a1cdc20a..d4bd2d4e3ee6a496 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -118,6 +118,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-unload \ + tst-unwind-thread \ + tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \ ++ tst-pthread-setuid-loop \ + tst-pthread_cancel-exited \ + tst-pthread_cancel-select-loop \ + tst-pthread_kill-exited \ +diff --git a/sysdeps/pthread/tst-pthread-setuid-loop.c b/sysdeps/pthread/tst-pthread-setuid-loop.c +new file mode 100644 +index 0000000000000000..fda2a49b7f0ccf81 +--- /dev/null ++++ b/sysdeps/pthread/tst-pthread-setuid-loop.c +@@ -0,0 +1,61 @@ ++/* Test that setuid, pthread_create, thread exit do not deadlock (bug 28361). ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++/* How many threads to launch during each iteration. */ ++enum { threads = 4 }; ++ ++/* How many iterations to perform. This value seems to reproduce ++ bug 28361 in a bout one in three runs. */ ++enum { iterations = 5000 }; ++ ++/* Cache of the real user ID used by setuid_thread. */ ++static uid_t uid; ++ ++/* Start routine for the threads. */ ++static void * ++setuid_thread (void *closure) ++{ ++ TEST_COMPARE (setuid (uid), 0); ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ /* The setxid machinery is still invoked even if the UID is ++ unchanged. (The kernel might reset other credentials as part of ++ the system call.) */ ++ uid = getuid (); ++ ++ for (int i = 0; i < iterations; ++i) ++ { ++ pthread_t thread_ids[threads]; ++ for (int j = 0; j < threads; ++j) ++ thread_ids[j] = xpthread_create (NULL, setuid_thread, NULL); ++ for (int j = 0; j < threads; ++j) ++ xpthread_join (thread_ids[j]); ++ } ++ ++ return 0; ++} ++ ++#include diff --git a/glibc.spec b/glibc.spec index b3f203c..9937dd8 100644 --- a/glibc.spec +++ b/glibc.spec @@ -151,7 +151,7 @@ end \ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 5%{?dist} +Release: 6%{?dist} # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -251,9 +251,15 @@ Patch48: glibc-upstream-2.34-17.patch Patch49: glibc-upstream-2.34-18.patch Patch50: glibc-upstream-2.34-19.patch Patch51: glibc-upstream-2.34-20.patch -Patch52: glibc-rh1992702-1.patch -Patch53: glibc-rh1992702-2.patch -Patch54: glibc-rh1992702-3.patch +Patch52: glibc-upstream-2.34-21.patch +Patch53: glibc-upstream-2.34-22.patch +Patch54: glibc-upstream-2.34-23.patch +Patch55: glibc-upstream-2.34-24.patch +Patch56: glibc-upstream-2.34-25.patch +Patch57: glibc-upstream-2.34-26.patch +Patch1001: glibc-rh1992702-1.patch +Patch1002: glibc-rh1992702-2.patch +Patch1003: glibc-rh1992702-3.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2285,6 +2291,17 @@ fi %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared %changelog +* Thu Sep 23 2021 Florian Weimer - 2.34-6 +- Sync with upstream branch release/2.34/master, + commit 33adeaa3e2b9143c38884bc5aa65ded222ed274e: +- nptl: Avoid setxid deadlock with blocked signals in thread exit [BZ #28361] +- Use support_open_dev_null_range io/tst-closefrom, misc/tst-close_range, and + posix/tst-spawn5 (BZ #28260) +- support: Add support_open_dev_null_range +- nptl: Fix type of pthread_mutexattr_getrobust_np, + pthread_mutexattr_setrobust_np (bug 28036) +- nptl: pthread_kill needs to return ESRCH for old programs (bug 19193) + * Wed Sep 15 2021 Florian Weimer - 2.34-5 - Use system CPU count for sysconf(_SC_NPROCESSORS_*) (#1992702)