From: Minep Date: Sat, 20 Aug 2022 18:48:37 +0000 (+0100) Subject: feat: mount point flags check X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/96cf56ea15a22b8b362aac6c3ab202d2608e9151 feat: mount point flags check refactor: eliminate edge case when try to access parent of root. chore: minor refactoring, clean-up and small fixes. --- diff --git a/lunaix-os/includes/lunaix/fctrl.h b/lunaix-os/includes/lunaix/fctrl.h index 8a46058..5ec0eef 100644 --- a/lunaix-os/includes/lunaix/fctrl.h +++ b/lunaix-os/includes/lunaix/fctrl.h @@ -25,14 +25,16 @@ __LXSYSCALL4(int, __LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size) -__LXSYSCALL3(int, +__LXSYSCALL4(int, mount, const char*, source, const char*, target, const char*, - fstype) + fstype, + int, + options) __LXSYSCALL1(int, unmount, const char*, target) diff --git a/lunaix-os/includes/lunaix/foptions.h b/lunaix-os/includes/lunaix/foptions.h index f43fb10..0bb6ac4 100644 --- a/lunaix-os/includes/lunaix/foptions.h +++ b/lunaix-os/includes/lunaix/foptions.h @@ -9,4 +9,6 @@ #define FSEEK_CUR 0x2 #define FSEEK_END 0x3 +#define MNT_RO 0x1 + #endif /* __LUNAIX_FOPTIONS_H */ diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index c86c6bc..099d47e 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -120,7 +120,7 @@ struct v_file_ops int (*write)(struct v_inode* inode, void* buffer, size_t len, size_t fpos); int (*read)(struct v_inode* inode, void* buffer, size_t len, size_t fpos); int (*readdir)(struct v_file* file, struct dir_context* dctx); - int (*seek)(struct v_inode* inode, size_t offset); + int (*seek)(struct v_inode* inode, size_t offset); // optional int (*close)(struct v_file* file); int (*sync)(struct v_file* file); }; @@ -140,9 +140,12 @@ struct v_inode_ops int (*rename)(struct v_inode* from_inode, struct v_dnode* from_dnode, struct v_dnode* to_dnode); - int (*getxattr)(struct v_inode* this, struct v_xattr_entry* entry); - int (*setxattr)(struct v_inode* this, struct v_xattr_entry* entry); - int (*delxattr)(struct v_inode* this, struct v_xattr_entry* entry); + int (*getxattr)(struct v_inode* this, + struct v_xattr_entry* entry); // optional + int (*setxattr)(struct v_inode* this, + struct v_xattr_entry* entry); // optional + int (*delxattr)(struct v_inode* this, + struct v_xattr_entry* entry); // optional }; struct v_xattr_entry @@ -202,6 +205,7 @@ struct v_mount struct v_dnode* mnt_point; struct v_superblock* super_block; uint32_t busy_counter; + int flags; }; struct v_dnode @@ -291,7 +295,10 @@ vfs_walk_proc(const char* path, int options); int -vfs_mount(const char* target, const char* fs_name, struct device* device); +vfs_mount(const char* target, + const char* fs_name, + struct device* device, + int options); int vfs_unmount(const char* target); @@ -299,7 +306,8 @@ vfs_unmount(const char* target); int vfs_mount_at(const char* fs_name, struct device* device, - struct v_dnode* mnt_point); + struct v_dnode* mnt_point, + int options); int vfs_unmount_at(struct v_dnode* mnt_point); @@ -407,6 +415,9 @@ vfs_mount_root(const char* fs_name, struct device* device); struct v_mount* vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point); +int +vfs_check_writable(struct v_dnode* dnode); + int default_file_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos); diff --git a/lunaix-os/includes/lunaix/status.h b/lunaix-os/includes/lunaix/status.h index 2368156..0e381b4 100644 --- a/lunaix-os/includes/lunaix/status.h +++ b/lunaix-os/includes/lunaix/status.h @@ -28,5 +28,6 @@ #define ERANGE -23 #define ENOMEM LXOUTOFMEM #define ENOTDEV -24 +#define EOVERFLOW -25 #endif /* __LUNAIX_CODE_H */ diff --git a/lunaix-os/kernel/fs/mount.c b/lunaix-os/kernel/fs/mount.c index aa4acef..7b83757 100644 --- a/lunaix-os/kernel/fs/mount.c +++ b/lunaix-os/kernel/fs/mount.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -95,18 +96,21 @@ vfs_mount_root(const char* fs_name, struct device* device) if (vfs_sysroot->mnt && (errno = vfs_unmount_at(vfs_sysroot))) { return errno; } - return vfs_mount_at(fs_name, device, vfs_sysroot); + return vfs_mount_at(fs_name, device, vfs_sysroot, 0); } int -vfs_mount(const char* target, const char* fs_name, struct device* device) +vfs_mount(const char* target, + const char* fs_name, + struct device* device, + int options) { int errno; struct v_dnode* mnt; if (!(errno = vfs_walk(__current->cwd, target, &mnt, NULL, VFS_WALK_MKPARENT))) { - errno = vfs_mount_at(fs_name, device, mnt); + errno = vfs_mount_at(fs_name, device, mnt, options); } return errno; @@ -128,7 +132,8 @@ vfs_unmount(const char* target) int vfs_mount_at(const char* fs_name, struct device* device, - struct v_dnode* mnt_point) + struct v_dnode* mnt_point, + int options) { if (mnt_point->inode && !(mnt_point->inode->itype & VFS_IFDIR)) { return ENOTDIR; @@ -153,6 +158,8 @@ vfs_mount_at(const char* fs_name, errno = ENOMEM; goto cleanup; } + + mnt_point->mnt->flags = options; } else { goto cleanup; } @@ -188,14 +195,25 @@ vfs_unmount_at(struct v_dnode* mnt_point) return errno; } -__DEFINE_LXSYSCALL3(int, +int +vfs_check_writable(struct v_dnode* dnode) +{ + if ((dnode->mnt->flags & MNT_RO)) { + return EROFS; + } + return 0; +} + +__DEFINE_LXSYSCALL4(int, mount, const char*, source, const char*, target, const char*, - fstype) + fstype, + int, + options) { struct v_dnode *dev, *mnt; int errno = 0; @@ -222,7 +240,7 @@ __DEFINE_LXSYSCALL3(int, goto done; } - errno = vfs_mount_at(fstype, device, mnt); + errno = vfs_mount_at(fstype, device, mnt, options); done: return DO_STATUS(errno); diff --git a/lunaix-os/kernel/fs/path_walk.c b/lunaix-os/kernel/fs/path_walk.c index 0ffbabb..ea5b1c5 100644 --- a/lunaix-os/kernel/fs/path_walk.c +++ b/lunaix-os/kernel/fs/path_walk.c @@ -21,7 +21,7 @@ __vfs_walk(struct v_dnode* start, int i = 0, j = 0; if (depth >= VFS_SYMLINK_DEPTH) { - return ENAMETOOLONG; + return ELOOP; } if (path[0] == VFS_PATH_DELIM || !start) { @@ -36,6 +36,8 @@ __vfs_walk(struct v_dnode* start, i++; } + assert(start); + struct v_dnode* dnode; struct v_inode* current_inode; struct v_dnode* current_level = start; @@ -43,7 +45,7 @@ __vfs_walk(struct v_dnode* start, struct hstr name = HSTR(fname_buffer, 0); char current = path[i++], lookahead; - while (current && current_level) { + while (current) { lookahead = path[i++]; if (current != VFS_PATH_DELIM) { if (j >= VFS_NAME_MAXLEN - 1) { diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index a69803e..83bd0bd 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -104,6 +104,7 @@ vfs_init() // 创建一个根dnode。 vfs_sysroot = vfs_d_alloc(NULL, &vfs_empty); + vfs_sysroot->parent = vfs_sysroot; atomic_fetch_add(&vfs_sysroot->ref_count, 1); } @@ -126,7 +127,7 @@ vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str) return parent; if (HSTR_EQ(str, &vfs_ddot)) { - return parent->parent ? parent->parent : parent; + return parent->parent; } uint32_t hash = str->hash; @@ -235,6 +236,10 @@ vfs_link(struct v_dnode* to_link, struct v_dnode* name) { int errno; + if ((errno = vfs_check_writable(to_link))) { + return errno; + } + lock_inode(to_link->inode); if (to_link->super_block->root != name->super_block->root) { errno = EXDEV; @@ -266,11 +271,16 @@ vfs_close(struct v_file* file) int vfs_fsync(struct v_file* file) { + int errno; + if ((errno = vfs_check_writable(file->dnode))) { + return errno; + } + lock_inode(file->inode); - int errno = ENOTSUP; pcache_commit_all(file->inode); + errno = ENOTSUP; if (file->ops->sync) { errno = file->ops->sync(file); } @@ -476,8 +486,7 @@ __vfs_try_locate_file(const char* path, char name_str[VFS_NAME_MAXLEN]; struct hstr name = HSTR(name_str, 0); int errno; - if ((errno = - vfs_walk(__current->cwd, path, fdir, &name, VFS_WALK_PARENT))) { + if ((errno = vfs_walk_proc(path, fdir, &name, VFS_WALK_PARENT))) { return errno; } @@ -663,6 +672,11 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) } struct v_file* file = fd_s->file; + + if ((errno = vfs_check_writable(file->dnode))) { + goto done; + } + if ((file->inode->itype & VFS_IFDIR)) { errno = EISDIR; goto done; @@ -702,21 +716,30 @@ __DEFINE_LXSYSCALL3(int, lseek, int, fd, int, offset, int, options) struct v_file* file = fd_s->file; + if (!file->ops->seek) { + errno = ENOTSUP; + goto done; + } + lock_inode(file->inode); - size_t fpos = file->f_pos; + int overflow = 0; + int fpos = file->f_pos; switch (options) { case FSEEK_CUR: - fpos = (size_t)((int)file->f_pos + offset); + overflow = __builtin_sadd_overflow((int)file->f_pos, offset, &fpos); break; case FSEEK_END: - fpos = (size_t)((int)file->inode->fsize + offset); + overflow = + __builtin_sadd_overflow((int)file->inode->fsize, offset, &fpos); break; case FSEEK_SET: fpos = offset; break; } - if (!(errno = file->ops->seek(file->inode, fpos))) { + if (overflow) { + errno = EOVERFLOW; + } else if (!(errno = file->ops->seek(file->inode, fpos))) { file->f_pos = fpos; } @@ -729,12 +752,12 @@ done: int vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth) { - if (!dnode) { + if (!dnode || dnode->parent == dnode) { return 0; } if (depth > 64) { - return ELOOP; + return ENAMETOOLONG; } size_t len = vfs_get_path(dnode->parent, buf, size, depth + 1); @@ -743,14 +766,12 @@ vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth) return len; } + buf[len++] = VFS_PATH_DELIM; + size_t cpy_size = MIN(dnode->name.len, size - len); strncpy(buf + len, dnode->name.value, cpy_size); len += cpy_size; - if (len < size) { - buf[len++] = VFS_PATH_DELIM; - } - return len; } @@ -794,8 +815,7 @@ __DEFINE_LXSYSCALL3(int, readlink, const char*, path, char*, buf, size_t, size) { int errno; struct v_dnode* dnode; - if (!(errno = - vfs_walk(__current->cwd, path, &dnode, NULL, VFS_WALK_NOFOLLOW))) { + if (!(errno = vfs_walk_proc(path, &dnode, NULL, VFS_WALK_NOFOLLOW))) { errno = vfs_readlink(dnode, buf, size); } @@ -849,12 +869,16 @@ __DEFINE_LXSYSCALL1(int, rmdir, const char*, pathname) { int errno; struct v_dnode* dnode; - if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) { + if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) { return DO_STATUS(errno); } lock_dnode(dnode); + if ((errno = vfs_check_writable(dnode))) { + goto done; + } + if ((dnode->super_block->fs->types & FSTYPE_ROFS)) { errno = EROFS; goto done; @@ -904,17 +928,18 @@ __DEFINE_LXSYSCALL1(int, mkdir, const char*, path) char name_value[VFS_NAME_MAXLEN]; struct hstr name = HHSTR(name_value, 0, 0); - if (!dir) { - errno = ENOMEM; + if ((errno = vfs_walk_proc(path, &parent, &name, VFS_WALK_PARENT))) { goto done; } - if ((errno = - vfs_walk(__current->cwd, path, &parent, &name, VFS_WALK_PARENT))) { + if ((errno = vfs_check_writable(parent))) { goto done; } - dir = vfs_d_alloc(parent, &name); + if (!(dir = vfs_d_alloc(parent, &name))) { + errno = ENOMEM; + goto done; + } lock_dnode(parent); lock_inode(parent->inode); @@ -942,15 +967,19 @@ done: int __vfs_do_unlink(struct v_dnode* dnode) { + int errno; struct v_inode* inode = dnode->inode; if (dnode->ref_count > 1) { return EBUSY; } + if ((errno = vfs_check_writable(dnode))) { + return errno; + } + lock_inode(inode); - int errno; if (inode->open_count) { errno = EBUSY; } else if (!(inode->itype & VFS_IFDIR)) { @@ -973,11 +1002,7 @@ __DEFINE_LXSYSCALL1(int, unlink, const char*, pathname) { int errno; struct v_dnode* dnode; - if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) { - goto done; - } - if ((dnode->super_block->fs->types & FSTYPE_ROFS)) { - errno = EROFS; + if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) { goto done; } @@ -1026,6 +1051,7 @@ __DEFINE_LXSYSCALL1(int, fsync, int, fildes) { int errno; struct v_fd* fd_s; + if (!(errno = vfs_getfd(fildes, &fd_s))) { errno = vfs_fsync(fd_s->file); } @@ -1112,13 +1138,14 @@ __DEFINE_LXSYSCALL2(int, { int errno; struct v_dnode* dnode; - if ((errno = vfs_walk(__current->cwd, pathname, &dnode, NULL, 0))) { + if ((errno = vfs_walk_proc(pathname, &dnode, NULL, 0))) { goto done; } - if ((dnode->super_block->fs->types & FSTYPE_ROFS)) { - errno = EROFS; + + if (errno = vfs_check_writable(dnode)) { goto done; } + if (!dnode->inode->ops->set_symlink) { errno = ENOTSUP; goto done; @@ -1166,7 +1193,7 @@ __DEFINE_LXSYSCALL1(int, chdir, const char*, path) struct v_dnode* dnode; int errno = 0; - if ((errno = vfs_walk(__current->cwd, path, &dnode, NULL, 0))) { + if ((errno = vfs_walk_proc(path, &dnode, NULL, 0))) { goto done; } @@ -1225,11 +1252,16 @@ done: int vfs_do_rename(struct v_dnode* current, struct v_dnode* target) { + int errno = 0; if (current->inode->id == target->inode->id) { // hard link return 0; } + if (errno = vfs_check_writable(current)) { + return errno; + } + if (current->ref_count > 1 || target->ref_count > 1) { return EBUSY; } @@ -1238,8 +1270,6 @@ vfs_do_rename(struct v_dnode* current, struct v_dnode* target) return EXDEV; } - int errno = 0; - struct v_dnode* oldparent = current->parent; struct v_dnode* newparent = target->parent; @@ -1287,7 +1317,7 @@ __DEFINE_LXSYSCALL2(int, rename, const char*, oldpath, const char*, newpath) struct hstr name = HSTR(valloc(VFS_NAME_MAXLEN), 0); int errno = 0; - if ((errno = vfs_walk(__current->cwd, oldpath, &cur, NULL, 0))) { + if ((errno = vfs_walk_proc(oldpath, &cur, NULL, 0))) { goto done; } diff --git a/lunaix-os/kernel/k_init.c b/lunaix-os/kernel/k_init.c index 1682859..30e06ca 100644 --- a/lunaix-os/kernel/k_init.c +++ b/lunaix-os/kernel/k_init.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -81,7 +82,7 @@ _kernel_init() } // FIXME replace with more specific fs for device. - vfs_mount("/dev", "twifs", NULL); + vfs_mount("/dev", "twifs", NULL, MNT_RO); lxconsole_init();