1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 05:08:13 +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:
Andreas Kling 2019-11-17 12:11:43 +01:00
parent 197ed1bb2a
commit 794758df3a
12 changed files with 101 additions and 5 deletions

View file

@ -207,12 +207,24 @@ void* Process::sys$mmap(const Syscall::SC_mmap_params* params)
return (void*)-EINVAL;
if ((flags & MAP_SHARED) && (flags & MAP_PRIVATE))
return (void*)-EINVAL;
// EINVAL: MAP_STACK cannot be used with shared or file-backed mappings
if ((flags & MAP_STACK) && ((flags & MAP_SHARED) || !(flags & MAP_PRIVATE) || !(flags & MAP_ANONYMOUS)))
return (void*)-EINVAL;
// EINVAL: MAP_STACK cannot be used with non-readable or non-writable memory
if ((flags & MAP_STACK) && (!(prot & PROT_READ) || !(prot & PROT_WRITE)))
return (void*)-EINVAL;
// FIXME: The rest of this function seems like it could share more code..
if (flags & MAP_ANONYMOUS) {
auto* region = allocate_region(VirtualAddress((u32)addr), size, name ? name : "mmap", prot, false);
if (!region)
return (void*)-ENOMEM;
if (flags & MAP_SHARED)
region->set_shared(true);
if (flags & MAP_STACK)
region->set_stack(true);
return region->vaddr().as_ptr();
}
if (offset & ~PAGE_MASK)
@ -813,13 +825,15 @@ void Process::dump_regions()
kprintf("Process %s(%u) regions:\n", name().characters(), pid());
kprintf("BEGIN END SIZE ACCESS NAME\n");
for (auto& region : m_regions) {
kprintf("%08x -- %08x %08x %c%c%c %s\n",
kprintf("%08x -- %08x %08x %c%c%c%c%c %s\n",
region.vaddr().get(),
region.vaddr().offset(region.size() - 1).get(),
region.size(),
region.is_readable() ? 'R' : ' ',
region.is_writable() ? 'W' : ' ',
region.is_executable() ? 'X' : ' ',
region.is_shared() ? 'S' : ' ',
region.is_stack() ? 'T' : ' ',
region.name().characters());
}
}