From af2f9184e03015dc3b188ea437bbf496638000ce Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sat, 11 Sep 2021 18:04:57 +0200 Subject: replace `user_ptr` with a linux-style `__user` annotation --- src/init/syscalls.c | 18 ++++++++--------- src/init/types.h | 3 ++- src/kernel/arch/generic.h | 4 ++-- src/kernel/arch/i386/pagedir.c | 16 ++++++++------- src/kernel/arch/i386/registers.h | 7 +++++-- src/kernel/arch/i386/sysenter.c | 8 ++++---- src/kernel/main.c | 2 +- src/kernel/mem/virt.c | 14 +++++++------- src/kernel/mem/virt.h | 8 ++++---- src/kernel/proc.c | 6 +++--- src/kernel/proc.h | 4 ++-- src/kernel/syscalls.c | 42 ++++++++++++++++++++-------------------- src/kernel/types.h | 9 ++++++++- src/shared/syscalls.h | 16 +++++++-------- src/shared/vfs.h | 2 +- 15 files changed, 86 insertions(+), 73 deletions(-) diff --git a/src/init/syscalls.c b/src/init/syscalls.c index c091247..4584837 100644 --- a/src/init/syscalls.c +++ b/src/init/syscalls.c @@ -4,7 +4,7 @@ int _syscall(int, int, int, int); -_Noreturn void _syscall_exit(const user_ptr msg, size_t len) { +_Noreturn void _syscall_exit(const char __user *msg, size_t len) { _syscall(_SYSCALL_EXIT, (int)msg, len, 0); __builtin_unreachable(); } @@ -13,23 +13,23 @@ int _syscall_fork(void) { return _syscall(_SYSCALL_FORK, 0, 0, 0); } -int _syscall_await(user_ptr buf, int len) { +int _syscall_await(char __user *buf, int len) { return _syscall(_SYSCALL_AWAIT, (int)buf, (int)len, 0); } -handle_t _syscall_open(const user_ptr path, int len) { +handle_t _syscall_open(const char __user *path, int len) { return _syscall(_SYSCALL_OPEN, (int)path, len, 0); } -int _syscall_mount(handle_t handle, const user_ptr path, int len) { +int _syscall_mount(handle_t handle, const char __user *path, int len) { return _syscall(_SYSCALL_MOUNT, handle, (int)path, len); } -int _syscall_read(handle_t handle, user_ptr buf, int len) { +int _syscall_read(handle_t handle, char __user *buf, int len) { return _syscall(_SYSCALL_READ, handle, (int)buf, len); } -int _syscall_write(handle_t handle, user_ptr buf, int len) { +int _syscall_write(handle_t handle, const char __user *buf, int len) { return _syscall(_SYSCALL_WRITE, handle, (int)buf, len); } @@ -37,10 +37,10 @@ int _syscall_close(handle_t handle) { return _syscall(_SYSCALL_CLOSE, handle, 0, 0); } -handle_t _syscall_fs_create(user_ptr back) { +handle_t _syscall_fs_create(handle_t __user *back) { return _syscall(_SYSCALL_FS_CREATE, (int)back, 0, 0); } -int _syscall_fs_wait(handle_t back, user_ptr info) { - return _syscall(_SYSCALL_FS_WAIT, back, info, 0); +int _syscall_fs_wait(handle_t back, void __user *info) { + return _syscall(_SYSCALL_FS_WAIT, back, (int)info, 0); } diff --git a/src/init/types.h b/src/init/types.h index 2c56484..9c6d64b 100644 --- a/src/init/types.h +++ b/src/init/types.h @@ -1,4 +1,5 @@ #pragma once #define TYPES_INCLUDED -typedef char* user_ptr; + +#define __user diff --git a/src/kernel/arch/generic.h b/src/kernel/arch/generic.h index e7afeff..547109f 100644 --- a/src/kernel/arch/generic.h +++ b/src/kernel/arch/generic.h @@ -23,11 +23,11 @@ int syscall_handler(int, int, int, int); // all of those can allocate memory struct pagedir *pagedir_new(void); struct pagedir *pagedir_copy(const struct pagedir *orig); -void pagedir_map(struct pagedir *dir, user_ptr virt, void *phys, +void pagedir_map(struct pagedir *dir, void __user *virt, void *phys, bool user, bool writeable); void pagedir_switch(struct pagedir *); // return 0 on failure -void *pagedir_virt2phys(struct pagedir *dir, const user_ptr virt, +void *pagedir_virt2phys(struct pagedir *dir, const void __user *virt, bool user, bool writeable); diff --git a/src/kernel/arch/i386/pagedir.c b/src/kernel/arch/i386/pagedir.c index 2fc96f4..770ff4e 100644 --- a/src/kernel/arch/i386/pagedir.c +++ b/src/kernel/arch/i386/pagedir.c @@ -46,11 +46,12 @@ struct pagedir *pagedir_new(void) { return dir; } -void pagedir_map(struct pagedir *dir, user_ptr virt, void *phys, +void pagedir_map(struct pagedir *dir, void __user *virt, void *phys, bool user, bool writeable) { - uint32_t pd_idx = virt >> 22; - uint32_t pt_idx = virt >> 12 & 0x03FF; + uintptr_t virt_cast = (uintptr_t) virt; + uint32_t pd_idx = virt_cast >> 22; + uint32_t pt_idx = virt_cast >> 12 & 0x03FF; struct pagetable_entry *pagetable; if (dir->e[pd_idx].present) { @@ -124,12 +125,13 @@ struct pagedir *pagedir_copy(const struct pagedir *orig) { return clone; } -void *pagedir_virt2phys(struct pagedir *dir, const user_ptr virt, +void *pagedir_virt2phys(struct pagedir *dir, const void __user *virt, bool user, bool writeable) { + uintptr_t virt_cast = (uintptr_t) virt; uintptr_t phys; - uint32_t pd_idx = virt >> 22; - uint32_t pt_idx = virt >> 12 & 0x03FF; + uint32_t pd_idx = virt_cast >> 22; + uint32_t pt_idx = virt_cast >> 12 & 0x03FF; struct pagetable_entry *pagetable, page; /* DOESN'T CHECK PERMISSIONS ON PAGE DIRS, TODO @@ -146,6 +148,6 @@ void *pagedir_virt2phys(struct pagedir *dir, const user_ptr virt, if (writeable && !page.writeable) return 0; phys = page.address << 11; - phys |= virt & 0xFFF; + phys |= virt_cast & 0xFFF; return (void*)phys; } diff --git a/src/kernel/arch/i386/registers.h b/src/kernel/arch/i386/registers.h index cca374d..fb369b7 100644 --- a/src/kernel/arch/i386/registers.h +++ b/src/kernel/arch/i386/registers.h @@ -1,13 +1,16 @@ #pragma once +#include #include struct registers { /* those are in the order of pushad/popad - so you can load/save this * struct in (almost) one instruction */ - uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; + uint32_t edi, esi; + userptr_t ebp, esp; + uint32_t ebx, edx, ecx, eax; // not part of pushad/popad, but still useful - uint32_t eip; + userptr_t eip; } __attribute__((__packed__)); // saves a return value according to the SysV ABI diff --git a/src/kernel/arch/i386/sysenter.c b/src/kernel/arch/i386/sysenter.c index 2470979..231aba5 100644 --- a/src/kernel/arch/i386/sysenter.c +++ b/src/kernel/arch/i386/sysenter.c @@ -7,8 +7,8 @@ extern void _sysexit_real(void); void sysexit(struct registers regs) { _sysexit_regs = regs; - _sysexit_regs.ecx = regs.esp; - _sysexit_regs.edx = regs.eip; + _sysexit_regs.ecx = (uintptr_t) regs.esp; + _sysexit_regs.edx = (uintptr_t) regs.eip; _sysexit_real(); __builtin_unreachable(); } @@ -18,8 +18,8 @@ _Noreturn void sysenter_stage2(void) { struct registers *regs = &process_current->regs; *regs = _sysexit_regs; // save the registers - regs->esp = regs->ecx; // fix them up - regs->eip = regs->edx; + regs->esp = (userptr_t) regs->ecx; // fix them up + regs->eip = (userptr_t) regs->edx; val = syscall_handler(regs->eax, regs->ebx, regs->esi, regs->edi); diff --git a/src/kernel/main.c b/src/kernel/main.c index 97fd6f1..07162b5 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -9,7 +9,7 @@ static void run_init(struct kmain_info *info) { struct process *proc = process_seed(); - user_ptr init_base = 0x200000; + void __user *init_base = (userptr_t)0x200000; // map the module as rw for (uintptr_t off = 0; off < info->init.size; off += PAGE_SIZE) diff --git a/src/kernel/mem/virt.c b/src/kernel/mem/virt.c index c3a1fca..e0d8e44 100644 --- a/src/kernel/mem/virt.c +++ b/src/kernel/mem/virt.c @@ -3,7 +3,7 @@ #include void virt_iter_new( - struct virt_iter *iter, user_ptr virt, size_t length, + struct virt_iter *iter, void __user *virt, size_t length, struct pagedir *pages, bool user, bool writeable) { iter->frag = 0; @@ -29,8 +29,8 @@ bool virt_iter_next(struct virt_iter *iter) { if (iter->_pages) { // if iterating over virtual memory // don't read past the page - if ((iter->_virt & PAGE_MASK) + partial > PAGE_SIZE) - partial = PAGE_SIZE - (iter->_virt & PAGE_MASK); + if (((uintptr_t)iter->_virt & PAGE_MASK) + partial > PAGE_SIZE) + partial = PAGE_SIZE - ((uintptr_t)iter->_virt & PAGE_MASK); iter->frag = pagedir_virt2phys(iter->_pages, iter->_virt, iter->_user, iter->_writeable); @@ -51,14 +51,14 @@ bool virt_iter_next(struct virt_iter *iter) { } bool virt_cpy( - struct pagedir *dest_pages, user_ptr dest, - struct pagedir *src_pages, const user_ptr src, size_t length) + struct pagedir *dest_pages, void __user *dest, + struct pagedir *src_pages, const void __user *src, size_t length) { struct virt_iter dest_iter, src_iter; size_t min; - virt_iter_new(&dest_iter, dest, length, dest_pages, true, true); - virt_iter_new( &src_iter, src, length, src_pages, true, false); + virt_iter_new(&dest_iter, dest, length, dest_pages, true, true); + virt_iter_new( &src_iter, (userptr_t)src, length, src_pages, true, false); dest_iter.frag_len = 0; src_iter.frag_len = 0; diff --git a/src/kernel/mem/virt.h b/src/kernel/mem/virt.h index 38410fb..7dac887 100644 --- a/src/kernel/mem/virt.h +++ b/src/kernel/mem/virt.h @@ -10,7 +10,7 @@ struct virt_iter { size_t prior; // sum of all prior frag_lens bool error; - user_ptr _virt; + void __user *_virt; size_t _remaining; struct pagedir *_pages; bool _user; @@ -19,11 +19,11 @@ struct virt_iter { /* if pages == NULL, create an iterator over physical memory. */ void virt_iter_new( - struct virt_iter *iter, user_ptr virt, size_t length, + struct virt_iter *iter, void __user *virt, size_t length, struct pagedir *pages, bool user, bool writeable); bool virt_iter_next(struct virt_iter *); bool virt_cpy( - struct pagedir *dest_pages, user_ptr dest, - struct pagedir *src_pages, const user_ptr src, size_t length); + struct pagedir *dest_pages, void __user *dest, + struct pagedir *src_pages, const void __user *src, size_t length); diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 8d363a8..21a1d54 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -26,14 +26,14 @@ struct process *process_seed(void) { proc->handles[i].type = HANDLE_EMPTY; // map the stack to the last page in memory - pagedir_map(proc->pages, ~PAGE_MASK, page_alloc(1), true, true); - proc->stack_top = proc->regs.esp = ~0xF; + pagedir_map(proc->pages, (userptr_t)~PAGE_MASK, page_alloc(1), true, true); + proc->stack_top = proc->regs.esp = (userptr_t) ~0xF; // map the kernel // yup, .text is writeable too. the plan is to not map the kernel // into user memory at all, but i'll implement that later. TODO for (size_t p = 0x100000; p < (size_t)&_bss_end; p += PAGE_SIZE) - pagedir_map(proc->pages, p, (void*)p, false, true); + pagedir_map(proc->pages, (userptr_t)p, (void*)p, false, true); // the kernel still has to load the executable code and set EIP return proc; diff --git a/src/kernel/proc.h b/src/kernel/proc.h index 9553dc2..0628ebf 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -13,7 +13,7 @@ enum process_state { }; struct process { - user_ptr stack_top; + void __user *stack_top; struct pagedir *pages; struct registers regs; enum process_state state; @@ -27,7 +27,7 @@ struct process { // saved value, meaning depends on .state union { struct { // PS_DEAD, PS_WAITS4CHILDDEATH - user_ptr buf; + char __user *buf; size_t len; } death_msg; struct vfs_op_request *pending_req; // PS_WAITS4FS diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index fcd3c1e..ab4fdbb 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -27,9 +27,9 @@ _Noreturn static void await_finish(struct process *dead, struct process *listene } -_Noreturn void _syscall_exit(const user_ptr msg, size_t len) { +_Noreturn void _syscall_exit(const char __user *msg, size_t len) { process_current->state = PS_DEAD; - process_current->death_msg.buf = msg; + process_current->death_msg.buf = (userptr_t) msg; // discarding const process_current->death_msg.len = len; if (process_current->parent->state == PS_WAITS4CHILDDEATH) @@ -42,7 +42,7 @@ _Noreturn void _syscall_exit(const user_ptr msg, size_t len) { process_switch_any(); } -int _syscall_await(user_ptr buf, int len) { +int _syscall_await(char __user *buf, int len) { process_current->state = PS_WAITS4CHILDDEATH; process_current->death_msg.buf = buf; process_current->death_msg.len = len; @@ -67,7 +67,7 @@ int _syscall_fork(void) { return 1; } -handle_t _syscall_open(const user_ptr path, int len) { +handle_t _syscall_open(const char __user *path, int len) { struct vfs_mount *mount; char *path_buf = NULL; @@ -83,7 +83,7 @@ handle_t _syscall_open(const user_ptr path, int len) { // it can handle copies to physical memory too, though // note 2: path_buf gets freed in vfs_backend_finish path_buf = kmalloc(len); - if (!virt_cpy(NULL, (uintptr_t)path_buf, + if (!virt_cpy(NULL, path_buf, process_current->pages, path, len)) goto fail; @@ -107,7 +107,7 @@ fail: return -1; } -int _syscall_mount(handle_t handle, const user_ptr path, int len) { +int _syscall_mount(handle_t handle, const char __user *path, int len) { struct vfs_mount *mount = NULL; char *path_buf; @@ -118,7 +118,7 @@ int _syscall_mount(handle_t handle, const user_ptr path, int len) { // copy the path to the kernel path_buf = kmalloc(len); - if (!virt_cpy(NULL, (uintptr_t)path_buf, + if (!virt_cpy(NULL, path_buf, process_current->pages, path, len)) goto fail; @@ -140,19 +140,19 @@ fail: return -1; } -int _syscall_read(handle_t handle, user_ptr buf, int len) { +int _syscall_read(handle_t handle, char __user *buf, int len) { if (handle < 0 || handle >= HANDLE_MAX) return -1; return -1; } -int _syscall_write(handle_t handle_num, user_ptr buf, int len) { +int _syscall_write(handle_t handle_num, const char __user *buf, int len) { struct handle *handle = &process_current->handles[handle_num]; if (handle_num < 0 || handle_num >= HANDLE_MAX) return -1; if (handle->type != HANDLE_FILE) return -1; vfs_backend_dispatch(handle->file.backend, (struct vfs_op) { .type = VFSOP_WRITE, .rw = { - .buf = buf, + .buf = (userptr_t) buf, .buf_len = len, .id = handle->file.id, } @@ -165,7 +165,7 @@ int _syscall_close(handle_t handle) { return -1; } -handle_t _syscall_fs_create(user_ptr back_user) { +handle_t _syscall_fs_create(handle_t __user *back_user) { handle_t front, back = 0; struct vfs_backend *backend; @@ -180,7 +180,7 @@ handle_t _syscall_fs_create(user_ptr back_user) { // copy the back handle to back_user if (!virt_cpy(process_current->pages, back_user, - NULL, (uintptr_t)&back, sizeof(handle_t))) + NULL, &back, sizeof(handle_t))) goto fail; backend = kmalloc(sizeof *backend); // TODO never freed @@ -200,7 +200,7 @@ fail: return -1; } -int _syscall_fs_wait(handle_t back, user_ptr info) { +int _syscall_fs_wait(handle_t back, void __user *info) { struct handle *back_handle; if (back < 0 || back >= HANDLE_MAX) return -1; @@ -224,25 +224,25 @@ int _syscall_fs_wait(handle_t back, user_ptr info) { int syscall_handler(int num, int a, int b, int c) { switch (num) { case _SYSCALL_EXIT: - _syscall_exit(a, b); + _syscall_exit((userptr_t)a, b); case _SYSCALL_AWAIT: - return _syscall_await(a, b); + return _syscall_await((userptr_t)a, b); case _SYSCALL_FORK: return _syscall_fork(); case _SYSCALL_OPEN: - return _syscall_open(a, b); + return _syscall_open((userptr_t)a, b); case _SYSCALL_MOUNT: - return _syscall_mount(a, b, c); + return _syscall_mount(a, (userptr_t)b, c); case _SYSCALL_READ: - return _syscall_read(a, b, c); + return _syscall_read(a, (userptr_t)b, c); case _SYSCALL_WRITE: - return _syscall_write(a, b, c); + return _syscall_write(a, (userptr_t)b, c); case _SYSCALL_CLOSE: return _syscall_close(a); case _SYSCALL_FS_CREATE: - return _syscall_fs_create(a); + return _syscall_fs_create((userptr_t)a); case _SYSCALL_FS_WAIT: - return _syscall_fs_wait(a, b); + return _syscall_fs_wait(a, (userptr_t)b); default: tty_const("unknown syscall "); panic(); diff --git a/src/kernel/types.h b/src/kernel/types.h index 891e644..44a0d46 100644 --- a/src/kernel/types.h +++ b/src/kernel/types.h @@ -2,4 +2,11 @@ #include #define TYPES_INCLUDED -typedef uintptr_t user_ptr; + +#ifdef __CHECKER__ +# define __user __attribute__((noderef, address_space(__user))) +#else +# define __user +#endif + +typedef void __user * userptr_t; diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h index 7b130c1..2c6a278 100644 --- a/src/shared/syscalls.h +++ b/src/shared/syscalls.h @@ -27,12 +27,12 @@ enum { /** Kills the current process. * TODO: what happens to the children? */ -_Noreturn void _syscall_exit(const user_ptr msg, size_t len); +_Noreturn void _syscall_exit(const char __user *msg, size_t len); /** Waits for a child to exit, putting its exit message into *buf. * @return the length of the message */ -int _syscall_await(user_ptr buf, int len); +int _syscall_await(char __user *buf, int len); /** Creates a copy of the current process, and executes it. * All user memory pages get copied too. @@ -40,16 +40,16 @@ int _syscall_await(user_ptr buf, int len); */ int _syscall_fork(void); -handle_t _syscall_open(const user_ptr path, int len); +handle_t _syscall_open(const char __user *path, int len); -int _syscall_mount(handle_t, const user_ptr path, int len); -int _syscall_read(handle_t, user_ptr buf, int len); -int _syscall_write(handle_t, user_ptr buf, int len); +int _syscall_mount(handle_t, const char __user *path, int len); +int _syscall_read(handle_t, char __user *buf, int len); +int _syscall_write(handle_t, const char __user *buf, int len); int _syscall_close(handle_t); /** Creates a pair of front/back filesystem handles. * @param back a pointer to a handle_t which will store the back pointer */ -handle_t _syscall_fs_create(user_ptr back); +handle_t _syscall_fs_create(handle_t __user *back); -int _syscall_fs_wait(handle_t back, user_ptr info); +int _syscall_fs_wait(handle_t back, void __user *info); diff --git a/src/shared/vfs.h b/src/shared/vfs.h index 9419b11..69891bc 100644 --- a/src/shared/vfs.h +++ b/src/shared/vfs.h @@ -20,7 +20,7 @@ struct vfs_op { int path_len; } open; struct { - user_ptr buf; + char __user *buf; int buf_len; int id; // filled in by the kernel } rw; -- cgit v1.2.3