diff --git a/LibELF/LibELF/LoadableELF.cpp b/LibELF/LibELF/LoadableELF.cpp index 7a580b3a..9ca3a8bb 100644 --- a/LibELF/LibELF/LoadableELF.cpp +++ b/LibELF/LibELF/LoadableELF.cpp @@ -27,6 +27,8 @@ namespace LibELF LoadableELF::~LoadableELF() { + if (!m_loaded) + return; for (const auto& program_header : m_program_headers) { switch (program_header.p_type) @@ -155,6 +157,29 @@ namespace LibELF return false; } + bool LoadableELF::is_address_space_free() const + { + for (const auto& program_header : m_program_headers) + { + switch (program_header.p_type) + { + case PT_NULL: + break; + case PT_LOAD: + { + vaddr_t page_vaddr = program_header.p_vaddr & PAGE_ADDR_MASK; + size_t pages = range_page_count(program_header.p_vaddr, program_header.p_memsz); + if (!m_page_table.is_range_free(page_vaddr, pages * PAGE_SIZE)) + return false; + break; + } + default: + ASSERT_NOT_REACHED(); + } + } + return true; + } + void LoadableELF::reserve_address_space() { for (const auto& program_header : m_program_headers) @@ -174,6 +199,7 @@ namespace LibELF ASSERT_NOT_REACHED(); } } + m_loaded = true; } BAN::ErrorOr LoadableELF::load_page_to_memory(vaddr_t address) diff --git a/LibELF/include/LibELF/LoadableELF.h b/LibELF/include/LibELF/LoadableELF.h index 1b3cc4ff..d4733fa0 100644 --- a/LibELF/include/LibELF/LoadableELF.h +++ b/LibELF/include/LibELF/LoadableELF.h @@ -27,6 +27,7 @@ namespace LibELF Kernel::vaddr_t entry_point() const; bool contains(Kernel::vaddr_t address) const; + bool is_address_space_free() const; void reserve_address_space(); BAN::ErrorOr load_page_to_memory(Kernel::vaddr_t address); @@ -47,6 +48,7 @@ namespace LibELF BAN::Vector m_program_headers; size_t m_virtual_page_count = 0; size_t m_physical_page_count = 0; + bool m_loaded { false }; }; } \ No newline at end of file diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index acce6aef..18ca6048 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -123,6 +123,11 @@ namespace Kernel TRY(process->m_cmdline.back().append(path)); process->m_loadable_elf = TRY(load_elf_for_exec(credentials, path, "/"sv, process->page_table())); + if (!process->m_loadable_elf->is_address_space_free()) + { + dprintln("Could not load ELF address space"); + return BAN::Error::from_errno(ENOEXEC); + } process->m_loadable_elf->reserve_address_space(); process->m_is_userspace = true; @@ -460,6 +465,11 @@ namespace Kernel m_loadable_elf.clear(); m_loadable_elf = TRY(load_elf_for_exec(m_credentials, executable_path, m_working_directory, page_table())); + if (!m_loadable_elf->is_address_space_free()) + { + dprintln("ELF has unloadable address space"); + MUST(sys_raise(SIGKILL)); + } m_loadable_elf->reserve_address_space(); m_userspace_info.entry = m_loadable_elf->entry_point();