diff options
author | dzwdz | 2022-10-02 19:25:17 +0200 |
---|---|---|
committer | dzwdz | 2022-10-02 19:25:17 +0200 |
commit | 710e9b2b5c16f74f66420c66d12455ad518d42c7 (patch) | |
tree | 82b88cc07ef3f122512354d649af68584bd4da4d /src/kernel | |
parent | 503d9ff758f8b83295830bdfc8c2ea56837d25e5 (diff) |
syscall/open: add the full suite of READ/WRITE flags
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/handle.h | 3 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 34 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 11 | ||||
-rw-r--r-- | src/kernel/vfs/request.h | 2 |
4 files changed, 33 insertions, 17 deletions
diff --git a/src/kernel/handle.h b/src/kernel/handle.h index 6b095e5..3c16061 100644 --- a/src/kernel/handle.h +++ b/src/kernel/handle.h @@ -19,7 +19,8 @@ struct handle { enum handle_type type; struct vfs_backend *backend; // HANDLE_FILE | HANDLE_FS_FRONT void __user *file_id; // only applicable to HANDLE_FILE - bool ro; /* currently only for HANDLE_FILE */ + // TODO readable/writeable could be reused for pipes + bool readable, writeable; /* currently only for HANDLE_FILE */ struct vfs_request *req; /* HANDLE_FS_REQ */ struct { struct process *queued; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index aa3c28f..dc8f9df 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -83,7 +83,7 @@ handle_t _syscall_open(const char __user *path, long len, int flags) { struct vfs_mount *mount; char *path_buf = NULL; - if (flags & ~(OPEN_CREATE | OPEN_RO)) SYSCALL_RETURN(-ENOSYS); + if (flags & ~(OPEN_RW | OPEN_CREATE)) SYSCALL_RETURN(-ENOSYS); if (PATH_MAX < len) SYSCALL_RETURN(-1); @@ -184,11 +184,16 @@ static long simple_vfsop( enum vfs_operation vfsop, handle_t hid, void __user *buf, size_t len, long offset, int flags) { - assert(vfsop != VFSOP_OPEN && vfsop != VFSOP_CLOSE); + assert(vfsop == VFSOP_READ + || vfsop == VFSOP_WRITE + || vfsop == VFSOP_GETSIZE); struct handle *h = process_handle_get(process_current, hid); if (!h) SYSCALL_RETURN(-1); if (h->type == HANDLE_FILE) { - if (h->ro && !(vfsop == VFSOP_READ || vfsop == VFSOP_GETSIZE)) + // TODO those checks really need some comprehensive tests + if (!h->readable && vfsop == VFSOP_READ) + SYSCALL_RETURN(-EACCES); + if (!h->writeable && vfsop == VFSOP_WRITE) SYSCALL_RETURN(-EACCES); struct vfs_request req = (struct vfs_request){ .type = vfsop, @@ -235,19 +240,22 @@ long _syscall_getsize(handle_t hid) { long _syscall_remove(handle_t hid) { struct handle *h = process_handle_get(process_current, hid); if (!h) SYSCALL_RETURN(-EBADF); - if (!h->ro && h->type == HANDLE_FILE) { - vfsreq_create((struct vfs_request) { - .type = VFSOP_REMOVE, - .id = h->file_id, - .caller = process_current, - .backend = h->backend, - }); + if (h->type != HANDLE_FILE) { process_handle_close(process_current, hid); - return -1; // dummy - } else { + SYSCALL_RETURN(-ENOSYS); + } + if (!h->writeable) { process_handle_close(process_current, hid); - SYSCALL_RETURN(h->ro ? -EACCES : -ENOSYS); + SYSCALL_RETURN(-EACCES); } + vfsreq_create((struct vfs_request) { + .type = VFSOP_REMOVE, + .id = h->file_id, + .caller = process_current, + .backend = h->backend, + }); + process_handle_close(process_current, hid); + return -1; // dummy } long _syscall_close(handle_t hid) { diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 24d5dac..0a377d3 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -23,8 +23,12 @@ void vfsreq_create(struct vfs_request req_) { memcpy(req, &req_, sizeof *req); if (req->backend) req->backend->refcount++; - if (req->type == VFSOP_OPEN && (req->flags & OPEN_RO)) - req->flags &= ~OPEN_CREATE; + if (req->type == VFSOP_OPEN && !(req->flags & OPEN_WRITE) && (req->flags & OPEN_CREATE)) { + vfsreq_finish_short(req, -EINVAL); + return; + } + + // TODO if i add a handle field to vfs_request, check ->readable ->writeable here if (req->backend && req->backend->potential_handlers) { struct vfs_request **iter = &req->backend->queue; @@ -47,7 +51,8 @@ void vfsreq_finish(struct vfs_request *req, char __user *stored, long ret, h = handle_init(HANDLE_FILE); h->backend = req->backend; req->backend->refcount++; h->file_id = stored; - h->ro = req->flags & OPEN_RO; + h->readable = OPEN_READABLE(req->flags); + h->writeable = OPEN_WRITEABLE(req->flags); } else { /* delegating - moving a handle to the caller */ assert(handler); diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h index 4e309b0..db707d0 100644 --- a/src/kernel/vfs/request.h +++ b/src/kernel/vfs/request.h @@ -42,6 +42,8 @@ struct vfs_request { size_t len; } output; + // TODO why doesn't this just have a reference to the handle? + void __user *id; // handle.file.id long offset; int flags; |