Fix ld.so PLT relocations by relocating lazily before is_me check

Previously, relocate() returned early for self.is_me before
calling lazy_relocate(), assuming ld.so had no lazy relocations
to process. However, ld.so is itself PIE and relies on lazy PLT
relocations internally, so its own PLT entries need the load
base added to them (see the PLT/Resolve::Lazy branch in
lazy_relocate()).

Skipping this step left ld.so's PLT stubs pointing at
unrelocated addresses. Once ld.so was loaded at a non-zero
base, any internal call through the PLT jumped to an invalid
address, triggering a synchronous exception during early boot
(observed as crashes in nvmed/redoxfs before switchroot
completed on AArch64).

Signed-off-by: Luiz Fernando Becher de Araujo <luiz.becher.araujo@gmail.com>
(cherry picked from commit 72c0078d5de565743c99a07fcff6557361d91694)
This commit is contained in:
Luiz Fernando Becher de Araujo
2026-07-19 17:04:35 -03:00
committed by vasilito
parent fb2e6d247a
commit df5226fb25
+5 -3
View File
@@ -1245,13 +1245,15 @@ impl DSO {
self.static_relocate(&global_scope, reloc)?;
}
// ld.so is itself PIE and uses lazy PLT relocations internally,
// so its own PLT entries must be adjusted by the load base before
// use.
self.lazy_relocate(&global_scope, resolve)?;
if self.is_me {
// TODO: assert that ld.so have no lazy relocations.
return Ok(());
}
self.lazy_relocate(&global_scope, resolve)?;
let ph = ph.unwrap();
// Protect pages