summaryrefslogtreecommitdiff
path: root/src/user/lib/fs/whitelist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/lib/fs/whitelist.c')
-rw-r--r--src/user/lib/fs/whitelist.c114
1 files changed, 0 insertions, 114 deletions
diff --git a/src/user/lib/fs/whitelist.c b/src/user/lib/fs/whitelist.c
deleted file mode 100644
index 54a79c3..0000000
--- a/src/user/lib/fs/whitelist.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include <camellia/flags.h>
-#include <camellia/syscalls.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <camellia/fs/dir.h>
-#include <camellia/fs/misc.h>
-
-static int dir_seglen2(const char *path, size_t len) {
- /* returns the length of the first segment of the path, including the trailing / (if any). */
- for (size_t i = 0; i < len; i++) {
- if (path[i] == '/')
- return i + 1;
- }
- return len;
-}
-
-/** @return the length of the path w/o suffixes */
-static size_t suffix_parse(const char *path, size_t len, bool *ro_ptr) {
- bool ro = false;
- if (len >= 3 && !memcmp(path + len - 3, ":ro", 3)) {
- ro = true;
- len -= 3;
- }
- if (ro_ptr) *ro_ptr = ro;
- return len;
-}
-
-/** Check if a path is a prefix of another path. */
-// TODO move to libc; tests
-static bool prefix_match(const char *prefix, size_t plen, const char *full, size_t flen) {
- if (flen < plen) return false;
- if (flen == plen)
- return memcmp(full, prefix, flen) == 0;
- return plen >= 1
- && prefix[plen - 1] == '/' /* prefixes must point to one of the parent directories */
- && memcmp(full, prefix, plen) == 0;
-}
-
-void fs_whitelist(const char **whitelist) {
- const size_t buflen = 1024;
- char *buf = malloc(buflen);
- if (!buf) exit(1);
- for (;;) {
- struct ufs_request res;
- hid_t reqh = _sys_fs_wait(buf, buflen, &res);
- if (reqh < 0) break;
-
- char *ipath = res.id; /* the path of the open()ed directory */
-
- switch (res.op) {
- case VFSOP_OPEN: {
- bool error = false;
- bool passthru = false;
- bool inject = false;
-
- for (const char **entry = whitelist; *entry; entry++) {
- bool ro = false;
- size_t entry_len = suffix_parse(*entry, strlen(*entry), &ro);
- /* If *entry is a prefix of the opened path, pass the open() through. */
- if (prefix_match(*entry, entry_len, buf, res.len)) {
- passthru = true;
- if (ro && OPEN_WRITEABLE(res.flags))
- error = true;
- break;
- }
- /* If the path is a prefix of *entry, we might need to inject a directory. */
- if (prefix_match(buf, res.len, *entry, entry_len)) {
- inject = true;
- }
- }
- if (error) {
- _sys_fs_respond(reqh, NULL, -EACCES, 0);
- } else if (passthru) {
- forward_open(reqh, buf, res.len, res.flags);
- } else if (inject) {
- // TODO all the inject points could be precomputed
- ipath = malloc(res.len + 1);
- memcpy(ipath, buf, res.len);
- ipath[res.len] = '\0';
- _sys_fs_respond(reqh, ipath, 0, 0);
- } else {
- _sys_fs_respond(reqh, NULL, -1, 0);
- }
- break;
- }
- case VFSOP_READ:
- case VFSOP_GETSIZE: {
- struct dirbuild db;
- size_t ilen = strlen(ipath);
- char *target = res.op == VFSOP_READ ? buf : NULL;
- dir_start(&db, res.offset, target, buflen);
- for (const char **entry = whitelist; *entry; entry++) {
- // TODO could be precomputed too
- size_t elen = suffix_parse(*entry, strlen(*entry), NULL);
- if (ilen < elen && !memcmp(ipath, *entry, ilen))
- dir_appendl(&db, *entry + ilen, dir_seglen2(*entry + ilen, elen - ilen));
- }
- _sys_fs_respond(reqh, target, dir_finish(&db), 0);
- break;
- }
- case VFSOP_CLOSE: {
- free(ipath);
- _sys_fs_respond(reqh, NULL, 0, 0);
- break;
- }
- default: {
- _sys_fs_respond(reqh, NULL, -1, 0);
- break;
- }
- }
- }
- exit(0);
-}