From c2ed59710a65ab32dae521cfe1a36e2ddf33fbd4 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Wed, 11 Feb 2026 19:46:34 -0300 Subject: [PATCH] feat: permissions support (uid/gid/mode, chmod, chown, getuid, getgid) - include/fs.h: added uid, gid, mode fields to fs_node_t - include/process.h: added uid, gid fields to struct process - include/stat.h: added st_uid, st_gid to struct stat, permission bit defines - include/syscall.h: added SYSCALL_CHMOD(50), SYSCALL_CHOWN(51), SYSCALL_GETUID(52), SYSCALL_GETGID(53) - src/kernel/syscall.c: chmod_impl, chown_impl, getuid/getgid dispatch; stat_from_node now populates uid/gid/mode - user/init.c: updated struct stat to match kernel layout - cppcheck clean, 19/19 smoke tests pass --- include/fs.h | 3 +++ include/process.h | 2 ++ include/stat.h | 15 +++++++++++ include/syscall.h | 5 ++++ src/kernel/syscall.c | 59 +++++++++++++++++++++++++++++++++++++++++++- user/init.c | 2 ++ 6 files changed, 85 insertions(+), 1 deletion(-) diff --git a/include/fs.h b/include/fs.h index de7825f4..fe8a8bcf 100644 --- a/include/fs.h +++ b/include/fs.h @@ -23,6 +23,9 @@ typedef struct fs_node { uint32_t flags; uint32_t inode; uint32_t length; + uint32_t uid; + uint32_t gid; + uint32_t mode; // Function pointers for operations (Polymorphism in C) uint32_t (*read)(struct fs_node* node, uint32_t offset, uint32_t size, uint8_t* buffer); diff --git a/include/process.h b/include/process.h index 3328cff4..7fc64f8f 100644 --- a/include/process.h +++ b/include/process.h @@ -39,6 +39,8 @@ struct process { uint32_t parent_pid; uint32_t session_id; uint32_t pgrp_id; + uint32_t uid; + uint32_t gid; uintptr_t sp; uintptr_t addr_space; uint32_t* kernel_stack; diff --git a/include/stat.h b/include/stat.h index 6dc89d18..5ea55d6b 100644 --- a/include/stat.h +++ b/include/stat.h @@ -17,10 +17,25 @@ #define S_IFDIR 0040000 #define S_IFCHR 0020000 +#define S_IRWXU 00700 +#define S_IRUSR 00400 +#define S_IWUSR 00200 +#define S_IXUSR 00100 +#define S_IRWXG 00070 +#define S_IRGRP 00040 +#define S_IWGRP 00020 +#define S_IXGRP 00010 +#define S_IRWXO 00007 +#define S_IROTH 00004 +#define S_IWOTH 00002 +#define S_IXOTH 00001 + struct stat { uint32_t st_ino; uint32_t st_mode; uint32_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; uint32_t st_size; }; diff --git a/include/syscall.h b/include/syscall.h index dc997f3e..f31cd327 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -76,6 +76,11 @@ enum { SYSCALL_SHMAT = 47, SYSCALL_SHMDT = 48, SYSCALL_SHMCTL = 49, + + SYSCALL_CHMOD = 50, + SYSCALL_CHOWN = 51, + SYSCALL_GETUID = 52, + SYSCALL_GETGID = 53, }; #endif diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 135165ac..5991f6ad 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -536,11 +536,14 @@ static int stat_from_node(const fs_node_t* node, struct stat* st) { st->st_ino = node->inode; st->st_nlink = 1; st->st_size = node->length; + st->st_uid = node->uid; + st->st_gid = node->gid; - uint32_t mode = 0; + uint32_t mode = node->mode & 07777; if (node->flags == FS_DIRECTORY) mode |= S_IFDIR; else if (node->flags == FS_CHARDEVICE) mode |= S_IFCHR; else mode |= S_IFREG; + if ((mode & 07777) == 0) mode |= 0755; st->st_mode = mode; return 0; } @@ -1615,6 +1618,35 @@ static uintptr_t syscall_brk_impl(uintptr_t addr) { return addr; } +static int syscall_chmod_impl(const char* user_path, uint32_t mode) { + if (!user_path) return -EFAULT; + + char path[128]; + int prc = path_resolve_user(user_path, path, sizeof(path)); + if (prc < 0) return prc; + + fs_node_t* node = vfs_lookup(path); + if (!node) return -ENOENT; + + node->mode = mode & 07777; + return 0; +} + +static int syscall_chown_impl(const char* user_path, uint32_t uid, uint32_t gid) { + if (!user_path) return -EFAULT; + + char path[128]; + int prc = path_resolve_user(user_path, path, sizeof(path)); + if (prc < 0) return prc; + + fs_node_t* node = vfs_lookup(path); + if (!node) return -ENOENT; + + node->uid = uid; + node->gid = gid; + return 0; +} + void syscall_handler(struct registers* regs) { uint32_t syscall_no = regs->eax; @@ -1997,6 +2029,31 @@ void syscall_handler(struct registers* regs) { return; } + if (syscall_no == SYSCALL_CHMOD) { + const char* path = (const char*)regs->ebx; + uint32_t mode = regs->ecx; + regs->eax = (uint32_t)syscall_chmod_impl(path, mode); + return; + } + + if (syscall_no == SYSCALL_CHOWN) { + const char* path = (const char*)regs->ebx; + uint32_t uid = regs->ecx; + uint32_t gid = regs->edx; + regs->eax = (uint32_t)syscall_chown_impl(path, uid, gid); + return; + } + + if (syscall_no == SYSCALL_GETUID) { + regs->eax = current_process ? current_process->uid : 0; + return; + } + + if (syscall_no == SYSCALL_GETGID) { + regs->eax = current_process ? current_process->gid : 0; + return; + } + regs->eax = (uint32_t)-ENOSYS; } diff --git a/user/init.c b/user/init.c index b6c2ca4e..7e2fb085 100644 --- a/user/init.c +++ b/user/init.c @@ -168,6 +168,8 @@ struct stat { uint32_t st_ino; uint32_t st_mode; uint32_t st_nlink; + uint32_t st_uid; + uint32_t st_gid; uint32_t st_size; }; -- 2.43.0