Remove section header insertion from syscall rewriter#636
Remove section header insertion from syscall rewriter#636
Conversation
litebox_common_linux/src/loader.rs
Outdated
| // Search backwards from the end of the file at page boundaries for the magic. | ||
| // We limit the search to a reasonable number of pages to avoid scanning the | ||
| // entire file. | ||
| let min_offset = file_size.saturating_sub((MAX_SEARCH_PAGES * PAGE_SIZE) as u64); |
There was a problem hiding this comment.
Why not put those entries at the end of the file (end of trampoline code instead of head of it) so that we only need to read the last 32/20 bytes for metadata?
There was a problem hiding this comment.
Great suggestion! Working on it.
5080bd9 to
9416585
Compare
|
I haven't reviewed the code, but quick note: we use a constant like |
|
I thought about if we should bump the version from LITEBOX0 to LITEBOX1 and decided to just keep LITEBOX0. Let me know if anyone thinks we should increase it to LITEBOX1. I'm okay with either way. |
This addresses reviewer feedback to simplify the trampoline parsing. Instead of searching for the magic at page boundaries, loaders can now just read the last 32/20 bytes of the file to get the metadata. File layout: [ELF][padding][trampoline code][header] - Header: magic(8) + entry(8/4) + vaddr(8/4) + code_size(8/4) - Trampoline code: entry_placeholder(8/4) + actual_code... Changes: - syscall rewriter: write code first, then header at end - Rust loader: read header from end of file, not page boundaries - rtld_audit.c: read header from end for shared libs, read entry from offset 0 for main binary (already mapped by loader) - Fix jmp displacement to point to offset 0 (entry) instead of 8
With the header moved to the end of the file, the syscall entry point is now at offset 0 (not offset 8). The 32-bit CALL [EAX + offset] displacement needs to target offset 0 instead of offset 8. The formula changes from -(len - 2) and -(len - 11) to -(len - 3) in all three locations where 32-bit indirect calls are generated.
The header at the end of the file now contains: - magic (8 bytes): "LITEBOX0" - file_offset (8/4 bytes): file offset where trampoline code starts - vaddr (8/4 bytes): virtual address of trampoline - code_size (8/4 bytes): size of trampoline code This is cleaner because: 1. Entry point stays at offset 0 of the code (no duplicate in header) 2. File offset is directly stored (no calculation needed from code_size) 3. Header is pure metadata about the trampoline location
c131be8 to
40b270e
Compare
|
🤖 SemverChecks 🤖 Click for details |
| // 64-bit: [0..8] magic, [8..16] file_offset, [16..24] vaddr, [24..32] code_size | ||
| let file_offset: u64 = u64::from_le_bytes(header_buf[8..16].try_into().unwrap()); | ||
| let vaddr: usize = u64::from_le_bytes(header_buf[16..24].try_into().unwrap()) | ||
| .try_into() | ||
| .map_err(|_| ElfParseError::BadTrampoline)?; | ||
| let trampoline_size: usize = u64::from_le_bytes(header_buf[24..32].try_into().unwrap()) | ||
| .try_into() | ||
| .map_err(|_| ElfParseError::BadTrampoline)?; | ||
| (file_offset, vaddr, trampoline_size) | ||
| } else { | ||
| // 32-bit: [0..8] magic, [8..12] file_offset, [12..16] vaddr, [16..20] code_size | ||
| let file_offset = u64::from(u32::from_le_bytes(header_buf[8..12].try_into().unwrap())); | ||
| let vaddr = u32::from_le_bytes(header_buf[12..16].try_into().unwrap()) as usize; | ||
| let trampoline_size = | ||
| u32::from_le_bytes(header_buf[16..20].try_into().unwrap()) as usize; | ||
| (file_offset, vaddr, trampoline_size) | ||
| }; |
There was a problem hiding this comment.
This is fine, but I believe a better way is to define a struct for it and then directly converting raw bytes to a struct.
| }; | ||
|
|
||
| // Validate trampoline size bounds | ||
| if trampoline_size == 0 || trampoline_size > MAX_TRAMPOLINE_SIZE { |
There was a problem hiding this comment.
Why we need MAX_TRAMPOLINE_SIZE? Looks like a small number to me.
| // Maximum number of pages to search for trampoline | ||
| #define MAX_SEARCH_PAGES 16 | ||
| // Maximum allowed trampoline size (must match Rust loader) | ||
| #define MAX_TRAMP_SIZE (MAX_SEARCH_PAGES * 0x1000) |
Instead of inserting a
.trampolineLB0section header into the ELF file, store trampoline metadata directly at the end of the ELF file. This fixes issues when there is no space in sections or symbol tables. A future PR will directly patch the ELF file without invoking any other crates to reassemble the ELF file.