From 1f7e7501660123ff8f26e8c65e75c2b282b933ef Mon Sep 17 00:00:00 2001 From: dzwdz Date: Fri, 8 Jul 2022 14:40:44 +0200 Subject: syscall/fs_respond: get the file id from the buf argument Previously, file ids could only be positive integers, so their range was 31 bits - not enough to represent the entire memory. Now, pointers can be safely used as file ids. --- src/init/driver/ansiterm.c | 2 +- src/init/driver/tmpfs.c | 21 ++++++++++++--------- src/init/fs/misc.c | 14 +++++++------- src/init/syscalls.c | 2 +- src/init/tar.c | 19 ++++++++----------- src/kernel/arch/i386/driver/fsroot.c | 7 ++++--- src/kernel/handle.h | 2 +- src/kernel/syscalls.c | 4 ++-- src/kernel/vfs/request.c | 7 ++++--- src/kernel/vfs/request.h | 6 +++--- src/shared/syscalls.h | 4 ++-- 11 files changed, 45 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/init/driver/ansiterm.c b/src/init/driver/ansiterm.c index 4d98972..b7f0b04 100644 --- a/src/init/driver/ansiterm.c +++ b/src/init/driver/ansiterm.c @@ -83,7 +83,7 @@ void ansiterm_drv(void) { break; } // TODO check path - _syscall_fs_respond(NULL, 1, 0); + _syscall_fs_respond(NULL, 0, 0); break; case VFSOP_WRITE: diff --git a/src/init/driver/tmpfs.c b/src/init/driver/tmpfs.c index 4b639da..bbed095 100644 --- a/src/init/driver/tmpfs.c +++ b/src/init/driver/tmpfs.c @@ -10,6 +10,7 @@ struct node { }; struct node *root = NULL; +static struct node special_root; static struct node *lookup(const char *path, size_t len) { for (struct node *iter = root; iter; iter = iter->next) { @@ -19,18 +20,18 @@ static struct node *lookup(const char *path, size_t len) { return NULL; } -static int tmpfs_open(const char *path, struct fs_wait_response *res) { - if (res->len == 0) return -1; +static struct node *tmpfs_open(const char *path, struct fs_wait_response *res) { + if (res->len == 0) return NULL; path++; res->len--; - if (res->len == 0) return 0; /* root */ + if (res->len == 0) return &special_root; // no directory support (yet) - if (memchr(path, '/', res->len)) return -1; + if (memchr(path, '/', res->len)) return NULL; if (res->flags & OPEN_CREATE) { - if (lookup(path, res->len)) return -1; /* already exists */ + if (lookup(path, res->len)) return NULL; /* already exists */ struct node *new = malloc(sizeof *new); char *namebuf = malloc(res->len); memcpy(namebuf, path, res->len); @@ -38,24 +39,26 @@ static int tmpfs_open(const char *path, struct fs_wait_response *res) { new->len = res->len; new->next = root; root = new; - return 1; + return new; } - return lookup(path, res->len) != 0 ? 1 : -1; + return lookup(path, res->len); } void tmpfs_drv(void) { // TODO replace all the static allocations in drivers with mallocs static char buf[512]; struct fs_wait_response res; + struct node *ptr; while (!_syscall_fs_wait(buf, sizeof buf, &res)) { switch (res.op) { case VFSOP_OPEN: - _syscall_fs_respond(NULL, tmpfs_open(buf, &res), 0); + ptr = tmpfs_open(buf, &res); + _syscall_fs_respond(ptr, ptr ? 0 : -1, 0); break; case VFSOP_READ: - if (res.id != 0) { + if (res.id != &special_root) { // rw unimplemented _syscall_fs_respond(NULL, -1, 0); break; diff --git a/src/init/fs/misc.c b/src/init/fs/misc.c index b394c26..701db9f 100644 --- a/src/init/fs/misc.c +++ b/src/init/fs/misc.c @@ -188,7 +188,7 @@ void fs_dir_inject(const char *path) { /* if we're making up the opened directory, disallow create */ if (ret < 0 && (res.flags & OPEN_CREATE)) hid = ret; - _syscall_fs_respond(NULL, hid, 0); + _syscall_fs_respond((void*)hid, hid, 0); } else { /* not injecting, don't allow opening nonexistent stuff */ @@ -198,16 +198,16 @@ void fs_dir_inject(const char *path) { break; case VFSOP_CLOSE: - if (handles[res.id].delegate >= 0) - _syscall_close(handles[res.id].delegate); - handles[res.id].taken = false; + if (handles[(int)res.id].delegate >= 0) + _syscall_close(handles[(int)res.id].delegate); + handles[(int)res.id].taken = false; _syscall_fs_respond(NULL, 0, 0); break; case VFSOP_READ: - if (handles[res.id].inject) { + if (handles[(int)res.id].inject) { if (res.offset > 0) _syscall_fs_respond(NULL, 0, 0); // TODO working offsets - struct fs_dir_handle h = handles[res.id]; + struct fs_dir_handle h = handles[(int)res.id]; int out_len = 0; while (h.inject[out_len] && h.inject[out_len] != '/') @@ -232,7 +232,7 @@ void fs_dir_inject(const char *path) { /* fallthrough */ default: { - struct fs_dir_handle h = handles[res.id]; + struct fs_dir_handle h = handles[(int)res.id]; if (h.delegate < 0) _syscall_fs_respond(NULL, -1, 0); else diff --git a/src/init/syscalls.c b/src/init/syscalls.c index f7e540f..14c0d52 100644 --- a/src/init/syscalls.c +++ b/src/init/syscalls.c @@ -42,7 +42,7 @@ int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __us return _syscall(_SYSCALL_FS_WAIT, (int)buf, max_len, (int)res, 0); } -int _syscall_fs_respond(char __user *buf, int ret, int flags) { +int _syscall_fs_respond(void __user *buf, int ret, int flags) { return _syscall(_SYSCALL_FS_RESPOND, (int)buf, ret, flags, 0); } diff --git a/src/init/tar.c b/src/init/tar.c index dfb0396..87236ae 100644 --- a/src/init/tar.c +++ b/src/init/tar.c @@ -5,7 +5,7 @@ #define BUF_SIZE 64 -static int tar_open(const char *path, int len, void *base, size_t base_len); +static void *tar_open(const char *path, int len, void *base, size_t base_len); static void tar_read(struct fs_wait_response *res, void *base, size_t base_len); static int tar_size(void *sector); static void *tar_find(const char *path, size_t path_len, void *base, size_t base_len); @@ -18,6 +18,7 @@ static const char *root_fakemeta = ""; /* see comment in tar_open */ void tar_driver(void *base) { static char buf[BUF_SIZE]; struct fs_wait_response res; + void *ptr; while (!_syscall_fs_wait(buf, BUF_SIZE, &res)) { switch (res.op) { case VFSOP_OPEN: @@ -25,7 +26,8 @@ void tar_driver(void *base) { _syscall_fs_respond(NULL, -1, 0); break; } - _syscall_fs_respond(NULL, tar_open(buf, res.len, base, ~0), 0); + ptr = tar_open(buf, res.len, base, ~0); + _syscall_fs_respond(ptr, ptr ? 0 : -1, 0); break; case VFSOP_READ: @@ -40,10 +42,8 @@ void tar_driver(void *base) { _syscall_exit(0); } -static int tar_open(const char *path, int len, void *base, size_t base_len) { - void *ptr; - - if (len <= 0) return -1; +static void *tar_open(const char *path, int len, void *base, size_t base_len) { + if (len <= 0) return NULL; path += 1; // skip the leading slash len -= 1; @@ -51,12 +51,9 @@ static int tar_open(const char *path, int len, void *base, size_t base_len) { * returning a fake one. this isn't a full entry because i'm currently too * lazy to create a full one - thus, it has to be special cased in tar_read */ if (len == 0) - return (int)root_fakemeta; + return (void*)root_fakemeta; - ptr = tar_find(path, len, base, base_len); - if (!ptr) return -1; - // TODO this won't work if ptr > 0x80000000 - return (int)ptr; + return tar_find(path, len, base, base_len); } static void tar_read(struct fs_wait_response *res, void *base, size_t base_len) { diff --git a/src/kernel/arch/i386/driver/fsroot.c b/src/kernel/arch/i386/driver/fsroot.c index ccba0b6..e16dd80 100644 --- a/src/kernel/arch/i386/driver/fsroot.c +++ b/src/kernel/arch/i386/driver/fsroot.c @@ -45,6 +45,7 @@ static void req_preprocess(struct vfs_request *req, size_t max_len) { static int handle(struct vfs_request *req) { assert(req->caller); + int id = (int)req->id; switch (req->type) { case VFSOP_OPEN: if (req->flags & OPEN_CREATE) return -1; @@ -65,7 +66,7 @@ static int handle(struct vfs_request *req) { return -1; case VFSOP_READ: - switch (req->id) { + switch (id) { case HANDLE_ROOT: { // TODO document directory read format const char src[] = @@ -106,7 +107,7 @@ static int handle(struct vfs_request *req) { char buf[512]; uint32_t sector = req->offset / 512; size_t len = min(req->output.len, 512 - ((size_t)req->offset & 511)); - ata_read(req->id - HANDLE_ATA, sector, buf); + ata_read(id - HANDLE_ATA, sector, buf); virt_cpy_to(req->caller->pages, req->output.buf, buf, len); return len; } @@ -114,7 +115,7 @@ static int handle(struct vfs_request *req) { } case VFSOP_WRITE: - switch (req->id) { + switch (id) { case HANDLE_VGA: { void *vga = (void*)0xB8000; req_preprocess(req, 80*25*2); diff --git a/src/kernel/handle.h b/src/kernel/handle.h index 423ea88..4a5cab2 100644 --- a/src/kernel/handle.h +++ b/src/kernel/handle.h @@ -16,7 +16,7 @@ enum handle_type { struct handle { enum handle_type type; struct vfs_backend *backend; // HANDLE_FILE | HANDLE_FS_FRONT - int file_id; // only applicable to HANDLE_FILE + void __user *file_id; // only applicable to HANDLE_FILE struct { struct process *reader, *writer; } pipe; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index cb26b70..e639d1f 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -246,7 +246,7 @@ int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __us return -1; // dummy } -int _syscall_fs_respond(char __user *buf, int ret, int flags) { +int _syscall_fs_respond(void __user *buf, int ret, int flags) { struct vfs_request *req = process_current->handled_req; if (!req) SYSCALL_RETURN(-1); @@ -261,7 +261,7 @@ int _syscall_fs_respond(char __user *buf, int ret, int flags) { } process_current->handled_req = NULL; - vfsreq_finish(req, ret, flags, process_current); + vfsreq_finish(req, buf, ret, flags, process_current); SYSCALL_RETURN(0); } diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index dfbd5cd..7c677cc 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -29,7 +29,9 @@ void vfsreq_create(struct vfs_request req_) { vfs_backend_tryaccept(req->backend); } -void vfsreq_finish(struct vfs_request *req, int ret, int flags, struct process *handler) { +void vfsreq_finish(struct vfs_request *req, char __user *stored, int ret, + int flags, struct process *handler) +{ if (req->type == VFSOP_OPEN && ret >= 0) { // TODO write tests for caller getting killed while opening a file if (!req->caller) panic_unimplemented(); @@ -43,8 +45,7 @@ void vfsreq_finish(struct vfs_request *req, int ret, int flags, struct process * struct handle *backing = handle_init(HANDLE_FILE); backing->backend = req->backend; req->backend->refcount++; - // TODO file ids can only be 31bit long, so they can't be pointers - backing->file_id = ret; + backing->file_id = stored; req->caller->handles[handle] = backing; } else { /* delegating - moving a handle to the caller */ diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h index 7d36a5d..29f1ee9 100644 --- a/src/kernel/vfs/request.h +++ b/src/kernel/vfs/request.h @@ -47,7 +47,7 @@ struct vfs_request { size_t len; } output; - int id; // handle.file.id + void __user *id; // handle.file.id int offset; int flags; @@ -59,10 +59,10 @@ struct vfs_request { /** Assigns the vfs_request to the caller, and dispatches the call */ void vfsreq_create(struct vfs_request); -void vfsreq_finish(struct vfs_request*, int ret, int flags, struct process *handler); +void vfsreq_finish(struct vfs_request*, char __user *stored, int ret, int flags, struct process *handler); static inline void vfsreq_finish_short(struct vfs_request *req, int ret) { - vfsreq_finish(req, ret, 0, NULL); + vfsreq_finish(req, (void __user *)ret, ret, 0, NULL); } /** Try to accept an enqueued request */ diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h index b9be23d..c6d3c33 100644 --- a/src/shared/syscalls.h +++ b/src/shared/syscalls.h @@ -63,14 +63,14 @@ struct fs_wait_response { enum vfs_operation op; size_t len; // how much was put in *buf size_t capacity; // how much output can be accepted by the caller - int id; // file id (returned by the open handler, passed to other calls) + void __user *id; // file id (returned by the open handler, passed to other calls) int offset; int flags; }; /** Blocks until an fs request is made. * @return 0 if everything was successful */ int _syscall_fs_wait(char __user *buf, int max_len, struct fs_wait_response __user *res); -int _syscall_fs_respond(char __user *buf, int ret, int flags); +int _syscall_fs_respond(void __user *buf, int ret, int flags); /** Modifies the virtual address space. * -- cgit v1.2.3