diff --git a/srcpkgs/glibc/patches/glibc-upstream-11.patch b/srcpkgs/glibc/patches/glibc-upstream-11.patch index 2930fbbf36..f08c5dca02 100644 --- a/srcpkgs/glibc/patches/glibc-upstream-11.patch +++ b/srcpkgs/glibc/patches/glibc-upstream-11.patch @@ -50,3 +50,4 @@ index 1fd2fee44b..9bfbb2bb9b 100644 "+:6:1873//01//01:1912//07//29::%EC%Ey";/ "+:1:0001//01//01:1872//12//31::%EC%Ey";/ "+:1:-0001//12//31:-*::%EC%Ey" + diff --git a/srcpkgs/glibc/patches/glibc-upstream-12.patch b/srcpkgs/glibc/patches/glibc-upstream-12.patch new file mode 100644 index 0000000000..cbf7641b46 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-12.patch @@ -0,0 +1,66 @@ +From 0941350c20a52447e53c5169354408e3db591f73 Mon Sep 17 00:00:00 2001 +From: TAMUKI Shoichi +Date: Tue, 2 Apr 2019 16:46:55 +0900 +Subject: [PATCH 12] ja_JP locale: Add entry for the new Japanese era [BZ + #22964] + +The Japanese era name will be changed on May 1, 2019. The Japanese +government made a preliminary announcement on April 1, 2019. + +The glibc ja_JP locale must be updated to include the new era name for +strftime's alternative year format support. + +This is a minimal cherry pick of just the required locale changes. + +(cherry picked from commit 466afec30896585b60c2106df7a722a86247c9f3) +--- + ChangeLog | 6 ++++++ + NEWS | 4 ++++ + localedata/locales/ja_JP | 4 +++- + 3 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/ChangeLog b/ChangeLog +index 048ca9644c..3b5d24cf67 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,9 @@ ++2019-04-02 TAMUKI Shoichi ++ ++ [BZ #22964] ++ * localedata/locales/ja_JP (LC_TIME): Add entry for the new Japanese ++ era. ++ + 2019-03-02 TAMUKI Shoichi + + [BZ #24162] +diff --git a/NEWS b/NEWS +index 271bf7a2cd..703864ac75 100644 +--- a/NEWS ++++ b/NEWS +@@ -7,6 +7,10 @@ using `glibc' in the "product" field. + + Version 2.29.1 + ++Major new features: ++ ++* The entry for the new Japanese era has been added for ja_JP locale. ++ + The following bugs are resolved with this release: + + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) +diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP +index 9bfbb2bb9b..c64aaaff55 100644 +--- a/localedata/locales/ja_JP ++++ b/localedata/locales/ja_JP +@@ -14946,7 +14946,9 @@ am_pm "";"" + + t_fmt_ampm "%p%I%M%S" + +-era "+:2:1990//01//01:+*::%EC%Ey";/ ++era "+:2:2020//01//01:+*::%EC%Ey";/ ++ "+:1:2019//05//01:2019//12//31::%EC";/ ++ "+:2:1990//01//01:2019//04//30::%EC%Ey";/ + "+:1:1989//01//08:1989//12//31::%EC";/ + "+:2:1927//01//01:1989//01//07::%EC%Ey";/ + "+:1:1926//12//25:1926//12//31::%EC";/ + diff --git a/srcpkgs/glibc/patches/glibc-upstream-13.patch b/srcpkgs/glibc/patches/glibc-upstream-13.patch new file mode 100644 index 0000000000..7aa56ba8de --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-13.patch @@ -0,0 +1,206 @@ +From dcd2b97dd1d695445d45beb4daa815cfe06691dd Mon Sep 17 00:00:00 2001 +From: Carlos O'Donell +Date: Mon, 15 Apr 2019 20:49:32 +0200 +Subject: [PATCH 13] malloc: Set and reset all hooks for tracing (Bug 16573) + +If an error occurs during the tracing operation, particularly during a +call to lock_and_info() which calls _dl_addr, we may end up calling back +into the malloc-subsystem and relock the loader lock and deadlock. For +all intents and purposes the call to _dl_addr can call any of the malloc +family API functions and so we should disable all tracing before calling +such loader functions. This is similar to the strategy that the new +malloc tracer takes when calling the real malloc, namely that all +tracing ceases at the boundary to the real function and any faults at +that point are the purvue of the library (though the new tracer does +this on a per-thread basis in an MT-safe fashion). Since the new tracer +and the hook deprecation are not yet complete we must fix these issues +where we can. + +Tested on x86_64 with no regressions. + +Co-authored-by: Kwok Cheung Yeung +Reviewed-by: DJ Delorie +(cherry picked from commit e621246ec6393ea08ae50310f9d5e72500f8c9bc) +--- + ChangeLog | 15 +++++++++++ + NEWS | 1 + + malloc/mtrace.c | 72 +++++++++++++++++++++++++++++++------------------ + 3 files changed, 62 insertions(+), 26 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 3b5d24cf67..077d0dae29 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,18 @@ ++2019-04-09 Carlos O'Donell ++ Kwok Cheung Yeung ++ ++ [BZ #16573] ++ * malloc/mtrace.c: Define prototypes for all hooks. ++ (set_default_hooks): New function. ++ (set_trace_hooks): Likewise. ++ (save_default_hooks): Likewise. ++ (tr_freehook): Use new s*_hooks functions. ++ (tr_mallochook): Likewise. ++ (tr_reallochook): Likewise. ++ (tr_memalignhook): Likewise. ++ (mtrace): Likewise. ++ (muntrace): Likewise. ++ + 2019-04-02 TAMUKI Shoichi + + [BZ #22964] +diff --git a/NEWS b/NEWS +index 703864ac75..117646df7b 100644 +--- a/NEWS ++++ b/NEWS +@@ -13,6 +13,7 @@ Major new features: + + The following bugs are resolved with this release: + ++ [16573] malloc: Set and reset all hooks for tracing + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) + [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 +diff --git a/malloc/mtrace.c b/malloc/mtrace.c +index a2facf65ea..2fda262508 100644 +--- a/malloc/mtrace.c ++++ b/malloc/mtrace.c +@@ -121,6 +121,41 @@ lock_and_info (const void *caller, Dl_info *mem) + return res; + } + ++static void tr_freehook (void *, const void *); ++static void * tr_mallochook (size_t, const void *); ++static void * tr_reallochook (void *, size_t, const void *); ++static void * tr_memalignhook (size_t, size_t, const void *); ++ ++/* Set all the default non-trace hooks. */ ++static __always_inline void ++set_default_hooks (void) ++{ ++ __free_hook = tr_old_free_hook; ++ __malloc_hook = tr_old_malloc_hook; ++ __realloc_hook = tr_old_realloc_hook; ++ __memalign_hook = tr_old_memalign_hook; ++} ++ ++/* Set all of the tracing hooks used for mtrace. */ ++static __always_inline void ++set_trace_hooks (void) ++{ ++ __free_hook = tr_freehook; ++ __malloc_hook = tr_mallochook; ++ __realloc_hook = tr_reallochook; ++ __memalign_hook = tr_memalignhook; ++} ++ ++/* Save the current set of hooks as the default hooks. */ ++static __always_inline void ++save_default_hooks (void) ++{ ++ tr_old_free_hook = __free_hook; ++ tr_old_malloc_hook = __malloc_hook; ++ tr_old_realloc_hook = __realloc_hook; ++ tr_old_memalign_hook = __memalign_hook; ++} ++ + static void + tr_freehook (void *ptr, const void *caller) + { +@@ -138,12 +173,12 @@ tr_freehook (void *ptr, const void *caller) + tr_break (); + __libc_lock_lock (lock); + } +- __free_hook = tr_old_free_hook; ++ set_default_hooks (); + if (tr_old_free_hook != NULL) + (*tr_old_free_hook)(ptr, caller); + else + free (ptr); +- __free_hook = tr_freehook; ++ set_trace_hooks (); + __libc_lock_unlock (lock); + } + +@@ -155,12 +190,12 @@ tr_mallochook (size_t size, const void *caller) + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); + +- __malloc_hook = tr_old_malloc_hook; ++ set_default_hooks (); + if (tr_old_malloc_hook != NULL) + hdr = (void *) (*tr_old_malloc_hook)(size, caller); + else + hdr = (void *) malloc (size); +- __malloc_hook = tr_mallochook; ++ set_trace_hooks (); + + tr_where (caller, info); + /* We could be printing a NULL here; that's OK. */ +@@ -185,16 +220,12 @@ tr_reallochook (void *ptr, size_t size, const void *caller) + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); + +- __free_hook = tr_old_free_hook; +- __malloc_hook = tr_old_malloc_hook; +- __realloc_hook = tr_old_realloc_hook; ++ set_default_hooks (); + if (tr_old_realloc_hook != NULL) + hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller); + else + hdr = (void *) realloc (ptr, size); +- __free_hook = tr_freehook; +- __malloc_hook = tr_mallochook; +- __realloc_hook = tr_reallochook; ++ set_trace_hooks (); + + tr_where (caller, info); + if (hdr == NULL) +@@ -230,14 +261,12 @@ tr_memalignhook (size_t alignment, size_t size, const void *caller) + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); + +- __memalign_hook = tr_old_memalign_hook; +- __malloc_hook = tr_old_malloc_hook; ++ set_default_hooks (); + if (tr_old_memalign_hook != NULL) + hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller); + else + hdr = (void *) memalign (alignment, size); +- __memalign_hook = tr_memalignhook; +- __malloc_hook = tr_mallochook; ++ set_trace_hooks (); + + tr_where (caller, info); + /* We could be printing a NULL here; that's OK. */ +@@ -305,14 +334,8 @@ mtrace (void) + malloc_trace_buffer = mtb; + setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE); + fprintf (mallstream, "= Start\n"); +- tr_old_free_hook = __free_hook; +- __free_hook = tr_freehook; +- tr_old_malloc_hook = __malloc_hook; +- __malloc_hook = tr_mallochook; +- tr_old_realloc_hook = __realloc_hook; +- __realloc_hook = tr_reallochook; +- tr_old_memalign_hook = __memalign_hook; +- __memalign_hook = tr_memalignhook; ++ save_default_hooks (); ++ set_trace_hooks (); + #ifdef _LIBC + if (!added_atexit_handler) + { +@@ -338,10 +361,7 @@ muntrace (void) + file. */ + FILE *f = mallstream; + mallstream = NULL; +- __free_hook = tr_old_free_hook; +- __malloc_hook = tr_old_malloc_hook; +- __realloc_hook = tr_old_realloc_hook; +- __memalign_hook = tr_old_memalign_hook; ++ set_default_hooks (); + + fprintf (f, "= End\n"); + fclose (f); + diff --git a/srcpkgs/glibc/patches/glibc-upstream-14.patch b/srcpkgs/glibc/patches/glibc-upstream-14.patch new file mode 100644 index 0000000000..ce4e75d90e --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-14.patch @@ -0,0 +1,69 @@ +From 42dfc13abf6fbb4c7a0215238eb636b7d374e0e0 Mon Sep 17 00:00:00 2001 +From: Mike Frysinger +Date: Wed, 24 Apr 2019 19:07:46 +0200 +Subject: [PATCH 14] memusagestat: use local glibc when linking [BZ #18465] + +The memusagestat is the only binary that has its own link line which +causes it to be linked against the existing installed C library. It +has been this way since it was originally committed in 1999, but I +don't see any reason as to why. Since we want all the programs we +build locally to be against the new copy of glibc, change the build +to be like all other programs. + +(cherry picked from commit f9b645b4b0a10c43753296ce3fa40053fa44606a) +--- + ChangeLog | 7 +++++++ + NEWS | 1 + + malloc/Makefile | 4 ++-- + 3 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 077d0dae29..5291a88f85 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2019-04-24 Mike Frysinger ++ ++ [BZ #18465] ++ * malloc/Makefile (others): Add memusagestat. ++ ($(objpfx)memusagestat): Delete rule. ++ (LDLIBS-memusagestat): New variable. ++ + 2019-04-09 Carlos O'Donell + Kwok Cheung Yeung + +diff --git a/NEWS b/NEWS +index 117646df7b..07e099b5ec 100644 +--- a/NEWS ++++ b/NEWS +@@ -14,6 +14,7 @@ Major new features: + The following bugs are resolved with this release: + + [16573] malloc: Set and reset all hooks for tracing ++ [18465] memusagestat: use local glibc when linking + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) + [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 +diff --git a/malloc/Makefile b/malloc/Makefile +index ab2eed09c6..aadf602dfd 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -131,6 +131,7 @@ ifneq ($(cross-compiling),yes) + # If the gd library is available we build the `memusagestat' program. + ifneq ($(LIBGD),no) + others: $(objpfx)memusage ++others += memusagestat + install-bin = memusagestat + install-bin-script += memusage + generated += memusagestat memusage +@@ -154,8 +155,7 @@ cpp-srcs-left := $(memusagestat-modules) + lib := memusagestat + include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) + +-$(objpfx)memusagestat: $(memusagestat-modules:%=$(objpfx)%.o) +- $(LINK.o) -o $@ $^ $(libgd-LDFLAGS) -lgd -lpng -lz -lm ++LDLIBS-memusagestat = $(libgd-LDFLAGS) -lgd -lpng -lz -lm + + ifeq ($(run-built-tests),yes) + ifeq (yes,$(build-shared)) + diff --git a/srcpkgs/glibc/patches/glibc-upstream-15.patch b/srcpkgs/glibc/patches/glibc-upstream-15.patch new file mode 100644 index 0000000000..51b163b4ce --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-15.patch @@ -0,0 +1,67 @@ +From 0744a268bc73e42b14b83e4cf3d083c6df6344e8 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 25 Apr 2019 14:58:13 +0200 +Subject: [PATCH 15] Revert "memusagestat: use local glibc when linking [BZ + #18465]" + +This reverts commit 42dfc13abf6fbb4c7a0215238eb636b7d374e0e0. + +The position of the -Wl,-rpath-link= options on the linker command +line is not correct, so the new way of linking memusagestat does not +always work. +--- + ChangeLog | 7 ------- + NEWS | 1 - + malloc/Makefile | 4 ++-- + 3 files changed, 2 insertions(+), 10 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 5291a88f85..077d0dae29 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,10 +1,3 @@ +-2019-04-24 Mike Frysinger +- +- [BZ #18465] +- * malloc/Makefile (others): Add memusagestat. +- ($(objpfx)memusagestat): Delete rule. +- (LDLIBS-memusagestat): New variable. +- + 2019-04-09 Carlos O'Donell + Kwok Cheung Yeung + +diff --git a/NEWS b/NEWS +index 07e099b5ec..117646df7b 100644 +--- a/NEWS ++++ b/NEWS +@@ -14,7 +14,6 @@ Major new features: + The following bugs are resolved with this release: + + [16573] malloc: Set and reset all hooks for tracing +- [18465] memusagestat: use local glibc when linking + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) + [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 +diff --git a/malloc/Makefile b/malloc/Makefile +index aadf602dfd..ab2eed09c6 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -131,7 +131,6 @@ ifneq ($(cross-compiling),yes) + # If the gd library is available we build the `memusagestat' program. + ifneq ($(LIBGD),no) + others: $(objpfx)memusage +-others += memusagestat + install-bin = memusagestat + install-bin-script += memusage + generated += memusagestat memusage +@@ -155,7 +154,8 @@ cpp-srcs-left := $(memusagestat-modules) + lib := memusagestat + include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) + +-LDLIBS-memusagestat = $(libgd-LDFLAGS) -lgd -lpng -lz -lm ++$(objpfx)memusagestat: $(memusagestat-modules:%=$(objpfx)%.o) ++ $(LINK.o) -o $@ $^ $(libgd-LDFLAGS) -lgd -lpng -lz -lm + + ifeq ($(run-built-tests),yes) + ifeq (yes,$(build-shared)) + diff --git a/srcpkgs/glibc/patches/glibc-upstream-16.patch b/srcpkgs/glibc/patches/glibc-upstream-16.patch new file mode 100644 index 0000000000..62678a2631 --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-16.patch @@ -0,0 +1,852 @@ +From f62d21a1f0107e6f7182f346293583c9121a877d Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Fri, 12 Apr 2019 17:39:53 -0300 +Subject: [PATCH 16] support: Add support_capture_subprogram + +Its API is similar to support_capture_subprocess, but rather creates a +new process based on the input path and arguments. Under the hoods it +uses posix_spawn to create the new process. + +It also allows the use of other support_capture_* functions to check +for expected results and free the resources. + +Checked on x86_64-linux-gnu. + + * support/Makefile (libsupport-routines): Add support_subprocess, + xposix_spawn, xposix_spawn_file_actions_addclose, and + xposix_spawn_file_actions_adddup2. + (tst-support_capture_subprocess-ARGS): New rule. + * support/capture_subprocess.h (support_capture_subprogram): New + prototype. + * support/support_capture_subprocess.c (support_capture_subprocess): + Refactor to use support_subprocess and support_capture_poll. + (support_capture_subprogram): New function. + * support/tst-support_capture_subprocess.c (write_mode_to_str, + str_to_write_mode, test_common, parse_int, handle_restart, + do_subprocess, do_subprogram, do_multiple_tests): New functions. + (do_test): Add support_capture_subprogram tests. + * support/subprocess.h: New file. + * support/support_subprocess.c: Likewise. + * support/xposix_spawn.c: Likewise. + * support/xposix_spawn_file_actions_addclose.c: Likewise. + * support/xposix_spawn_file_actions_adddup2.c: Likewise. + * support/xspawn.h: Likewise. + +Reviewed-by: Carlos O'Donell +(cherry picked from commit 0e169691290a6d2187a4ff41495fc5678cbfdcdc) +--- + ChangeLog | 22 +++ + support/Makefile | 6 + + support/capture_subprocess.h | 6 + + support/subprocess.h | 49 +++++ + support/support_capture_subprocess.c | 80 ++++---- + support/support_subprocess.c | 152 +++++++++++++++ + support/tst-support_capture_subprocess.c | 183 ++++++++++++++++++- + support/xposix_spawn.c | 32 ++++ + support/xposix_spawn_file_actions_addclose.c | 29 +++ + support/xposix_spawn_file_actions_adddup2.c | 30 +++ + support/xspawn.h | 34 ++++ + 11 files changed, 573 insertions(+), 50 deletions(-) + create mode 100644 support/subprocess.h + create mode 100644 support/support_subprocess.c + create mode 100644 support/xposix_spawn.c + create mode 100644 support/xposix_spawn_file_actions_addclose.c + create mode 100644 support/xposix_spawn_file_actions_adddup2.c + create mode 100644 support/xspawn.h + +diff --git a/ChangeLog b/ChangeLog +index 077d0dae29..2524e25697 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,25 @@ ++2019-04-17 Adhemerval Zanella ++ ++ * support/Makefile (libsupport-routines): Add support_subprocess, ++ xposix_spawn, xposix_spawn_file_actions_addclose, and ++ xposix_spawn_file_actions_adddup2. ++ (tst-support_capture_subprocess-ARGS): New rule. ++ * support/capture_subprocess.h (support_capture_subprogram): New ++ prototype. ++ * support/support_capture_subprocess.c (support_capture_subprocess): ++ Refactor to use support_subprocess and support_capture_poll. ++ (support_capture_subprogram): New function. ++ * support/tst-support_capture_subprocess.c (write_mode_to_str, ++ str_to_write_mode, test_common, parse_int, handle_restart, ++ do_subprocess, do_subprogram, do_multiple_tests): New functions. ++ (do_test): Add support_capture_subprogram tests. ++ * support/subprocess.h: New file. ++ * support/support_subprocess.c: Likewise. ++ * support/xposix_spawn.c: Likewise. ++ * support/xposix_spawn_file_actions_addclose.c: Likewise. ++ * support/xposix_spawn_file_actions_adddup2.c: Likewise. ++ * support/xspawn.h: Likewise. ++ + 2019-04-09 Carlos O'Donell + Kwok Cheung Yeung + +diff --git a/support/Makefile b/support/Makefile +index c15b93647c..8d61de6c57 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -63,6 +63,7 @@ libsupport-routines = \ + support_record_failure \ + support_run_diff \ + support_shared_allocate \ ++ support_subprocess \ + support_test_compare_blob \ + support_test_compare_failure \ + support_test_compare_string \ +@@ -148,6 +149,9 @@ libsupport-routines = \ + xsignal \ + xsigstack \ + xsocket \ ++ xposix_spawn \ ++ xposix_spawn_file_actions_addclose \ ++ xposix_spawn_file_actions_adddup2 \ + xstrdup \ + xstrndup \ + xsymlink \ +@@ -223,4 +227,6 @@ endif + + $(objpfx)tst-support_format_dns_packet: $(common-objpfx)resolv/libresolv.so + ++tst-support_capture_subprocess-ARGS = -- $(host-test-program-cmd) ++ + include ../Rules +diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h +index 2dce42e3a3..2832cfc635 100644 +--- a/support/capture_subprocess.h ++++ b/support/capture_subprocess.h +@@ -35,6 +35,12 @@ struct support_capture_subprocess + struct support_capture_subprocess support_capture_subprocess + (void (*callback) (void *), void *closure); + ++/* Issue FILE with ARGV arguments by using posix_spawn and capture standard ++ output, standard error, and the exit status. The out.buffer and err.buffer ++ are handle as support_capture_subprocess. */ ++struct support_capture_subprocess support_capture_subprogram ++ (const char *file, char *const argv[]); ++ + /* Deallocate the subprocess data captured by + support_capture_subprocess. */ + void support_capture_subprocess_free (struct support_capture_subprocess *); +diff --git a/support/subprocess.h b/support/subprocess.h +new file mode 100644 +index 0000000000..c031878d94 +--- /dev/null ++++ b/support/subprocess.h +@@ -0,0 +1,49 @@ ++/* Create a subprocess. ++ Copyright (C) 2019 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 ++ . */ ++ ++#ifndef SUPPORT_SUBPROCESS_H ++#define SUPPORT_SUBPROCESS_H ++ ++#include ++ ++struct support_subprocess ++{ ++ int stdout_pipe[2]; ++ int stderr_pipe[2]; ++ pid_t pid; ++}; ++ ++/* Invoke CALLBACK (CLOSURE) in a subprocess created with fork and return ++ its PID, a pipe redirected to STDOUT, and a pipe redirected to STDERR. */ ++struct support_subprocess support_subprocess ++ (void (*callback) (void *), void *closure); ++ ++/* Issue FILE with ARGV arguments by using posix_spawn and return is PID, a ++ pipe redirected to STDOUT, and a pipe redirected to STDERR. */ ++struct support_subprocess support_subprogram ++ (const char *file, char *const argv[]); ++ ++/* Wait for the subprocess indicated by PROC::PID. Return the status ++ indicate by waitpid call. */ ++int support_process_wait (struct support_subprocess *proc); ++ ++/* Terminate the subprocess indicated by PROC::PID, first with a SIGTERM and ++ then with a SIGKILL. Return the status as for waitpid call. */ ++int support_process_terminate (struct support_subprocess *proc); ++ ++#endif +diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +index 167514faf1..948ce5a0c6 100644 +--- a/support/support_capture_subprocess.c ++++ b/support/support_capture_subprocess.c +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + + #include +@@ -23,6 +24,7 @@ + #include + #include + #include ++#include + + static void + transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream) +@@ -50,59 +52,53 @@ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream) + } + } + +-struct support_capture_subprocess +-support_capture_subprocess (void (*callback) (void *), void *closure) ++static void ++support_capture_poll (struct support_capture_subprocess *result, ++ struct support_subprocess *proc) + { +- struct support_capture_subprocess result; +- xopen_memstream (&result.out); +- xopen_memstream (&result.err); +- +- int stdout_pipe[2]; +- xpipe (stdout_pipe); +- TEST_VERIFY (stdout_pipe[0] > STDERR_FILENO); +- TEST_VERIFY (stdout_pipe[1] > STDERR_FILENO); +- int stderr_pipe[2]; +- xpipe (stderr_pipe); +- TEST_VERIFY (stderr_pipe[0] > STDERR_FILENO); +- TEST_VERIFY (stderr_pipe[1] > STDERR_FILENO); +- +- TEST_VERIFY (fflush (stdout) == 0); +- TEST_VERIFY (fflush (stderr) == 0); +- +- pid_t pid = xfork (); +- if (pid == 0) +- { +- xclose (stdout_pipe[0]); +- xclose (stderr_pipe[0]); +- xdup2 (stdout_pipe[1], STDOUT_FILENO); +- xdup2 (stderr_pipe[1], STDERR_FILENO); +- xclose (stdout_pipe[1]); +- xclose (stderr_pipe[1]); +- callback (closure); +- _exit (0); +- } +- xclose (stdout_pipe[1]); +- xclose (stderr_pipe[1]); +- + struct pollfd fds[2] = + { +- { .fd = stdout_pipe[0], .events = POLLIN }, +- { .fd = stderr_pipe[0], .events = POLLIN }, ++ { .fd = proc->stdout_pipe[0], .events = POLLIN }, ++ { .fd = proc->stderr_pipe[0], .events = POLLIN }, + }; + + do + { + xpoll (fds, 2, -1); +- transfer ("stdout", &fds[0], &result.out); +- transfer ("stderr", &fds[1], &result.err); ++ transfer ("stdout", &fds[0], &result->out); ++ transfer ("stderr", &fds[1], &result->err); + } + while (fds[0].events != 0 || fds[1].events != 0); +- xclose (stdout_pipe[0]); +- xclose (stderr_pipe[0]); + +- xfclose_memstream (&result.out); +- xfclose_memstream (&result.err); +- xwaitpid (pid, &result.status, 0); ++ xfclose_memstream (&result->out); ++ xfclose_memstream (&result->err); ++ ++ result->status = support_process_wait (proc); ++} ++ ++struct support_capture_subprocess ++support_capture_subprocess (void (*callback) (void *), void *closure) ++{ ++ struct support_capture_subprocess result; ++ xopen_memstream (&result.out); ++ xopen_memstream (&result.err); ++ ++ struct support_subprocess proc = support_subprocess (callback, closure); ++ ++ support_capture_poll (&result, &proc); ++ return result; ++} ++ ++struct support_capture_subprocess ++support_capture_subprogram (const char *file, char *const argv[]) ++{ ++ struct support_capture_subprocess result; ++ xopen_memstream (&result.out); ++ xopen_memstream (&result.err); ++ ++ struct support_subprocess proc = support_subprogram (file, argv); ++ ++ support_capture_poll (&result, &proc); + return result; + } + +diff --git a/support/support_subprocess.c b/support/support_subprocess.c +new file mode 100644 +index 0000000000..0c8cc6af30 +--- /dev/null ++++ b/support/support_subprocess.c +@@ -0,0 +1,152 @@ ++/* Create subprocess. ++ Copyright (C) 2019 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 ++ ++static struct support_subprocess ++support_suprocess_init (void) ++{ ++ struct support_subprocess result; ++ ++ xpipe (result.stdout_pipe); ++ TEST_VERIFY (result.stdout_pipe[0] > STDERR_FILENO); ++ TEST_VERIFY (result.stdout_pipe[1] > STDERR_FILENO); ++ ++ xpipe (result.stderr_pipe); ++ TEST_VERIFY (result.stderr_pipe[0] > STDERR_FILENO); ++ TEST_VERIFY (result.stderr_pipe[1] > STDERR_FILENO); ++ ++ TEST_VERIFY (fflush (stdout) == 0); ++ TEST_VERIFY (fflush (stderr) == 0); ++ ++ return result; ++} ++ ++struct support_subprocess ++support_subprocess (void (*callback) (void *), void *closure) ++{ ++ struct support_subprocess result = support_suprocess_init (); ++ ++ result.pid = xfork (); ++ if (result.pid == 0) ++ { ++ xclose (result.stdout_pipe[0]); ++ xclose (result.stderr_pipe[0]); ++ xdup2 (result.stdout_pipe[1], STDOUT_FILENO); ++ xdup2 (result.stderr_pipe[1], STDERR_FILENO); ++ xclose (result.stdout_pipe[1]); ++ xclose (result.stderr_pipe[1]); ++ callback (closure); ++ _exit (0); ++ } ++ xclose (result.stdout_pipe[1]); ++ xclose (result.stderr_pipe[1]); ++ ++ return result; ++} ++ ++struct support_subprocess ++support_subprogram (const char *file, char *const argv[]) ++{ ++ struct support_subprocess result = support_suprocess_init (); ++ ++ posix_spawn_file_actions_t fa; ++ /* posix_spawn_file_actions_init does not fail. */ ++ posix_spawn_file_actions_init (&fa); ++ ++ xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[0]); ++ xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[0]); ++ xposix_spawn_file_actions_adddup2 (&fa, result.stdout_pipe[1], STDOUT_FILENO); ++ xposix_spawn_file_actions_adddup2 (&fa, result.stderr_pipe[1], STDERR_FILENO); ++ xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[1]); ++ xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[1]); ++ ++ result.pid = xposix_spawn (file, &fa, NULL, argv, NULL); ++ ++ xclose (result.stdout_pipe[1]); ++ xclose (result.stderr_pipe[1]); ++ ++ return result; ++} ++ ++int ++support_process_wait (struct support_subprocess *proc) ++{ ++ xclose (proc->stdout_pipe[0]); ++ xclose (proc->stderr_pipe[0]); ++ ++ int status; ++ xwaitpid (proc->pid, &status, 0); ++ return status; ++} ++ ++ ++static bool ++support_process_kill (int pid, int signo, int *status) ++{ ++ /* Kill the whole process group. */ ++ kill (-pid, signo); ++ /* In case setpgid failed in the child, kill it individually too. */ ++ kill (pid, signo); ++ ++ /* Wait for it to terminate. */ ++ pid_t killed; ++ for (int i = 0; i < 5; ++i) ++ { ++ int status; ++ killed = xwaitpid (pid, &status, WNOHANG|WUNTRACED); ++ if (killed != 0) ++ break; ++ ++ /* Delay, give the system time to process the kill. If the ++ nanosleep() call return prematurely, all the better. We ++ won't restart it since this probably means the child process ++ finally died. */ ++ nanosleep (&((struct timespec) { 0, 100000000 }), NULL); ++ } ++ if (killed != 0 && killed != pid) ++ return false; ++ ++ return true; ++} ++ ++int ++support_process_terminate (struct support_subprocess *proc) ++{ ++ xclose (proc->stdout_pipe[0]); ++ xclose (proc->stderr_pipe[0]); ++ ++ int status; ++ pid_t killed = xwaitpid (proc->pid, &status, WNOHANG|WUNTRACED); ++ if (killed != 0 && killed == proc->pid) ++ return status; ++ ++ /* Subprocess is still running, terminate it. */ ++ if (!support_process_kill (proc->pid, SIGTERM, &status) ) ++ support_process_kill (proc->pid, SIGKILL, &status); ++ ++ return status; ++} +diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c +index d8ba42ea8b..ab363e41ac 100644 +--- a/support/tst-support_capture_subprocess.c ++++ b/support/tst-support_capture_subprocess.c +@@ -23,8 +23,20 @@ + #include + #include + #include ++#include + #include + #include ++#include ++#include ++#include ++#include ++#include ++ ++/* Nonzero if the program gets called via 'exec'. */ ++static int restart; ++ ++/* Hold the four initial argument used to respawn the process. */ ++static char *initial_argv[5]; + + /* Write one byte at *P to FD and advance *P. Do nothing if *P is + '\0'. */ +@@ -42,6 +54,30 @@ transfer (const unsigned char **p, int fd) + enum write_mode { out_first, err_first, interleave, + write_mode_last = interleave }; + ++static const char * ++write_mode_to_str (enum write_mode mode) ++{ ++ switch (mode) ++ { ++ case out_first: return "out_first"; ++ case err_first: return "err_first"; ++ case interleave: return "interleave"; ++ default: return "write_mode_last"; ++ } ++} ++ ++static enum write_mode ++str_to_write_mode (const char *mode) ++{ ++ if (strcmp (mode, "out_first") == 0) ++ return out_first; ++ else if (strcmp (mode, "err_first") == 0) ++ return err_first; ++ else if (strcmp (mode, "interleave") == 0) ++ return interleave; ++ return write_mode_last; ++} ++ + /* Describe what to write in the subprocess. */ + struct test + { +@@ -52,11 +88,9 @@ struct test + int status; + }; + +-/* For use with support_capture_subprocess. */ +-static void +-callback (void *closure) ++_Noreturn static void ++test_common (const struct test *test) + { +- const struct test *test = closure; + bool mode_ok = false; + switch (test->write_mode) + { +@@ -95,6 +129,40 @@ callback (void *closure) + exit (test->status); + } + ++static int ++parse_int (const char *str) ++{ ++ char *endptr; ++ long int ret = strtol (str, &endptr, 10); ++ TEST_COMPARE (errno, 0); ++ TEST_VERIFY (ret >= 0 && ret <= INT_MAX); ++ return ret; ++} ++ ++/* For use with support_capture_subprogram. */ ++_Noreturn static void ++handle_restart (char *out, char *err, const char *write_mode, ++ const char *signal, const char *status) ++{ ++ struct test test = ++ { ++ out, ++ err, ++ str_to_write_mode (write_mode), ++ parse_int (signal), ++ parse_int (status) ++ }; ++ test_common (&test); ++} ++ ++/* For use with support_capture_subprocess. */ ++_Noreturn static void ++callback (void *closure) ++{ ++ const struct test *test = closure; ++ test_common (test); ++} ++ + /* Create a heap-allocated random string of letters. */ + static char * + random_string (size_t length) +@@ -130,12 +198,59 @@ check_stream (const char *what, const struct xmemstream *stream, + } + } + ++static struct support_capture_subprocess ++do_subprocess (struct test *test) ++{ ++ return support_capture_subprocess (callback, test); ++} ++ ++static struct support_capture_subprocess ++do_subprogram (const struct test *test) ++{ ++ /* Three digits per byte plus null terminator. */ ++ char signalstr[3 * sizeof(int) + 1]; ++ snprintf (signalstr, sizeof (signalstr), "%d", test->signal); ++ char statusstr[3 * sizeof(int) + 1]; ++ snprintf (statusstr, sizeof (statusstr), "%d", test->status); ++ ++ int argc = 0; ++ enum { ++ /* 4 elements from initial_argv (path to ld.so, '--library-path', the ++ path', and application name'), 2 for restart argument ('--direct', ++ '--restart'), 5 arguments plus NULL. */ ++ argv_size = 12 ++ }; ++ char *args[argv_size]; ++ ++ for (char **arg = initial_argv; *arg != NULL; arg++) ++ args[argc++] = *arg; ++ ++ args[argc++] = (char*) "--direct"; ++ args[argc++] = (char*) "--restart"; ++ ++ args[argc++] = test->out; ++ args[argc++] = test->err; ++ args[argc++] = (char*) write_mode_to_str (test->write_mode); ++ args[argc++] = signalstr; ++ args[argc++] = statusstr; ++ args[argc] = NULL; ++ TEST_VERIFY (argc < argv_size); ++ ++ return support_capture_subprogram (args[0], args); ++} ++ ++enum test_type ++{ ++ subprocess, ++ subprogram, ++}; ++ + static int +-do_test (void) ++do_multiple_tests (enum test_type type) + { + const int lengths[] = {0, 1, 17, 512, 20000, -1}; + +- /* Test multiple combinations of support_capture_subprocess. ++ /* Test multiple combinations of support_capture_sub{process,program}. + + length_idx_stdout: Index into the lengths array above, + controls how many bytes are written by the subprocess to +@@ -164,8 +279,10 @@ do_test (void) + TEST_VERIFY (strlen (test.out) == lengths[length_idx_stdout]); + TEST_VERIFY (strlen (test.err) == lengths[length_idx_stderr]); + +- struct support_capture_subprocess result +- = support_capture_subprocess (callback, &test); ++ struct support_capture_subprocess result ++ = type == subprocess ? do_subprocess (&test) ++ : do_subprogram (&test); ++ + check_stream ("stdout", &result.out, test.out); + check_stream ("stderr", &result.err, test.err); + +@@ -199,4 +316,54 @@ do_test (void) + return 0; + } + ++static int ++do_test (int argc, char *argv[]) ++{ ++ /* We must have either: ++ ++ - one or four parameters if called initially: ++ + argv[1]: path for ld.so optional ++ + argv[2]: "--library-path" optional ++ + argv[3]: the library path optional ++ + argv[4]: the application name ++ ++ - six parameters left if called through re-execution: ++ + argv[1]: the application name ++ + argv[2]: the stdout to print ++ + argv[3]: the stderr to print ++ + argv[4]: the write mode to use ++ + argv[5]: the signal to issue ++ + argv[6]: the exit status code to use ++ ++ * When built with --enable-hardcoded-path-in-tests or issued without ++ using the loader directly. ++ */ ++ ++ if (argc != (restart ? 6 : 5) && argc != (restart ? 6 : 2)) ++ FAIL_EXIT1 ("wrong number of arguments (%d)", argc); ++ ++ if (restart) ++ { ++ handle_restart (argv[1], /* stdout */ ++ argv[2], /* stderr */ ++ argv[3], /* write_mode */ ++ argv[4], /* signal */ ++ argv[5]); /* status */ ++ } ++ ++ initial_argv[0] = argv[1]; /* path for ld.so */ ++ initial_argv[1] = argv[2]; /* "--library-path" */ ++ initial_argv[2] = argv[3]; /* the library path */ ++ initial_argv[3] = argv[4]; /* the application name */ ++ initial_argv[4] = NULL; ++ ++ do_multiple_tests (subprocess); ++ do_multiple_tests (subprogram); ++ ++ return 0; ++} ++ ++#define CMDLINE_OPTIONS \ ++ { "restart", no_argument, &restart, 1 }, ++#define TEST_FUNCTION_ARGV do_test + #include +diff --git a/support/xposix_spawn.c b/support/xposix_spawn.c +new file mode 100644 +index 0000000000..e846017632 +--- /dev/null ++++ b/support/xposix_spawn.c +@@ -0,0 +1,32 @@ ++/* xposix_spawn implementation. ++ Copyright (C) 2019 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 ++ ++pid_t ++xposix_spawn (const char *file, const posix_spawn_file_actions_t *fa, ++ const posix_spawnattr_t *attr, char *const args[], ++ char *const envp[]) ++{ ++ pid_t pid; ++ int status = posix_spawn (&pid, file, fa, attr, args, envp); ++ if (status != 0) ++ FAIL_EXIT1 ("posix_spawn to %s file failed: %m", file); ++ return pid; ++} +diff --git a/support/xposix_spawn_file_actions_addclose.c b/support/xposix_spawn_file_actions_addclose.c +new file mode 100644 +index 0000000000..eed54a6514 +--- /dev/null ++++ b/support/xposix_spawn_file_actions_addclose.c +@@ -0,0 +1,29 @@ ++/* xposix_spawn_file_actions_addclose implementation. ++ Copyright (C) 2019 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 ++ ++int ++xposix_spawn_file_actions_addclose (posix_spawn_file_actions_t *fa, int fd) ++{ ++ int status = posix_spawn_file_actions_addclose (fa, fd); ++ if (status == -1) ++ FAIL_EXIT1 ("posix_spawn_file_actions_addclose failed: %m\n"); ++ return status; ++} +diff --git a/support/xposix_spawn_file_actions_adddup2.c b/support/xposix_spawn_file_actions_adddup2.c +new file mode 100644 +index 0000000000..a43b6490be +--- /dev/null ++++ b/support/xposix_spawn_file_actions_adddup2.c +@@ -0,0 +1,30 @@ ++/* xposix_spawn_file_actions_adddup2 implementation. ++ Copyright (C) 2019 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 ++ ++int ++xposix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *fa, int fd, ++ int newfd) ++{ ++ int status = posix_spawn_file_actions_adddup2 (fa, fd, newfd); ++ if (status == -1) ++ FAIL_EXIT1 ("posix_spawn_file_actions_adddup2 failed: %m\n"); ++ return status; ++} +diff --git a/support/xspawn.h b/support/xspawn.h +new file mode 100644 +index 0000000000..bbf89132e4 +--- /dev/null ++++ b/support/xspawn.h +@@ -0,0 +1,34 @@ ++/* posix_spawn with support checks. ++ Copyright (C) 2019 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 ++ . */ ++ ++#ifndef SUPPORT_XSPAWN_H ++#define SUPPORT_XSPAWN_H ++ ++#include ++ ++__BEGIN_DECLS ++ ++int xposix_spawn_file_actions_addclose (posix_spawn_file_actions_t *, int); ++int xposix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *, int, int); ++ ++pid_t xposix_spawn (const char *, const posix_spawn_file_actions_t *, ++ const posix_spawnattr_t *, char *const [], char *const []); ++ ++__END_DECLS ++ ++#endif + diff --git a/srcpkgs/glibc/patches/glibc-upstream-17.patch b/srcpkgs/glibc/patches/glibc-upstream-17.patch new file mode 100644 index 0000000000..742cfaac4c --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-17.patch @@ -0,0 +1,616 @@ +From eaea1dfbe95a31c29adc259100569962cddb6f19 Mon Sep 17 00:00:00 2001 +From: Adhemerval Zanella +Date: Fri, 26 Apr 2019 13:58:31 +0200 +Subject: [PATCH 17] elf: Fix pldd (BZ#18035) + +Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map +for executable itself and loader will have both l_name and l_libname->name +holding the same value due: + + elf/dl-object.c + + 95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1; + +Since newname->name points to new->l_libname->name. + +This leads to pldd to an infinite call at: + + elf/pldd-xx.c + +203 again: +204 while (1) +205 { +206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset); + +228 /* Try the l_libname element. */ +229 struct E(libname_list) ln; +230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln)) +231 { +232 name_offset = ln.name; +233 goto again; +234 } + +Since the value at ln.name (l_libname->name) will be the same as previously +read. The straightforward fix is just avoid the check and read the new list +entry. + +I checked also against binaries issues with old loaders with fix for BZ#387, +and pldd could dump the shared objects. + +Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and +powerpc64le-linux-gnu. + + [BZ #18035] + * elf/Makefile (tests-container): Add tst-pldd. + * elf/pldd-xx.c: Use _Static_assert in of pldd_assert. + (E(find_maps)): Avoid use alloca, use default read file operations + instead of explicit LFS names, and fix infinite loop. + * elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers. + (get_process_info): Use _Static_assert instead of assert, use default + directory operations instead of explicit LFS names, and free some + leadek pointers. + * elf/tst-pldd.c: New file. + +(cherry picked from commit 1a4c27355e146b6d8cc6487b998462c7fdd1048f) +--- + ChangeLog | 13 ++++++ + NEWS | 1 + + elf/Makefile | 1 + + elf/pldd-xx.c | 114 +++++++++++++++++------------------------------ + elf/pldd.c | 64 +++++++++++++-------------- + elf/tst-pldd.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++ + 6 files changed, 203 insertions(+), 108 deletions(-) + create mode 100644 elf/tst-pldd.c + +diff --git a/ChangeLog b/ChangeLog +index 2524e25697..5af8e27ab9 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,16 @@ ++2019-04-23 Adhemerval Zanella ++ ++ [BZ #18035] ++ * elf/Makefile (tests-container): Add tst-pldd. ++ * elf/pldd-xx.c: Use _Static_assert in of pldd_assert. ++ (E(find_maps)): Avoid use alloca, use default read file operations ++ instead of explicit LFS names, and fix infinite loop. ++ * elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers. ++ (get_process_info): Use _Static_assert instead of assert, use default ++ directory operations instead of explicit LFS names, and free some ++ leadek pointers. ++ * elf/tst-pldd.c: New file. ++ + 2019-04-17 Adhemerval Zanella + + * support/Makefile (libsupport-routines): Add support_subprocess, +diff --git a/NEWS b/NEWS +index 117646df7b..b39a0ccf91 100644 +--- a/NEWS ++++ b/NEWS +@@ -14,6 +14,7 @@ Major new features: + The following bugs are resolved with this release: + + [16573] malloc: Set and reset all hooks for tracing ++ [18035] Fix pldd hang + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) + [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 +diff --git a/elf/Makefile b/elf/Makefile +index 9cf5cd8dfd..e7457e809f 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -194,6 +194,7 @@ tests-internal += loadtest unload unload2 circleload1 \ + tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ + tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym \ + tst-create_format1 ++tests-container += tst-pldd + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout + tst-dlopen-aout-no-pie = yes +diff --git a/elf/pldd-xx.c b/elf/pldd-xx.c +index 547f840ee1..756f6d7a1c 100644 +--- a/elf/pldd-xx.c ++++ b/elf/pldd-xx.c +@@ -23,10 +23,6 @@ + #define EW_(e, w, t) EW__(e, w, _##t) + #define EW__(e, w, t) e##w##t + +-#define pldd_assert(name, exp) \ +- typedef int __assert_##name[((exp) != 0) - 1] +- +- + struct E(link_map) + { + EW(Addr) l_addr; +@@ -39,12 +35,12 @@ struct E(link_map) + EW(Addr) l_libname; + }; + #if CLASS == __ELF_NATIVE_CLASS +-pldd_assert (l_addr, (offsetof (struct link_map, l_addr) +- == offsetof (struct E(link_map), l_addr))); +-pldd_assert (l_name, (offsetof (struct link_map, l_name) +- == offsetof (struct E(link_map), l_name))); +-pldd_assert (l_next, (offsetof (struct link_map, l_next) +- == offsetof (struct E(link_map), l_next))); ++_Static_assert (offsetof (struct link_map, l_addr) ++ == offsetof (struct E(link_map), l_addr), "l_addr"); ++_Static_assert (offsetof (struct link_map, l_name) ++ == offsetof (struct E(link_map), l_name), "l_name"); ++_Static_assert (offsetof (struct link_map, l_next) ++ == offsetof (struct E(link_map), l_next), "l_next"); + #endif + + +@@ -54,10 +50,10 @@ struct E(libname_list) + EW(Addr) next; + }; + #if CLASS == __ELF_NATIVE_CLASS +-pldd_assert (name, (offsetof (struct libname_list, name) +- == offsetof (struct E(libname_list), name))); +-pldd_assert (next, (offsetof (struct libname_list, next) +- == offsetof (struct E(libname_list), next))); ++_Static_assert (offsetof (struct libname_list, name) ++ == offsetof (struct E(libname_list), name), "name"); ++_Static_assert (offsetof (struct libname_list, next) ++ == offsetof (struct E(libname_list), next), "next"); + #endif + + struct E(r_debug) +@@ -69,16 +65,17 @@ struct E(r_debug) + EW(Addr) r_map; + }; + #if CLASS == __ELF_NATIVE_CLASS +-pldd_assert (r_version, (offsetof (struct r_debug, r_version) +- == offsetof (struct E(r_debug), r_version))); +-pldd_assert (r_map, (offsetof (struct r_debug, r_map) +- == offsetof (struct E(r_debug), r_map))); ++_Static_assert (offsetof (struct r_debug, r_version) ++ == offsetof (struct E(r_debug), r_version), "r_version"); ++_Static_assert (offsetof (struct r_debug, r_map) ++ == offsetof (struct E(r_debug), r_map), "r_map"); + #endif + + + static int + +-E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) ++E(find_maps) (const char *exe, int memfd, pid_t pid, void *auxv, ++ size_t auxv_size) + { + EW(Addr) phdr = 0; + unsigned int phnum = 0; +@@ -104,12 +101,9 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) + if (phdr == 0 || phnum == 0 || phent == 0) + error (EXIT_FAILURE, 0, gettext ("cannot find program header of process")); + +- EW(Phdr) *p = alloca (phnum * phent); +- if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent) +- { +- error (0, 0, gettext ("cannot read program header")); +- return EXIT_FAILURE; +- } ++ EW(Phdr) *p = xmalloc (phnum * phent); ++ if (pread (memfd, p, phnum * phent, phdr) != phnum * phent) ++ error (EXIT_FAILURE, 0, gettext ("cannot read program header")); + + /* Determine the load offset. We need this for interpreting the + other program header entries so we do this in a separate loop. +@@ -129,24 +123,18 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) + if (p[i].p_type == PT_DYNAMIC) + { + EW(Dyn) *dyn = xmalloc (p[i].p_filesz); +- if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr) ++ if (pread (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr) + != p[i].p_filesz) +- { +- error (0, 0, gettext ("cannot read dynamic section")); +- return EXIT_FAILURE; +- } ++ error (EXIT_FAILURE, 0, gettext ("cannot read dynamic section")); + + /* Search for the DT_DEBUG entry. */ + for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j) + if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0) + { + struct E(r_debug) r; +- if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr) ++ if (pread (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr) + != sizeof (r)) +- { +- error (0, 0, gettext ("cannot read r_debug")); +- return EXIT_FAILURE; +- } ++ error (EXIT_FAILURE, 0, gettext ("cannot read r_debug")); + + if (r.r_map != 0) + { +@@ -160,13 +148,10 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) + } + else if (p[i].p_type == PT_INTERP) + { +- interp = alloca (p[i].p_filesz); +- if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr) ++ interp = xmalloc (p[i].p_filesz); ++ if (pread (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr) + != p[i].p_filesz) +- { +- error (0, 0, gettext ("cannot read program interpreter")); +- return EXIT_FAILURE; +- } ++ error (EXIT_FAILURE, 0, gettext ("cannot read program interpreter")); + } + + if (list == 0) +@@ -174,14 +159,16 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) + if (interp == NULL) + { + // XXX check whether the executable itself is the loader +- return EXIT_FAILURE; ++ exit (EXIT_FAILURE); + } + + // XXX perhaps try finding ld.so and _r_debug in it +- +- return EXIT_FAILURE; ++ exit (EXIT_FAILURE); + } + ++ free (p); ++ free (interp); ++ + /* Print the PID and program name first. */ + printf ("%lu:\t%s\n", (unsigned long int) pid, exe); + +@@ -192,47 +179,27 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) + do + { + struct E(link_map) m; +- if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m)) +- { +- error (0, 0, gettext ("cannot read link map")); +- status = EXIT_FAILURE; +- goto out; +- } ++ if (pread (memfd, &m, sizeof (m), list) != sizeof (m)) ++ error (EXIT_FAILURE, 0, gettext ("cannot read link map")); + + EW(Addr) name_offset = m.l_name; +- again: + while (1) + { +- ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset); ++ ssize_t n = pread (memfd, tmpbuf.data, tmpbuf.length, name_offset); + if (n == -1) +- { +- error (0, 0, gettext ("cannot read object name")); +- status = EXIT_FAILURE; +- goto out; +- } ++ error (EXIT_FAILURE, 0, gettext ("cannot read object name")); + + if (memchr (tmpbuf.data, '\0', n) != NULL) + break; + + if (!scratch_buffer_grow (&tmpbuf)) +- { +- error (0, 0, gettext ("cannot allocate buffer for object name")); +- status = EXIT_FAILURE; +- goto out; +- } ++ error (EXIT_FAILURE, 0, ++ gettext ("cannot allocate buffer for object name")); + } + +- if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name +- && m.l_libname != 0) +- { +- /* Try the l_libname element. */ +- struct E(libname_list) ln; +- if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln)) +- { +- name_offset = ln.name; +- goto again; +- } +- } ++ /* The m.l_name and m.l_libname.name for loader linkmap points to same ++ values (since BZ#387 fix). Trying to use l_libname name as the ++ shared object name might lead to an infinite loop (BZ#18035). */ + + /* Skip over the executable. */ + if (((char *)tmpbuf.data)[0] != '\0') +@@ -242,7 +209,6 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size) + } + while (list != 0); + +- out: + scratch_buffer_free (&tmpbuf); + return status; + } +diff --git a/elf/pldd.c b/elf/pldd.c +index f3fac4e487..69629bd5d2 100644 +--- a/elf/pldd.c ++++ b/elf/pldd.c +@@ -17,23 +17,17 @@ + License along with the GNU C Library; if not, see + . */ + +-#include ++#define _FILE_OFFSET_BITS 64 ++ + #include +-#include + #include +-#include +-#include + #include + #include + #include +-#include +-#include + #include + #include +-#include + #include + #include +-#include + #include + #include + +@@ -76,14 +70,9 @@ static struct argp argp = + options, parse_opt, args_doc, doc, NULL, more_help, NULL + }; + +-// File descriptor of /proc/*/mem file. +-static int memfd; +- +-/* Name of the executable */ +-static char *exe; + + /* Local functions. */ +-static int get_process_info (int dfd, long int pid); ++static int get_process_info (const char *exe, int dfd, long int pid); + static void wait_for_ptrace_stop (long int pid); + + +@@ -102,8 +91,10 @@ main (int argc, char *argv[]) + return 1; + } + +- assert (sizeof (pid_t) == sizeof (int) +- || sizeof (pid_t) == sizeof (long int)); ++ _Static_assert (sizeof (pid_t) == sizeof (int) ++ || sizeof (pid_t) == sizeof (long int), ++ "sizeof (pid_t) != sizeof (int) or sizeof (long int)"); ++ + char *endp; + errno = 0; + long int pid = strtol (argv[remaining], &endp, 10); +@@ -119,25 +110,24 @@ main (int argc, char *argv[]) + if (dfd == -1) + error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf); + +- struct scratch_buffer exebuf; +- scratch_buffer_init (&exebuf); ++ /* Name of the executable */ ++ struct scratch_buffer exe; ++ scratch_buffer_init (&exe); + ssize_t nexe; + while ((nexe = readlinkat (dfd, "exe", +- exebuf.data, exebuf.length)) == exebuf.length) ++ exe.data, exe.length)) == exe.length) + { +- if (!scratch_buffer_grow (&exebuf)) ++ if (!scratch_buffer_grow (&exe)) + { + nexe = -1; + break; + } + } + if (nexe == -1) +- exe = (char *) ""; ++ /* Default stack allocation is at least 1024. */ ++ snprintf (exe.data, exe.length, ""); + else +- { +- exe = exebuf.data; +- exe[nexe] = '\0'; +- } ++ ((char*)exe.data)[nexe] = '\0'; + + /* Stop all threads since otherwise the list of loaded modules might + change while we are reading it. */ +@@ -155,8 +145,8 @@ main (int argc, char *argv[]) + error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"), + buf); + +- struct dirent64 *d; +- while ((d = readdir64 (dir)) != NULL) ++ struct dirent *d; ++ while ((d = readdir (dir)) != NULL) + { + if (! isdigit (d->d_name[0])) + continue; +@@ -182,7 +172,7 @@ main (int argc, char *argv[]) + + wait_for_ptrace_stop (tid); + +- struct thread_list *newp = alloca (sizeof (*newp)); ++ struct thread_list *newp = xmalloc (sizeof (*newp)); + newp->tid = tid; + newp->next = thread_list; + thread_list = newp; +@@ -190,17 +180,22 @@ main (int argc, char *argv[]) + + closedir (dir); + +- int status = get_process_info (dfd, pid); ++ if (thread_list == NULL) ++ error (EXIT_FAILURE, 0, gettext ("no valid %s/task entries"), buf); ++ ++ int status = get_process_info (exe.data, dfd, pid); + +- assert (thread_list != NULL); + do + { + ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL); ++ struct thread_list *prev = thread_list; + thread_list = thread_list->next; ++ free (prev); + } + while (thread_list != NULL); + + close (dfd); ++ scratch_buffer_free (&exe); + + return status; + } +@@ -281,9 +276,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ + + + static int +-get_process_info (int dfd, long int pid) ++get_process_info (const char *exe, int dfd, long int pid) + { +- memfd = openat (dfd, "mem", O_RDONLY); ++ /* File descriptor of /proc//mem file. */ ++ int memfd = openat (dfd, "mem", O_RDONLY); + if (memfd == -1) + goto no_info; + +@@ -333,9 +329,9 @@ get_process_info (int dfd, long int pid) + + int retval; + if (e_ident[EI_CLASS] == ELFCLASS32) +- retval = find_maps32 (pid, auxv, auxv_size); ++ retval = find_maps32 (exe, memfd, pid, auxv, auxv_size); + else +- retval = find_maps64 (pid, auxv, auxv_size); ++ retval = find_maps64 (exe, memfd, pid, auxv, auxv_size); + + free (auxv); + close (memfd); +diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c +new file mode 100644 +index 0000000000..ed19cedd05 +--- /dev/null ++++ b/elf/tst-pldd.c +@@ -0,0 +1,118 @@ ++/* Basic tests for pldd program. ++ Copyright (C) 2019 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 ++#include ++#include ++ ++static void ++target_process (void *arg) ++{ ++ pause (); ++} ++ ++/* The test runs in a container because pldd does not support tracing ++ a binary started by the loader iself (as with testrun.sh). */ ++ ++static int ++do_test (void) ++{ ++ /* Create a copy of current test to check with pldd. */ ++ struct support_subprocess target = support_subprocess (target_process, NULL); ++ ++ /* Run 'pldd' on test subprocess. */ ++ struct support_capture_subprocess pldd; ++ { ++ /* Three digits per byte plus null terminator. */ ++ char pid[3 * sizeof (uint32_t) + 1]; ++ snprintf (pid, array_length (pid), "%d", target.pid); ++ ++ const char prog[] = "/usr/bin/pldd"; ++ ++ pldd = support_capture_subprogram (prog, ++ (char *const []) { (char *) prog, pid, NULL }); ++ ++ support_capture_subprocess_check (&pldd, "pldd", 0, sc_allow_stdout); ++ } ++ ++ /* Check 'pldd' output. The test is expected to be linked against only ++ loader and libc. */ ++ { ++ pid_t pid; ++ char buffer[512]; ++#define STRINPUT(size) "%" # size "s" ++ ++ FILE *out = fmemopen (pldd.out.buffer, pldd.out.length, "r"); ++ TEST_VERIFY (out != NULL); ++ ++ /* First line is in the form of : */ ++ TEST_COMPARE (fscanf (out, "%u: " STRINPUT (512), &pid, buffer), 2); ++ ++ TEST_COMPARE (pid, target.pid); ++ TEST_COMPARE (strcmp (basename (buffer), "tst-pldd"), 0); ++ ++ /* It expects only one loader and libc loaded by the program. */ ++ bool interpreter_found = false, libc_found = false; ++ while (fgets (buffer, array_length (buffer), out) != NULL) ++ { ++ /* Ignore vDSO. */ ++ if (buffer[0] != '/') ++ continue; ++ ++ /* Remove newline so baseline (buffer) can compare against the ++ LD_SO and LIBC_SO macros unmodified. */ ++ if (buffer[strlen(buffer)-1] == '\n') ++ buffer[strlen(buffer)-1] = '\0'; ++ ++ if (strcmp (basename (buffer), LD_SO) == 0) ++ { ++ TEST_COMPARE (interpreter_found, false); ++ interpreter_found = true; ++ continue; ++ } ++ ++ if (strcmp (basename (buffer), LIBC_SO) == 0) ++ { ++ TEST_COMPARE (libc_found, false); ++ libc_found = true; ++ continue; ++ } ++ } ++ TEST_COMPARE (interpreter_found, true); ++ TEST_COMPARE (libc_found, true); ++ ++ fclose (out); ++ } ++ ++ support_capture_subprocess_free (&pldd); ++ support_process_terminate (&target); ++ ++ return 0; ++} ++ ++#include + diff --git a/srcpkgs/glibc/patches/glibc-upstream-18.patch b/srcpkgs/glibc/patches/glibc-upstream-18.patch new file mode 100644 index 0000000000..e6059c51cb --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-18.patch @@ -0,0 +1,37 @@ +From 52b7cd6e9a701bb203023d56e84551943dc6a4c0 Mon Sep 17 00:00:00 2001 +From: Adam Maris +Date: Thu, 14 Mar 2019 16:51:16 -0400 +Subject: [PATCH 18] malloc: Check for large bin list corruption when + inserting unsorted chunk + +Fixes bug 24216. This patch adds security checks for bk and bk_nextsize pointers +of chunks in large bin when inserting chunk from unsorted bin. It was possible +to write the pointer to victim (newly inserted chunk) to arbitrary memory +locations if bk or bk_nextsize pointers of the next large bin chunk +got corrupted. + +(cherry picked from commit 5b06f538c5aee0389ed034f60d90a8884d6d54de) +--- + malloc/malloc.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index feaf7ee0bf..ce771375b6 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3876,10 +3876,14 @@ _int_malloc (mstate av, size_t bytes) + { + victim->fd_nextsize = fwd; + victim->bk_nextsize = fwd->bk_nextsize; ++ if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd)) ++ malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)"); + fwd->bk_nextsize = victim; + victim->bk_nextsize->fd_nextsize = victim; + } + bck = fwd->bk; ++ if (bck->fd != fwd) ++ malloc_printerr ("malloc(): largebin double linked list corrupted (bk)"); + } + } + else + diff --git a/srcpkgs/glibc/patches/glibc-upstream-19.patch b/srcpkgs/glibc/patches/glibc-upstream-19.patch new file mode 100644 index 0000000000..18ce8aa33b --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-19.patch @@ -0,0 +1,144 @@ +From c6177be4b92d5d7df50a785652d1912db511423e Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Wed, 15 May 2019 17:09:05 +0200 +Subject: [PATCH 19] Fix crash in _IO_wfile_sync (bug 20568) + +When computing the length of the converted part of the stdio buffer, use +the number of consumed wide characters, not the (negative) distance to the +end of the wide buffer. + +(cherry picked from commit 32ff397533715988c19cbf3675dcbd727ec13e18) +--- + ChangeLog | 10 ++++++++++ + NEWS | 1 + + libio/Makefile | 3 ++- + libio/tst-wfile-sync.c | 39 ++++++++++++++++++++++++++++++++++++++ + libio/tst-wfile-sync.input | 1 + + libio/wfileops.c | 5 +++-- + 6 files changed, 56 insertions(+), 3 deletions(-) + create mode 100644 libio/tst-wfile-sync.c + create mode 100644 libio/tst-wfile-sync.input + +diff --git a/ChangeLog b/ChangeLog +index 5af8e27ab9..d3fcf73e47 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,13 @@ ++2019-05-15 Andreas Schwab ++ ++ [BZ #20568] ++ * libio/wfileops.c (_IO_wfile_sync): Correct last argument to ++ __codecvt_do_length. ++ * libio/Makefile (tests): Add tst-wfile-sync. ++ ($(objpfx)tst-wfile-sync.out): Depend on $(gen-locales). ++ * libio/tst-wfile-sync.c: New file. ++ * libio/tst-wfile-sync.input: New file. ++ + 2019-04-23 Adhemerval Zanella + + [BZ #18035] +diff --git a/NEWS b/NEWS +index b39a0ccf91..c10ab5e851 100644 +--- a/NEWS ++++ b/NEWS +@@ -15,6 +15,7 @@ The following bugs are resolved with this release: + + [16573] malloc: Set and reset all hooks for tracing + [18035] Fix pldd hang ++ [20568] Fix crash in _IO_wfile_sync + [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) + [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 +diff --git a/libio/Makefile b/libio/Makefile +index 5bee83e55c..ee3a34cc3b 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -65,7 +65,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ + tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \ + tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \ + tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \ +- tst-sprintf-ub tst-sprintf-chk-ub ++ tst-sprintf-ub tst-sprintf-chk-ub tst-wfile-sync + + tests-internal = tst-vtables tst-vtables-interposed tst-readline + +@@ -212,6 +212,7 @@ $(objpfx)tst-ungetwc1.out: $(gen-locales) + $(objpfx)tst-ungetwc2.out: $(gen-locales) + $(objpfx)tst-widetext.out: $(gen-locales) + $(objpfx)tst_wprintf2.out: $(gen-locales) ++$(objpfx)tst-wfile-sync.out: $(gen-locales) + endif + + $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen +diff --git a/libio/tst-wfile-sync.c b/libio/tst-wfile-sync.c +new file mode 100644 +index 0000000000..618682064d +--- /dev/null ++++ b/libio/tst-wfile-sync.c +@@ -0,0 +1,39 @@ ++/* Test that _IO_wfile_sync does not crash (bug 20568). ++ Copyright (C) 2019 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 ++ ++static int ++do_test (void) ++{ ++ TEST_VERIFY_EXIT (setlocale (LC_ALL, "de_DE.UTF-8") != NULL); ++ /* Fill the stdio buffer and advance the read pointer. */ ++ TEST_VERIFY_EXIT (fgetwc (stdin) != WEOF); ++ /* This calls _IO_wfile_sync, it should not crash. */ ++ TEST_VERIFY_EXIT (setvbuf (stdin, NULL, _IONBF, 0) == 0); ++ /* Verify that the external file offset has been synchronized. */ ++ TEST_COMPARE (xlseek (0, 0, SEEK_CUR), 1); ++ ++ return 0; ++} ++ ++#include +diff --git a/libio/tst-wfile-sync.input b/libio/tst-wfile-sync.input +new file mode 100644 +index 0000000000..12d0958f7a +--- /dev/null ++++ b/libio/tst-wfile-sync.input +@@ -0,0 +1 @@ ++This is a test of _IO_wfile_sync. +diff --git a/libio/wfileops.c b/libio/wfileops.c +index 78f20486e5..bab2ba4892 100644 +--- a/libio/wfileops.c ++++ b/libio/wfileops.c +@@ -508,11 +508,12 @@ _IO_wfile_sync (FILE *fp) + generate the wide characters up to the current reading + position. */ + int nread; +- ++ size_t wnread = (fp->_wide_data->_IO_read_ptr ++ - fp->_wide_data->_IO_read_base); + fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state; + nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state, + fp->_IO_read_base, +- fp->_IO_read_end, delta); ++ fp->_IO_read_end, wnread); + fp->_IO_read_ptr = fp->_IO_read_base + nread; + delta = -(fp->_IO_read_end - fp->_IO_read_base - nread); + } + diff --git a/srcpkgs/glibc/patches/glibc-upstream-20.patch b/srcpkgs/glibc/patches/glibc-upstream-20.patch new file mode 100644 index 0000000000..cd2baca69d --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-20.patch @@ -0,0 +1,93 @@ +From e3f828b8bd6e21922da8be8dee35edef09382d8d Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Wed, 15 May 2019 17:14:01 +0200 +Subject: [PATCH 20] dlfcn: Guard __dlerror_main_freeres with + __libc_once_get (once) [BZ#24476] + +dlerror.c (__dlerror_main_freeres) will try to free resources which only +have been initialized when init () has been called. That function is +called when resources are needed using __libc_once (once, init) where +once is a __libc_once_define (static, once) in the dlerror.c file. +Trying to free those resources if init () hasn't been called will +produce errors under valgrind memcheck. So guard the freeing of those +resources using __libc_once_get (once) and make sure we have a valid +key. Also add a similar guard to __dlerror (). + + * dlfcn/dlerror.c (__dlerror_main_freeres): Guard using + __libc_once_get (once) and static_bug == NULL. + (__dlerror): Check we have a valid key, set result to static_buf + otherwise. + +Reviewed-by: Carlos O'Donell +(cherry picked from commit 11b451c8868d8a2b0edc5dfd44fc58d9ee538be0) +--- + ChangeLog | 8 ++++++++ + dlfcn/dlerror.c | 29 +++++++++++++++++++++-------- + 2 files changed, 29 insertions(+), 8 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index d3fcf73e47..de8c5c214d 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,11 @@ ++2019-05-15 Mark Wielaard ++ ++ [BZ#24476] ++ * dlfcn/dlerror.c (__dlerror_main_freeres): Guard using ++ __libc_once_get (once) and static_buf == NULL. ++ (__dlerror): Check we have a valid key, set result to static_buf ++ otherwise. ++ + 2019-05-15 Andreas Schwab + + [BZ #20568] +diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c +index 27376582d0..ca42c126c1 100644 +--- a/dlfcn/dlerror.c ++++ b/dlfcn/dlerror.c +@@ -72,9 +72,16 @@ __dlerror (void) + __libc_once (once, init); + + /* Get error string. */ +- result = (struct dl_action_result *) __libc_getspecific (key); +- if (result == NULL) +- result = &last_result; ++ if (static_buf != NULL) ++ result = static_buf; ++ else ++ { ++ /* init () has been run and we don't use the static buffer. ++ So we have a valid key. */ ++ result = (struct dl_action_result *) __libc_getspecific (key); ++ if (result == NULL) ++ result = &last_result; ++ } + + /* Test whether we already returned the string. */ + if (result->returned != 0) +@@ -230,13 +237,19 @@ free_key_mem (void *mem) + void + __dlerror_main_freeres (void) + { +- void *mem; + /* Free the global memory if used. */ + check_free (&last_result); +- /* Free the TSD memory if used. */ +- mem = __libc_getspecific (key); +- if (mem != NULL) +- free_key_mem (mem); ++ ++ if (__libc_once_get (once) && static_buf == NULL) ++ { ++ /* init () has been run and we don't use the static buffer. ++ So we have a valid key. */ ++ void *mem; ++ /* Free the TSD memory if used. */ ++ mem = __libc_getspecific (key); ++ if (mem != NULL) ++ free_key_mem (mem); ++ } + } + + struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon)); + diff --git a/srcpkgs/glibc/patches/glibc-upstream-21.patch b/srcpkgs/glibc/patches/glibc-upstream-21.patch new file mode 100644 index 0000000000..c46d58d7fc --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-21.patch @@ -0,0 +1,22 @@ +From 980cb43f15c4320afc6272e7a508f1415413b945 Mon Sep 17 00:00:00 2001 +From: Mark Wielaard +Date: Thu, 16 May 2019 15:25:40 +0200 +Subject: [PATCH 21] Update NEWS for BZ#24476 Guard __dlerror_main_freeres. + +--- + NEWS | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/NEWS b/NEWS +index c10ab5e851..17dcaa7b74 100644 +--- a/NEWS ++++ b/NEWS +@@ -20,6 +20,7 @@ The following bugs are resolved with this release: + [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm + [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 + [24211] Use-after-free in Systemtap probe in pthread_join ++ [24476] dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once) + + Security related changes: + + diff --git a/srcpkgs/glibc/patches/glibc-upstream-22.patch b/srcpkgs/glibc/patches/glibc-upstream-22.patch new file mode 100644 index 0000000000..c8effc2b3a --- /dev/null +++ b/srcpkgs/glibc/patches/glibc-upstream-22.patch @@ -0,0 +1,79 @@ +From 95d66fecaabbc92ab53027e808f0fc1929c9f21a Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Fri, 10 May 2019 16:38:21 +0100 +Subject: [PATCH 22] Fix tcache count maximum (BZ #24531) + +The tcache counts[] array is a char, which has a very small range and thus +may overflow. When setting tcache_count tunable, there is no overflow check. +However the tunable must not be larger than the maximum value of the tcache +counts[] array, otherwise it can overflow when filling the tcache. + + [BZ #24531] + * malloc/malloc.c (MAX_TCACHE_COUNT): New define. + (do_set_tcache_count): Only update if count is small enough. + * manual/tunables.texi (glibc.malloc.tcache_count): Document max value. + +(cherry picked from commit 5ad533e8e65092be962e414e0417112c65d154fb) +--- + ChangeLog | 7 +++++++ + malloc/malloc.c | 9 +++++++-- + manual/tunables.texi | 4 ++-- + 3 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index de8c5c214d..f4586d34a3 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2019-05-22 Wilco Dijkstra ++ ++ [BZ #24531] ++ * malloc/malloc.c (MAX_TCACHE_COUNT): New define. ++ (do_set_tcache_count): Only update if count is small enough. ++ * manual/tunables.texi (glibc.malloc.tcache_count): Document max value. ++ + 2019-05-15 Mark Wielaard + + [BZ#24476] +diff --git a/malloc/malloc.c b/malloc/malloc.c +index ce771375b6..0abd653be2 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2919,6 +2919,8 @@ typedef struct tcache_perthread_struct + tcache_entry *entries[TCACHE_MAX_BINS]; + } tcache_perthread_struct; + ++#define MAX_TCACHE_COUNT 127 /* Maximum value of counts[] entries. */ ++ + static __thread bool tcache_shutting_down = false; + static __thread tcache_perthread_struct *tcache = NULL; + +@@ -5124,8 +5126,11 @@ static inline int + __always_inline + do_set_tcache_count (size_t value) + { +- LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count); +- mp_.tcache_count = value; ++ if (value <= MAX_TCACHE_COUNT) ++ { ++ LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count); ++ mp_.tcache_count = value; ++ } + return 1; + } + +diff --git a/manual/tunables.texi b/manual/tunables.texi +index af820820e0..8edfea4edd 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -189,8 +189,8 @@ per-thread cache. The default (and maximum) value is 1032 bytes on + + @deftp Tunable glibc.malloc.tcache_count + The maximum number of chunks of each size to cache. The default is 7. +-There is no upper limit, other than available system memory. If set +-to zero, the per-thread cache is effectively disabled. ++The upper limit is 127. If set to zero, the per-thread cache is effectively ++disabled. + + The approximate maximum overhead of the per-thread cache is thus equal + to the number of bins times the chunk count in each bin times the size diff --git a/srcpkgs/glibc/template b/srcpkgs/glibc/template index 37592c7fc0..29358d3ef7 100644 --- a/srcpkgs/glibc/template +++ b/srcpkgs/glibc/template @@ -1,7 +1,7 @@ # Template file for 'glibc' pkgname=glibc version=2.29 -revision=3 +revision=4 bootstrap=yes short_desc="GNU C library" maintainer="Juan RP "