From df73e8b46b3b5634320f2f2075954d5d2dad682c Mon Sep 17 00:00:00 2001 From: Jelle Raaijmakers Date: Sat, 22 Jan 2022 00:30:42 +0100 Subject: [PATCH] Kernel: Allow program headers to align on multiples of `PAGE_SIZE` These checks in `sys$execve` could trip up the system whenever you try to execute an `.so` file. For example, double-clicking `libwasm.so` in Terminal crashes the kernel. This changes the program header alignment checks to reflect the same checks in LibELF, and passes the requested alignment on to `::try_allocate_range()`. --- Kernel/Syscalls/execve.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Kernel/Syscalls/execve.cpp b/Kernel/Syscalls/execve.cpp index 52fe068611..189a6746ba 100644 --- a/Kernel/Syscalls/execve.cpp +++ b/Kernel/Syscalls/execve.cpp @@ -306,7 +306,7 @@ static ErrorOr load_elf_object(NonnullOwnPtr n auto load_writable_section = [&](auto& program_header) -> ErrorOr { // Writable section: create a copy in memory. - VERIFY(program_header.alignment() == PAGE_SIZE); + VERIFY(program_header.alignment() % PAGE_SIZE == 0); if (!elf_image.is_within_image(program_header.raw_data(), program_header.size_in_image())) { dbgln("Shenanigans! Writable ELF PT_LOAD header sneaks outside of executable."); @@ -324,7 +324,7 @@ static ErrorOr load_elf_object(NonnullOwnPtr n size_t rounded_range_end = TRY(Memory::page_round_up(program_header.vaddr().offset(load_offset).offset(program_header.size_in_memory()).get())); auto range_end = VirtualAddress { rounded_range_end }; - auto range = TRY(new_space->try_allocate_range(range_base, range_end.get() - range_base.get())); + auto range = TRY(new_space->try_allocate_range(range_base, range_end.get() - range_base.get(), program_header.alignment())); auto region = TRY(new_space->allocate_region(range, region_name->view(), prot, AllocationStrategy::Reserve)); // It's not always the case with PIE executables (and very well shouldn't be) that the @@ -348,7 +348,7 @@ static ErrorOr load_elf_object(NonnullOwnPtr n return load_writable_section(program_header); // Non-writable section: map the executable itself in memory. - VERIFY(program_header.alignment() == PAGE_SIZE); + VERIFY(program_header.alignment() % PAGE_SIZE == 0); int prot = 0; if (program_header.is_readable()) prot |= PROT_READ; @@ -360,7 +360,7 @@ static ErrorOr load_elf_object(NonnullOwnPtr n auto range_base = VirtualAddress { Memory::page_round_down(program_header.vaddr().offset(load_offset).get()) }; size_t rounded_range_end = TRY(Memory::page_round_up(program_header.vaddr().offset(load_offset).offset(program_header.size_in_memory()).get())); auto range_end = VirtualAddress { rounded_range_end }; - auto range = TRY(new_space->try_allocate_range(range_base, range_end.get() - range_base.get())); + auto range = TRY(new_space->try_allocate_range(range_base, range_end.get() - range_base.get(), program_header.alignment())); auto region = TRY(new_space->allocate_region_with_vmobject(range, *vmobject, program_header.offset(), elf_name->view(), prot, true)); if (should_allow_syscalls == ShouldAllowSyscalls::Yes)