mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 03:07:36 +00:00
Kernel: Implement some basic stack pointer validation
VM regions can now be marked as stack regions, which is then validated on syscall, and on page fault. If a thread is caught with its stack pointer pointing into anything that's *not* a Region with its stack bit set, we'll crash the whole process with SIGSTKFLT. Userspace must now allocate custom stacks by using mmap() with the new MAP_STACK flag. This mechanism was first introduced in OpenBSD, and now we have it too, yay! :^)
This commit is contained in:
parent
197ed1bb2a
commit
794758df3a
12 changed files with 101 additions and 5 deletions
|
@ -549,6 +549,12 @@ void MemoryManager::unquickmap_page()
|
|||
m_quickmap_in_use = false;
|
||||
}
|
||||
|
||||
bool MemoryManager::validate_user_stack(const Process& process, VirtualAddress vaddr) const
|
||||
{
|
||||
auto* region = region_from_vaddr(process, vaddr);
|
||||
return region && region->is_stack();
|
||||
}
|
||||
|
||||
bool MemoryManager::validate_user_read(const Process& process, VirtualAddress vaddr) const
|
||||
{
|
||||
auto* region = region_from_vaddr(process, vaddr);
|
||||
|
|
|
@ -46,6 +46,7 @@ public:
|
|||
|
||||
void enter_process_paging_scope(Process&);
|
||||
|
||||
bool validate_user_stack(const Process&, VirtualAddress) const;
|
||||
bool validate_user_read(const Process&, VirtualAddress) const;
|
||||
bool validate_user_write(const Process&, VirtualAddress) const;
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ NonnullOwnPtr<Region> Region::clone()
|
|||
ASSERT(is_user_accessible());
|
||||
|
||||
if (m_shared || (is_readable() && !is_writable())) {
|
||||
ASSERT(!m_stack);
|
||||
#ifdef MM_DEBUG
|
||||
dbgprintf("%s<%u> Region::clone(): sharing %s (V%p)\n",
|
||||
current->process().name().characters(),
|
||||
|
@ -81,6 +82,13 @@ NonnullOwnPtr<Region> Region::clone()
|
|||
remap();
|
||||
auto clone_region = Region::create_user_accessible(m_range, m_vmobject->clone(), m_offset_in_vmo, m_name, m_access);
|
||||
clone_region->ensure_cow_map();
|
||||
if (m_stack) {
|
||||
ASSERT(is_readable());
|
||||
ASSERT(is_writable());
|
||||
ASSERT(!is_shared());
|
||||
ASSERT(vmobject().is_anonymous());
|
||||
clone_region->set_stack(true);
|
||||
}
|
||||
return clone_region;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,9 @@ public:
|
|||
bool is_shared() const { return m_shared; }
|
||||
void set_shared(bool shared) { m_shared = shared; }
|
||||
|
||||
bool is_stack() const { return m_stack; }
|
||||
void set_stack(bool stack) { m_stack = stack; }
|
||||
|
||||
bool is_user_accessible() const { return m_user_accessible; }
|
||||
|
||||
PageFaultResponse handle_fault(const PageFault&);
|
||||
|
@ -141,5 +144,6 @@ private:
|
|||
u8 m_access { 0 };
|
||||
bool m_shared { false };
|
||||
bool m_user_accessible { false };
|
||||
bool m_stack { false };
|
||||
mutable OwnPtr<Bitmap> m_cow_map;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue