-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Summary
Scanning the codebase for integer overflow vulnerabilities on usize values derived from untrusted guest input (ELF binary headers and OP-TEE guest syscall parameters) found multiple locations where direct arithmetic operators (+, -) are used instead of wrapping methods. In Rust debug builds these will panic; in release builds with overflow checks enabled they are also undefined behaviour triggers.
Findings
1. litebox_shim_linux/src/loader/elf.rs and litebox_shim_optee/src/loader/elf.rs — CRITICAL
Both shims have identical vulnerable code in MapMemory::reserve(). len and align come from ELF program header fields (p_memsz/p_vaddr range and p_align) which are fully controlled by a malicious guest binary.
Lines 77, 91-92, 95, 99-100 (both files):
// Line 77 — overflow: if align is a large power-of-two (e.g., 2^63), the sum overflows
let mapping_len = len + (align.max(PAGE_SIZE) - PAGE_SIZE);
// Line 90 — next_multiple_of can overflow/panic in debug if mapping_ptr is near usize::MAX
let ptr = mapping_ptr.next_multiple_of(align);
// Line 91 — overflow: ptr and len are ELF-derived
let end = ptr + len;
// Line 92 — overflow: mapping_ptr from mmap, mapping_len ELF-derived
let mapping_end = mapping_ptr + mapping_len;
// Line 95 — underflow: if next_multiple_of overflowed, ptr < mapping_ptr
.sys_munmap(MutPtr::from_usize(mapping_ptr), ptr - mapping_ptr)?;
// Line 99 — underflow: if end/mapping_end overflowed
.sys_munmap(MutPtr::from_usize(end), mapping_end - end)?;Attack vector: A crafted ELF with p_align = 2^63 (largest valid power-of-two usize) causes mapping_len to overflow.
Fix:
let mapping_len = len.wrapping_add(align.max(PAGE_SIZE).wrapping_sub(PAGE_SIZE));
// ...
let end = ptr.wrapping_add(len);
let mapping_end = mapping_ptr.wrapping_add(mapping_len);
// ...
.sys_munmap(MutPtr::from_usize(mapping_ptr), ptr.wrapping_sub(mapping_ptr))?;
// ...
.sys_munmap(MutPtr::from_usize(end), mapping_end.wrapping_sub(end))?;2. litebox_common_linux/src/loader.rs — HIGH
The ELF segment loading loop computes virtual addresses by adding a base_addr (the mmap result from reserve()) to ELF-provided p_vaddr, p_filesz, and p_memsz. While line 410 checks p_vaddr.checked_add(p_memsz), it does not protect against base_addr + p_vaddr overflowing.
Lines 420–423, 443:
// Line 420 — overflow: base_addr (mmap result) + p_vaddr (ELF-controlled)
let adjusted_vaddr = base_addr + p_vaddr;
// Line 422 — overflow: adjusted_vaddr + p_filesz (ELF-controlled)
let file_end = page_align_up(adjusted_vaddr + p_filesz);
// Line 423 — overflow: adjusted_vaddr + p_memsz (ELF-controlled)
let load_end = page_align_up(adjusted_vaddr + p_memsz);
// ...
// Line 443 — overflow: same as line 422
let unaligned_file_end = adjusted_vaddr + p_filesz;page_align_up uses next_multiple_of(PAGE_SIZE) which will also panic in debug on an already-overflowed input.
Fix:
let adjusted_vaddr = base_addr.wrapping_add(p_vaddr);
let file_end = page_align_up(adjusted_vaddr.wrapping_add(p_filesz));
let load_end = page_align_up(adjusted_vaddr.wrapping_add(p_memsz));
// ...
let unaligned_file_end = adjusted_vaddr.wrapping_add(p_filesz);Note: overflow guards (checked arithmetic + early return) should be added before these calculations rather than just wrapping, to avoid mapping garbage addresses in release builds.
3. litebox_shim_optee/src/syscalls/ldelf.rs — MEDIUM
Both sys_map_zi and sys_map_bin validate total_size using checked_add (lines 52–56) and check orig_addr + total_size (line 57). However, after sys_mmap (lines 68–70 / 196–205) the variable addr is rebound to the kernel-chosen mmap result address, which may differ from the guest-provided address when the guest passes addr = 0. Subsequent arithmetic on this new addr is not protected.
sys_map_zi (lines 71, 81–82):
// Line 71 — overflow: addr is now the mmap result, pad_begin is guest-controlled
let padded_start = addr.as_usize() + pad_begin;
// Line 81 — overflow: padded_start + num_bytes, both indirectly guest-controlled
let pad_end_start = (padded_start + num_bytes).next_multiple_of(PAGE_SIZE);
// Line 82 — overflow: addr (mmap result) + total_size (guest-derived)
let region_end = addr.as_usize() + total_size;
// Line 86 — safe: guarded by `if pad_end_start < region_end`sys_map_bin (lines 206, 234, 252–253):
// Line 206 — same as line 71
let padded_start = addr.as_usize() + pad_begin;
// Line 234 — overflow: num_bytes + padded_start could overflow before the subtraction
(num_bytes + padded_start - align_down(padded_start, PAGE_SIZE)).next_multiple_of(PAGE_SIZE)
// Line 252 — same as line 81
let pad_end_start = (padded_start + num_bytes).next_multiple_of(PAGE_SIZE);
// Line 253 — same as line 82
let region_end = addr.as_usize() + total_size;
// Line 257 — safe: guarded by `if pad_end_start < region_end`Fix for both functions:
let padded_start = addr.as_usize().wrapping_add(pad_begin);
let pad_end_start = padded_start.wrapping_add(num_bytes).next_multiple_of(PAGE_SIZE);
let region_end = addr.as_usize().wrapping_add(total_size);
// Line 234 fix:
num_bytes.wrapping_add(padded_start).wrapping_sub(align_down(padded_start, PAGE_SIZE))
.next_multiple_of(PAGE_SIZE)Impact
All vulnerabilities can cause debug-build panics when loading a maliciously crafted guest ELF binary or when a malicious OP-TEE TA issues crafted ldelf syscalls. In release builds without overflow checks, the corrupted addresses could lead to incorrect memory mappings.
Recommended Fix Priority
- CRITICAL —
elf.rs:77(both shims): exploitable with a well-craftedp_alignpower-of-two value - HIGH —
loader.rs:420–423,443: exploitable with craftedp_vaddr/p_filesz/p_memszvalues combined with a non-zerobase_addr - MEDIUM —
ldelf.rsarithmetic: exploitable only when the kernel mmap returns a high address (unusual but possible)
Generated by Integer Overflow Scanner