glibc: update patches

Signed-off-by: Jürgen Buchmüller <pullmoll@t-online.de>
This commit is contained in:
Jürgen Buchmüller 2019-05-28 12:50:16 +02:00
parent f9590020d9
commit 12d24f1120
No known key found for this signature in database
GPG key ID: DE55AD8DBEBB4EE8
13 changed files with 2253 additions and 1 deletions

View file

@ -50,3 +50,4 @@ index 1fd2fee44b..9bfbb2bb9b 100644
"+:6:1873//01//01:1912//07//29:<U660E><U6CBB>:%EC%Ey<U5E74>";/
"+:1:0001//01//01:1872//12//31:<U897F><U66A6>:%EC%Ey<U5E74>";/
"+:1:-0001//12//31:-*:<U7D00><U5143><U524D>:%EC%Ey<U5E74>"

View file

@ -0,0 +1,66 @@
From 0941350c20a52447e53c5169354408e3db591f73 Mon Sep 17 00:00:00 2001
From: TAMUKI Shoichi <tamuki@linet.gr.jp>
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 <tamuki@linet.gr.jp>
+
+ [BZ #22964]
+ * localedata/locales/ja_JP (LC_TIME): Add entry for the new Japanese
+ era.
+
2019-03-02 TAMUKI Shoichi <tamuki@linet.gr.jp>
[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 "<U5348><U524D>";"<U5348><U5F8C>"
t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
-era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
+era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
+ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
+ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
"+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
"+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
"+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/

View file

@ -0,0 +1,206 @@
From dcd2b97dd1d695445d45beb4daa815cfe06691dd Mon Sep 17 00:00:00 2001
From: Carlos O'Donell <carlos@redhat.com>
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 <kcy@codesourcery.com>
Reviewed-by: DJ Delorie <dj@redhat.com>
(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 <carlos@redhat.com>
+ Kwok Cheung Yeung <kcy@codesourcery.com>
+
+ [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 <tamuki@linet.gr.jp>
[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);

View file

@ -0,0 +1,69 @@
From 42dfc13abf6fbb4c7a0215238eb636b7d374e0e0 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
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 <vapier@gentoo.org>
+
+ [BZ #18465]
+ * malloc/Makefile (others): Add memusagestat.
+ ($(objpfx)memusagestat): Delete rule.
+ (LDLIBS-memusagestat): New variable.
+
2019-04-09 Carlos O'Donell <carlos@redhat.com>
Kwok Cheung Yeung <kcy@codesourcery.com>
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))

View file

@ -0,0 +1,67 @@
From 0744a268bc73e42b14b83e4cf3d083c6df6344e8 Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
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 <vapier@gentoo.org>
-
- [BZ #18465]
- * malloc/Makefile (others): Add memusagestat.
- ($(objpfx)memusagestat): Delete rule.
- (LDLIBS-memusagestat): New variable.
-
2019-04-09 Carlos O'Donell <carlos@redhat.com>
Kwok Cheung Yeung <kcy@codesourcery.com>
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))

View file

@ -0,0 +1,852 @@
From f62d21a1f0107e6f7182f346293583c9121a877d Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
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 <carlos@redhat.com>
(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 <adhemerval.zanella@linaro.org>
+
+ * 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 <carlos@redhat.com>
Kwok Cheung Yeung <kcy@codesourcery.com>
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
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef SUPPORT_SUBPROCESS_H
+#define SUPPORT_SUBPROCESS_H
+
+#include <sys/types.h>
+
+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
<http://www.gnu.org/licenses/>. */
+#include <support/subprocess.h>
#include <support/capture_subprocess.h>
#include <errno.h>
@@ -23,6 +24,7 @@
#include <support/check.h>
#include <support/xunistd.h>
#include <support/xsocket.h>
+#include <support/xspawn.h>
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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/wait.h>
+#include <stdbool.h>
+#include <support/xspawn.h>
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <support/subprocess.h>
+
+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 <support/capture_subprocess.h>
#include <support/check.h>
#include <support/support.h>
+#include <support/temp_file.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <paths.h>
+#include <getopt.h>
+#include <limits.h>
+#include <errno.h>
+#include <array_length.h>
+
+/* 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 <support/test-driver.c>
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
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/xspawn.h>
+#include <support/check.h>
+
+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
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/xspawn.h>
+#include <support/check.h>
+
+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
+ <http://www.gnu.org/licenses/>. */
+
+#include <support/xspawn.h>
+#include <support/check.h>
+
+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
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef SUPPORT_XSPAWN_H
+#define SUPPORT_XSPAWN_H
+
+#include <spawn.h>
+
+__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

View file

@ -0,0 +1,616 @@
From eaea1dfbe95a31c29adc259100569962cddb6f19 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
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 <adhemerval.zanella@linaro.org>
+
+ [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 <adhemerval.zanella@linaro.org>
* 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
<http://www.gnu.org/licenses/>. */
-#include <alloca.h>
+#define _FILE_OFFSET_BITS 64
+
#include <argp.h>
-#include <assert.h>
#include <dirent.h>
-#include <elf.h>
-#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <libintl.h>
-#include <link.h>
-#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
#include <sys/ptrace.h>
-#include <sys/stat.h>
#include <sys/wait.h>
#include <scratch_buffer.h>
@@ -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 *) "<program name undetermined>";
+ /* Default stack allocation is at least 1024. */
+ snprintf (exe.data, exe.length, "<program name undetermined>");
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/<pid>/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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <libgen.h>
+#include <stdbool.h>
+
+#include <array_length.h>
+#include <gnu/lib-names.h>
+
+#include <support/subprocess.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+
+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 <pid>: <full path of executable> */
+ 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 <support/test-driver.c>

View file

@ -0,0 +1,37 @@
From 52b7cd6e9a701bb203023d56e84551943dc6a4c0 Mon Sep 17 00:00:00 2001
From: Adam Maris <amaris@redhat.com>
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

View file

@ -0,0 +1,144 @@
From c6177be4b92d5d7df50a785652d1912db511423e Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@suse.de>
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 <schwab@suse.de>
+
+ [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 <adhemerval.zanella@linaro.org>
[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
+ <http://www.gnu.org/licenses/>. */
+
+#include <locale.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <support/check.h>
+#include <support/xunistd.h>
+
+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 <support/test-driver.c>
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);
}

View file

@ -0,0 +1,93 @@
From e3f828b8bd6e21922da8be8dee35edef09382d8d Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
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 <carlos@redhat.com>
(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 <mark@klomp.org>
+
+ [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 <schwab@suse.de>
[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));

View file

@ -0,0 +1,22 @@
From 980cb43f15c4320afc6272e7a508f1415413b945 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mark@klomp.org>
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:

View file

@ -0,0 +1,79 @@
From 95d66fecaabbc92ab53027e808f0fc1929c9f21a Mon Sep 17 00:00:00 2001
From: Wilco Dijkstra <wdijkstr@arm.com>
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 <wdijkstr@arm.com>
+
+ [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 <mark@klomp.org>
[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

View file

@ -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 <xtraeme@voidlinux.org>"