From d026ce97b8faaa2f3f196281b96df0a04e30e4f9 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Thu, 21 Oct 2021 06:21:34 +0000 Subject: init/shell: fix crash when cat is ran without arguments --- src/init/shell.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/init/shell.c b/src/init/shell.c index 53ad995..33f6da3 100644 --- a/src/init/shell.c +++ b/src/init/shell.c @@ -44,10 +44,13 @@ static int readline(char *buf, size_t max) { } static void cmd_cat(const char *args) { - int fd = _syscall_open(args, strlen(args)); + int fd; static char buf[256]; int len = 256; + if (!args) return; // no argument + + fd = _syscall_open(args, strlen(args)); if (fd < 0) { printf("couldn't open.\n"); return; -- cgit v1.2.3 From d477902853ff07e8aa80fcc10307446680e28749 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Thu, 21 Oct 2021 06:41:24 +0000 Subject: init/shell: add a `catall` cmd - works like the old fs test --- src/init/shell.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/init/shell.c b/src/init/shell.c index 33f6da3..40283f8 100644 --- a/src/init/shell.c +++ b/src/init/shell.c @@ -74,6 +74,16 @@ void shell_loop(void) { printf("%s\n", args); } else if (!strcmp(cmd, "cat")) { cmd_cat(args); + } else if (!strcmp(cmd, "catall")) { + const char *files[] = { + "/init/fake.txt", + "/init/1.txt", "/init/2.txt", + "/init/dir/3.txt", NULL}; + for (int i = 0; files[i]; i++) { + printf("%s:\n", files[i]); + cmd_cat(files[i]); + printf("\n"); + } } else if (!strcmp(cmd, "exit")) { _syscall_exit(0); } else if (!strcmp(cmd, "fork")) { -- cgit v1.2.3 From 6d3960c8fdd361af32f88e4fb1e2deb892166932 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Thu, 21 Oct 2021 06:44:03 +0000 Subject: init/shell: add a `shadow` command for null mounts --- src/init/shell.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/init/shell.c b/src/init/shell.c index 40283f8..7cb8a8c 100644 --- a/src/init/shell.c +++ b/src/init/shell.c @@ -84,6 +84,8 @@ void shell_loop(void) { cmd_cat(files[i]); printf("\n"); } + } else if (!strcmp(cmd, "shadow")) { + _syscall_mount(-1, args, strlen(args)); } else if (!strcmp(cmd, "exit")) { _syscall_exit(0); } else if (!strcmp(cmd, "fork")) { -- cgit v1.2.3 From d7225aa75814788828387ad5871b6aa1dddf2cec Mon Sep 17 00:00:00 2001 From: dzwdz Date: Wed, 3 Nov 2021 07:38:30 +0000 Subject: kernel: implement virt_cpy2kmalloc --- src/kernel/mem/virt.h | 13 +++++++++++++ src/kernel/syscalls.c | 12 +++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/kernel/mem/virt.h b/src/kernel/mem/virt.h index 3a42e9e..b858bdd 100644 --- a/src/kernel/mem/virt.h +++ b/src/kernel/mem/virt.h @@ -1,5 +1,6 @@ /* contains utilities for interacting with virtual memory */ #pragma once +#include #include #include #include @@ -38,3 +39,15 @@ static inline bool virt_cpy_from(struct pagedir *src_pages, // virtual -> physic void *dest, const void __user *src, size_t length) { return virt_cpy(NULL, (userptr_t)dest, src_pages, src, length); } + +/** Copies a chunk of virtual memory to a newly kmalloc'd buffer. */ +static inline void *virt_cpy2kmalloc(struct pagedir *src_pages, + const void __user *src, size_t length) { + void *buf = kmalloc(length); + if (virt_cpy_from(src_pages, buf, src, length)) { + return buf; + } else { + kfree(buf); + return NULL; + } +} diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 22bf1f6..a819b64 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -49,10 +49,8 @@ handle_t _syscall_open(const char __user *path, int len) { if (process_find_handle(process_current) < 0) return -1; - // copy the path to the kernel, simplify it - path_buf = kmalloc(len); // gets freed in vfs_request_finish - if (!virt_cpy_from(process_current->pages, path_buf, path, len)) - goto fail; + path_buf = virt_cpy2kmalloc(process_current->pages, path, len); + if (!path_buf) goto fail; len = path_simplify(path_buf, path_buf, len); if (len < 0) goto fail; @@ -90,9 +88,9 @@ int _syscall_mount(handle_t handle, const char __user *path, int len) { if (PATH_MAX < len) return -1; // copy the path to the kernel to simplify it - path_buf = kmalloc(len); - if (!virt_cpy_from(process_current->pages, path_buf, path, len)) - goto fail; + path_buf = virt_cpy2kmalloc(process_current->pages, path, len); + if (!path_buf) goto fail; + len = path_simplify(path_buf, path_buf, len); if (len < 0) goto fail; -- cgit v1.2.3 From e0ddaaa6290f74fcce6e067c1e5f1c9c87974f4c Mon Sep 17 00:00:00 2001 From: dzwdz Date: Wed, 3 Nov 2021 07:54:29 +0000 Subject: kernel/vfs: tidy up path_simplify, fix a bug and add regression tests the bug related to paths ending with /.. and not resolving to / --- src/kernel/tests/vfs.c | 6 ++++++ src/kernel/vfs/path.c | 27 ++++++++++----------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/kernel/tests/vfs.c b/src/kernel/tests/vfs.c index 8b450e5..339c6bd 100644 --- a/src/kernel/tests/vfs.c +++ b/src/kernel/tests/vfs.c @@ -38,6 +38,12 @@ TEST(path_simplify) { TEST_WRAPPER("/asdf/.", "/asdf/"); TEST_WRAPPER("/asdf//.", "/asdf/"); + TEST_WRAPPER("/foo/bar/..", "/foo/"); + TEST_WRAPPER("/foo/bar/../bar", "/foo/bar"); + TEST_WRAPPER("/foo/bar/../bar/", "/foo/bar/"); + TEST_WRAPPER("/foo/bar/xyz/..", "/foo/bar/"); + TEST_WRAPPER("/foo/bar/xyz/../", "/foo/bar/"); + // going under the root or close to it TEST_WRAPPER("/..", NULL); TEST_WRAPPER("/../asdf", NULL); diff --git a/src/kernel/vfs/path.c b/src/kernel/vfs/path.c index 00af95c..096d3fe 100644 --- a/src/kernel/vfs/path.c +++ b/src/kernel/vfs/path.c @@ -5,7 +5,6 @@ int path_simplify(const char *in, char *out, size_t len) { if (len == 0) return -1; // empty paths are invalid if (in[0] != '/') return -1; // so are relative paths - int depth = 0; // shouldn't be needed! int seg_len; // the length of the current path segment int out_pos = 0; bool directory = 0; @@ -33,32 +32,26 @@ int path_simplify(const char *in, char *out, size_t len) { * (segment starts at i+1) */ if (seg_len == 0 || (seg_len == 1 && in[i + 1] == '.')) { - // the segment is // or /./ + /* // or /./ */ directory = true; } else if (seg_len == 2 && in[i + 1] == '.' && in[i + 2] == '.') { - // the segment is /../ - if (--depth < 0) - return -1; - // backtrack to last slash - while (out[--out_pos] != '/'); + /* /../ */ + directory = true; + + /* try to backtrack to the last slash */ + while (--out_pos >= 0 && out[out_pos] != '/'); + if (out_pos < 0) return -1; } else { - // normal segment + /* a normal segment, e.g. /asdf/ */ out[out_pos] = '/'; memcpy(&out[out_pos + 1], &in[i + 1], seg_len); out_pos += seg_len + 1; - depth++; } } - /* if we were backtracking, out_pos can become 0. i don't like this, - * it feels sloppy. this algorithm should be implemented differently. TODO? */ - if (out_pos == 0) - out[out_pos++] = '/'; - - if (directory) // if the path refers to a directory, append a trailing slash - if (out[out_pos-1] != '/') // unless it's already there - out[out_pos++] = '/'; + /* paths to directories should have a trailing slash */ + if (directory) out[out_pos++] = '/'; return out_pos; } -- cgit v1.2.3