summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2021-09-11 18:04:57 +0200
committerdzwdz2021-09-11 18:04:57 +0200
commitaf2f9184e03015dc3b188ea437bbf496638000ce (patch)
tree4b4186d8df73bc1b96e14e5c8eadcf1a4f66692a
parent0994192f6cab853f4a49ac73aa63f6820c886ec2 (diff)
replace `user_ptr` with a linux-style `__user` annotation
-rw-r--r--src/init/syscalls.c18
-rw-r--r--src/init/types.h3
-rw-r--r--src/kernel/arch/generic.h4
-rw-r--r--src/kernel/arch/i386/pagedir.c16
-rw-r--r--src/kernel/arch/i386/registers.h7
-rw-r--r--src/kernel/arch/i386/sysenter.c8
-rw-r--r--src/kernel/main.c2
-rw-r--r--src/kernel/mem/virt.c14
-rw-r--r--src/kernel/mem/virt.h8
-rw-r--r--src/kernel/proc.c6
-rw-r--r--src/kernel/proc.h4
-rw-r--r--src/kernel/syscalls.c42
-rw-r--r--src/kernel/types.h9
-rw-r--r--src/shared/syscalls.h16
-rw-r--r--src/shared/vfs.h2
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 <kernel/types.h>
#include <stdint.h>
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 <kernel/util.h>
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 <stdint.h>
#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;