Skip to content

Commit

Permalink
elf: fix arithmetic overflow with invalid program headers
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandrod committed May 18, 2022
1 parent 3896fea commit 4f47c11
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,23 @@ impl<E: UserDefinedError, I: InstructionMeter> Executable<E, I> {
config.static_syscalls = false;
}

if config.enable_elf_vaddr {
// This is needed to avoid an overflow error in header.vm_range() as
// used by relocate(). See https://github.com/m4b/goblin/pull/306.
//
// Once we bump to a version of goblin that includes the fix, this
// check can be removed, and relocate() will still return
// ValueOutOfBounds on malformed program headers.
if elf
.program_headers
.iter()
.find(|header| header.p_vaddr.checked_add(header.p_memsz).is_none())
.is_some()
{
return Err(ElfError::ValueOutOfBounds);
}
}

let num_text_sections =
elf.section_headers
.iter()
Expand Down Expand Up @@ -2054,6 +2071,15 @@ mod test {
.expect("validation failed");
}

#[test]
#[should_panic(expected = "validation failed: ValueOutOfBounds")]
fn test_program_headers_overflow() {
let elf_bytes = std::fs::read("tests/elfs/program_headers_overflow.so")
.expect("failed to read elf file");
ElfExecutable::load(Config::default(), &elf_bytes, syscall_registry())
.expect("validation failed");
}

#[cfg(all(not(windows), target_arch = "x86_64"))]
#[test]
fn test_size() {
Expand Down
4 changes: 4 additions & 0 deletions tests/elfs/elfs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,7 @@ rm syscall_static_unknown.o
"$LLVM_DIR"clang -Werror -target sbf -mcpu=sbfv2 -O2 -fno-builtin -fPIC -o syscall_static.o -c syscall_static.c
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --script elf.ld -o syscall_static.so syscall_static.o
rm syscall_static.o

"$LLVM_DIR"clang -Werror -target sbf -mcpu=sbfv2 -O2 -fno-builtin -fPIC -o program_headers_overflow.o -c rodata.c
"$LLVM_DIR"ld.lld -z notext -shared --Bdynamic -entry entrypoint --script program_headers_overflow.ld --noinhibit-exec -o program_headers_overflow.so program_headers_overflow.o
rm program_headers_overflow.o
24 changes: 24 additions & 0 deletions tests/elfs/program_headers_overflow.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
PHDRS
{
text PT_LOAD ;
rodata PT_LOAD ;
data PT_LOAD ;
dynamic PT_DYNAMIC ;
}

SECTIONS
{
. = SIZEOF_HEADERS;
.text 0xFFFFFFFFFFFFFFF0 : { *(.text*) } :text
.rodata : { *(.rodata*) } :rodata
.data.rel.ro : { *(.data.rel.ro*) } :rodata
.dynamic : { *(.dynamic) } :dynamic
.dynsym : { *(.dynsym) } :data
.dynstr : { *(.dynstr) } :data
.rel.dyn : { *(.rel.dyn) } :data
/DISCARD/ : {
*(.eh_frame*)
*(.gnu.hash*)
*(.hash*)
}
}
Binary file added tests/elfs/program_headers_overflow.so
Binary file not shown.

0 comments on commit 4f47c11

Please sign in to comment.