From 64d37931908486a53de389b3d4cbc95c4617d134 Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Wed, 10 Dec 2025 13:18:21 +1100 Subject: [PATCH] fix(ld_so): page faulting when library not found The error handling was already in place. The reason it was page faulting is that, on failure, the function exits as soon as it encounters an `Err` variant. When that happens, the DSO object for which the dependency was being loaded is dropped. Dropping it calls `munmap` to unload the executable and also runs the functions in `.fini`. However, `run_fini` should only be called if the `DSO` is being unloaded after it has been successfully loaded (i.e. all dependencies were satisfied and all init functions had run). Closes #1599 Signed-off-by: Anhad Singh --- src/ld_so/dso.rs | 16 +++++++++++++++- src/ld_so/linker.rs | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ld_so/dso.rs b/src/ld_so/dso.rs index e29d327033..64b0ef7298 100644 --- a/src/ld_so/dso.rs +++ b/src/ld_so/dso.rs @@ -30,6 +30,7 @@ use core::{ mem::{offset_of, size_of}, ptr::{self, NonNull}, slice, + sync::atomic::{AtomicBool, Ordering}, }; pub const CHAR_BITS: usize = size_of::() * 8; @@ -334,6 +335,9 @@ pub struct DSO { pub scope: spin::Once, /// Position Independent Executable. pub pie: bool, + + /// Whether this DSO *and* its dependencies have been successfully loaded. + is_ready: AtomicBool, } impl DSO { @@ -380,11 +384,17 @@ impl DSO { pie: is_pie_enabled(&elf), dynamic, scope: spin::Once::new(), + is_ready: AtomicBool::new(false), }; Ok((dso, tcb_master, elf.elf_program_headers().to_vec())) } + #[inline] + pub fn mark_ready(&self) { + self.is_ready.store(true, Ordering::SeqCst); + } + #[inline] pub fn scope(&self) -> &Scope { self.scope.get().expect("scope not initialized") @@ -1120,7 +1130,11 @@ impl DSO { impl Drop for DSO { fn drop(&mut self) { - self.run_fini(); + if self.is_ready.load(Ordering::SeqCst) { + // `run_fini` should not be called if we are being prematurely + // dropped (e.g. failed to satisfy dependencies). + self.run_fini(); + } unsafe { Sys::munmap(self.mmap.as_ptr() as *mut c_void, self.mmap.len()).unwrap() }; } } diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 073966ef1d..52b79dc5f1 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -715,6 +715,7 @@ impl Linker { } for obj in new_objects.into_iter() { + obj.mark_ready(); self.run_init(&obj); self.register_object(obj); }