[Bug libc/34503] New: powerpc: INIT_ARCH() dereferences unrelocated _rtld_global_ro, IFUNC resolvers crash under BIND_NOW
micpf at westermo dot com via Glibc-bugs <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.bugs |
|---|---|
| Message-ID | <[email protected]/bugzilla/> |
https://sourceware.org/bugzilla/show_bug.cgi?id=34503
Bug ID: 34503
Summary: powerpc: INIT_ARCH() dereferences unrelocated
_rtld_global_ro, IFUNC resolvers crash under BIND_NOW
Product: glibc
Version: unspecified
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: libc
Assignee: unassigned at sourceware dot org
Reporter: micpf at westermo dot com
CC: drepper.fsp at gmail dot com
Target Milestone: ---
Description
===========
Since commit 21841f0d562f ("PowerPC: Influence cpu/arch hwcap features
via GLIBC_TUNABLES", first released in 2.41), the INIT_ARCH() macro in
sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h
(also used by powerpc64 through a one-line include in
sysdeps/powerpc/powerpc64/multiarch/init-arch.h) reads hwcap and
hwcap2 via a direct
const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features);
unsigned long int hwcap = features->hwcap;
unsigned long int hwcap2 = features->hwcap2;
instead of the previous __GLRO() wrapper. __GLRO() performs a volatile
NULL check on _rtld_global_ro, which matters because IFUNC resolvers can
run before _rtld_global_ro has been relocated for the current library.
The bug is still present on master (init-arch.h @ HEAD):
#define INIT_ARCH() \
const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features); \
unsigned long int hwcap = features->hwcap; \
unsigned long int __attribute__((unused)) hwcap2 = features->hwcap2; \
bool __attribute__((unused)) use_cached_memopt = \
__GLRO(dl_powerpc_cpu_features.use_cached_memopt); \
...
Note that use_cached_memopt in the same macro still uses __GLRO(); only
hwcap and hwcap2 were converted to a direct dereference.
Impact
------
When a shared library A references an IFUNC symbol from library B and
A does not carry a DT_NEEDED on B, the dynamic linker can process A's
relocations before B's GOT is set up. Under BIND_NOW (full RELRO) the
IFUNC resolver in B is invoked immediately as part of relocation. With
the current INIT_ARCH(), that resolver dereferences a still-NULL
_rtld_global_ro at offset dl_powerpc_cpu_features.hwcap and segfaults.
Before 21841f0d562f the same access went through __GLRO(), whose
NULL check returned 0 in that early window; the IFUNC then simply
picked the default variant and initialisation completed correctly.
Concrete failure
----------------
Observed on PowerPC64 BE (NXP T1042 / e5500 core) with glibc 2.41 built
by OpenWrt with CONFIG_PKG_RELRO_FULL=y (BIND_NOW):
rsyslogd (BIND_NOW binary)
-> librsyslog
-> libfastjson (no DT_NEEDED on libm)
-> modf() IFUNC resolver in libm
-> INIT_ARCH()
-> load of &_rtld_global_ro->dl_powerpc_cpu_features.hwcap
with _rtld_global_ro == NULL -> SIGSEGV
rsyslogd crashes immediately on startup. Downgrading glibc to 2.38,
or applying the fix below, makes the crash disappear.
A previous attempt to work around this at the application level by
adding a "libm" dependency to libfastjson was rejected because libm is
not a separately installable package on OpenWrt; the root cause is in
glibc.
Proposed fix
------------
Restore the __GLRO()-based access for hwcap and hwcap2, matching both
the pre-2.41 behaviour and how use_cached_memopt is already read in
the same macro. This is a no-op once _rtld_global_ro is fully
initialised and simply reinstates the early-startup NULL guard:
--- a/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h
+++ b/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h
@@ -36,9 +36,9 @@
/* Get the hardware information post the tunables set, the macro checks
it and fills the previous ones. */
#define INIT_ARCH() \
- const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features);
\
- unsigned long int hwcap = features->hwcap; \
- unsigned long int __attribute__((unused)) hwcap2 = features->hwcap2; \
+ unsigned long int hwcap = __GLRO(dl_powerpc_cpu_features.hwcap); \
--
You are receiving this mail because:
You are on the CC list for the bug.