2a30b8f4b2
Upstream commit: dcaf51b41e259387602774829c45222d0507f90a - elf: Change ldconfig auxcache magic number (bug 32231) - Make tst-strtod-underflow type-generic - Add crt1-2.0.o for glibc 2.0 compatibility tests - Add tests of more strtod special cases - Add more tests of strtod end pointer - Make tst-strtod2 and tst-strtod5 type-generic - powerpc64le: Build new strtod tests with long double ABI flags (bug 32145) - Do not set errno for overflowing NaN payload in strtod/nan (bug 32045) - Improve NaN payload testing - Make __strtod_internal tests type-generic - Fix strtod subnormal rounding (bug 30220) - More thoroughly test underflow / errno in tst-strtod-round - Test errno setting on strtod overflow in tst-strtod-round - Add tests of fread - stdio-common: Add new test for fdopen - libio: Attempt wide backup free only for non-legacy code - debug: Fix read error handling in pcprofiledump - elf: Fix tst-dlopen-tlsreinit1.out test dependency - elf: Avoid re-initializing already allocated TLS in dlopen (bug 31717) - elf: Clarify and invert second argument of _dl_allocate_tls_init - elf: Support recursive use of dynamic TLS in interposed malloc - nptl: Use <support/check.h> facilities in tst-setuid3 - posix: Use <support/check.h> facilities in tst-truncate and tst-truncate64 - ungetc: Fix backup buffer leak on program exit [BZ #27821] - ungetc: Fix uninitialized read when putting into unused streams [BZ #27821] - Make tst-ungetc use libsupport - stdio-common: Add test for vfscanf with matches longer than INT_MAX [BZ #27650] - support: Add FAIL test failure helper - string: strerror, strsignal cannot use buffer after dlmopen (bug 32026) - Define __libc_initial for the static libc - x86: Fix bug in strchrnul-evex512 [BZ #32078] - Adjust check-local-headers test for libaudit 4.0 - x32/cet: Support shadow stack during startup for Linux 6.10 - x86-64: Remove sysdeps/x86_64/x32/dl-machine.h - support: Add options list terminator to the test driver - manual/stdio: Further clarify putc, putwc, getc, and getwc - Fix name space violation in fortify wrappers (bug 32052) - resolv: Fix tst-resolv-short-response for older GCC (bug 32042) - Add mremap tests - mremap: Update manual entry - linux: Update the mremap C implementation [BZ #31968] - Enhanced test coverage for strncmp, wcsncmp - Enhance test coverage for strnlen, wcsnlen Resolves: RHEL-57776 Resolves: RHEL-57777 Resolves: RHEL-61392
140 lines
4.6 KiB
Diff
140 lines
4.6 KiB
Diff
commit e73fd06b7f12d6ddaae4f91f9c5088a621a82ce4
|
|
Author: Florian Weimer <fweimer@redhat.com>
|
|
Date: Mon Aug 19 15:48:03 2024 +0200
|
|
|
|
string: strerror, strsignal cannot use buffer after dlmopen (bug 32026)
|
|
|
|
Secondary namespaces have a different malloc. Allocating the
|
|
buffer in one namespace and freeing it another results in
|
|
heap corruption. Fix this by using a static string (potentially
|
|
translated) in secondary namespaces. It would also be possible
|
|
to use the malloc from the initial namespace to manage the
|
|
buffer, but these functions would still not be safe to use in
|
|
auditors etc. because a call to strerror could still free a
|
|
buffer while it is used by the application. Another approach
|
|
could use proper initial-exec TLS, duplicated in secondary
|
|
namespaces, but that would need a callback interface for freeing
|
|
libc resources in namespaces on thread exit, which does not exist
|
|
today.
|
|
|
|
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
(cherry picked from commit 25a5eb4010df94b412c67db9e346029de316d06b)
|
|
|
|
diff --git a/string/strerror_l.c b/string/strerror_l.c
|
|
index 15cce261e6b406a7..70456e5bb45e5b52 100644
|
|
--- a/string/strerror_l.c
|
|
+++ b/string/strerror_l.c
|
|
@@ -20,7 +20,7 @@
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <tls-internal.h>
|
|
-
|
|
+#include <libc-internal.h>
|
|
|
|
static const char *
|
|
translate (const char *str, locale_t loc)
|
|
@@ -31,6 +31,12 @@ translate (const char *str, locale_t loc)
|
|
return res;
|
|
}
|
|
|
|
+static char *
|
|
+unknown_error (locale_t loc)
|
|
+{
|
|
+ return (char *) translate ("Unknown error", loc);
|
|
+}
|
|
+
|
|
|
|
/* Return a string describing the errno code in ERRNUM. */
|
|
char *
|
|
@@ -40,18 +46,25 @@ __strerror_l (int errnum, locale_t loc)
|
|
char *err = (char *) __get_errlist (errnum);
|
|
if (__glibc_unlikely (err == NULL))
|
|
{
|
|
- struct tls_internal_t *tls_internal = __glibc_tls_internal ();
|
|
- free (tls_internal->strerror_l_buf);
|
|
- if (__asprintf (&tls_internal->strerror_l_buf, "%s%d",
|
|
- translate ("Unknown error ", loc), errnum) > 0)
|
|
- err = tls_internal->strerror_l_buf;
|
|
- else
|
|
+ if (__libc_initial)
|
|
{
|
|
- /* The memory was freed above. */
|
|
- tls_internal->strerror_l_buf = NULL;
|
|
- /* Provide a fallback translation. */
|
|
- err = (char *) translate ("Unknown error", loc);
|
|
+ struct tls_internal_t *tls_internal = __glibc_tls_internal ();
|
|
+ free (tls_internal->strerror_l_buf);
|
|
+ if (__asprintf (&tls_internal->strerror_l_buf, "%s%d",
|
|
+ translate ("Unknown error ", loc), errnum) > 0)
|
|
+ err = tls_internal->strerror_l_buf;
|
|
+ else
|
|
+ {
|
|
+ /* The memory was freed above. */
|
|
+ tls_internal->strerror_l_buf = NULL;
|
|
+ /* Provide a fallback translation. */
|
|
+ err = unknown_error (loc);
|
|
+ }
|
|
}
|
|
+ else
|
|
+ /* Secondary namespaces use a different malloc, so cannot
|
|
+ participate in the buffer management. */
|
|
+ err = unknown_error (loc);
|
|
}
|
|
else
|
|
err = (char *) translate (err, loc);
|
|
diff --git a/string/strsignal.c b/string/strsignal.c
|
|
index 31146015647c1d4a..d9b03654683a6805 100644
|
|
--- a/string/strsignal.c
|
|
+++ b/string/strsignal.c
|
|
@@ -21,6 +21,7 @@
|
|
#include <string.h>
|
|
#include <libintl.h>
|
|
#include <tls-internal.h>
|
|
+#include <libc-internal.h>
|
|
|
|
/* Return a string describing the meaning of the signal number SIGNUM. */
|
|
char *
|
|
@@ -30,21 +31,28 @@ strsignal (int signum)
|
|
if (desc != NULL)
|
|
return _(desc);
|
|
|
|
- struct tls_internal_t *tls_internal = __glibc_tls_internal ();
|
|
- free (tls_internal->strsignal_buf);
|
|
+ if (__libc_initial)
|
|
+ {
|
|
+ struct tls_internal_t *tls_internal = __glibc_tls_internal ();
|
|
+ free (tls_internal->strsignal_buf);
|
|
|
|
- int r;
|
|
+ int r;
|
|
#ifdef SIGRTMIN
|
|
- if (signum >= SIGRTMIN && signum <= SIGRTMAX)
|
|
- r = __asprintf (&tls_internal->strsignal_buf, _("Real-time signal %d"),
|
|
- signum - SIGRTMIN);
|
|
- else
|
|
+ if (signum >= SIGRTMIN && signum <= SIGRTMAX)
|
|
+ r = __asprintf (&tls_internal->strsignal_buf, _("Real-time signal %d"),
|
|
+ signum - SIGRTMIN);
|
|
+ else
|
|
#endif
|
|
- r = __asprintf (&tls_internal->strsignal_buf, _("Unknown signal %d"),
|
|
- signum);
|
|
-
|
|
- if (r == -1)
|
|
- tls_internal->strsignal_buf = NULL;
|
|
-
|
|
- return tls_internal->strsignal_buf;
|
|
+ r = __asprintf (&tls_internal->strsignal_buf, _("Unknown signal %d"),
|
|
+ signum);
|
|
+
|
|
+ if (r >= 0)
|
|
+ return tls_internal->strsignal_buf;
|
|
+ else
|
|
+ tls_internal->strsignal_buf = NULL;
|
|
+ }
|
|
+ /* Fall through on asprintf error, and for !__libc_initial:
|
|
+ secondary namespaces use a different malloc and cannot
|
|
+ participate in the buffer management. */
|
|
+ return _("Unknown signal");
|
|
}
|