diff --git a/src/include/kernel/syscalls.h b/src/include/kernel/syscalls.h index 2f5d7d6..09b3400 100644 --- a/src/include/kernel/syscalls.h +++ b/src/include/kernel/syscalls.h @@ -11,7 +11,7 @@ #include #include -#define MAX_SYSCALL 12 // for now +#define MAX_SYSCALL 37 // for now typedef struct SyscallRequest { bool busy, queued, unblock; diff --git a/src/syscalls/dispatch.c b/src/syscalls/dispatch.c index d680fb2..e1a5ffd 100644 --- a/src/syscalls/dispatch.c +++ b/src/syscalls/dispatch.c @@ -6,7 +6,11 @@ */ #include +#include +#include +#include #include +#include #include #include @@ -14,6 +18,26 @@ * their behavior. This ensures the exposed functionality is always as close * as possible to the Unix specification */ +/* syscallVerifyPointer(): ensure user programs don't violate memory permissions + * params: req - syscall request + * params: base - base pointer + * params: len - length of the structure at the point + * returns: true if safe, false if unsafe, user program terminated as well + */ + +bool syscallVerifyPointer(SyscallRequest *req, uintptr_t base, uintptr_t len) { + uintptr_t end = base + len; + if(base < USER_BASE_ADDRESS || end > USER_LIMIT_ADDRESS) { + KWARN("killing tid %d for memory access violation at 0x%X (%d)\n", req->thread->tid, base, len); + terminateThread(req->thread, -1, false); + return false; + } + + return true; +} + +/* Group 1: Scheduler */ + void syscallDispatchExit(SyscallRequest *req) { exit(req->thread, req->params[0]); } @@ -66,6 +90,56 @@ void syscallDispatchMSleep(SyscallRequest *req) { req->ret = msleep(req->thread, req->params[0]); } +/* TODO: Group 2: File System */ + +/* Group 3: Interprocess Communication */ + +void syscallDispatchSocket(SyscallRequest *req) { + req->ret = socket(req->thread, req->params[0], req->params[1], req->params[2]); + req->unblock = true; +} + +void syscallDispatchConnect(SyscallRequest *req) { + if(syscallVerifyPointer(req, req->params[1], req->params[2])) { + req->ret = connect(req->thread, req->params[0], (const struct sockaddr *)req->params[1], req->params[2]); + req->unblock = true; + } +} + +void syscallDispatchBind(SyscallRequest *req) { + if(syscallVerifyPointer(req, req->params[1], req->params[2])) { + req->ret = bind(req->thread, req->params[0], (const struct sockaddr *)req->params[1], req->params[2]); + req->unblock = true; + } +} + +void syscallDispatchListen(SyscallRequest *req) { + req->ret = listen(req->thread, req->params[0], req->params[1]); + req->unblock = true; +} + +void syscallDispatchAccept(SyscallRequest *req) { + int status; + if(!req->params[1]) { + status = accept(req->thread, req->params[0], NULL, NULL); + } else { + if(syscallVerifyPointer(req, req->params[1], sizeof(const struct sockaddr)) && + syscallVerifyPointer(req, req->params[2], sizeof(socklen_t))) { + status = accept(req->thread, req->params[0], (struct sockaddr *)req->params[1], (socklen_t *)req->params[2]); + } + } + + if(status == -EWOULDBLOCK || status == -EAGAIN) { + // return without unblocking if necessary + Process *p = getProcess(req->thread->pid); + if(!(p->io[req->params[0]].flags & O_NONBLOCK)) + req->unblock = false; + } else { + req->ret = status; + req->unblock = true; + } +} + void (*syscallDispatchTable[])(SyscallRequest *) = { /* group 1: scheduler functions */ syscallDispatchExit, // 0 - exit() @@ -81,4 +155,33 @@ void (*syscallDispatchTable[])(SyscallRequest *) = { NULL, // 10 - setuid() NULL, // 11 - setgid() syscallDispatchMSleep, // 12 - msleep() + + /* group 2: file system manipulation */ + NULL, // 13 - open() + NULL, // 14 - close() + NULL, // 15 - read() + NULL, // 16 - write() + NULL, // 17 - stat() + NULL, // 18 - lseek() + NULL, // 19 - chown() + NULL, // 20 - chmod() + NULL, // 21 - link() + NULL, // 22 - unlink() + NULL, // 23 - mknod() + NULL, // 24 - mkdir() + NULL, // 25 - rmdir() + NULL, // 26 - utime() + NULL, // 27 - chroot() + NULL, // 28 - mount() + NULL, // 29 - umount() + NULL, // 30 - fnctl() + + /* group 3: interprocess communication */ + syscallDispatchSocket, // 31 - socket() + syscallDispatchConnect, // 32 - connect() + syscallDispatchBind, // 33 - bind() + syscallDispatchListen, // 34 - listen() + syscallDispatchAccept, // 35 - accept() + NULL, // 36 - recv() + NULL, // 37 - send() };