Kernel+LibC+crash: Add mprotect() syscall

This patch adds the mprotect() syscall to allow changing the protection
flags for memory regions. We don't do any region splitting/merging yet,
so this only works on whole mmap() regions.

Added a "crash -r" flag to verify that we crash when you attempt to
write to read-only memory. :^)
This commit is contained in:
Andreas Kling 2019-08-12 19:33:24 +02:00
parent 4917445e2e
commit 7d6689055f
Notes: sideshowbarker 2024-07-19 12:42:29 +09:00
7 changed files with 36 additions and 1 deletions

View File

@ -224,6 +224,16 @@ int Process::sys$munmap(void* addr, size_t size)
return 0;
}
int Process::sys$mprotect(void* addr, size_t size, int prot)
{
auto* region = region_from_range(VirtualAddress((u32)addr), size);
if (!region)
return -EINVAL;
region->set_writable(prot & PROT_WRITE);
MM.remap_region(page_directory(), *region);
return 0;
}
int Process::sys$gethostname(char* buffer, ssize_t size)
{
if (size < 0)

View File

@ -145,6 +145,7 @@ public:
void* sys$mmap(const Syscall::SC_mmap_params*);
int sys$munmap(void*, size_t size);
int sys$set_mmap_name(void*, size_t, const char*);
int sys$mprotect(void*, size_t, int prot);
int sys$select(const Syscall::SC_select_params*);
int sys$poll(pollfd*, int nfds, int timeout);
ssize_t sys$get_dir_entries(int fd, void*, ssize_t);

View File

@ -305,6 +305,8 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3
return current->process().sys$share_buffer_globally((int)arg1);
case Syscall::SC_set_process_icon:
return current->process().sys$set_process_icon((int)arg1);
case Syscall::SC_mprotect:
return current->process().sys$mprotect((void*)arg1, (size_t)arg2, (int)arg3);
default:
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
return -ENOSYS;

View File

@ -122,7 +122,8 @@ struct timeval;
__ENUMERATE_SYSCALL(dbgputstr) \
__ENUMERATE_SYSCALL(watch_file) \
__ENUMERATE_SYSCALL(share_buffer_globally) \
__ENUMERATE_SYSCALL(set_process_icon)
__ENUMERATE_SYSCALL(set_process_icon) \
__ENUMERATE_SYSCALL(mprotect)
namespace Syscall {

View File

@ -33,6 +33,12 @@ int munmap(void* addr, size_t size)
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int mprotect(void* addr, size_t size, int prot)
{
int rc = syscall(SC_mprotect, addr, size, prot);
__RETURN_WITH_ERRNO(rc, rc, -1);
}
int set_mmap_name(void* addr, size_t size, const char* name)
{
int rc = syscall(SC_set_mmap_name, addr, size, name);

View File

@ -21,6 +21,7 @@ __BEGIN_DECLS
void* mmap(void* addr, size_t, int prot, int flags, int fd, off_t);
void* mmap_with_name(void* addr, size_t, int prot, int flags, int fd, off_t, const char* name);
int munmap(void*, size_t);
int mprotect(void*, size_t, int prot);
int set_mmap_name(void*, size_t, const char*);
int shm_open(const char* name, int flags, mode_t);
int shm_unlink(const char* name);

View File

@ -1,6 +1,7 @@
#include <AK/AKString.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
static void print_usage_and_exit()
{
@ -20,6 +21,7 @@ int main(int argc, char** argv)
WriteToFreedMemory,
ReadFromUninitializedMallocMemory,
ReadFromFreedMemory,
WriteToReadonlyMemory,
};
Mode mode = SegmentationViolation;
@ -42,6 +44,8 @@ int main(int argc, char** argv)
mode = WriteToUninitializedMallocMemory;
else if (String(argv[1]) == "-F")
mode = WriteToFreedMemory;
else if (String(argv[1]) == "-r")
mode = WriteToReadonlyMemory;
else
print_usage_and_exit();
@ -97,6 +101,16 @@ int main(int argc, char** argv)
ASSERT_NOT_REACHED();
}
if (mode == WriteToReadonlyMemory) {
auto* ptr = (u8*)mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0);
ASSERT(ptr != MAP_FAILED);
*ptr = 'x'; // This should work fine.
int rc = mprotect(ptr, 4096, PROT_READ);
ASSERT(rc == 0);
ASSERT(*ptr == 'x');
*ptr = 'y'; // This should crash!
}
ASSERT_NOT_REACHED();
return 0;
}