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 <andypython@protonmail.com>
This commit is contained in:
+15
-1
@@ -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::<c_char>() * 8;
|
||||
@@ -334,6 +335,9 @@ pub struct DSO {
|
||||
pub scope: spin::Once<Scope>,
|
||||
/// 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() };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,6 +715,7 @@ impl Linker {
|
||||
}
|
||||
|
||||
for obj in new_objects.into_iter() {
|
||||
obj.mark_ready();
|
||||
self.run_init(&obj);
|
||||
self.register_object(obj);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user