kernel: Initial try at actual user buffer validation
This commit is contained in:
parent
ebd86b1a3f
commit
1f0d982240
|
@ -0,0 +1,12 @@
|
|||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
int fd = open("/dev/dsp",O_WRONLY);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "failed to open dsp\n");
|
||||
return 1;
|
||||
}
|
||||
return write(fd, &fd, -1);
|
||||
}
|
|
@ -12,6 +12,9 @@
|
|||
#define MMU_GET_MAKE 0x01
|
||||
|
||||
|
||||
#define MMU_PTR_NULL 1
|
||||
#define MMU_PTR_WRITE 2
|
||||
|
||||
void mmu_frame_set(uintptr_t frame_addr);
|
||||
void mmu_frame_clear(uintptr_t frame_addr);
|
||||
int mmu_frame_test(uintptr_t frame_addr);
|
||||
|
@ -40,3 +43,5 @@ size_t mmu_total_memory(void);
|
|||
size_t mmu_used_memory(void);
|
||||
|
||||
void * sbrk(size_t);
|
||||
|
||||
int mmu_validate_user_pointer(void * addr, size_t size, int flags);
|
||||
|
|
|
@ -899,3 +899,26 @@ void * mmu_map_module(size_t size) {
|
|||
}
|
||||
|
||||
|
||||
int mmu_validate_user_pointer(void * addr, size_t size, int flags) {
|
||||
if (addr == NULL && !(flags & MMU_PTR_NULL)) return 0;
|
||||
if (size > 0x800000000000) return 0;
|
||||
|
||||
uintptr_t base = (uintptr_t)addr;
|
||||
uintptr_t end = size ? (base + (size - 1)) : base;
|
||||
|
||||
/* Get start page, end page */
|
||||
uintptr_t page_base = base >> 12;
|
||||
uintptr_t page_end = end >> 12;
|
||||
|
||||
for (uintptr_t page = page_base; page <= page_end; ++page) {
|
||||
if ((page & 0xffff800000000) != 0 && (page & 0xffff800000000) != 0xffff800000000) return 0;
|
||||
union PML * page_entry = mmu_get_page_other(this_core->current_process->thread.page_directory->directory, page << 12);
|
||||
if (!page_entry) return 0;
|
||||
if (!page_entry->bits.present) return 0;
|
||||
if (!page_entry->bits.user) return 0;
|
||||
if (!page_entry->bits.writable && (flags & MMU_PTR_WRITE)) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,14 +25,20 @@
|
|||
static char hostname[256];
|
||||
static size_t hostname_len = 0;
|
||||
|
||||
extern union PML * mmu_get_page_other(union PML * root, uintptr_t virtAddr);
|
||||
int ptr_validate(void * ptr, const char * syscall) {
|
||||
if (ptr && !PTR_INRANGE(ptr)) {
|
||||
send_signal(this_core->current_process->id, SIGSEGV, 1);
|
||||
return 1;
|
||||
if (ptr) {
|
||||
if (!PTR_INRANGE(ptr)) {
|
||||
send_signal(this_core->current_process->id, SIGSEGV, 1);
|
||||
return 1;
|
||||
}
|
||||
if (!mmu_validate_user_pointer(ptr,1,0)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PTRCHECK(addr,size,flags) do { if (!mmu_validate_user_pointer(addr,size,flags)) return -EFAULT; } while (0)
|
||||
|
||||
static long sys_sbrk(ssize_t size) {
|
||||
if (size & 0xFFF) return -EINVAL;
|
||||
volatile process_t * volatile proc = this_core->current_process;
|
||||
|
@ -97,7 +103,7 @@ static long sys_sysfunc(long fn, char ** args) {
|
|||
* the stuff in the middle to be mapped necessarily... */
|
||||
PTR_VALIDATE(args);
|
||||
if (!args) return -EFAULT;
|
||||
PTR_VALIDATE(args[0]);
|
||||
if (!PTR_INRANGE(args[0])) return -EFAULT;
|
||||
if (!args[0]) return -EFAULT;
|
||||
volatile process_t * volatile proc = this_core->current_process;
|
||||
if (proc->group != 0) proc = process_from_pid(proc->group);
|
||||
|
@ -119,8 +125,8 @@ static long sys_sysfunc(long fn, char ** args) {
|
|||
/* Align inputs */
|
||||
uintptr_t start = ((uintptr_t)args[0]) & 0xFFFFffffFFFFf000UL;
|
||||
uintptr_t end = ((uintptr_t)args[0] + (size_t)args[1] + 0xFFF) & 0xFFFFffffFFFFf000UL;
|
||||
PTR_VALIDATE(start);
|
||||
PTR_VALIDATE(end);
|
||||
if (!PTR_INRANGE(start)) return -EFAULT;
|
||||
if (!PTR_INRANGE(end)) return -EFAULT;
|
||||
for (uintptr_t i = start; i < end; i += 0x1000) {
|
||||
union PML * page = mmu_get_page(i, MMU_GET_MAKE);
|
||||
mmu_frame_allocate(page, MMU_FLAG_WRITABLE);
|
||||
|
@ -177,7 +183,7 @@ static long sys_exit(long exitcode) {
|
|||
|
||||
static long sys_write(int fd, char * ptr, unsigned long len) {
|
||||
if (FD_CHECK(fd)) {
|
||||
PTR_VALIDATE(ptr);
|
||||
PTRCHECK(ptr,len,MMU_PTR_NULL);
|
||||
fs_node_t * node = FD_ENTRY(fd);
|
||||
if (!(FD_MODE(fd) & 2)) return -EACCES;
|
||||
if (len && !ptr) {
|
||||
|
@ -394,7 +400,7 @@ static long sys_seek(int fd, long offset, long whence) {
|
|||
|
||||
static long sys_read(int fd, char * ptr, unsigned long len) {
|
||||
if (FD_CHECK(fd)) {
|
||||
PTR_VALIDATE(ptr);
|
||||
PTRCHECK(ptr,len,MMU_PTR_NULL|MMU_PTR_WRITE);
|
||||
if (len && !ptr) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue