mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:27:35 +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
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();
|
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);
|
auto range = allocate_range(vaddr, size);
|
||||||
if (!range.is_valid())
|
if (!range.is_valid())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
offset_in_vmobject &= PAGE_MASK;
|
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());
|
m_regions.last().map(page_directory());
|
||||||
return &m_regions.last();
|
return &m_regions.last();
|
||||||
}
|
}
|
||||||
|
@ -669,7 +672,7 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
|
||||||
|
|
||||||
ASSERT(description->inode());
|
ASSERT(description->inode());
|
||||||
auto vmobject = InodeVMObject::create_with_inode(*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);
|
ASSERT(region);
|
||||||
|
|
||||||
// NOTE: We yank this out of 'm_regions' since we're about to manipulate the vector
|
// 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;
|
OwnPtr<ELFLoader> loader;
|
||||||
{
|
{
|
||||||
SmapDisabler disabler;
|
|
||||||
// Okay, here comes the sleight of hand, pay close attention..
|
// Okay, here comes the sleight of hand, pay close attention..
|
||||||
auto old_regions = move(m_regions);
|
auto old_regions = move(m_regions);
|
||||||
m_regions.append(move(executable_region));
|
m_regions.append(move(executable_region));
|
||||||
|
@ -741,9 +743,6 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> envir
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
region->set_user_accessible(false);
|
|
||||||
region->remap();
|
|
||||||
|
|
||||||
m_elf_loader = move(loader);
|
m_elf_loader = move(loader);
|
||||||
m_executable = description->custody();
|
m_executable = description->custody();
|
||||||
|
|
||||||
|
|
|
@ -279,7 +279,7 @@ public:
|
||||||
|
|
||||||
bool is_superuser() const { return m_euid == 0; }
|
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_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);
|
Region* allocate_region(VirtualAddress, size_t, const String& name, int prot = PROT_READ | PROT_WRITE, bool commit = true);
|
||||||
bool deallocate_region(Region& region);
|
bool deallocate_region(Region& region);
|
||||||
|
|
|
@ -189,6 +189,13 @@ NonnullOwnPtr<Region> Region::create_kernel_only(const Range& range, const Strin
|
||||||
return region;
|
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
|
bool Region::should_cow(size_t page_index) const
|
||||||
{
|
{
|
||||||
if (m_shared)
|
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<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_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&, 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();
|
~Region();
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
#ifdef KERNEL
|
#ifdef KERNEL
|
||||||
#include <Kernel/VM/MemoryManager.h>
|
#include <Kernel/VM/MemoryManager.h>
|
||||||
|
#define do_memcpy copy_to_user
|
||||||
|
#else
|
||||||
|
#define do_memcpy memcpy
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define ELFLOADER_DEBUG
|
//#define ELFLOADER_DEBUG
|
||||||
|
@ -48,7 +51,7 @@ bool ELFLoader::layout()
|
||||||
failed = true;
|
failed = true;
|
||||||
return;
|
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
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +78,7 @@ bool ELFLoader::layout()
|
||||||
failed = true;
|
failed = true;
|
||||||
return;
|
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 {
|
} else {
|
||||||
auto* mapped_section = map_section_hook(
|
auto* mapped_section = map_section_hook(
|
||||||
program_header.vaddr(),
|
program_header.vaddr(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue