True. Other links I posted pertain to userland - including one inside rtld. Every time I return to this thread, it's because I've learned a little bit more.
I'm about to go off into the weeds so please bear with me.
The loader loads the executable and any referenced shared objects into memory. The loader also loads the rtld shared object into each process. You get this library for free - whether you want it or not. At some point, rtld is given control, well before main() is executed.
Look at src/libexec/rtld-elf/amd64/reloc.c
Inside is a call to
rtld_resolve_ifunc to resolve an IFUNC symbol. This ultimately calls the IFUNC "resolver" function - located inside the executable or shared object that was freshly loaded but does not yet have resolved symbols. Note that '
call_ifunc_resolver' is a macro. That function returns a pointer to the implementation to use for the given symbol. rtld stores that pointer some place and that place is writable at the time of the call(s) to the resolver(s).
If I understand the xz-utils CVE well enough, the issue lay during this window of opportunity. It's bad enough to load a library with malicious code but it is even worse if that code is allowed to subvert other libraries - before those libs even have a chance to be initialized.
How to prevent this - or at least make it harder for some IFUNC resolver to make educated guesses as to where rtld stores symbol information? Address randomization and call the resolver(s) from a different stack - might do the trick.
I am assuming that - at some point before calling main(), rtld write-protects this information. I'm trying to locate where that takes place in the code.
If it doesn't, then none of this matters.