mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:57:36 +00:00
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:
parent
4917445e2e
commit
7d6689055f
7 changed files with 36 additions and 1 deletions
|
@ -224,6 +224,16 @@ int Process::sys$munmap(void* addr, size_t size)
|
||||||
return 0;
|
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)
|
int Process::sys$gethostname(char* buffer, ssize_t size)
|
||||||
{
|
{
|
||||||
if (size < 0)
|
if (size < 0)
|
||||||
|
|
|
@ -145,6 +145,7 @@ public:
|
||||||
void* sys$mmap(const Syscall::SC_mmap_params*);
|
void* sys$mmap(const Syscall::SC_mmap_params*);
|
||||||
int sys$munmap(void*, size_t size);
|
int sys$munmap(void*, size_t size);
|
||||||
int sys$set_mmap_name(void*, size_t, const char*);
|
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$select(const Syscall::SC_select_params*);
|
||||||
int sys$poll(pollfd*, int nfds, int timeout);
|
int sys$poll(pollfd*, int nfds, int timeout);
|
||||||
ssize_t sys$get_dir_entries(int fd, void*, ssize_t);
|
ssize_t sys$get_dir_entries(int fd, void*, ssize_t);
|
||||||
|
|
|
@ -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);
|
return current->process().sys$share_buffer_globally((int)arg1);
|
||||||
case Syscall::SC_set_process_icon:
|
case Syscall::SC_set_process_icon:
|
||||||
return current->process().sys$set_process_icon((int)arg1);
|
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:
|
default:
|
||||||
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
|
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
|
@ -122,7 +122,8 @@ struct timeval;
|
||||||
__ENUMERATE_SYSCALL(dbgputstr) \
|
__ENUMERATE_SYSCALL(dbgputstr) \
|
||||||
__ENUMERATE_SYSCALL(watch_file) \
|
__ENUMERATE_SYSCALL(watch_file) \
|
||||||
__ENUMERATE_SYSCALL(share_buffer_globally) \
|
__ENUMERATE_SYSCALL(share_buffer_globally) \
|
||||||
__ENUMERATE_SYSCALL(set_process_icon)
|
__ENUMERATE_SYSCALL(set_process_icon) \
|
||||||
|
__ENUMERATE_SYSCALL(mprotect)
|
||||||
|
|
||||||
namespace Syscall {
|
namespace Syscall {
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,12 @@ int munmap(void* addr, size_t size)
|
||||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
__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 set_mmap_name(void* addr, size_t size, const char* name)
|
||||||
{
|
{
|
||||||
int rc = syscall(SC_set_mmap_name, addr, size, name);
|
int rc = syscall(SC_set_mmap_name, addr, size, name);
|
||||||
|
|
|
@ -21,6 +21,7 @@ __BEGIN_DECLS
|
||||||
void* mmap(void* addr, size_t, int prot, int flags, int fd, off_t);
|
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);
|
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 munmap(void*, size_t);
|
||||||
|
int mprotect(void*, size_t, int prot);
|
||||||
int set_mmap_name(void*, size_t, const char*);
|
int set_mmap_name(void*, size_t, const char*);
|
||||||
int shm_open(const char* name, int flags, mode_t);
|
int shm_open(const char* name, int flags, mode_t);
|
||||||
int shm_unlink(const char* name);
|
int shm_unlink(const char* name);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include <AK/AKString.h>
|
#include <AK/AKString.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
static void print_usage_and_exit()
|
static void print_usage_and_exit()
|
||||||
{
|
{
|
||||||
|
@ -20,6 +21,7 @@ int main(int argc, char** argv)
|
||||||
WriteToFreedMemory,
|
WriteToFreedMemory,
|
||||||
ReadFromUninitializedMallocMemory,
|
ReadFromUninitializedMallocMemory,
|
||||||
ReadFromFreedMemory,
|
ReadFromFreedMemory,
|
||||||
|
WriteToReadonlyMemory,
|
||||||
};
|
};
|
||||||
Mode mode = SegmentationViolation;
|
Mode mode = SegmentationViolation;
|
||||||
|
|
||||||
|
@ -42,6 +44,8 @@ int main(int argc, char** argv)
|
||||||
mode = WriteToUninitializedMallocMemory;
|
mode = WriteToUninitializedMallocMemory;
|
||||||
else if (String(argv[1]) == "-F")
|
else if (String(argv[1]) == "-F")
|
||||||
mode = WriteToFreedMemory;
|
mode = WriteToFreedMemory;
|
||||||
|
else if (String(argv[1]) == "-r")
|
||||||
|
mode = WriteToReadonlyMemory;
|
||||||
else
|
else
|
||||||
print_usage_and_exit();
|
print_usage_and_exit();
|
||||||
|
|
||||||
|
@ -97,6 +101,16 @@ int main(int argc, char** argv)
|
||||||
ASSERT_NOT_REACHED();
|
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();
|
ASSERT_NOT_REACHED();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue