diff options
author | dzwdz | 2023-06-17 22:19:36 +0200 |
---|---|---|
committer | dzwdz | 2023-06-17 23:39:27 +0200 |
commit | b528a54a708c4cd2149c8e6884af2063c2b272cd (patch) | |
tree | ded8aff45f2d5e7f08eb68f710edc7b9b164d5a2 | |
parent | 8929eb838bec8d3f5eb0d5a1c6b91a4f27d0baff (diff) |
kernel: fix procfs overflow bug, add safeguard to prevent similar ones
-rw-r--r-- | src/kernel/arch/amd64/driver/util.h | 1 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 2 | ||||
-rw-r--r-- | src/kernel/vfs/procfs.c | 8 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 4 |
4 files changed, 8 insertions, 7 deletions
diff --git a/src/kernel/arch/amd64/driver/util.h b/src/kernel/arch/amd64/driver/util.h index 4b8bb04..c49b859 100644 --- a/src/kernel/arch/amd64/driver/util.h +++ b/src/kernel/arch/amd64/driver/util.h @@ -4,6 +4,7 @@ #include <stdbool.h> #include <stddef.h> +// TODO put req_readcopy in a global header int req_readcopy(VfsReq *req, const void *buf, size_t len); /* compare request path. path MUST be a static string */ diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 66f8757..ebdf64e 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -295,7 +295,7 @@ long _sys_fs_respond(hid_t hid, const void __user *buf, long ret, int flags) { if (!h || h->type != HANDLE_FS_REQ) SYSCALL_RETURN(-EBADF); VfsReq *req = h->req; if (req) { - if (req->output.len > 0 && ret > 0) { + if (ret > 0 && req->type == VFSOP_READ) { // if this vfsop outputs data and ret is positive, it's the length of the buffer // TODO document // TODO move to vfsreq_finish diff --git a/src/kernel/vfs/procfs.c b/src/kernel/vfs/procfs.c index 7669b78..fc17f1d 100644 --- a/src/kernel/vfs/procfs.c +++ b/src/kernel/vfs/procfs.c @@ -1,4 +1,5 @@ #include <camellia/errno.h> +#include <kernel/arch/amd64/driver/util.h> // portable despite the name #include <kernel/malloc.h> #include <kernel/panic.h> #include <kernel/proc.h> @@ -119,10 +120,6 @@ procfs_accept(VfsReq *req) if (req->type == VFSOP_READ && (h->type == PhDir || h->type == PhRoot)) { // TODO port dirbuild to kernel int pos = 0; - if (req->offset != 0) { - vfsreq_finish_short(req, -ENOSYS); - return; - } if (h->type == PhDir) { pos += snprintf(buf + pos, 512 - pos, "intr")+1; pos += snprintf(buf + pos, 512 - pos, "mem")+1; @@ -136,8 +133,7 @@ procfs_accept(VfsReq *req) } } assert(0 <= pos && (size_t)pos <= sizeof buf); - pcpy_to(req->caller, req->output.buf, buf, pos); - vfsreq_finish_short(req, pos); + vfsreq_finish_short(req, req_readcopy(req, buf, pos)); } else if (req->type == VFSOP_READ && h->type == PhMem) { if (p->pages == NULL || req->caller->pages == NULL) { vfsreq_finish_short(req, 0); diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 410e41e..5723201 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -73,6 +73,10 @@ void vfsreq_finish(VfsReq *req, char __user *stored, long ret, } } + if (req->type == VFSOP_READ && ret >= 0) { + assert((size_t)ret <= req->output.len); + } + if (req->input.kern) kfree(req->input.buf_kern); |