From: Lunaixsky Date: Tue, 1 Apr 2025 19:08:48 +0000 (+0100) Subject: Multiuser, Capabilities and Access Controls (#54) X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/0fd474df7001837bde53da0e42e83081827c9641?hp=cbc8fdbfe473e23e19690204418e19999a9522d1 Multiuser, Capabilities and Access Controls (#54) * basic user, group and capability housekeeping. add usrscope for process-wise user management implement {get,set}*{uid,euid,gid,egid,groups} syscalls basic acl checking mechanism move common syscall table to arch/generic. * patch file systems with the acl checks make sure the user scope is copied upon fork * syscalls: chroot, fchmodat, fchownat, faccessat enable access check in path walker add default directory permission for ramfs and devfs * release the dnode lock after EACCESS in path walk make struct stats conforming to POSIX minor tweaks stock shell environment for better look and feel * allow specifiying access mode when creating twifs file node twifs: refactor the interface for easy twimap/twifs export cake: fix overflow of index guessing when freeing, causing false positive and possibly failing double free assertion --- diff --git a/README.md b/README.md index 5dc1656..c4a4ea9 100644 --- a/README.md +++ b/README.md @@ -282,22 +282,22 @@ As a personal challenge, this project is independently developed by the author s 2. `mkdir(2)` 2. `lseek(2)` 2. `readdir(2)` -2. `readlink(2)`※ -2. `readlinkat(2)`※ -2. `rmdir(2)`※ -2. `unlink(2)`※ -2. `unlinkat(2)`※ -2. `link(2)`※ -2. `fsync(2)`※ +2. `readlink(2)` +2. `readlinkat(2)` +2. `rmdir(2)` +2. `unlink(2)` +2. `unlinkat(2)` +2. `link(2)` +2. `fsync(2)` 2. `dup(2)` 2. `dup2(2)` -2. `symlink(2)`※ +2. `symlink(2)` 2. `chdir(2)` 2. `fchdir(2)` 2. `getcwd(2)` 2. `rename(2)`※ 2. `mount(2)` -2. `unmount` (a.k.a `umount(2)`)※ +2. `unmount` (a.k.a `umount(2)`) 2. `getxattr(2)`※ 2. `setxattr(2)`※ 2. `fgetxattr(2)`※ @@ -319,6 +319,20 @@ As a personal challenge, this project is independently developed by the author s 4. `pthread_kill` 4. `pthread_detach` 4. `pthread_sigmask` +4. `getuid` +4. `getgid` +4. `geteuid` +4. `getegid` +4. `getgroups` +4. `setuid` +4. `setgid` +4. `seteuid` +4. `setegid` +4. `setgroups` +4. `chroot` +4. `fchmodat` +4. `fchownat` +4. `faccessat` **LunaixOS** diff --git a/lunaix-os/arch/generic/includes/asm-generic/syscall_nr.inc b/lunaix-os/arch/generic/includes/asm-generic/syscall_nr.inc new file mode 100644 index 0000000..0da2e62 --- /dev/null +++ b/lunaix-os/arch/generic/includes/asm-generic/syscall_nr.inc @@ -0,0 +1,82 @@ +#ifndef SYSCALL +# error "SYSCALL missing pointer type" +#endif + +SYSCALL 0 +SYSCALL __lxsys_fork /* 1 */ +SYSCALL __lxsys_yield +SYSCALL __lxsys_sbrk +SYSCALL __lxsys_brk +SYSCALL __lxsys_getpid /* 5 */ +SYSCALL __lxsys_getppid +SYSCALL __lxsys_sleep +SYSCALL __lxsys_exit +SYSCALL __lxsys_wait +SYSCALL __lxsys_waitpid /* 10 */ +SYSCALL __lxsys_sigreturn +SYSCALL __lxsys_sigprocmask +SYSCALL __lxsys_sys_sigaction +SYSCALL __lxsys_pause +SYSCALL __lxsys_kill /* 15 */ +SYSCALL __lxsys_alarm +SYSCALL __lxsys_sigpending +SYSCALL __lxsys_sigsuspend +SYSCALL __lxsys_open +SYSCALL __lxsys_close /* 20 */ +SYSCALL __lxsys_read +SYSCALL __lxsys_write +SYSCALL __lxsys_sys_readdir +SYSCALL __lxsys_mkdir +SYSCALL __lxsys_lseek /* 25 */ +SYSCALL __lxsys_geterrno +SYSCALL __lxsys_readlink +SYSCALL __lxsys_readlinkat +SYSCALL __lxsys_rmdir +SYSCALL __lxsys_unlink /* 30 */ +SYSCALL __lxsys_unlinkat +SYSCALL __lxsys_link +SYSCALL __lxsys_fsync +SYSCALL __lxsys_dup +SYSCALL __lxsys_dup2 /* 35 */ +SYSCALL __lxsys_realpathat +SYSCALL __lxsys_symlink +SYSCALL __lxsys_chdir +SYSCALL __lxsys_fchdir +SYSCALL __lxsys_getcwd /* 40 */ +SYSCALL __lxsys_rename +SYSCALL __lxsys_mount +SYSCALL __lxsys_unmount +SYSCALL __lxsys_getxattr +SYSCALL __lxsys_setxattr /* 45 */ +SYSCALL __lxsys_fgetxattr +SYSCALL __lxsys_fsetxattr +SYSCALL __lxsys_ioctl +SYSCALL __lxsys_getpgid +SYSCALL __lxsys_setpgid /* 50 */ +SYSCALL __lxsys_syslog +SYSCALL __lxsys_sys_mmap +SYSCALL __lxsys_munmap +SYSCALL __lxsys_execve +SYSCALL __lxsys_fstat /* 55 */ +SYSCALL __lxsys_pollctl +SYSCALL __lxsys_th_create +SYSCALL __lxsys_th_self +SYSCALL __lxsys_th_exit +SYSCALL __lxsys_th_join /* 60 */ +SYSCALL __lxsys_th_kill +SYSCALL __lxsys_th_detach +SYSCALL __lxsys_th_sigmask +SYSCALL __lxsys_getuid +SYSCALL __lxsys_getgid +SYSCALL __lxsys_geteuid +SYSCALL __lxsys_getegid +SYSCALL __lxsys_getgroups +SYSCALL __lxsys_setuid +SYSCALL __lxsys_setgid +SYSCALL __lxsys_seteuid +SYSCALL __lxsys_setegid +SYSCALL __lxsys_setgroups +SYSCALL __lxsys_chroot +SYSCALL __lxsys_fchmodat +SYSCALL __lxsys_fchownat +SYSCALL __lxsys_faccessat \ No newline at end of file diff --git a/lunaix-os/arch/x86/LBuild b/lunaix-os/arch/x86/LBuild index 941453b..ed4b4f8 100644 --- a/lunaix-os/arch/x86/LBuild +++ b/lunaix-os/arch/x86/LBuild @@ -29,7 +29,8 @@ sources([ "gdbstub.c", "trace.c", "hart.c", - "failsafe.S" + "failsafe.S", + "syscall_lut.S" ]) sources({ diff --git a/lunaix-os/arch/x86/syscall32.S b/lunaix-os/arch/x86/syscall32.S index b8915ed..3fb96b4 100644 --- a/lunaix-os/arch/x86/syscall32.S +++ b/lunaix-os/arch/x86/syscall32.S @@ -1,6 +1,5 @@ #define __ASM__ #include -#include "syscall_nr.inc" .section .text .type syscall_hndlr, @function @@ -16,7 +15,7 @@ jae 2f shll $2, %eax - addl $syscall_table, %eax + addl $__syscall_table, %eax cmpl $0, (%eax) jne 1f 2: diff --git a/lunaix-os/arch/x86/syscall64.S b/lunaix-os/arch/x86/syscall64.S index 6125a84..cce528a 100644 --- a/lunaix-os/arch/x86/syscall64.S +++ b/lunaix-os/arch/x86/syscall64.S @@ -1,6 +1,5 @@ #define __ASM__ #include -#include "syscall_nr.inc" #include "asm/variants/interrupt64.S.inc" .section .text @@ -18,7 +17,7 @@ jae 2f shlq $3, %rax // %rax * 8 - movabsq $syscall_table, %r8 + movabsq $__syscall_table, %r8 addq %r8, %rax cmpq $0, (%rax) jne 1f diff --git a/lunaix-os/arch/x86/syscall_lut.S b/lunaix-os/arch/x86/syscall_lut.S new file mode 100644 index 0000000..4bee0b4 --- /dev/null +++ b/lunaix-os/arch/x86/syscall_lut.S @@ -0,0 +1,20 @@ +#define __ASM__ +#include + +#ifdef CONFIG_ARCH_X86_64 +# define SYSCALL .8byte +# define SIZE 8 +#else +# define SIZE 4 +# define SYSCALL .4byte +#endif + +.section .data + .global __syscall_table + __syscall_table: + 1: + #include "syscall_nr.inc" + 2: + .rept __SYSCALL_MAX - (2b - 1b) / SIZE + .long 0 + .endr \ No newline at end of file diff --git a/lunaix-os/arch/x86/syscall_nr.inc b/lunaix-os/arch/x86/syscall_nr.inc index c30a720..85762da 100644 --- a/lunaix-os/arch/x86/syscall_nr.inc +++ b/lunaix-os/arch/x86/syscall_nr.inc @@ -1,79 +1,3 @@ -#ifdef CONFIG_ARCH_X86_64 -# define PTR .8byte -# define SIZE 8 -#else -# define PTR .4byte -# define SIZE 4 -#endif +#include -.section .data - syscall_table: - 1: - PTR 0 - PTR __lxsys_fork /* 1 */ - PTR __lxsys_yield - PTR __lxsys_sbrk - PTR __lxsys_brk - PTR __lxsys_getpid /* 5 */ - PTR __lxsys_getppid - PTR __lxsys_sleep - PTR __lxsys_exit - PTR __lxsys_wait - PTR __lxsys_waitpid /* 10 */ - PTR __lxsys_sigreturn - PTR __lxsys_sigprocmask - PTR __lxsys_sys_sigaction - PTR __lxsys_pause - PTR __lxsys_kill /* 15 */ - PTR __lxsys_alarm - PTR __lxsys_sigpending - PTR __lxsys_sigsuspend - PTR __lxsys_open - PTR __lxsys_close /* 20 */ - PTR __lxsys_read - PTR __lxsys_write - PTR __lxsys_sys_readdir - PTR __lxsys_mkdir - PTR __lxsys_lseek /* 25 */ - PTR __lxsys_geterrno - PTR __lxsys_readlink - PTR __lxsys_readlinkat - PTR __lxsys_rmdir - PTR __lxsys_unlink /* 30 */ - PTR __lxsys_unlinkat - PTR __lxsys_link - PTR __lxsys_fsync - PTR __lxsys_dup - PTR __lxsys_dup2 /* 35 */ - PTR __lxsys_realpathat - PTR __lxsys_symlink - PTR __lxsys_chdir - PTR __lxsys_fchdir - PTR __lxsys_getcwd /* 40 */ - PTR __lxsys_rename - PTR __lxsys_mount - PTR __lxsys_unmount - PTR __lxsys_getxattr - PTR __lxsys_setxattr /* 45 */ - PTR __lxsys_fgetxattr - PTR __lxsys_fsetxattr - PTR __lxsys_ioctl - PTR __lxsys_getpgid - PTR __lxsys_setpgid /* 50 */ - PTR __lxsys_syslog - PTR __lxsys_sys_mmap - PTR __lxsys_munmap - PTR __lxsys_execve - PTR __lxsys_fstat /* 55 */ - PTR __lxsys_pollctl - PTR __lxsys_th_create - PTR __lxsys_th_self - PTR __lxsys_th_exit - PTR __lxsys_th_join /* 60 */ - PTR __lxsys_th_kill - PTR __lxsys_th_detach - PTR __lxsys_th_sigmask - 2: - .rept __SYSCALL_MAX - (2b - 1b) / SIZE - .long 0 - .endr \ No newline at end of file +// arch specifics syscalls goes here diff --git a/lunaix-os/hal/ahci/hbadev_export.c b/lunaix-os/hal/ahci/hbadev_export.c index 3fea81d..f6c52bf 100644 --- a/lunaix-os/hal/ahci/hbadev_export.c +++ b/lunaix-os/hal/ahci/hbadev_export.c @@ -3,14 +3,14 @@ #include void -__blk_rd_serial(struct twimap* map) +__twimap_read_serial(struct twimap* map) { struct hba_device* hbadev = twimap_data(map, struct hba_device*); twimap_printf(map, "%s", hbadev->serial_num); } void -__blk_rd_last_status(struct twimap* map) +__twimap_read_last_status(struct twimap* map) { struct hba_device* hbadev = twimap_data(map, struct hba_device*); twimap_printf(map, @@ -21,21 +21,21 @@ __blk_rd_last_status(struct twimap* map) } void -__blk_rd_capabilities(struct twimap* map) +__twimap_read_capabilities(struct twimap* map) { struct hba_device* hbadev = twimap_data(map, struct hba_device*); twimap_printf(map, "%p", hbadev->capabilities); } void -__blk_rd_aoffset(struct twimap* map) +__twimap_read_alignment(struct twimap* map) { struct hba_device* hbadev = twimap_data(map, struct hba_device*); twimap_printf(map, "%d", hbadev->alignment_offset); } void -__blk_rd_wwid(struct twimap* map) +__twimap_read_wwid(struct twimap* map) { struct hba_device* hbadev = twimap_data(map, struct hba_device*); u32_t h = hbadev->wwn >> 32; @@ -53,18 +53,9 @@ ahci_fsexport(struct block_dev* bdev, void* fs_node) struct twifs_node* dev_root = (struct twifs_node*)fs_node; struct twimap* map; - map = twifs_mapping(dev_root, bdev->driver, "serial"); - map->read = __blk_rd_serial; - - map = twifs_mapping(dev_root, bdev->driver, "last_status"); - map->read = __blk_rd_last_status; - - map = twifs_mapping(dev_root, bdev->driver, "wwid"); - map->read = __blk_rd_wwid; - - map = twifs_mapping(dev_root, bdev->driver, "capabilities"); - map->read = __blk_rd_capabilities; - - map = twifs_mapping(dev_root, bdev->driver, "alignment_offset"); - map->read = __blk_rd_aoffset; + twimap_export_value(dev_root, serial, FSACL_aR, bdev->driver); + twimap_export_value(dev_root, last_status, FSACL_aR, bdev->driver); + twimap_export_value(dev_root, wwid, FSACL_aR, bdev->driver); + twimap_export_value(dev_root, capabilities, FSACL_aR, bdev->driver); + twimap_export_value(dev_root, alignment, FSACL_aR, bdev->driver); } \ No newline at end of file diff --git a/lunaix-os/hal/bus/pci.c b/lunaix-os/hal/bus/pci.c index 0543d0a..cbad179 100644 --- a/lunaix-os/hal/bus/pci.c +++ b/lunaix-os/hal/bus/pci.c @@ -371,7 +371,7 @@ pci_apply_command(struct pci_probe* probe, pci_reg_t cmd) } static void -__pci_read_cspace(struct twimap* map) +__twimap_read_config(struct twimap* map) { struct pci_probe* probe; @@ -388,7 +388,7 @@ __pci_read_cspace(struct twimap* map) /*---------- TwiFS interface definition ----------*/ static void -__pci_read_revid(struct twimap* map) +__twimap_read_revision(struct twimap* map) { struct pci_probe* probe; @@ -397,7 +397,7 @@ __pci_read_revid(struct twimap* map) } static void -__pci_read_class(struct twimap* map) +__twimap_read_class(struct twimap* map) { struct pci_probe* probe; @@ -406,7 +406,7 @@ __pci_read_class(struct twimap* map) } static void -__pci_read_devinfo(struct twimap* map) +__twimap_read_pci_devinfo(struct twimap* map) { struct pci_probe* probe; @@ -417,7 +417,7 @@ __pci_read_devinfo(struct twimap* map) } static void -__pci_bar_read(struct twimap* map) +__twimap_read_io_bases(struct twimap* map) { struct pci_probe* probe; int bar_index; @@ -448,7 +448,7 @@ __pci_bar_read(struct twimap* map) } static int -__pci_bar_gonext(struct twimap* map) +__twimap_gonext_io_bases(struct twimap* map) { if (twimap_index(map, int) >= 5) { return 0; @@ -458,7 +458,13 @@ __pci_bar_gonext(struct twimap* map) } static void -__pci_read_binding(struct twimap* map) +__twimap_reset_io_bases(struct twimap* map) +{ + map->index = 0; +} + +static void +__twimap_read_binding(struct twimap* map) { struct pci_probe* probe; struct devident* devid; @@ -499,21 +505,11 @@ pci_build_fsmapping() probe = changeling_reveal(pos, pci_probe_morpher); pci_dev = twifs_dir_node(pci_class, "%x", probe->loc); - map = twifs_mapping(pci_dev, probe, "config"); - map->read = __pci_read_cspace; - - map = twifs_mapping(pci_dev, probe, "revision"); - map->read = __pci_read_revid; - - map = twifs_mapping(pci_dev, probe, "class"); - map->read = __pci_read_class; - - map = twifs_mapping(pci_dev, probe, "binding"); - map->read = __pci_read_binding; - - map = twifs_mapping(pci_dev, probe, "io_bases"); - map->read = __pci_bar_read; - map->go_next = __pci_bar_gonext; + twimap_export_value(pci_dev, config, FSACL_aR, probe); + twimap_export_value(pci_dev, revision, FSACL_aR, probe); + twimap_export_value(pci_dev, class, FSACL_aR, probe); + twimap_export_value(pci_dev, binding, FSACL_aR, probe); + twimap_export_list (pci_dev, io_bases, FSACL_aR, probe); } } EXPORT_TWIFS_PLUGIN(pci_devs, pci_build_fsmapping); diff --git a/lunaix-os/hal/rtc/rtc_device.c b/lunaix-os/hal/rtc/rtc_device.c index 396c9bb..8676b3f 100644 --- a/lunaix-os/hal/rtc/rtc_device.c +++ b/lunaix-os/hal/rtc/rtc_device.c @@ -166,7 +166,9 @@ static void hwrtc_twifs_export(struct hwrtc_potens* pot) { const char* name = pot->rtc_proxy->name_val; - struct twimap* rtc_mapping = twifs_mapping(NULL, pot, name); + struct twimap* rtc_mapping; + + rtc_mapping = twifs_mapping(NULL, pot, FSACL_aR, name); rtc_mapping->read = __hwrtc_readinfo; } diff --git a/lunaix-os/includes/lunaix/compiler.h b/lunaix-os/includes/lunaix/compiler.h index a41c741..aea7e58 100644 --- a/lunaix-os/includes/lunaix/compiler.h +++ b/lunaix-os/includes/lunaix/compiler.h @@ -39,8 +39,9 @@ #define prefetch_rd(ptr, ll) __builtin_prefetch((ptr), 0, ll) #define prefetch_wr(ptr, ll) __builtin_prefetch((ptr), 1, ll) -#define stringify(v) #v -#define stringify__(v) stringify(v) +#define v__(v) (v) +#define stringify(v) #v +#define stringify__(v) stringify(v) #define compact __attribute__((packed)) #define align(v) __attribute__((aligned (v))) diff --git a/lunaix-os/includes/lunaix/exec.h b/lunaix-os/includes/lunaix/exec.h index 64e0f2d..50f9489 100644 --- a/lunaix-os/includes/lunaix/exec.h +++ b/lunaix-os/includes/lunaix/exec.h @@ -14,6 +14,7 @@ struct load_context { struct exec_host* container; + ptr_t base; ptr_t end; ptr_t mem_sz; @@ -36,6 +37,7 @@ struct exec_host ptr_t vms_mnt; struct load_context exe; + struct v_inode* inode; struct exec_arrptr argv; struct exec_arrptr envp; diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 6feb2aa..bba939c 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -248,6 +249,11 @@ struct v_inode u32_t link_count; u32_t lb_usage; u32_t fsize; + + u32_t acl; + uid_t uid; + gid_t gid; + void* data; // 允许底层FS绑定他的一些专有数据 struct llist_header aka_dnodes; struct llist_header xattrs; @@ -389,6 +395,10 @@ vfs_walk_proc(const char* path, struct hstr* component, int options); +int +vfs_walkat(int fd, const char* path, int at_opts, + struct v_dnode** dnode_out); + int vfs_mount(const char* target, const char* fs_name, @@ -707,4 +717,28 @@ check_symlink_node(struct v_inode* inode) return check_itype(inode->itype, VFS_IFSYMLINK); } +static inline bool +check_allow_ops(struct v_inode* inode, unsigned int perm) +{ + return fsacl_allow_ops(perm, inode->acl, inode->uid, inode->gid); +} + +static inline bool +check_allow_read(struct v_inode* inode) +{ + return check_allow_ops(inode, FSACL_aR); +} + +static inline bool +check_allow_write(struct v_inode* inode) +{ + return check_allow_ops(inode, FSACL_aW); +} + +static inline bool +check_allow_execute(struct v_inode* inode) +{ + return check_allow_ops(inode, FSACL_aX); +} + #endif /* __LUNAIX_VFS_H */ diff --git a/lunaix-os/includes/lunaix/fs/api.h b/lunaix-os/includes/lunaix/fs/api.h index d002774..e9c1437 100644 --- a/lunaix-os/includes/lunaix/fs/api.h +++ b/lunaix-os/includes/lunaix/fs/api.h @@ -160,6 +160,19 @@ fsapi_inode_settime(struct v_inode* inode, inode->atime = atime; } +static inline void +fsapi_inode_setaccess(struct v_inode* inode, unsigned int acl) +{ + inode->acl = acl; +} + +static inline void +fsapi_inode_setowner(struct v_inode* inode, uid_t uid, gid_t gid) +{ + inode->uid = uid; + inode->gid = gid; +} + static inline void fsapi_dnode_setdector(struct v_dnode* dnode, dnode_free free_cb) diff --git a/lunaix-os/includes/lunaix/fs/twifs.h b/lunaix-os/includes/lunaix/fs/twifs.h index 50579ae..733db19 100644 --- a/lunaix-os/includes/lunaix/fs/twifs.h +++ b/lunaix-os/includes/lunaix/fs/twifs.h @@ -6,26 +6,44 @@ #include #include +struct twifs_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); +}; + struct twifs_node { struct hstr name; inode_t ino_id; void* data; u32_t itype; + int acl; + char name_val[VFS_NAME_MAXLEN]; struct llist_header children; struct llist_header siblings; - struct - { - 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); - } ops; + struct twifs_ops ops; +}; + +struct twifs_export +{ + char* name; + int acl; + struct twifs_ops ops; +}; + +struct twimap_export +{ + char* name; + int acl; + struct twimap_ops ops; }; #define twinode_getdata(inode, type) \ @@ -38,32 +56,78 @@ struct twifs_node #define EXPORT_TWIFS_PLUGIN(label, plg_init) \ export_ldga_el(twiplugin_inits, label, ptr_t, plg_init) -void -twifs_register_plugins(); +#define __twifs_export_base(name_, acl_) \ + .name=stringify(name_), .acl=(acl_) + +#define twifs_node_ro(name_, acl_) \ + struct twifs_export __twifs_exp_##name_ = \ + { __twifs_export_base(name_, acl_), \ + .ops = { .read = __twifs_read_##name_ }} + +#define twifs_node_rw(name_, acl_) \ + struct twifs_export __twifs_exp_##name_ = \ + { __twifs_export_base(name_, acl_), \ + .ops = { .read = __twifs_read_##name_, \ + .write = __twifs_write_##name_ }} + +#define twimap_value_export(name_, acl_) \ + struct twimap_export __twimap_exp_##name_ = \ + { __twifs_export_base(name_, acl_), \ + .ops = { .read = __twimap_read_##name_ }} + +#define twimap_list_export(name_, acl_) \ + struct twimap_export __twimap_exp_##name_ = \ + { __twifs_export_base(name_, acl_), \ + .ops = { .read = __twimap_read_##name_, \ + .go_next = __twimap_gonext_##name_, \ + .reset = __twimap_reset_##name_, }} + +#define twifs_export(parent, name_, data_) \ + twifs_basic_node_from(parent, &__twifs_exp_##name_, data_) + +#define twimap_export(parent, name_, data_) \ + twifs_mapped_node_from(parent, &__twimap_exp_##name_, data_) + +#define twifs_export_ro(parent, name_, acl_, data_) \ + ({ \ + twifs_node_ro(name_, acl_); \ + twifs_export(parent, name_, data_); \ + }) + +#define twimap_export_value(parent, name_, acl_, data_) \ + ({ \ + twimap_value_export(name_, acl_); \ + twimap_export(parent, name_, data_); \ + }) + +#define twimap_export_list(parent, name_, acl_, data_) \ + ({ \ + twimap_list_export(name_, acl_); \ + twimap_export(parent, name_, data_); \ + }) void -twifs_init(); +twifs_register_plugins(); struct twifs_node* twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args); -struct twifs_node* -twifs_file_node(struct twifs_node* parent, const char* fmt, ...); - struct twifs_node* twifs_dir_node(struct twifs_node* parent, const char* fmt, ...); int twifs_rm_node(struct twifs_node* node); -struct twimap* -twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...); +struct twifs_node* +twifs_basic_node_from(struct twifs_node* parent, + struct twifs_export* exp_def, void* data); -#define twimap_entry_simple(parent, name, data, read_cb) \ - ({ \ - struct twimap* map = twifs_mapping((parent), (data), (name)); \ - map->read = (read_cb); \ - map; \ - }) +struct twifs_node* +twifs_mapped_node_from(struct twifs_node* parent, + struct twimap_export* exp_def, void* data); + +struct twimap* +twifs_mapping(struct twifs_node* parent, + void* data, int acl, const char* fmt, ...); #endif /* __LUNAIX_TWIFS_H */ diff --git a/lunaix-os/includes/lunaix/fs/twimap.h b/lunaix-os/includes/lunaix/fs/twimap.h index c9d56a2..3086c63 100644 --- a/lunaix-os/includes/lunaix/fs/twimap.h +++ b/lunaix-os/includes/lunaix/fs/twimap.h @@ -8,15 +8,29 @@ extern struct v_file_ops twimap_file_ops; +#define __TWIMAP_OPS \ + void (*read)(struct twimap* mapping); \ + int (*go_next)(struct twimap* mapping); \ + void (*reset)(struct twimap* mapping); + +struct twimap; +struct twimap_ops +{ + __TWIMAP_OPS +}; + struct twimap { void* index; void* buffer; void* data; size_t size_acc; - void (*read)(struct twimap* mapping); - int (*go_next)(struct twimap* mapping); - void (*reset)(struct twimap* mapping); + union + { + struct twimap_ops ops; + struct { __TWIMAP_OPS }; + }; + }; int diff --git a/lunaix-os/includes/lunaix/fs_acl.h b/lunaix-os/includes/lunaix/fs_acl.h new file mode 100644 index 0000000..43ab5e2 --- /dev/null +++ b/lunaix-os/includes/lunaix/fs_acl.h @@ -0,0 +1,76 @@ +#ifndef __LUNAIX_FS_ACL_H +#define __LUNAIX_FS_ACL_H + +#include +#include "compiler.h" + +#define FSACL_READ 4 +#define FSACL_WRITE 2 +#define FSACL_EXEC 1 + +#define FSACL_MASK 03777 +#define FSACL_RWXMASK 0777 +#define FSACL_U(x) (((x) & 0b111) << 6) +#define FSACL_G(x) (((x) & 0b111) << 3) +#define FSACL_O(x) ((x) & 0b111) + +#define FSACL_uR FSACL_U(FSACL_READ) +#define FSACL_uW FSACL_U(FSACL_WRITE) +#define FSACL_uX FSACL_U(FSACL_EXEC) + +#define FSACL_gR FSACL_G(FSACL_READ) +#define FSACL_gW FSACL_G(FSACL_WRITE) +#define FSACL_gX FSACL_G(FSACL_EXEC) + +#define FSACL_oR FSACL_O(FSACL_READ) +#define FSACL_oW FSACL_O(FSACL_WRITE) +#define FSACL_oX FSACL_O(FSACL_EXEC) + +#define FSACL_suid 04000 +#define FSACL_sgid 02000 +#define FSACL_svtx 01000 + +// permitted read (any usr or group matched) +#define FSACL_RD (FSACL_uRD | FSACL_gRD) +// permitted write (any usr or group matched) +#define FSACL_WR (FSACL_uWR | FSACL_gWR) +// permitted execute (any usr or group matched) +#define FSACL_X (FSACL_uX | FSACL_gX) + +#define FSACL_u_ 0 +#define FSACL_g_ 0 +#define FSACL_o_ 0 + +// any +#define FSACL_aR (FSACL_uR | FSACL_gR | FSACL_oR) +#define FSACL_aW (FSACL_uW | FSACL_gW | FSACL_oW) +#define FSACL_aX (FSACL_uX | FSACL_gX | FSACL_oX) + +// user/group +#define FSACL_ugR (FSACL_uR | FSACL_gR) +#define FSACL_ugW (FSACL_uW | FSACL_gW) +#define FSACL_ugX (FSACL_uX | FSACL_gX) + + +#define __fsacl_sel(scope, type) (FSACL_##scope##type) +#define FSACL_u(r, w, x) \ + (v__(__fsacl_sel(u, r)) | v__(__fsacl_sel(u, w)) | v__(__fsacl_sel(u, x))) + +#define FSACL_g(r, w, x) \ + (v__(__fsacl_sel(g, r)) | v__(__fsacl_sel(g, w)) | v__(__fsacl_sel(g, x))) + +#define FSACL_o(r, w, x) \ + (v__(__fsacl_sel(o, r)) | v__(__fsacl_sel(o, w)) | v__(__fsacl_sel(o, x))) + +#define FSACL_DEFAULT \ + (FSACL_u(R, W, X) | FSACL_g(R, W, X) | FSACL_o(R, _, X)) + +#define fsacl_test(acl, type) ((acl) & (FSACL_##type)) + +static inline bool must_inline +fsacl_allow_ops(unsigned int ops, unsigned int acl, uid_t uid, gid_t gid) +{ + return !!(acl & ops & check_current_acl(uid, gid)); +} + +#endif /* __LUNAIX_FS_ACL_H */ diff --git a/lunaix-os/includes/lunaix/limits.h b/lunaix-os/includes/lunaix/limits.h new file mode 100644 index 0000000..9855801 --- /dev/null +++ b/lunaix-os/includes/lunaix/limits.h @@ -0,0 +1,6 @@ +#ifndef __LUNAIX_LIMITS_H +#define __LUNAIX_LIMITS_H + +#define NGROUPS_MAX 128 + +#endif /* __LUNAIX_LIMITS_H */ diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index 86e485e..868a9fc 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -13,6 +13,8 @@ #include #include #include +#include + #include @@ -113,7 +115,7 @@ struct thread { /* Any change to *critical section*, including layout, size - must be reflected in arch/x86/interrupt.S.inc to avoid + must be reflected in arch//interrupt.S.inc to avoid disaster! */ struct @@ -167,6 +169,14 @@ struct proc_info pid_t pgid; time_t created; + uid_t euid; + uid_t suid; + gid_t egid; + gid_t sgid; + + struct user_scope uscope; + struct v_dnode* root; + int state; int exit_code; }; @@ -463,5 +473,40 @@ thread_stats_user_elapse(struct thread* thread) return stats->last_entry - stats->last_leave; } +static inline struct user_scope* +current_user_scope() +{ + return &__current->uscope; +} + +static inline uid_t must_inline +current_euid() +{ + return __current->euid; +} + +static inline bool must_inline +current_is_root() +{ + return current_euid() == 0; +} + +static inline gid_t must_inline +current_egid() +{ + return __current->egid; +} + +static inline void must_inline +current_set_egid(gid_t gid) +{ + __current->egid = gid; +} + +static inline void must_inline +current_set_euid(uid_t uid) +{ + __current->euid = uid; +} #endif /* __LUNAIX_PROCESS_H */ diff --git a/lunaix-os/includes/lunaix/types.h b/lunaix-os/includes/lunaix/types.h index e065273..6ce5fcf 100644 --- a/lunaix-os/includes/lunaix/types.h +++ b/lunaix-os/includes/lunaix/types.h @@ -2,6 +2,7 @@ #define __LUNAIX_TYPES_H #include +#include #include #include diff --git a/lunaix-os/includes/lunaix/usercaps.h b/lunaix-os/includes/lunaix/usercaps.h new file mode 100644 index 0000000..b30aea9 --- /dev/null +++ b/lunaix-os/includes/lunaix/usercaps.h @@ -0,0 +1,19 @@ +#ifndef __LUNAIX_USERCAPS_H +#define __LUNAIX_USERCAPS_H + +typedef unsigned long caps_t; + +/* + * Definition of user capabilities (withdrawn draft POSIX.1e) + */ + +#define CAP_SETUID 0 +#define CAP_SETGID 1 +#define CAP_CHOWN 2 +#define CAP_DAC_OVERRIDE 3 +#define CAP_FSETID 4 +#define CAP_KILL 5 +#define CAP_SYS_CHROOT 6 +#define CAP_SYS_TIM 7 + +#endif /* __LUNAIX_USERCAPS_H */ diff --git a/lunaix-os/includes/lunaix/usrscope.h b/lunaix-os/includes/lunaix/usrscope.h new file mode 100644 index 0000000..8de27b7 --- /dev/null +++ b/lunaix-os/includes/lunaix/usrscope.h @@ -0,0 +1,60 @@ +#ifndef __LUNAIX_USRSCOPE_H +#define __LUNAIX_USRSCOPE_H + +#include +#include "usercaps.h" + +struct ugroup_obj +{ + gid_t* list; + unsigned int maxcap; + unsigned int refs; +}; + +struct user_scope +{ + uid_t ruid; + gid_t rgid; + caps_t capabilities; + + struct ugroup_obj* grps; +}; + +/* + Process ACL check result. + The encoding here is designed to be the mask for file ACL value +*/ +enum acl_match +{ + ACL_MATCH_U = 0b111000000, // (U)ser + ACL_MATCH_G = 0b000111000, // (G)roup + ACL_NO_MATCH = 0b000000111, // (O)ther +}; + +#define user_groups(uscope) ((uscope)->grps) + +#define grp_list_end ((gid_t)-1) + +int +uscope_setgroups(struct user_scope* proc_usr, + const gid_t* grps, unsigned int len); + +void +uscope_copy(struct user_scope* from, struct user_scope* to); + +bool +uscope_membership(struct user_scope* proc_usr, gid_t gid); + +enum acl_match +check_current_acl(uid_t desired_u, gid_t desired_g); + +enum acl_match +check_acl_between(uid_t u1, gid_t g1, uid_t u2, gid_t g2); + +static inline bool +uscope_with_capability(const struct user_scope* proc_usr, caps_t cap) +{ + return !!(proc_usr->capabilities & (1UL << cap)); +} + +#endif /* __LUNAIX_USRSCOPE_H */ diff --git a/lunaix-os/includes/usr/lunaix/fcntl_defs.h b/lunaix-os/includes/usr/lunaix/fcntl_defs.h index 186f5f4..36af62e 100644 --- a/lunaix-os/includes/usr/lunaix/fcntl_defs.h +++ b/lunaix-os/includes/usr/lunaix/fcntl_defs.h @@ -26,22 +26,43 @@ #define O_RDWR FO_RDWR #define O_TRUNC FO_TRUNC +#define AT_SYMLINK_FOLLOW 0b0000 +#define AT_SYMLINK_NOFOLLOW 0b0001 +#define AT_FDCWD 0b0010 +#define AT_EACCESS 0b0100 + +#define R_OK 0b100100100 +#define W_OK 0b010010010 +#define X_OK 0b001001001 +#define F_OK 0b111111111 + /* Mount with read-only flag */ #define MNT_RO (1 << 0) /* Mount with block-cache-disabled flag */ #define MNT_NC (1 << 1) +typedef unsigned int mode_t; +typedef unsigned int nlink_t; + struct file_stat { - dev_t st_dev; - ino_t st_ino; - unsigned int mode; - dev_t st_rdev; - off_t st_size; - size_t st_blksize; - size_t st_ioblksize; - size_t st_blocks; + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + gid_t st_gid; + dev_t st_rdev; + off_t st_size; + size_t st_blksize; + size_t st_blocks; + + unsigned long st_atim; + unsigned long st_ctim; + unsigned long st_mtim; + + size_t st_ioblksize; }; #endif /* __LUNAIX_FNCTL_DEFS_H */ diff --git a/lunaix-os/includes/usr/lunaix/status.h b/lunaix-os/includes/usr/lunaix/status.h index df37b61..e457232 100644 --- a/lunaix-os/includes/usr/lunaix/status.h +++ b/lunaix-os/includes/usr/lunaix/status.h @@ -36,5 +36,7 @@ #define EAGAIN -30 #define EDEADLK -31 #define EDQUOT -32 +#define EPERM -33 +#define EACCESS -34 #endif /* __LUNAIX_STATUS_H */ diff --git a/lunaix-os/includes/usr/lunaix/types.h b/lunaix-os/includes/usr/lunaix/types.h index 19094e9..3dbddb5 100644 --- a/lunaix-os/includes/usr/lunaix/types.h +++ b/lunaix-os/includes/usr/lunaix/types.h @@ -24,6 +24,8 @@ typedef signed long ssize_t; typedef int pid_t; typedef int tid_t; +typedef int uid_t; +typedef int gid_t; typedef __SIZE_TYPE__ size_t; diff --git a/lunaix-os/kernel/LBuild b/lunaix-os/kernel/LBuild index 8e92773..3e0a7be 100644 --- a/lunaix-os/kernel/LBuild +++ b/lunaix-os/kernel/LBuild @@ -17,6 +17,7 @@ sources([ "bcache.c", "syscall.c", "changeling.c", + "usrscope.c", "kprint/kp_records.c", "kprint/kprintf.c", "time/clock.c", diff --git a/lunaix-os/kernel/block/blk_mapping.c b/lunaix-os/kernel/block/blk_mapping.c index 7dae2b8..ddc360a 100644 --- a/lunaix-os/kernel/block/blk_mapping.c +++ b/lunaix-os/kernel/block/blk_mapping.c @@ -9,37 +9,37 @@ blk_mapping_init() blk_root = twifs_dir_node(NULL, "block"); } -void -__blk_rd_lblksz(struct twimap* map) +static void +__twimap_read_lblk_size(struct twimap* map) { struct block_dev* bdev = twimap_data(map, struct block_dev*); size_t lblksz = bdev->blk_size; twimap_printf(map, "%u", lblksz); } -void -__blk_rd_name(struct twimap* map) +static void +__twimap_read_name(struct twimap* map) { struct block_dev* bdev = twimap_data(map, struct block_dev*); twimap_printf(map, "%s", bdev->name); } -void -__blk_rd_start_lba(struct twimap* map) +static void +__twimap_read_lba_begin(struct twimap* map) { struct block_dev* bdev = twimap_data(map, struct block_dev*); twimap_printf(map, "%d", bdev->start_lba); } -void -__blk_rd_end_lba(struct twimap* map) +static void +__twimap_read_lba_end(struct twimap* map) { struct block_dev* bdev = twimap_data(map, struct block_dev*); twimap_printf(map, "%d", bdev->end_lba); } -void -__blk_rd_size(struct twimap* map) +static void +__twimap_read_size(struct twimap* map) { struct block_dev* bdev = twimap_data(map, struct block_dev*); twimap_printf( @@ -49,22 +49,15 @@ __blk_rd_size(struct twimap* map) void __map_internal(struct block_dev* bdev, void* fsnode) { - struct twifs_node* dev_root = (struct twifs_node*)fsnode; - - struct twimap* map = twifs_mapping(dev_root, bdev, "size"); - map->read = __blk_rd_size; - - map = twifs_mapping(dev_root, bdev, "lblk_size"); - map->read = __blk_rd_lblksz; - - map = twifs_mapping(dev_root, bdev, "name"); - map->read = __blk_rd_name; - - map = twifs_mapping(dev_root, bdev, "begin"); - map->read = __blk_rd_start_lba; - - map = twifs_mapping(dev_root, bdev, "end"); - map->read = __blk_rd_end_lba; + struct twifs_node* dev_root; + + dev_root = (struct twifs_node*)fsnode; + + twimap_export_value(dev_root, size, FSACL_aR, bdev); + twimap_export_value(dev_root, lblk_size, FSACL_aR, bdev); + twimap_export_value(dev_root, name, FSACL_aR, bdev); + twimap_export_value(dev_root, lba_begin, FSACL_aR, bdev); + twimap_export_value(dev_root, lba_end, FSACL_aR, bdev); } void diff --git a/lunaix-os/kernel/device/devdb.c b/lunaix-os/kernel/device/devdb.c index a41364d..42452f8 100644 --- a/lunaix-os/kernel/device/devdb.c +++ b/lunaix-os/kernel/device/devdb.c @@ -133,7 +133,7 @@ device_sysconf_load() } static int -__devdb_db_gonext(struct twimap* mapping) +__twimap_gonext_devtab(struct twimap* mapping) { struct device_def* current = twimap_index(mapping, struct device_def*); if (current->dev_list.next == &dev_registry_flat) { @@ -145,7 +145,7 @@ __devdb_db_gonext(struct twimap* mapping) } static void -__devdb_twifs_lsdb(struct twimap* mapping) +__twimap_read_devtab(struct twimap* mapping) { char flags[64]; struct device_def* def = twimap_index(mapping, struct device_def*); @@ -161,8 +161,8 @@ __devdb_twifs_lsdb(struct twimap* mapping) flags); } -void -__devdb_reset(struct twimap* map) +static void +__twimap_reset_devtab(struct twimap* map) { map->index = container_of(dev_registry_flat.next, struct device_def, dev_list); @@ -171,9 +171,6 @@ __devdb_reset(struct twimap* map) static void devdb_twifs_plugin() { - struct twimap* map = twifs_mapping(NULL, NULL, "devtab"); - map->reset = __devdb_reset; - map->read = __devdb_twifs_lsdb; - map->go_next = __devdb_db_gonext; + twimap_export_list(NULL, devtab, FSACL_aR, NULL); } EXPORT_TWIFS_PLUGIN(devdb, devdb_twifs_plugin); \ No newline at end of file diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c index c105f66..969c828 100644 --- a/lunaix-os/kernel/device/devfs.c +++ b/lunaix-os/kernel/device/devfs.c @@ -179,6 +179,12 @@ devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode) { inode->ops = &devfs_inode_ops; inode->default_fops = &devfs_file_ops; + + // we set default access right to be 0775. + // TODO need a way to allow this to be changed + + fsapi_inode_setaccess(inode, FSACL_DEFAULT); + fsapi_inode_setowner(inode, 0, 0); } int diff --git a/lunaix-os/kernel/ds/waitq.c b/lunaix-os/kernel/ds/waitq.c index c102882..e67c44d 100644 --- a/lunaix-os/kernel/ds/waitq.c +++ b/lunaix-os/kernel/ds/waitq.c @@ -12,7 +12,7 @@ __try_wait(bool check_stall) if (waitq_empty(current_wq)) { return; } - + block_current_thread(); if (!check_stall) { @@ -54,7 +54,7 @@ pwait_check_stall(waitq_t* queue) void pwake_one(waitq_t* queue) { - if (llist_empty(&queue->waiters)) { + if (waitq_empty(queue)) { return; } @@ -69,7 +69,7 @@ pwake_one(waitq_t* queue) void pwake_all(waitq_t* queue) { - if (llist_empty(&queue->waiters)) { + if (waitq_empty(queue)) { return; } diff --git a/lunaix-os/kernel/exe/exec.c b/lunaix-os/kernel/exe/exec.c index 0dace13..3c1fb42 100644 --- a/lunaix-os/kernel/exe/exec.c +++ b/lunaix-os/kernel/exe/exec.c @@ -202,6 +202,7 @@ exec_load(struct exec_host* container, struct v_file* executable) } save_process_cmd(proc, argv); + container->inode = executable->inode; errno = load_executable(&container->exe, executable); if (errno) { @@ -223,7 +224,8 @@ exec_load_byname(struct exec_host* container, const char* filename) goto done; } - if ((errno = vfs_open(dnode, &file))) { + if (!check_allow_execute(dnode->inode)) { + errno = EPERM; goto done; } @@ -231,6 +233,10 @@ exec_load_byname(struct exec_host* container, const char* filename) errno = EISDIR; goto done; } + + if ((errno = vfs_open(dnode, &file))) { + goto done; + } errno = exec_load(container, file); @@ -270,16 +276,11 @@ exec_kexecve(const char* filename, const char* argv[], const char* envp[]) return errno; } -__DEFINE_LXSYSCALL3(int, - execve, - const char*, - filename, - const char*, - argv[], - const char*, - envp[]) +__DEFINE_LXSYSCALL3(int, execve, const char*, filename, + const char*, argv[], const char*, envp[]) { int errno = 0; + int acl; struct exec_host container; if (!argv || !envp) { @@ -303,6 +304,15 @@ __DEFINE_LXSYSCALL3(int, signal_reset_context(¤t_thread->sigctx); signal_reset_registry(__current->sigreg); + acl = container.inode->acl; + if (fsacl_test(acl, suid)) { + current_set_euid(container.inode->uid); + } + + if (fsacl_test(acl, sgid)) { + current_set_egid(container.inode->gid); + } + done: // set return value store_retval(DO_STATUS(errno)); @@ -310,6 +320,5 @@ done: // Always yield the process that want execve! schedule(); - // this will never get executed! - return -1; + unreachable; } \ No newline at end of file diff --git a/lunaix-os/kernel/fs/ext2/ext2.h b/lunaix-os/kernel/fs/ext2/ext2.h index 14b2218..1f12315 100644 --- a/lunaix-os/kernel/fs/ext2/ext2.h +++ b/lunaix-os/kernel/fs/ext2/ext2.h @@ -30,6 +30,7 @@ #define IMODE_ORD 0x0004 #define IMODE_OWR 0x0002 #define IMODE_OEX 0x0001 +#define IMODE_ACL_MASK 0x01ff #define ext2_aligned compact align(4) #define to_ext2ino_id(fsblock_id) ((fsblock_id) + 1) diff --git a/lunaix-os/kernel/fs/ext2/inode.c b/lunaix-os/kernel/fs/ext2/inode.c index 389bdea..5871d07 100644 --- a/lunaix-os/kernel/fs/ext2/inode.c +++ b/lunaix-os/kernel/fs/ext2/inode.c @@ -295,6 +295,10 @@ ext2ino_fill(struct v_inode* inode, ino_t ino_id) b_ino->i_mtime, b_ino->i_atime); + fsapi_inode_setaccess(inode, b_ino->i_mode & IMODE_ACL_MASK); + fsapi_inode_setowner(inode, b_ino->i_uid, + b_ino->i_gid); + __ext2ino_fill_common(inode, ino_id); if (check_itype(b_ino->i_mode, IMODE_IFLNK)) { diff --git a/lunaix-os/kernel/fs/fs_export.c b/lunaix-os/kernel/fs/fs_export.c index 1fedef6..452bcdf 100644 --- a/lunaix-os/kernel/fs/fs_export.c +++ b/lunaix-os/kernel/fs/fs_export.c @@ -4,8 +4,8 @@ extern struct llist_header all_mnts; -void -__mount_read(struct twimap* map) +static void +__twimap_read_mounts(struct twimap* map) { char path[512]; struct v_mount* mnt = twimap_index(map, struct v_mount*); @@ -20,8 +20,8 @@ __mount_read(struct twimap* map) twimap_printf(map, "\n"); } -int -__mount_next(struct twimap* map) +static int +__twimap_gonext_mounts(struct twimap* map) { struct v_mount* mnt = twimap_index(map, struct v_mount*); if (mnt->list.next == &all_mnts) { @@ -31,14 +31,14 @@ __mount_next(struct twimap* map) return 1; } -void -__mount_reset(struct twimap* map) +static void +__twimap_reset_mounts(struct twimap* map) { map->index = container_of(all_mnts.next, struct v_mount, list); } void -__version_rd(struct twimap* map) +__twimap_read_version(struct twimap* map) { twimap_printf(map, "Lunaix " @@ -49,12 +49,7 @@ __version_rd(struct twimap* map) void vfs_export_attributes() { - struct twimap* map = twifs_mapping(NULL, NULL, "mounts"); - map->read = __mount_read; - map->go_next = __mount_next; - map->reset = __mount_reset; - - map = twifs_mapping(NULL, NULL, "version"); - map->read = __version_rd; + twimap_export_list (NULL, mounts, FSACL_ugR, NULL); + twimap_export_value(NULL, version, FSACL_ugR, NULL); } EXPORT_TWIFS_PLUGIN(vfs_general, vfs_export_attributes); \ No newline at end of file diff --git a/lunaix-os/kernel/fs/fsm.c b/lunaix-os/kernel/fs/fsm.c index 722ffd0..8638905 100644 --- a/lunaix-os/kernel/fs/fsm.c +++ b/lunaix-os/kernel/fs/fsm.c @@ -80,7 +80,7 @@ fsm_itnext(struct fs_iter* iterator) } static void -read_fslist(struct twimap *mapping) +__twimap_read_fstab(struct twimap *mapping) { struct filesystem *pos, *n; llist_for_each(pos, n, &fs_flatlist, fs_flat) @@ -92,7 +92,6 @@ read_fslist(struct twimap *mapping) static void fstab_twifs_plugin() { - struct twimap* map = twifs_mapping(NULL, NULL, "fstab"); - map->read = read_fslist; + twimap_export_value(NULL, fstab, FSACL_ugR, NULL); } EXPORT_TWIFS_PLUGIN(fstab, fstab_twifs_plugin); \ No newline at end of file diff --git a/lunaix-os/kernel/fs/iso9660/inode.c b/lunaix-os/kernel/fs/iso9660/inode.c index ab66ca4..ab6a396 100644 --- a/lunaix-os/kernel/fs/iso9660/inode.c +++ b/lunaix-os/kernel/fs/iso9660/inode.c @@ -1,5 +1,5 @@ #include -#include +#include #include "iso9660.h" #include #include @@ -87,10 +87,17 @@ iso9660_fill_inode(struct v_inode* inode, struct iso_drecache* dir, int ino) inode->ctime = iso9660_dt2unix(&xattr->ctime); inode->mtime = iso9660_dt2unix(&xattr->mtime); + fsapi_inode_setaccess(inode, xattr->perm); + fsapi_inode_setowner(inode, xattr->owner.le, xattr->group.le); + inode->lb_addr += dir->xattr_len * dir->fu_size; vfree(xattr); } + else { + fsapi_inode_setaccess(inode, FSACL_u(R, W, _) | FSACL_g(R, W, _)); + fsapi_inode_setowner(inode, 0, 0); + } inode->ctime = dir->ctime ? dir->ctime : inode->ctime; inode->mtime = dir->mtime ? dir->mtime : inode->mtime; diff --git a/lunaix-os/kernel/fs/iso9660/iso9660.h b/lunaix-os/kernel/fs/iso9660/iso9660.h index 708a28a..754301b 100644 --- a/lunaix-os/kernel/fs/iso9660/iso9660.h +++ b/lunaix-os/kernel/fs/iso9660/iso9660.h @@ -289,6 +289,7 @@ struct iso_drecache time_t ctime; time_t atime; time_t mtime; + struct hstr name; char name_val[ISO9660_IDLEN]; }; diff --git a/lunaix-os/kernel/fs/mount.c b/lunaix-os/kernel/fs/mount.c index 282ae78..b62b77f 100644 --- a/lunaix-os/kernel/fs/mount.c +++ b/lunaix-os/kernel/fs/mount.c @@ -293,6 +293,11 @@ vfs_check_writable(struct v_dnode* dnode) if ((dnode->mnt->flags & MNT_RO)) { return EROFS; } + + if (!check_allow_write(dnode->inode)) { + return EPERM; + } + return 0; } diff --git a/lunaix-os/kernel/fs/path_walk.c b/lunaix-os/kernel/fs/path_walk.c index 84e04d0..246e903 100644 --- a/lunaix-os/kernel/fs/path_walk.c +++ b/lunaix-os/kernel/fs/path_walk.c @@ -3,6 +3,8 @@ #include #include +#include + #include #define VFS_SYMLINK_DEPTH 16 @@ -29,11 +31,16 @@ __vfs_walk(struct v_dnode* start, if (path[0] == VFS_PATH_DELIM || !start) { if ((walk_options & VFS_WALK_FSRELATIVE) && start) { start = start->super_block->root; - } else { + } + else if (unlikely(!__current)) { start = vfs_sysroot; - if (!vfs_sysroot->mnt) { - fail("vfs: no root"); - } + } + else { + start = __current->root ?: vfs_sysroot; + } + + if (unlikely(!start || !start->mnt)) { + fail("vfs: no root"); } if (path[0] == VFS_PATH_DELIM) { @@ -50,9 +57,12 @@ __vfs_walk(struct v_dnode* start, struct hstr name = HSTR(fname_buffer, 0); char current = path[i++], lookahead; - while (current) { + while (current) + { lookahead = path[i++]; - if (current != VFS_PATH_DELIM) { + + if (current != VFS_PATH_DELIM) + { if (j >= VFS_NAME_MAXLEN - 1) { return ENAMETOOLONG; } @@ -83,13 +93,21 @@ __vfs_walk(struct v_dnode* start, lock_dnode(current_level); + if (!check_allow_execute(current_inode)) { + errno = EACCESS; + unlock_dnode(current_level); + goto error; + } + dnode = vfs_dcache_lookup(current_level, &name); - if (!dnode) { + if (!dnode) + { dnode = vfs_d_alloc(current_level, &name); if (!dnode) { errno = ENOMEM; + unlock_dnode(current_level); goto error; } @@ -123,7 +141,8 @@ __vfs_walk(struct v_dnode* start, assert(current_inode); if (check_symlink_node(current_inode) && - !(walk_options & VFS_WALK_NOFOLLOW)) { + !(walk_options & VFS_WALK_NOFOLLOW)) + { const char* link; struct v_inode_ops* iops; @@ -169,6 +188,7 @@ __vfs_walk(struct v_dnode* start, cleanup: vfs_d_free(dnode); + error: *dentry = NULL; return errno; @@ -204,4 +224,36 @@ vfs_walk_proc(const char* path, int options) { return vfs_walk(__current->cwd, path, dentry, component, options); +} + +int +vfs_walkat(int fd, const char* path, int at_opts, struct v_dnode** dnode_out) +{ + int errno, options = 0; + struct v_dnode *root_dnode; + struct v_fd* _fd; + + if ((at_opts & AT_FDCWD)) { + root_dnode = __current->cwd; + } + else + { + errno = vfs_getfd(fd, &_fd); + if (errno) { + return errno; + } + + root_dnode = _fd->file->dnode; + } + + if ((at_opts & AT_SYMLINK_NOFOLLOW)) { + options |= VFS_WALK_NOFOLLOW; + } + + errno = vfs_walk(root_dnode, path, dnode_out, NULL, options); + if (errno) { + return errno; + } + + return 0; } \ No newline at end of file diff --git a/lunaix-os/kernel/fs/ramfs/ramfs.c b/lunaix-os/kernel/fs/ramfs/ramfs.c index b7512e5..0944088 100644 --- a/lunaix-os/kernel/fs/ramfs/ramfs.c +++ b/lunaix-os/kernel/fs/ramfs/ramfs.c @@ -132,7 +132,13 @@ ramfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) { vsb->ops.init_inode = ramfs_inode_init; - return __ramfs_mknod(mount_point, NULL, RAMF_DIR); + int errno = __ramfs_mknod(mount_point, NULL, RAMF_DIR); + + if (!errno) { + fsapi_inode_setaccess(mount_point->inode, FSACL_DEFAULT); + } + + return errno; } int diff --git a/lunaix-os/kernel/fs/twifs/twifs.c b/lunaix-os/kernel/fs/twifs/twifs.c index 165d0bd..2fdf023 100644 --- a/lunaix-os/kernel/fs/twifs/twifs.c +++ b/lunaix-os/kernel/fs/twifs/twifs.c @@ -21,19 +21,15 @@ #include static struct twifs_node* fs_root; - static struct cake_pile* twi_pile; - static volatile u32_t inode_id = 0; extern const struct v_file_ops twifs_file_ops; extern const struct v_inode_ops twifs_inode_ops; -struct twifs_node* +static struct twifs_node* __twifs_new_node(struct twifs_node* parent, - const char* name, - int name_len, - u32_t itype) + const char* name, int name_len, u32_t itype) { struct twifs_node* node = cake_grab(twi_pile); memset(node, 0, sizeof(*node)); @@ -53,14 +49,21 @@ __twifs_new_node(struct twifs_node* parent, return node; } -void +static void __twifs_init_inode(struct v_superblock* vsb, struct v_inode* inode) { inode->ops = (struct v_inode_ops*)&twifs_inode_ops; inode->default_fops = (struct v_file_ops*)&twifs_file_ops; + + + // we set default access right to be 0660. + // TODO need a way to allow this to be changed + + fsapi_inode_setaccess(inode, FSACL_DEFAULT); + fsapi_inode_setowner(inode, 0, 0); } -int +static int __twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) { vsb->ops.init_inode = __twifs_init_inode; @@ -79,13 +82,13 @@ __twifs_mount(struct v_superblock* vsb, struct v_dnode* mount_point) return 0; } -int +static int __twifs_unmount(struct v_superblock* vsb) { return 0; } -int +static int __twifs_fwrite(struct v_inode* inode, void* buffer, size_t len, size_t fpos) { struct twifs_node* twi_node = (struct twifs_node*)inode->data; @@ -95,13 +98,13 @@ __twifs_fwrite(struct v_inode* inode, void* buffer, size_t len, size_t fpos) return twi_node->ops.write(inode, buffer, len, fpos); } -int +static int __twifs_fwrite_pg(struct v_inode* inode, void* buffer, size_t fpos) { return __twifs_fwrite(inode, buffer, PAGE_SIZE, fpos); } -int +static int __twifs_fread(struct v_inode* inode, void* buffer, size_t len, size_t fpos) { struct twifs_node* twi_node = (struct twifs_node*)inode->data; @@ -111,13 +114,13 @@ __twifs_fread(struct v_inode* inode, void* buffer, size_t len, size_t fpos) return twi_node->ops.read(inode, buffer, len, fpos); } -int +static int __twifs_fread_pg(struct v_inode* inode, void* buffer, size_t fpos) { return __twifs_fread(inode, buffer, PAGE_SIZE, fpos); } -struct twifs_node* +static struct twifs_node* __twifs_get_node(struct twifs_node* parent, struct hstr* name) { if (!parent) @@ -133,7 +136,7 @@ __twifs_get_node(struct twifs_node* parent, struct hstr* name) return NULL; } -int +static int __twifs_dirlookup(struct v_inode* inode, struct v_dnode* dnode) { struct twifs_node* twi_node = (struct twifs_node*)inode->data; @@ -142,9 +145,9 @@ __twifs_dirlookup(struct v_inode* inode, struct v_dnode* dnode) return ENOTDIR; } - struct twifs_node* child_node = __twifs_get_node(twi_node, &dnode->name); - if (child_node) { - struct v_inode* child_inode = vfs_i_find(inode->sb, child_node->ino_id); + struct twifs_node* twinode = __twifs_get_node(twi_node, &dnode->name); + if (twinode) { + struct v_inode* child_inode = vfs_i_find(inode->sb, twinode->ino_id); if (child_inode) { goto done; } @@ -153,21 +156,25 @@ __twifs_dirlookup(struct v_inode* inode, struct v_dnode* dnode) return ENOENT; } - child_inode->id = child_node->ino_id; - child_inode->itype = child_node->itype; - child_inode->data = child_node; + child_inode->id = twinode->ino_id; + child_inode->itype = twinode->itype; + child_inode->data = twinode; + + if (twinode->acl != -1) { + fsapi_inode_setaccess(child_inode, twinode->acl); + } vfs_i_addhash(child_inode); done: - dnode->data = child_node->data; + dnode->data = twinode->data; vfs_assign_inode(dnode, child_inode); return 0; } return ENOENT; } -int +static int __twifs_iterate_dir(struct v_file* file, struct dir_context* dctx) { struct twifs_node* twi_node = (struct twifs_node*)(file->inode->data); @@ -190,7 +197,7 @@ __twifs_iterate_dir(struct v_file* file, struct dir_context* dctx) return 0; } -int +static int __twifs_openfile(struct v_inode* inode, struct v_file* file) { struct twifs_node* twi_node = (struct twifs_node*)inode->data; @@ -200,6 +207,30 @@ __twifs_openfile(struct v_inode* inode, struct v_file* file) return ENOTSUP; } +static inline struct twifs_node* +__twifs_create_node(struct twifs_node* parent, + const char* name, int acl) +{ + struct twifs_node* twi_node; + unsigned int size; + + size = strlen(name); + parent = parent ?: fs_root; + twi_node = __twifs_new_node(parent, name, size, F_FILE); + twi_node->acl = acl; + + return twi_node; +} + +static int +__twifs_twimap_file_read(struct v_inode* inode, + void* buf, size_t len, size_t fpos) +{ + struct twimap* map = twinode_getdata(inode, struct twimap*); + return twimap_read(map, buf, len, fpos); +} + + int twifs_rm_node(struct twifs_node* node) { @@ -221,78 +252,90 @@ twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args) } struct twifs_node* -twifs_file_node(struct twifs_node* parent, const char* fmt, ...) +twifs_dir_node(struct twifs_node* parent, const char* fmt, ...) { + size_t len; + char buf[VFS_NAME_MAXLEN]; + struct twifs_node* twi_node; + va_list args; va_start(args, fmt); - struct twifs_node* twi_node = twifs_file_node_vargs(parent, fmt, args); + len = ksnprintfv(buf, fmt, VFS_NAME_MAXLEN, args); + twi_node = + __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFDIR); + + twi_node->acl = FSACL_aR | FSACL_aX; va_end(args); return twi_node; } + struct twifs_node* -twifs_dir_node(struct twifs_node* parent, const char* fmt, ...) +twifs_basic_node_from(struct twifs_node* parent, + struct twifs_export* def, void* data) { - va_list args; - va_start(args, fmt); - - char buf[VFS_NAME_MAXLEN]; - size_t len = ksnprintfv(buf, fmt, VFS_NAME_MAXLEN, args); - struct twifs_node* twi_node = - __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFDIR); - - va_end(args); + struct twifs_node* twi_node; + + twi_node = __twifs_create_node(parent, def->name, def->acl); + twi_node->ops = def->ops; + twi_node->data = data; return twi_node; } -void -twifs_init() +struct twifs_node* +twifs_mapped_node_from(struct twifs_node* parent, + struct twimap_export* def, void* data) { - struct filesystem* fs; - fs = fsapi_fs_declare("twifs", FSTYPE_PSEUDO | FSTYPE_ROFS); + struct twifs_node* twi_node; + struct twimap* map_; - fsapi_fs_set_mntops(fs, __twifs_mount, __twifs_unmount); - fsapi_fs_finalise(fs); + map_ = twimap_create(data); + twi_node = __twifs_create_node(parent, def->name, def->acl); - twi_pile = cake_new_pile("twifs_node", sizeof(struct twifs_node), 1, 0); - fs_root = twifs_dir_node(NULL, NULL, 0, 0); -} -EXPORT_FILE_SYSTEM(twifs, twifs_init); + twi_node->data = map_; + twi_node->ops.read = __twifs_twimap_file_read; + // twi_node->ops.write = __twifs_twimap_file_write; -void -twifs_register_plugins() -{ - ldga_invoke_fn0(twiplugin_inits); -} + if (def->ops.go_next) { + map_->ops.go_next = def->ops.go_next; + } -int -__twifs_twimap_file_read(struct v_inode* inode, - void* buf, - size_t len, - size_t fpos) -{ - struct twimap* map = twinode_getdata(inode, struct twimap*); - return twimap_read(map, buf, len, fpos); + if (def->ops.reset) { + map_->ops.reset = def->ops.reset; + } + + map_->ops.read = def->ops.read; + + return twi_node; } struct twimap* -twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...) +twifs_mapping(struct twifs_node* parent, + void* data, int acl, const char* fmt, ...) { va_list args; va_start(args, fmt); struct twimap* map = twimap_create(data); struct twifs_node* node = twifs_file_node_vargs(parent, fmt, args); + node->ops.read = __twifs_twimap_file_read; node->data = map; + node->acl = acl; return map; } +void +twifs_register_plugins() +{ + ldga_invoke_fn0(twiplugin_inits); +} + const struct v_file_ops twifs_file_ops = { .close = default_file_close, .read = __twifs_fread, .read_page = __twifs_fread_pg, @@ -303,4 +346,19 @@ const struct v_file_ops twifs_file_ops = { .close = default_file_close, const struct v_inode_ops twifs_inode_ops = { .dir_lookup = __twifs_dirlookup, .mkdir = default_inode_mkdir, .rmdir = default_inode_rmdir, - .open = __twifs_openfile }; \ No newline at end of file + .open = __twifs_openfile }; + + +static void +twifs_init() +{ + struct filesystem* fs; + fs = fsapi_fs_declare("twifs", FSTYPE_PSEUDO | FSTYPE_ROFS); + + fsapi_fs_set_mntops(fs, __twifs_mount, __twifs_unmount); + fsapi_fs_finalise(fs); + + twi_pile = cake_new_pile("twifs_node", sizeof(struct twifs_node), 1, 0); + fs_root = twifs_dir_node(NULL, NULL, 0, 0); +} +EXPORT_FILE_SYSTEM(twifs, twifs_init); \ No newline at end of file diff --git a/lunaix-os/kernel/fs/vfs.c b/lunaix-os/kernel/fs/vfs.c index 1696d6e..32014d3 100644 --- a/lunaix-os/kernel/fs/vfs.c +++ b/lunaix-os/kernel/fs/vfs.c @@ -57,13 +57,16 @@ #include +#define INODE_ACCESSED 0 +#define INODE_MODIFY 1 + static struct cake_pile* dnode_pile; static struct cake_pile* inode_pile; static struct cake_pile* file_pile; static struct cake_pile* superblock_pile; static struct cake_pile* fd_pile; -struct v_dnode* vfs_sysroot; +struct v_dnode* vfs_sysroot = NULL; struct lru_zone *dnode_lru, *inode_lru; @@ -152,6 +155,20 @@ vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str) return NULL; } +static void +__vfs_touch_inode(struct v_inode* inode, const int type) +{ + if (type == INODE_MODIFY) { + inode->mtime = clock_unixtime(); + } + + else if (type == INODE_ACCESSED) { + inode->atime = clock_unixtime(); + } + + lru_use_one(inode_lru, &inode->lru); +} + void vfs_dcache_add(struct v_dnode* parent, struct v_dnode* dnode) { @@ -192,12 +209,12 @@ vfs_dcache_rehash(struct v_dnode* new_parent, struct v_dnode* dnode) int vfs_open(struct v_dnode* dnode, struct v_file** file) { - if (!dnode->inode || !dnode->inode->ops->open) { + struct v_inode* inode = dnode->inode; + + if (!inode || !inode->ops->open) { return ENOTSUP; } - struct v_inode* inode = dnode->inode; - lock_inode(inode); struct v_file* vfile = cake_grab(file_pile); @@ -696,6 +713,31 @@ done: return errno; } + +static bool +__check_unlinkable(struct v_dnode* dnode) +{ + int acl; + bool wr_self, wr_parent; + struct v_dnode* parent; + + parent = dnode->parent; + acl = dnode->inode->acl; + + wr_self = check_allow_write(dnode->inode); + wr_parent = check_allow_write(parent->inode); + + if (!fsacl_test(acl, svtx)) { + return wr_self; + } + + if (current_euid() == dnode->inode->uid) { + return true; + } + + return wr_self && wr_parent; +} + int vfs_do_open(const char* path, int options) { @@ -814,6 +856,11 @@ __DEFINE_LXSYSCALL2(int, sys_readdir, int, fd, struct lx_dirent*, dent) goto unlock; } + if (!check_allow_read(inode)) { + errno = EPERM; + goto unlock; + } + struct dir_context dctx = (struct dir_context) { .cb_data = dent, .read_complete_callback = __vfs_readdir_callback @@ -836,6 +883,8 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) { int errno = 0; struct v_fd* fd_s; + struct v_inode* inode; + if ((errno = vfs_getfd(fd, &fd_s))) { goto done; } @@ -846,23 +895,29 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count) goto done; } - lock_inode(file->inode); + if (!check_allow_read(file->inode)) { + errno = EPERM; + goto done; + } - file->inode->atime = clock_unixtime(); + inode = file->inode; + lock_inode(inode); - if (check_seqdev_node(file->inode) || (fd_s->flags & FO_DIRECT)) { - errno = file->ops->read(file->inode, buf, count, file->f_pos); + __vfs_touch_inode(inode, INODE_ACCESSED); + + if (check_seqdev_node(inode) || (fd_s->flags & FO_DIRECT)) { + errno = file->ops->read(inode, buf, count, file->f_pos); } else { - errno = pcache_read(file->inode, buf, count, file->f_pos); + errno = pcache_read(inode, buf, count, file->f_pos); } if (errno > 0) { file->f_pos += errno; - unlock_inode(file->inode); + unlock_inode(inode); return errno; } - unlock_inode(file->inode); + unlock_inode(inode); done: return DO_STATUS(errno); @@ -891,7 +946,7 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count) inode = file->inode; lock_inode(inode); - inode->mtime = clock_unixtime(); + __vfs_touch_inode(inode, INODE_MODIFY); if ((fd_s->flags & O_APPEND)) { file->f_pos = inode->fsize; } @@ -932,6 +987,11 @@ __DEFINE_LXSYSCALL3(int, lseek, int, fd, int, offset, int, options) goto done; } + if (!check_allow_read(inode)) { + errno = EPERM; + goto done; + } + lock_inode(inode); int overflow = 0; @@ -1012,6 +1072,10 @@ vfs_readlink(struct v_dnode* dnode, char* buf, size_t size) return ENOTSUP; } + if (!check_allow_read(inode)) { + return EPERM; + } + lock_inode(inode); int errno = inode->ops->read_symlink(inode, &link); @@ -1118,6 +1182,11 @@ __DEFINE_LXSYSCALL1(int, rmdir, const char*, pathname) lock_dnode(dnode); + if (!__check_unlinkable(dnode)) { + errno = EPERM; + goto done; + } + if ((errno = vfs_check_writable(dnode))) { goto done; } @@ -1214,7 +1283,7 @@ done: return DO_STATUS(errno); } -int +static int __vfs_do_unlink(struct v_dnode* dnode) { int errno; @@ -1224,6 +1293,10 @@ __vfs_do_unlink(struct v_dnode* dnode) return EBUSY; } + if (!__check_unlinkable(dnode)) { + return EPERM; + } + if ((errno = vfs_check_writable(dnode))) { return errno; } @@ -1434,16 +1507,11 @@ done: return DO_STATUS(errno); } -int -vfs_do_chdir(struct proc_info* proc, struct v_dnode* dnode) +static int +vfs_do_chdir_nolock(struct proc_info* proc, struct v_dnode* dnode) { - int errno = 0; - - lock_dnode(dnode); - if (!check_directory_node(dnode->inode)) { - errno = ENOTDIR; - goto done; + return ENOTDIR; } if (proc->cwd) { @@ -1453,9 +1521,20 @@ vfs_do_chdir(struct proc_info* proc, struct v_dnode* dnode) vfs_ref_dnode(dnode); proc->cwd = dnode; + return 0; +} + +static int +vfs_do_chdir(struct proc_info* proc, struct v_dnode* dnode) +{ + int errno = 0; + + lock_dnode(dnode); + + errno = vfs_do_chdir_nolock(proc, dnode); + unlock_dnode(dnode); -done: return errno; } @@ -1489,6 +1568,31 @@ done: return DO_STATUS(errno); } + +__DEFINE_LXSYSCALL1(int, chroot, const char*, path) +{ + int errno; + struct v_dnode* dnode; + if ((errno = vfs_walk_proc(path, &dnode, NULL, 0))) { + return errno; + } + + lock_dnode(dnode); + + errno = vfs_do_chdir_nolock(__current, dnode); + if (errno) { + unlock_dnode(dnode); + goto done; + } + + __current->root = dnode; + + unlock_dnode(dnode); + +done: + return DO_STATUS(errno); +} + __DEFINE_LXSYSCALL2(char*, getcwd, char*, buf, size_t, size) { int errno = 0; @@ -1629,12 +1733,21 @@ __DEFINE_LXSYSCALL2(int, fstat, int, fd, struct file_stat*, stat) struct v_inode* vino = fds->file->inode; struct device* fdev = vino->sb->dev; - *stat = (struct file_stat){.st_ino = vino->id, - .st_blocks = vino->lb_usage, - .st_size = vino->fsize, - .mode = vino->itype, - .st_ioblksize = PAGE_SIZE, - .st_blksize = vino->sb->blksize}; + stat->st_ino = vino->id; + stat->st_blocks = vino->lb_usage; + stat->st_size = vino->fsize; + stat->st_blksize = vino->sb->blksize; + stat->st_nlink = vino->link_count; + stat->st_uid = vino->uid; + stat->st_gid = vino->gid; + + stat->st_ctim = vino->ctime; + stat->st_atim = vino->atime; + stat->st_mtim = vino->mtime; + + stat->st_mode = (vino->itype << 16) | vino->acl; + + stat->st_ioblksize = PAGE_SIZE; if (check_device_node(vino)) { struct device* rdev = resolve_device(vino->data); @@ -1654,6 +1767,108 @@ __DEFINE_LXSYSCALL2(int, fstat, int, fd, struct file_stat*, stat) .index = dev_uid(fdev) }; } +done: + return DO_STATUS(errno); +} + +__DEFINE_LXSYSCALL4(int, fchmodat, int, fd, + const char*, path, int, mode, int, flags) +{ + int errno; + struct v_dnode *dnode; + struct v_inode* inode; + + errno = vfs_walkat(fd, path, flags, &dnode); + if (errno) { + goto done; + } + + errno = vfs_check_writable(dnode); + if (errno) { + return errno; + } + + inode = dnode->inode; + lock_inode(inode); + + if (!current_is_root()) { + mode = mode & FSACL_RWXMASK; + } + + inode->acl = mode; + __vfs_touch_inode(inode, INODE_MODIFY); + + unlock_inode(inode); + +done: + return DO_STATUS(errno); +} + +__DEFINE_LXSYSCALL5(int, fchownat, int, fd, + const char*, path, uid_t, uid, gid_t, gid, int, flags) +{ + int errno; + struct v_dnode *dnode; + struct v_inode *inode; + + errno = vfs_walkat(fd, path, flags, &dnode); + if (errno) { + goto done; + } + + errno = vfs_check_writable(dnode); + if (errno) { + return errno; + } + + inode = dnode->inode; + lock_inode(inode); + + inode->uid = uid; + inode->gid = gid; + __vfs_touch_inode(inode, INODE_MODIFY); + + unlock_inode(inode); + +done: + return DO_STATUS(errno); +} + +__DEFINE_LXSYSCALL4(int, faccessat, int, fd, + const char*, path, int, amode, int, flags) +{ + int errno, acl; + struct v_dnode *dnode; + struct v_inode *inode; + struct user_scope* uscope; + + uid_t tuid; + gid_t tgid; + + errno = vfs_walkat(fd, path, flags, &dnode); + if (errno) { + goto done; + } + + if ((flags & AT_EACCESS)) { + tuid = current_euid(); + tgid = current_egid(); + } + else { + uscope = current_user_scope(); + tuid = uscope->ruid; + tgid = uscope->rgid; + } + + inode = dnode->inode; + + acl = inode->acl; + acl &= amode; + acl &= check_acl_between(inode->uid, inode->gid, tuid, tgid); + if (!acl) { + errno = EACCESS; + } + done: return DO_STATUS(errno); } \ No newline at end of file diff --git a/lunaix-os/kernel/kprint/kprintf.c b/lunaix-os/kernel/kprint/kprintf.c index 363abc6..dc46628 100644 --- a/lunaix-os/kernel/kprint/kprintf.c +++ b/lunaix-os/kernel/kprint/kprintf.c @@ -99,7 +99,7 @@ kprintf_v(const char* component, const char* fmt, ...) } static void -__twimap_kprintf_read(struct twimap* map) +__twimap_read_kmsg(struct twimap* map) { struct kp_records* __kprecs = twimap_data(map, struct kp_records*); @@ -112,14 +112,14 @@ __twimap_kprintf_read(struct twimap* map) { time_t s = pos->time / 1000; time_t ms = pos->time % 1000; - twimap_printf(map, "[%05d.%03d] %s\n", s, ms, pos->content); + twimap_printf(map, "[%05d.%03d] %s", s, ms, pos->content); } } static void kprintf_mapping_init() { - twimap_entry_simple(NULL, "kmsg", &kprecs, __twimap_kprintf_read); + twimap_export_value(NULL, kmsg, FSACL_ugR, &kprecs); } EXPORT_TWIFS_PLUGIN(kprintf, kprintf_mapping_init); diff --git a/lunaix-os/kernel/lrud.c b/lunaix-os/kernel/lrud.c index dc9ee34..0395e42 100644 --- a/lunaix-os/kernel/lrud.c +++ b/lunaix-os/kernel/lrud.c @@ -159,7 +159,7 @@ lru_remove(struct lru_zone* zone, struct lru_node* node) } static void -read_lrulist_entry(struct twimap* map) +__twimap_read_lru_pool(struct twimap* map) { struct lru_zone* zone; @@ -181,14 +181,14 @@ read_lrulist_entry(struct twimap* map) } static void -read_lrulist_reset(struct twimap* map) +__twimap_reset_lru_pool(struct twimap* map) { map->index = container_of(&zone_lead, struct lru_zone, zones); twimap_printf(map, "name, n_objs, hot, n_evt, n_half, n_full, status\n"); } static int -read_lrulist_next(struct twimap* map) +__twimap_gonext_lru_pool(struct twimap* map) { struct lru_zone* zone; struct llist_header* next; @@ -206,11 +206,6 @@ read_lrulist_next(struct twimap* map) static void lru_pool_twimappable() { - struct twimap* map; - - map = twifs_mapping(NULL, NULL, "lru_pool"); - map->read = read_lrulist_entry; - map->reset = read_lrulist_reset; - map->go_next = read_lrulist_next; + twimap_export_list(NULL, lru_pool, FSACL_aR, NULL); } EXPORT_TWIFS_PLUGIN(__lru_twimap, lru_pool_twimappable); \ No newline at end of file diff --git a/lunaix-os/kernel/mm/cake.c b/lunaix-os/kernel/mm/cake.c index b1e699f..179145a 100644 --- a/lunaix-os/kernel/mm/cake.c +++ b/lunaix-os/kernel/mm/cake.c @@ -303,7 +303,7 @@ cake_grab(struct cake_pile* pile) if (!pos) return NULL; - + void* piece; piece_t found_index, *fl_slot; @@ -337,7 +337,9 @@ int cake_release(struct cake_pile* pile, void* area) { piece_t piece_index; - size_t dsize = 0; + size_t dsize = 0, maybe_index; + + piece_t *fl_slot; struct cake_s *pos, *n; struct llist_header* hdrs[2] = { &pile->full, &pile->partial }; @@ -347,9 +349,12 @@ cake_release(struct cake_pile* pile, void* area) if (pos->first_piece > area) { continue; } - dsize = (ptr_t)(area - pos->first_piece); - piece_index = dsize / pile->piece_size; - if (piece_index < pile->pieces_per_cake) { + + dsize = __ptr(area - pos->first_piece); + maybe_index = dsize / pile->piece_size; + + if (maybe_index < pile->pieces_per_cake) { + piece_index = (piece_t)maybe_index; goto found; } } @@ -360,14 +365,12 @@ cake_release(struct cake_pile* pile, void* area) found: assert(!(dsize % pile->piece_size)); - piece_t *fl_slot; + assert_msg(piece_index != pos->next_free, "double free"); fl_slot = __fl_slot(pos, piece_index); *fl_slot = pos->next_free; pos->next_free = piece_index; - assert_msg(*fl_slot != pos->next_free, "double free"); - pos->used_pieces--; pile->alloced_pieces--; diff --git a/lunaix-os/kernel/mm/cake_export.c b/lunaix-os/kernel/mm/cake_export.c index e2ecb3a..cde255c 100644 --- a/lunaix-os/kernel/mm/cake_export.c +++ b/lunaix-os/kernel/mm/cake_export.c @@ -3,8 +3,8 @@ extern struct llist_header piles; -int -__cake_stat_gonext(struct twimap* map) +static int +__twimap_gonext_pinkiepie(struct twimap* map) { struct cake_pile* pile = twimap_index(map, struct cake_pile*); if (pile->piles.next == &piles) { @@ -14,15 +14,15 @@ __cake_stat_gonext(struct twimap* map) return 1; } -void -__cake_stat_reset(struct twimap* map) +static void +__twimap_reset_pinkiepie(struct twimap* map) { map->index = container_of(&piles, struct cake_pile, piles); twimap_printf(map, "name cakes pages size slices actives\n"); } -void -__cake_rd_stat(struct twimap* map) +static void +__twimap_read_pinkiepie(struct twimap* map) { struct cake_pile* pos = twimap_index(map, struct cake_pile*); twimap_printf(map, @@ -35,36 +35,36 @@ __cake_rd_stat(struct twimap* map) pos->alloced_pieces); } -void -__cake_rd_psize(struct twimap* map) +static void +__twimap_read_piece_size(struct twimap* map) { struct cake_pile* pile = twimap_data(map, struct cake_pile*); twimap_printf(map, "%u", pile->piece_size); } -void -__cake_rd_ccount(struct twimap* map) +static void +__twimap_read_cake_count(struct twimap* map) { struct cake_pile* pile = twimap_data(map, struct cake_pile*); twimap_printf(map, "%u", pile->cakes_count); } -void -__cake_rd_alloced(struct twimap* map) +static void +__twimap_read_grabbed(struct twimap* map) { struct cake_pile* pile = twimap_data(map, struct cake_pile*); twimap_printf(map, "%u", pile->alloced_pieces); } -void -__cake_rd_ppc(struct twimap* map) +static void +__twimap_read_pieces_per_cake(struct twimap* map) { struct cake_pile* pile = twimap_data(map, struct cake_pile*); twimap_printf(map, "%u", pile->pieces_per_cake); } -void -__cake_rd_ppg(struct twimap* map) +static void +__twimap_read_page_per_cake(struct twimap* map) { struct cake_pile* pile = twimap_data(map, struct cake_pile*); twimap_printf(map, "%u", pile->pg_per_cake); @@ -73,37 +73,28 @@ __cake_rd_ppg(struct twimap* map) void cake_export_pile(struct twifs_node* root, struct cake_pile* pile) { - struct twifs_node* pile_rt = twifs_dir_node(root, pile->pile_name); - - struct twimap* map = twifs_mapping(pile_rt, pile, "piece_size"); - map->read = __cake_rd_psize; - - map = twifs_mapping(pile_rt, pile, "cake_count"); - map->read = __cake_rd_ccount; - - map = twifs_mapping(pile_rt, pile, "grabbed"); - map->read = __cake_rd_alloced; - - map = twifs_mapping(pile_rt, pile, "pieces_per_cake"); - map->read = __cake_rd_ppc; - - map = twifs_mapping(pile_rt, pile, "page_per_cake"); - map->read = __cake_rd_ppg; + struct twifs_node* pile_rt; + + pile_rt = twifs_dir_node(root, pile->pile_name); + + twimap_export_value(pile_rt, piece_size, FSACL_ugR, pile); + twimap_export_value(pile_rt, cake_count, FSACL_ugR, pile); + twimap_export_value(pile_rt, grabbed, FSACL_ugR, pile); + twimap_export_value(pile_rt, pieces_per_cake, FSACL_ugR, pile); + twimap_export_value(pile_rt, page_per_cake, FSACL_ugR, pile); } void cake_export() { - struct twifs_node* cake_root = twifs_dir_node(NULL, "cake"); + struct cake_pile *pos, *n; + struct twifs_node* cake_root; + + cake_root = twifs_dir_node(NULL, "cake"); - struct twimap* map = twifs_mapping(cake_root, NULL, "pinkiepie"); - map->reset = __cake_stat_reset; - map->go_next = __cake_stat_gonext; - map->read = __cake_rd_stat; + twimap_export_list(cake_root, pinkiepie, FSACL_ugR, NULL); - struct cake_pile *pos, *n; - llist_for_each(pos, n, &piles, piles) - { + llist_for_each(pos, n, &piles, piles) { cake_export_pile(cake_root, pos); } } diff --git a/lunaix-os/kernel/process/fork.c b/lunaix-os/kernel/process/fork.c index 6a6be4b..674e5c6 100644 --- a/lunaix-os/kernel/process/fork.c +++ b/lunaix-os/kernel/process/fork.c @@ -173,6 +173,7 @@ dup_proc() } __dup_fdtable(pcb); + uscope_copy(&pcb->uscope, current_user_scope()); struct proc_mm* mm = vmspace(pcb); procvm_dupvms_mount(mm); diff --git a/lunaix-os/kernel/process/process.c b/lunaix-os/kernel/process/process.c index bb5008d..2a24f50 100644 --- a/lunaix-os/kernel/process/process.c +++ b/lunaix-os/kernel/process/process.c @@ -17,46 +17,6 @@ LOG_MODULE("PROC") -__DEFINE_LXSYSCALL(pid_t, getpid) -{ - return __current->pid; -} - -__DEFINE_LXSYSCALL(pid_t, getppid) -{ - return __current->parent->pid; -} - -__DEFINE_LXSYSCALL(pid_t, getpgid) -{ - return __current->pgid; -} - -__DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid) -{ - struct proc_info* proc = pid ? get_process(pid) : __current; - - if (!proc) { - syscall_result(EINVAL); - return -1; - } - - pgid = pgid ? pgid : proc->pid; - - struct proc_info* gruppenfuhrer = get_process(pgid); - - if (!gruppenfuhrer || proc->pgid == gruppenfuhrer->pid) { - syscall_result(EINVAL); - return -1; - } - - llist_delete(&proc->grp_member); - llist_append(&gruppenfuhrer->grp_member, &proc->grp_member); - - proc->pgid = pgid; - return 0; -} - int spawn_process(struct thread** created, ptr_t entry, bool with_ustack) { @@ -130,4 +90,163 @@ fail: ptr_t proc_vmroot() { return __current->mm->vmroot; -} \ No newline at end of file +} + +__DEFINE_LXSYSCALL(pid_t, getpid) +{ + return __current->pid; +} + +__DEFINE_LXSYSCALL(pid_t, getppid) +{ + return __current->parent->pid; +} + +__DEFINE_LXSYSCALL(pid_t, getpgid) +{ + return __current->pgid; +} + +__DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid) +{ + struct proc_info* proc = pid ? get_process(pid) : __current; + + if (!proc) { + syscall_result(EINVAL); + return -1; + } + + pgid = pgid ? pgid : proc->pid; + + struct proc_info* gruppenfuhrer = get_process(pgid); + + if (!gruppenfuhrer || proc->pgid == gruppenfuhrer->pid) { + syscall_result(EINVAL); + return -1; + } + + llist_delete(&proc->grp_member); + llist_append(&gruppenfuhrer->grp_member, &proc->grp_member); + + proc->pgid = pgid; + return 0; +} + +static inline bool +__can_change_real_id(const struct user_scope* procu, caps_t id_cap) { + if (uscope_with_capability(procu, id_cap)) { + return true; + } + + if (check_current_acl(0, 0) != ACL_NO_MATCH) { + return true; + } + + return false; +} + +__DEFINE_LXSYSCALL1(int, setuid, uid_t, uid) +{ + struct user_scope* procu; + + procu = current_user_scope(); + + if (__can_change_real_id(procu, CAP_SETUID)) + { + procu->ruid = uid; + } + + __current->suid = uid; + __current->euid = uid; + + return 0; +} + +__DEFINE_LXSYSCALL1(int, setgid, gid_t, gid) +{ + struct user_scope* procu; + + procu = current_user_scope(); + + if (__can_change_real_id(procu, CAP_SETGID)) + { + procu->rgid = gid; + } + + __current->sgid = gid; + __current->egid = gid; + + return 0; +} + +__DEFINE_LXSYSCALL1(int, seteuid, uid_t, euid) +{ + __current->euid = euid; + + return 0; +} + +__DEFINE_LXSYSCALL1(int, setegid, gid_t, egid) +{ + __current->egid = egid; + + return 0; +} + +__DEFINE_LXSYSCALL2(int, setgroups, const gid_t*, gids, unsigned int, len) +{ + struct user_scope* procu; + + procu = current_user_scope(); + + if (check_current_acl(0, 0) == ACL_NO_MATCH) { + return EPERM; + } + + if (uscope_with_capability(procu, CAP_SETGID)) { + return EPERM; + } + + return uscope_setgroups(procu, gids, len); +} + + +__DEFINE_LXSYSCALL(uid_t, getuid) +{ + return current_user_scope()->ruid; +} + +__DEFINE_LXSYSCALL(gid_t, getgid) +{ + return current_user_scope()->rgid; +} + +__DEFINE_LXSYSCALL(uid_t, geteuid) +{ + return __current->euid; +} + +__DEFINE_LXSYSCALL(gid_t, getegid) +{ + return __current->egid; +} + +__DEFINE_LXSYSCALL2(int, getgroups, gid_t*, out_buf, unsigned int, len) +{ + struct user_scope* procu; + struct ugroup_obj* gobj; + + procu = current_user_scope(); + gobj = user_groups(procu); + + assert(gobj); + len = MIN(gobj->maxcap, len); + + unsigned i = 0; + for (; i < len && gobj->list[i] != grp_list_end; i++) + { + out_buf[i] = gobj->list[i]; + } + + return i + 1; +} diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index e9f61b3..112741c 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -24,7 +24,7 @@ struct thread empty_thread_obj; -volatile struct proc_info* __current; +volatile struct proc_info* __current = NULL; volatile struct thread* current_thread = &empty_thread_obj; struct scheduler sched_ctx; @@ -393,6 +393,8 @@ alloc_process() proc->created = clock_systime(); proc->pgid = proc->pid; + proc->root = vfs_sysroot; + proc->sigreg = vzalloc(sizeof(struct sigregistry)); proc->fdtable = vzalloc(sizeof(struct v_fdtable)); diff --git a/lunaix-os/kernel/time/clock.c b/lunaix-os/kernel/time/clock.c index a5b9dd8..93354bb 100644 --- a/lunaix-os/kernel/time/clock.c +++ b/lunaix-os/kernel/time/clock.c @@ -5,15 +5,15 @@ #include -void -__clock_read_systime(struct twimap* map) +static void +__twimap_read_systime(struct twimap* map) { ticks_t sys_time = clock_systime(); twimap_printf(map, "%u", sys_time); } -void -__clock_read_datetime(struct twimap* map) +static void +__twimap_read_datetime(struct twimap* map) { datetime_t dt; clock_walltime(&dt); @@ -23,29 +23,12 @@ __clock_read_datetime(struct twimap* map) dt.hour, dt.minute, dt.second); } -void -__clock_read_unix(struct twimap* map) +static void +__twimap_read_unixtime(struct twimap* map) { twimap_printf(map, "%u", clock_unixtime()); } -void -clock_build_mapping() -{ - struct twifs_node* root = twifs_dir_node(NULL, "clock"); - struct twimap* map; - - map = twifs_mapping(root, NULL, "systime"); - map->read = __clock_read_systime; - - map = twifs_mapping(root, NULL, "unix"); - map->read = __clock_read_unix; - - map = twifs_mapping(root, NULL, "datetime"); - map->read = __clock_read_datetime; -} -EXPORT_TWIFS_PLUGIN(sys_clock, clock_build_mapping); - time_t clock_unixtime() { @@ -75,4 +58,18 @@ void clock_walltime(datetime_t* datetime) { sysrtc->ops->get_walltime(sysrtc, datetime); -} \ No newline at end of file +} + +static void +clock_build_mapping() +{ + struct twifs_node* root; + struct twimap* map; + + root = twifs_dir_node(NULL, "clock"); + + twimap_export_value(root, systime, FSACL_ugR, NULL); + twimap_export_value(root, unixtime, FSACL_ugR, NULL); + twimap_export_value(root, datetime, FSACL_ugR, NULL); +} +EXPORT_TWIFS_PLUGIN(sys_clock, clock_build_mapping); diff --git a/lunaix-os/kernel/usrscope.c b/lunaix-os/kernel/usrscope.c new file mode 100644 index 0000000..8a6bc99 --- /dev/null +++ b/lunaix-os/kernel/usrscope.c @@ -0,0 +1,156 @@ +#include +#include +#include +#include +#include + +#include + +#define GLIST_INIT_LEN 8 + +static struct ugroup_obj* +__alloc_groups_obj(unsigned int len) +{ + unsigned int size; + struct ugroup_obj* ugo; + + assert(len >= GLIST_INIT_LEN); + + ugo = valloc(sizeof(*ugo)); + ugo->refs = 1; + + size = len * sizeof(gid_t); + ugo->list = valloc(size); + ugo->maxcap = size; + + memset(ugo->list, grp_list_end, size); + return ugo; +} + +static inline void +__ref_groups_obj(struct ugroup_obj* ugo) +{ + if (unlikely(!ugo)) { + return; + } + + ugo->refs++; +} + +static void +__unref_groups_obj(struct ugroup_obj* ugo) +{ + ugo->refs--; + if (ugo->refs) { + return; + } + + vfree_safe(ugo->list); + vfree(ugo); +} + +static struct ugroup_obj* +__modify_group_obj(struct user_scope* procu, unsigned int new_len) +{ + struct ugroup_obj* ugo; + + ugo = procu->grps; + if (!ugo) { + return __alloc_groups_obj(GLIST_INIT_LEN); + } + + __unref_groups_obj(ugo); + + new_len = MAX(new_len, ugo->maxcap); + ugo = __alloc_groups_obj(new_len); + procu->grps = ugo; + + return ugo; +} + +int +uscope_setgroups(struct user_scope* proc_usr, + const gid_t* grps, unsigned int len) +{ + struct ugroup_obj* ugo; + + if (len > NGROUPS_MAX) { + return E2BIG; + } + + ugo = __modify_group_obj(proc_usr, len); + memcpy(ugo->list, grps, len * sizeof(gid_t)); + + return 0; +} + +bool +uscope_membership(struct user_scope* proc_usr, gid_t gid) +{ + struct ugroup_obj* ugo; + + ugo = proc_usr->grps; + if (unlikely(!ugo)) { + return false; + } + + for (unsigned i = 0; i < ugo->maxcap; i++) + { + if (ugo->list[i] != grp_list_end) { + break; + } + + if (ugo->list[i] == gid) { + return true; + } + } + + return false; +} + +void +uscope_copy(struct user_scope* to, struct user_scope* from) +{ + __ref_groups_obj(from->grps); + memcpy(to, from, sizeof(*to)); +} + +enum acl_match +check_acl_between(uid_t u1, gid_t g1, uid_t u2, gid_t g2) +{ + struct user_scope* uscope; + + if (!u1 || u1 == u2) + return ACL_MATCH_U; + + if (g1 == g2) + return ACL_MATCH_G; + + return ACL_NO_MATCH; +} + + +enum acl_match +check_current_acl(uid_t desired_u, gid_t desired_g) +{ + enum acl_match match; + struct user_scope* uscope; + + if (unlikely(!__current)) { + return ACL_NO_MATCH; + } + + match = check_acl_between(__current->euid, __current->egid, + desired_u, desired_g); + + if (match != ACL_NO_MATCH) { + return match; + } + + uscope = current_user_scope(); + if (uscope_membership(uscope, desired_g)) { + return ACL_MATCH_G; + } + + return ACL_NO_MATCH; +} \ No newline at end of file diff --git a/lunaix-os/usr/cat.c b/lunaix-os/usr/cat.c index cd8cad0..1fe6c16 100644 --- a/lunaix-os/usr/cat.c +++ b/lunaix-os/usr/cat.c @@ -26,7 +26,7 @@ main(int argc, const char* argv[]) return 1; } - if ((stat.mode & F_DIR)) { + if (((stat.st_mode >> 16) & F_DIR)) { printf("%s is a directory", argv[i]); return 1; } diff --git a/lunaix-os/usr/init/init.c b/lunaix-os/usr/init/init.c index 25996ce..804b8f8 100644 --- a/lunaix-os/usr/init/init.c +++ b/lunaix-os/usr/init/init.c @@ -39,7 +39,7 @@ init_termios(int fd) { check(tcgetattr(fd, &term)); - term.c_lflag = ICANON | IEXTEN | ISIG | ECHO | ECHOE | ECHONL; + term.c_lflag = ICANON | IEXTEN | ISIG | ECHO | ECHOE; term.c_iflag = ICRNL | IGNBRK; term.c_oflag = ONLCR | OPOST; term.c_cflag = CREAD | CLOCAL | CS8 | CPARENB; diff --git a/lunaix-os/usr/libc/src/_vprintf.c b/lunaix-os/usr/libc/src/_vprintf.c index 16d8133..7659e28 100644 --- a/lunaix-os/usr/libc/src/_vprintf.c +++ b/lunaix-os/usr/libc/src/_vprintf.c @@ -112,6 +112,9 @@ __vprintf_internal(char* buffer, const char* fmt, size_t max_len, va_list vargs) flags = flags | FLAG_CAPS; base = 16; goto format_unsigned; + case 'o': + base = 8; + goto format_unsigned; case 'p': num = (uintptr_t)va_arg(vargs, void*); base = 16; diff --git a/lunaix-os/usr/ls.c b/lunaix-os/usr/ls.c index caea32d..3fdfc6e 100644 --- a/lunaix-os/usr/ls.c +++ b/lunaix-os/usr/ls.c @@ -13,27 +13,43 @@ main(int argc, const char* argv[]) DIR* dir = opendir(path); if (!dir) { - return errno; + goto done; } struct dirent* dent; + int i = 0, sz; + char bf[100]; while ((dent = readdir(dir))) { if (dent->d_type == DT_DIR) { - printf(" %s/\n", dent->d_name); + sz = snprintf(bf, 100, "%s/", dent->d_name); } else if (dent->d_type == DT_SYMLINK) { - printf(" %s@\n", dent->d_name); + sz = snprintf(bf, 100, "%s@", dent->d_name); } else { - printf(" %s\n", dent->d_name); + sz = snprintf(bf, 100, "%s", dent->d_name); } + + bf[sz] = 0; + printf("%-15s ", bf); + + i++; + if ((i % 4) == 0) { + printf("\n"); + } + } + + if ((i % 4) != 0) { + printf("\n"); } +done: int err = errno; if (err) { printf("failed: %d\n",err); } - closedir(dir); + if (dir) + closedir(dir); return err; } \ No newline at end of file diff --git a/lunaix-os/usr/rm.c b/lunaix-os/usr/rm.c index 7fea833..c6046ce 100644 --- a/lunaix-os/usr/rm.c +++ b/lunaix-os/usr/rm.c @@ -29,7 +29,7 @@ main(int argc, const char* argv[]) close(fd); - if ((stat.mode & F_DIR)) { + if (((stat.st_mode >> 16) & F_DIR)) { err = rmdir(path); } else { diff --git a/lunaix-os/usr/sh/sh.c b/lunaix-os/usr/sh/sh.c index 5ca47ed..764404b 100644 --- a/lunaix-os/usr/sh/sh.c +++ b/lunaix-os/usr/sh/sh.c @@ -182,7 +182,7 @@ sh_loop() while (1) { getcwd(pwd, 512); - printf("[%s]$ ", pwd); + printf("%s # ", pwd); int sz = read(stdin, buf, 511); if (sz < 0) { @@ -195,8 +195,7 @@ sh_loop() // currently, this shell only support single argument if (!parse_cmdline(buf, argv)) { - printf("\n"); - goto cont; + continue; } // cmd=="exit" @@ -204,9 +203,7 @@ sh_loop() break; } - sh_exec((const char**)argv); - cont: - printf("\n"); + sh_exec((const char**)argv); } } diff --git a/lunaix-os/usr/stat.c b/lunaix-os/usr/stat.c index ea40200..1bd79f3 100644 --- a/lunaix-os/usr/stat.c +++ b/lunaix-os/usr/stat.c @@ -28,7 +28,7 @@ main(int argc, char* argv[]) printf("File: %s ", argv[1]); char* ftype = "directory"; - int mode = stat.mode; + int mode = stat.st_mode >> 16; if ((mode & F_DEV)) { ftype = "mappable (sequential) device"; @@ -53,16 +53,25 @@ main(int argc, char* argv[]) stat.st_blocks, stat.st_blksize, stat.st_ioblksize); - printf("Inode: %d; ", stat.st_ino); dev_t* dev; - if (!(stat.mode & F_DEV)) { + if (!(mode & F_DEV)) { dev = &stat.st_dev; } else { dev = &stat.st_rdev; } + printf("Device: %xh:%xh@%d; Inode: %d; Links: %d\n", + dev->meta, dev->unique, dev->index, + stat.st_ino, stat.st_nlink); - printf("Device: %xh:%xh@%d;\n", dev->meta, dev->unique, dev->index); + printf("Access: 0%o; Uid: %d; Gid: %d\n", + stat.st_mode & 0xffff, + stat.st_uid, + stat.st_gid); + + printf("Access: %lu\n", stat.st_atim); + printf("Modify: %lu\n", stat.st_mtim); + printf("Create: %lu\n", stat.st_ctim); close(fd); return 0;