summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/handle.h1
-rw-r--r--src/kernel/syscalls.c5
-rw-r--r--src/kernel/vfs/request.c8
-rw-r--r--src/shared/include/camellia/errno.h1
-rw-r--r--src/shared/include/camellia/flags.h1
-rw-r--r--src/user/lib/fs/misc.c4
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;