//! Live parse-only gate for bounded ELF64 program headers. No file bytes are //! installed in a UserSpace and no ELF entry is executed by this image. use super::*; use turkos_kernel::elf::{self, Error}; fn fail(reason: &str) -> ! { write_str("TURKOS/ELF-LAYOUT-ERROR: "); write_line(reason); park() } fn fixture() -> [u8; 124] { let mut bytes = [0u8; 124]; bytes[..20].copy_from_slice(&[ 0x7f, b'E', b'L', b'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0xb7, 0, ]); bytes[16..18].copy_from_slice(&2u16.to_le_bytes()); bytes[20..24].copy_from_slice(&1u32.to_le_bytes()); bytes[24..32].copy_from_slice(&mmu::USER_CODE_VA.to_le_bytes()); bytes[32..40].copy_from_slice(&64u64.to_le_bytes()); bytes[52..54].copy_from_slice(&64u16.to_le_bytes()); bytes[54..56].copy_from_slice(&56u16.to_le_bytes()); bytes[56..58].copy_from_slice(&1u16.to_le_bytes()); bytes[64..68].copy_from_slice(&1u32.to_le_bytes()); bytes[68..72].copy_from_slice(&5u32.to_le_bytes()); bytes[72..80].copy_from_slice(&120u64.to_le_bytes()); bytes[80..88].copy_from_slice(&mmu::USER_CODE_VA.to_le_bytes()); bytes[96..104].copy_from_slice(&4u64.to_le_bytes()); bytes[104..112].copy_from_slice(&4u64.to_le_bytes()); bytes[112..120].copy_from_slice(&1u64.to_le_bytes()); bytes[120..124].copy_from_slice(b"CODE"); bytes } pub(super) fn smoke_test() -> ! { let good = fixture(); let layout = elf::parse_layout(&good).unwrap_or_else(|_| fail("valid static layout")); let Some(segment) = layout.segments[0] else { fail("missing load segment"); }; if layout.count != 1 || layout.entry != mmu::USER_CODE_VA || segment.file_offset != 120 || segment.virtual_address != mmu::USER_CODE_VA || segment.file_size != 4 || segment.memory_size != 4 || segment.flags != 5 { fail("layout fields"); } write_str("TURKOS/ELF-LAYOUT-ACCEPT: COUNT=0x"); write_hex(layout.count); write_str(" ENTRY=0x"); write_hex(layout.entry as usize); write_str(" FILE=0x"); write_hex(segment.file_size as usize); write_str(" MEM=0x"); write_hex(segment.memory_size as usize); write_str(" FLAGS=0x"); write_hex(segment.flags as usize); write_str("\r\n"); let mut bad = good; bad[56..58].copy_from_slice(&5u16.to_le_bytes()); if elf::parse_layout(&bad) != Err(Error::BadProgramCount) { fail("PHDR count"); } write_line("TURKOS/ELF-LAYOUT-COUNT: REJECT"); bad = good; bad[32..40].copy_from_slice(&u64::MAX.to_le_bytes()); if elf::parse_layout(&bad) != Err(Error::BadProgramTable) { fail("PHDR table range"); } write_line("TURKOS/ELF-LAYOUT-TABLE: REJECT"); bad = good; bad[72..80].copy_from_slice(&u64::MAX.to_le_bytes()); if elf::parse_layout(&bad) != Err(Error::BadFileRange) { fail("file range overflow"); } write_line("TURKOS/ELF-LAYOUT-FILE: REJECT"); bad = good; bad[104..112].copy_from_slice(&3u64.to_le_bytes()); if elf::parse_layout(&bad) != Err(Error::FileLargerThanMemory) { fail("filesz > memsz"); } write_line("TURKOS/ELF-LAYOUT-MEM: REJECT"); bad = good; bad[80..88].copy_from_slice(&0x4000_0000u64.to_le_bytes()); if elf::parse_layout(&bad) != Err(Error::BadUserAddress) { fail("kernel virtual address"); } write_line("TURKOS/ELF-LAYOUT-VA: REJECT"); bad = good; bad[68..72].copy_from_slice(&7u32.to_le_bytes()); if elf::parse_layout(&bad) != Err(Error::WritableExecutable) { fail("W+X segment"); } write_line("TURKOS/ELF-LAYOUT-WX: REJECT"); write_line("TURKOS/ELF-LAYOUT: PASS"); park() }