* 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
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)`※
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**
--- /dev/null
+#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
"gdbstub.c",
"trace.c",
"hart.c",
- "failsafe.S"
+ "failsafe.S",
+ "syscall_lut.S"
])
sources({
#define __ASM__
#include <lunaix/syscall.h>
-#include "syscall_nr.inc"
.section .text
.type syscall_hndlr, @function
jae 2f
shll $2, %eax
- addl $syscall_table, %eax
+ addl $__syscall_table, %eax
cmpl $0, (%eax)
jne 1f
2:
#define __ASM__
#include <lunaix/syscall.h>
-#include "syscall_nr.inc"
#include "asm/variants/interrupt64.S.inc"
.section .text
jae 2f
shlq $3, %rax // %rax * 8
- movabsq $syscall_table, %r8
+ movabsq $__syscall_table, %r8
addq %r8, %rax
cmpq $0, (%rax)
jne 1f
--- /dev/null
+#define __ASM__
+#include <lunaix/syscall.h>
+
+#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
-#ifdef CONFIG_ARCH_X86_64
-# define PTR .8byte
-# define SIZE 8
-#else
-# define PTR .4byte
-# define SIZE 4
-#endif
+#include <asm-generic/syscall_nr.inc>
-.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
#include <lunaix/fs/twifs.h>
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,
}
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;
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
}
static void
-__pci_read_cspace(struct twimap* map)
+__twimap_read_config(struct twimap* map)
{
struct pci_probe* probe;
/*---------- TwiFS interface definition ----------*/
static void
-__pci_read_revid(struct twimap* map)
+__twimap_read_revision(struct twimap* map)
{
struct pci_probe* probe;
}
static void
-__pci_read_class(struct twimap* map)
+__twimap_read_class(struct twimap* map)
{
struct pci_probe* probe;
}
static void
-__pci_read_devinfo(struct twimap* map)
+__twimap_read_pci_devinfo(struct twimap* map)
{
struct pci_probe* probe;
}
static void
-__pci_bar_read(struct twimap* map)
+__twimap_read_io_bases(struct twimap* map)
{
struct pci_probe* probe;
int bar_index;
}
static int
-__pci_bar_gonext(struct twimap* map)
+__twimap_gonext_io_bases(struct twimap* map)
{
if (twimap_index(map, int) >= 5) {
return 0;
}
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;
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);
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;
}
#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)))
struct load_context
{
struct exec_host* container;
+
ptr_t base;
ptr_t end;
ptr_t mem_sz;
ptr_t vms_mnt;
struct load_context exe;
+ struct v_inode* inode;
struct exec_arrptr argv;
struct exec_arrptr envp;
#include <lunaix/status.h>
#include <lunaix/spike.h>
#include <lunaix/bcache.h>
+#include <lunaix/fs_acl.h>
#include <usr/lunaix/fstypes.h>
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;
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,
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 */
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)
#include <lunaix/fs/twimap.h>
#include <lunaix/spike.h>
+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) \
#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 */
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
--- /dev/null
+#ifndef __LUNAIX_FS_ACL_H
+#define __LUNAIX_FS_ACL_H
+
+#include <lunaix/usrscope.h>
+#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 */
--- /dev/null
+#ifndef __LUNAIX_LIMITS_H
+#define __LUNAIX_LIMITS_H
+
+#define NGROUPS_MAX 128
+
+#endif /* __LUNAIX_LIMITS_H */
#include <lunaix/types.h>
#include <lunaix/spike.h>
#include <lunaix/hart_state.h>
+#include <lunaix/usrscope.h>
+
#include <stdint.h>
{
/*
Any change to *critical section*, including layout, size
- must be reflected in arch/x86/interrupt.S.inc to avoid
+ must be reflected in arch/<arch>/interrupt.S.inc to avoid
disaster!
*/
struct
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;
};
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 */
#define __LUNAIX_TYPES_H
#include <lunaix/compiler.h>
+#include <lunaix/limits.h>
#include <stdarg.h>
#include <usr/lunaix/types.h>
--- /dev/null
+#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 */
--- /dev/null
+#ifndef __LUNAIX_USRSCOPE_H
+#define __LUNAIX_USRSCOPE_H
+
+#include <lunaix/types.h>
+#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 */
#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 */
#define EAGAIN -30
#define EDEADLK -31
#define EDQUOT -32
+#define EPERM -33
+#define EACCESS -34
#endif /* __LUNAIX_STATUS_H */
typedef int pid_t;
typedef int tid_t;
+typedef int uid_t;
+typedef int gid_t;
typedef __SIZE_TYPE__ size_t;
"bcache.c",
"syscall.c",
"changeling.c",
+ "usrscope.c",
"kprint/kp_records.c",
"kprint/kprintf.c",
"time/clock.c",
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(
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
}
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) {
}
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*);
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);
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
{
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
if (waitq_empty(current_wq)) {
return;
}
-
+
block_current_thread();
if (!check_stall) {
void
pwake_one(waitq_t* queue)
{
- if (llist_empty(&queue->waiters)) {
+ if (waitq_empty(queue)) {
return;
}
void
pwake_all(waitq_t* queue)
{
- if (llist_empty(&queue->waiters)) {
+ if (waitq_empty(queue)) {
return;
}
}
save_process_cmd(proc, argv);
+ container->inode = executable->inode;
errno = load_executable(&container->exe, executable);
if (errno) {
goto done;
}
- if ((errno = vfs_open(dnode, &file))) {
+ if (!check_allow_execute(dnode->inode)) {
+ errno = EPERM;
goto done;
}
errno = EISDIR;
goto done;
}
+
+ if ((errno = vfs_open(dnode, &file))) {
+ goto done;
+ }
errno = exec_load(container, file);
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) {
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));
// Always yield the process that want execve!
schedule();
- // this will never get executed!
- return -1;
+ unreachable;
}
\ No newline at end of file
#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)
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)) {
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*);
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) {
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 "
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
}
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)
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
#include <klibc/string.h>
-#include <lunaix/fs.h>
+#include <lunaix/fs/api.h>
#include "iso9660.h"
#include <lunaix/mm/cake.h>
#include <lunaix/mm/valloc.h>
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;
time_t ctime;
time_t atime;
time_t mtime;
+
struct hstr name;
char name_val[ISO9660_IDLEN];
};
if ((dnode->mnt->flags & MNT_RO)) {
return EROFS;
}
+
+ if (!check_allow_write(dnode->inode)) {
+ return EPERM;
+ }
+
return 0;
}
#include <lunaix/process.h>
#include <lunaix/spike.h>
+#include <usr/lunaix/fcntl_defs.h>
+
#include <klibc/string.h>
#define VFS_SYMLINK_DEPTH 16
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) {
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;
}
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;
}
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;
cleanup:
vfs_d_free(dnode);
+
error:
*dentry = NULL;
return errno;
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
{
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
#include <asm/pagetable.h>
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));
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;
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;
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;
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)
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;
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;
}
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);
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;
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)
{
}
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,
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
#include <usr/lunaix/dirent_defs.h>
+#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;
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)
{
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);
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)
{
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
{
int errno = 0;
struct v_fd* fd_s;
+ struct v_inode* inode;
+
if ((errno = vfs_getfd(fd, &fd_s))) {
goto done;
}
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);
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;
}
goto done;
}
+ if (!check_allow_read(inode)) {
+ errno = EPERM;
+ goto done;
+ }
+
lock_inode(inode);
int overflow = 0;
return ENOTSUP;
}
+ if (!check_allow_read(inode)) {
+ return EPERM;
+ }
+
lock_inode(inode);
int errno = inode->ops->read_symlink(inode, &link);
lock_dnode(dnode);
+ if (!__check_unlinkable(dnode)) {
+ errno = EPERM;
+ goto done;
+ }
+
if ((errno = vfs_check_writable(dnode))) {
goto done;
}
return DO_STATUS(errno);
}
-int
+static int
__vfs_do_unlink(struct v_dnode* dnode)
{
int errno;
return EBUSY;
}
+ if (!__check_unlinkable(dnode)) {
+ return EPERM;
+ }
+
if ((errno = vfs_check_writable(dnode))) {
return errno;
}
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) {
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;
}
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;
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);
.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
}
static void
-__twimap_kprintf_read(struct twimap* map)
+__twimap_read_kmsg(struct twimap* map)
{
struct kp_records* __kprecs = twimap_data(map, struct kp_records*);
{
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);
}
static void
-read_lrulist_entry(struct twimap* map)
+__twimap_read_lru_pool(struct twimap* map)
{
struct lru_zone* zone;
}
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;
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
if (!pos)
return NULL;
-
+
void* piece;
piece_t found_index, *fl_slot;
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 };
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;
}
}
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--;
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) {
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,
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);
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);
}
}
}
__dup_fdtable(pcb);
+ uscope_copy(&pcb->uscope, current_user_scope());
struct proc_mm* mm = vmspace(pcb);
procvm_dupvms_mount(mm);
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)
{
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;
+}
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;
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));
#include <klibc/string.h>
-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);
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()
{
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);
--- /dev/null
+#include <lunaix/usrscope.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/status.h>
+#include <lunaix/spike.h>
+#include <lunaix/process.h>
+
+#include <klibc/string.h>
+
+#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
return 1;
}
- if ((stat.mode & F_DIR)) {
+ if (((stat.st_mode >> 16) & F_DIR)) {
printf("%s is a directory", argv[i]);
return 1;
}
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;
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;
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
close(fd);
- if ((stat.mode & F_DIR)) {
+ if (((stat.st_mode >> 16) & F_DIR)) {
err = rmdir(path);
}
else {
while (1) {
getcwd(pwd, 512);
- printf("[%s]$ ", pwd);
+ printf("%s # ", pwd);
int sz = read(stdin, buf, 511);
if (sz < 0) {
// currently, this shell only support single argument
if (!parse_cmdline(buf, argv)) {
- printf("\n");
- goto cont;
+ continue;
}
// cmd=="exit"
break;
}
- sh_exec((const char**)argv);
- cont:
- printf("\n");
+ sh_exec((const 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";
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;