Commit 5fcf9206 authored by Ahmed Abd El Mawgood's avatar Ahmed Abd El Mawgood
Browse files

Fix bugs in handling non pie elfs

The problem here was that we alway added the base address, and we
assumed that all addresses we access are relative but this is not the
case in case of non pie binaries. The issue is that all addresses were
base+offset. so if we added the base again it will ofcourse generate
wrong address.
parent db6a5894
......@@ -10,6 +10,7 @@ use core::{
};
use goblin::{
elf::{
header::ET_DYN,
program_header,
r#dyn::{Dyn, DT_DEBUG},
reloc, sym, Elf,
......@@ -199,7 +200,11 @@ impl Linker {
let value: usize;
if let Some(name_res) = elf.dynstrtab.get(sym.st_name) {
name = name_res?.to_string();
value = mmap.as_ptr() as usize + sym.st_value as usize;
value = if is_pie_enabled(elf) {
mmap.as_ptr() as usize + sym.st_value as usize
} else {
sym.st_value as usize
};
} else {
continue;
}
......@@ -256,7 +261,7 @@ impl Linker {
None => return Ok(()),
};
let elf = Elf::parse(self.objects.get(&root.name).unwrap())?;
for section in elf.section_headers {
for section in &elf.section_headers {
let name = match elf.shdr_strtab.get(section.sh_name) {
Some(x) => match x {
Ok(y) => y,
......@@ -265,7 +270,11 @@ impl Linker {
_ => continue,
};
if name == ".init_array" {
let addr = mmap.as_ptr() as usize + section.vm_range().start;
let addr = if is_pie_enabled(&elf) {
mmap.as_ptr() as usize + section.vm_range().start
} else {
section.vm_range().start
};
for i in (0..section.sh_size).step_by(8) {
unsafe { call_inits_finis(addr + i as usize) };
}
......@@ -287,7 +296,7 @@ impl Linker {
None => return Ok(()),
};
let elf = Elf::parse(self.objects.get(&root.name).unwrap())?;
for section in elf.section_headers {
for section in &elf.section_headers {
let name = match elf.shdr_strtab.get(section.sh_name) {
Some(x) => match x {
Ok(y) => y,
......@@ -296,7 +305,11 @@ impl Linker {
_ => continue,
};
if name == ".fini_array" {
let addr = mmap.as_ptr() as usize + section.vm_range().start;
let addr = if is_pie_enabled(&elf) {
mmap.as_ptr() as usize + section.vm_range().start
} else {
section.vm_range().start
};
for i in (0..section.sh_size).step_by(8) {
unsafe { call_inits_finis(addr + i as usize) };
}
......@@ -396,7 +409,12 @@ impl Linker {
};
if same_elf {
let addr = dso.as_ref().unwrap().base_addr;
let size = bounds.1;
let size = if is_pie_enabled(&elf) {
bounds.1
} else {
bounds.1 - bounds.0
};
// Fill the gaps i the binary
let mut ranges = Vec::new();
for ph in elf.program_headers.iter() {
......@@ -405,7 +423,11 @@ impl Linker {
let vaddr = ph.p_vaddr as usize - voff;
let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE)
* PAGE_SIZE;
ranges.push((vaddr, vsize));
if is_pie_enabled(&elf) {
ranges.push((vaddr, vsize));
} else {
ranges.push((vaddr - addr, vsize));
}
}
}
ranges.sort();
......@@ -651,7 +673,11 @@ impl Linker {
(0, 0)
};
let ptr = unsafe { mmap.as_mut_ptr().add(rel.r_offset as usize) };
let ptr = if is_pie_enabled(&elf) {
unsafe { mmap.as_mut_ptr().add(rel.r_offset as usize) }
} else {
rel.r_offset as *mut u8
};
let set_u64 = |value| {
// println!(" set_u64 {:#x}", value);
......@@ -717,7 +743,12 @@ impl Linker {
};
let bytes: [u8; size_of::<Dyn>() / 2] =
unsafe { transmute((&_r_debug) as *const RTLDDebug as usize) };
let start = dyn_start_addr + i * size_of::<Dyn>() + size_of::<Dyn>() / 2;
let start = if is_pie_enabled(elf) {
dyn_start_addr + i * size_of::<Dyn>() + size_of::<Dyn>() / 2
} else {
dyn_start_addr + i * size_of::<Dyn>() + size_of::<Dyn>() / 2
- mmap.as_mut_ptr() as usize
};
mmap[start..start + size_of::<Dyn>() / 2].clone_from_slice(&bytes);
}
}
......@@ -748,7 +779,11 @@ impl Linker {
None => continue,
};
let res = unsafe {
let ptr = mmap.as_mut_ptr().add(vaddr);
let ptr = if is_pie_enabled(elf) {
mmap.as_mut_ptr().add(vaddr)
} else {
vaddr as *const u8
};
if self.verbose {
println!(" prot {:#x}, {:#x}: {:p}, {:#x}", vaddr, vsize, ptr, prot);
}
......@@ -780,7 +815,11 @@ impl Linker {
println!("entry {}", elf_name);
}
if Some(*elf_name) == primary_opt {
entry_opt = Some(mmap.as_mut_ptr() as usize + elf.header.e_entry as usize);
if is_pie_enabled(&elf) {
entry_opt = Some(mmap.as_mut_ptr() as usize + elf.header.e_entry as usize);
} else {
entry_opt = Some(elf.header.e_entry as usize);
}
}
// Relocate
......@@ -815,7 +854,6 @@ impl Linker {
}
}
}
// Protect pages
for ph in elf.program_headers.iter() {
if let program_header::PT_LOAD = ph.p_type {
......@@ -838,7 +876,11 @@ impl Linker {
}
let res = unsafe {
let ptr = mmap.as_mut_ptr().add(vaddr);
let ptr = if is_pie_enabled(&elf) {
mmap.as_mut_ptr().add(vaddr)
} else {
vaddr as *const u8
};
if self.verbose {
println!(" prot {:#x}, {:#x}: {:p}, {:#x}", vaddr, vsize, ptr, prot);
}
......@@ -852,12 +894,20 @@ impl Linker {
}
}
unsafe { _r_debug.state = RTLDState::RT_CONSISTENT };
_dl_debug_state();
//_dl_debug_state();
Ok(entry_opt)
}
}
unsafe extern "C" fn call_inits_finis(addr: usize) {
unsafe fn call_inits_finis(addr: usize) {
let func = transmute::<usize, *const Option<extern "C" fn()>>(addr);
(*func).map(|x| x());
}
fn is_pie_enabled(elf: &Elf) -> bool {
if elf.header.e_type == ET_DYN {
true
} else {
false
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment