Kernel: Check whether ELF address space can be loaded
Before reserving address space in SYS_EXEC verify that ELF address space is actually loadable. For example when trying to execute the kernel binary in userspace, binarys address space would overlap with current kernel address space. Now kernel won't crash anymore and will just send SIGKILL to the process calling exec*().
This commit is contained in:
parent
f0820e6f24
commit
773dcdd3a2
|
@ -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<void> LoadableELF::load_page_to_memory(vaddr_t address)
|
||||
|
|
|
@ -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<void> load_page_to_memory(Kernel::vaddr_t address);
|
||||
|
@ -47,6 +48,7 @@ namespace LibELF
|
|||
BAN::Vector<ElfNativeProgramHeader> m_program_headers;
|
||||
size_t m_virtual_page_count = 0;
|
||||
size_t m_physical_page_count = 0;
|
||||
bool m_loaded { false };
|
||||
};
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue