diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/handle.h | 1 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 5 | ||||
-rw-r--r-- | src/kernel/vfs/request.c | 8 | ||||
-rw-r--r-- | src/shared/include/camellia/errno.h | 1 | ||||
-rw-r--r-- | src/shared/include/camellia/flags.h | 1 | ||||
-rw-r--r-- | src/user/lib/fs/misc.c | 4 |
6 files changed, 17 insertions, 3 deletions
diff --git a/src/kernel/handle.h b/src/kernel/handle.h index 233c2fa..54ef412 100644 --- a/src/kernel/handle.h +++ b/src/kernel/handle.h @@ -17,6 +17,7 @@ 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 */ struct { struct process *queued; bool write_end; diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 7bc018d..68c0241 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -88,6 +88,8 @@ 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 (PATH_MAX < len) SYSCALL_RETURN(-1); if (process_find_free_handle(process_current, 0) < 0) @@ -210,6 +212,8 @@ static long simple_vfsop( 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)) + SYSCALL_RETURN(-EACCES); struct vfs_request req = (struct vfs_request){ .type = vfsop, .backend = h->backend, @@ -257,6 +261,7 @@ long _syscall_remove(handle_t hid) { struct handle **hslot = &process_current->handles[hid]; struct handle *h = *hslot; if (!h) SYSCALL_RETURN(-1); + if (h->ro) SYSCALL_RETURN(-EACCES); if (h->type == HANDLE_FILE) { vfsreq_create((struct vfs_request) { .type = VFSOP_REMOVE, diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index 82f4731..f4db0db 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -1,5 +1,5 @@ #include <camellia/errno.h> -#include <kernel/arch/amd64/driver/fsroot.h> +#include <camellia/flags.h> #include <kernel/mem/alloc.h> #include <kernel/mem/virt.h> #include <kernel/panic.h> @@ -19,9 +19,10 @@ void vfsreq_create(struct vfs_request req_) { req = kmalloc(sizeof *req); } memcpy(req, &req_, sizeof *req); + if (req->backend) req->backend->refcount++; - if (req->backend) - req->backend->refcount++; + if (req->type == VFSOP_OPEN && (req->flags & OPEN_RO)) + req->flags &= ~OPEN_CREATE; if (req->backend && req->backend->potential_handlers) { struct vfs_request **iter = &req->backend->queue; @@ -51,6 +52,7 @@ void vfsreq_finish(struct vfs_request *req, char __user *stored, long ret, backing->backend = req->backend; req->backend->refcount++; backing->file_id = stored; + backing->ro = req->flags & OPEN_RO; req->caller->handles[handle] = backing; } else { /* delegating - moving a handle to the caller */ diff --git a/src/shared/include/camellia/errno.h b/src/shared/include/camellia/errno.h index e352015..9d3eddc 100644 --- a/src/shared/include/camellia/errno.h +++ b/src/shared/include/camellia/errno.h @@ -8,3 +8,4 @@ #define ENOMEM 7 #define ENOENT 8 #define ENOTEMPTY 9 +#define EACCES 10 diff --git a/src/shared/include/camellia/flags.h b/src/shared/include/camellia/flags.h index 2a208c3..5b8f834 100644 --- a/src/shared/include/camellia/flags.h +++ b/src/shared/include/camellia/flags.h @@ -9,5 +9,6 @@ #define WRITE_TRUNCATE 1 #define OPEN_CREATE 1 +#define OPEN_RO 2 #define FSR_DELEGATE 1 diff --git a/src/user/lib/fs/misc.c b/src/user/lib/fs/misc.c index 16e95e7..038cd3b 100644 --- a/src/user/lib/fs/misc.c +++ b/src/user/lib/fs/misc.c @@ -87,6 +87,10 @@ void fs_whitelist(const char **list) { for (const char **iter = list; *iter; iter++) { size_t len = strlen(*iter); + if (len >= 3 && !memcmp(*iter + len - 3, ":ro", 3)) { + res.flags = res.flags | OPEN_RO; + len -= 3; + } if (len <= res.len && !memcmp(buf, *iter, len)) { passthru = true; break; |