At $WORK, we've been looking at some memory safety mitigations and we wanted to stop having to build a load of different allocator configurations and switch between them at load time using the ifunc mechanism. Unfortunately, this didn't work because other globals in the library were not resolved during ifunc resolution. I'm not 100% sure that this is intended to work, but there's a comment in the rtld code indicating that we resolve non-ifunc PLT relocations first to make it work, so I presume that this is a bug.
I've put together a quick-and-dirty fix that I'm now using. It's probably not the correct fix, but I wanted to upload it for review to see if:
- This is something that we'd like to work.
- This is approximately the correct fix.
Rtld was deferring handling of ifuncs until after it had processed all of the other relocations in a global. This is allows an ifunc resolver to depend on other global symbols in the same library.
Unfortunately, ifunc resolvers can be invoked in one library as a result of processing relocations in another. If library A depends on library B, and library B provides a symbol X that is resolved via an ifunc, then the ifunc resolver for X in B was being called after all of the relocations in A had been processed, but before the relocations in B had been processed. Any references to symbols in B by the ifunc resolver would then cause a crash.