mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
Kernel+LibELF: Enable SMAP protection during non-syscall exec()
When loading a new executable, we now map the ELF image in kernel-only memory and parse it there. Then we use copy_to_user() when initializing writable regions with data from the executable. Note that the exec() syscall still disables SMAP protection and will require additional work. This patch only affects kernel-originated process spawns.
This commit is contained in:
parent
66b0002acb
commit
197e73ee31
Notes:
sideshowbarker
2024-07-19 10:14:13 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/197e73ee311
5 changed files with 20 additions and 10 deletions
|
@ -165,13 +165,16 @@ Region* Process::allocate_file_backed_region(VirtualAddress vaddr, size_t size,
|
|||
return &m_regions.last();
|
||||
}
|
||||
|
||||
Region* Process::allocate_region_with_vmobject(VirtualAddress vaddr, size_t size, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, const String& name, int prot)
|
||||
Region* Process::allocate_region_with_vmobject(VirtualAddress vaddr, size_t size, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, const String& name, int prot, bool user_accessible)
|
||||
{
|
||||
auto range = allocate_range(vaddr, size);
|
||||
if (!range.is_valid())
|
||||
return nullptr;
|
||||
offset_in_vmobject &= PAGE_MASK;
|
||||
m_regions.append(Region::create_user_accessible(range, move(vmobject), offset_in_vmobject, name, prot_to_region_access_flags(prot)));
|
||||
if (user_accessible)
|
||||
m_regions.append(Region::create_user_accessible(range, move(vmobject), offset_in_vmobject, name, prot_to_region_access_flags(prot)));
|
||||
else
|
||||
m_regions.append(Region::create_kernel_only(range, move(vmobject), offset_in_vmobject, name, prot_to_region_access_flags(prot)));
|
||||
m_regions.last().map(page_directory());
|
||||
return &m_regions.last();
|
||||
}
|
||||
|
@ -669,7 +672,7 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
|
|||
|
||||
ASSERT(description->inode());
|
||||
auto vmobject = InodeVMObject::create_with_inode(*description->inode());
|
||||
auto* region = allocate_region_with_vmobject(VirtualAddress(), metadata.size, vmobject, 0, description->absolute_path(), PROT_READ);
|
||||
auto* region = allocate_region_with_vmobject(VirtualAddress(), metadata.size, vmobject, 0, description->absolute_path(), PROT_READ, false);
|
||||
ASSERT(region);
|
||||
|
||||
// NOTE: We yank this out of 'm_regions' since we're about to manipulate the vector
|
||||
|
@ -682,7 +685,6 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
|
|||
|
||||
OwnPtr<ELFLoader> loader;
|
||||
{
|
||||
SmapDisabler disabler;
|
||||
// Okay, here comes the sleight of hand, pay close attention..
|
||||
auto old_regions = move(m_regions);
|
||||
m_regions.append(move(executable_region));
|
||||
|
@ -741,9 +743,6 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
|
|||
#endif
|
||||
}
|
||||
|
||||
region->set_user_accessible(false);
|
||||
region->remap();
|
||||
|
||||
m_elf_loader = move(loader);
|
||||
m_executable = description->custody();
|
||||
|
||||
|
|
|
@ -279,7 +279,7 @@ public:
|
|||
|
||||
bool is_superuser() const { return m_euid == 0; }
|
||||
|
||||
Region* allocate_region_with_vmobject(VirtualAddress, size_t, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, const String& name, int prot);
|
||||
Region* allocate_region_with_vmobject(VirtualAddress, size_t, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, const String& name, int prot, bool user_accessible = true);
|
||||
Region* allocate_file_backed_region(VirtualAddress, size_t, NonnullRefPtr<Inode>, const String& name, int prot);
|
||||
Region* allocate_region(VirtualAddress, size_t, const String& name, int prot = PROT_READ | PROT_WRITE, bool commit = true);
|
||||
bool deallocate_region(Region& region);
|
||||
|
|
|
@ -189,6 +189,13 @@ NonnullOwnPtr<Region> Region::create_kernel_only(const Range& range, const Strin
|
|||
return region;
|
||||
}
|
||||
|
||||
NonnullOwnPtr<Region> Region::create_kernel_only(const Range& range, NonnullRefPtr<VMObject> vmobject, size_t offset_in_vmobject, const StringView& name, u8 access)
|
||||
{
|
||||
auto region = make<Region>(range, move(vmobject), offset_in_vmobject, name, access);
|
||||
region->m_user_accessible = false;
|
||||
return region;
|
||||
}
|
||||
|
||||
bool Region::should_cow(size_t page_index) const
|
||||
{
|
||||
if (m_shared)
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
static NonnullOwnPtr<Region> create_user_accessible(const Range&, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, const StringView& name, u8 access);
|
||||
static NonnullOwnPtr<Region> create_user_accessible(const Range&, NonnullRefPtr<Inode>, const StringView& name, u8 access);
|
||||
static NonnullOwnPtr<Region> create_kernel_only(const Range&, const StringView& name, u8 access);
|
||||
static NonnullOwnPtr<Region> create_kernel_only(const Range&, NonnullRefPtr<VMObject>, size_t offset_in_vmobject, const StringView& name, u8 access);
|
||||
|
||||
~Region();
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
#ifdef KERNEL
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
#define do_memcpy copy_to_user
|
||||
#else
|
||||
#define do_memcpy memcpy
|
||||
#endif
|
||||
|
||||
//#define ELFLOADER_DEBUG
|
||||
|
@ -48,7 +51,7 @@ bool ELFLoader::layout()
|
|||
failed = true;
|
||||
return;
|
||||
}
|
||||
memcpy(tls_image, program_header.raw_data(), program_header.size_in_image());
|
||||
do_memcpy(tls_image, program_header.raw_data(), program_header.size_in_image());
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -75,7 +78,7 @@ bool ELFLoader::layout()
|
|||
failed = true;
|
||||
return;
|
||||
}
|
||||
memcpy(program_header.vaddr().as_ptr(), program_header.raw_data(), program_header.size_in_image());
|
||||
do_memcpy(program_header.vaddr().as_ptr(), program_header.raw_data(), program_header.size_in_image());
|
||||
} else {
|
||||
auto* mapped_section = map_section_hook(
|
||||
program_header.vaddr(),
|
||||
|
|
Loading…
Reference in a new issue