From: Tulio A M Mendes Date: Mon, 25 May 2026 14:34:19 +0000 (-0300) Subject: kernel: hardening and cleanup fixes (Round 4) X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=beae9b7ed06d3f18846ce0ab07294c98fe9cd70c;p=AdrOS.git kernel: hardening and cleanup fixes (Round 4) - Rename socket_syscall_dispatch to extended_syscall_dispatch (handles MQ, SEM, DLOPEN, EPOLL, INOTIFY, AIO, MOUNT, etc., not just sockets) - Implement POSIX saved set-user-ID / set-group-ID: - Add suid/sgid fields to struct process (at end to preserve offsets) - setuid(2): when root, sets uid/euid/suid; non-root can set euid to uid or suid (POSIX spec) - setgid(2): same pattern for gid/egid/sgid - seteuid(2): saves old euid to suid, allows switch to suid - setegid(2): saves old egid to sgid, allows switch to sgid - suid/sgid inherited on fork and clone - Add SYSCALL_REBOOT (142): root-only, cmd 0=halt, 1=reboot, 2=poweroff. Uses hal_system_reboot() and new hal_system_shutdown() (QEMU ACPI port 0x604 for poweroff) Fixes: L04 (saved set-user-ID), L05 (reboot syscall), L06 (naming) --- diff --git a/include/hal/system.h b/include/hal/system.h index fbcdfcfb..fd666c92 100644 --- a/include/hal/system.h +++ b/include/hal/system.h @@ -11,5 +11,6 @@ #define HAL_SYSTEM_H void hal_system_reboot(void); +void hal_system_shutdown(void); #endif diff --git a/include/process.h b/include/process.h index 7f0ce7f0..5b56766f 100644 --- a/include/process.h +++ b/include/process.h @@ -159,6 +159,9 @@ struct process { /* SMP: which CPU's runqueue this process is assigned to */ uint32_t cpu_id; + uint32_t suid; /* saved set-user-ID */ + uint32_t sgid; /* saved set-group-ID */ + uint8_t fpu_state[FPU_STATE_SIZE] __attribute__((aligned(FPU_STATE_ALIGN))); }; diff --git a/include/syscall.h b/include/syscall.h index 58d3ec8d..f2348965 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -183,6 +183,7 @@ enum { SYSCALL_WAIT4 = 139, SYSCALL_MADVISE = 140, SYSCALL_EXECVEAT = 141, + SYSCALL_REBOOT = 142, }; #endif diff --git a/src/hal/x86/system.c b/src/hal/x86/system.c index 1e255905..7fa181a1 100644 --- a/src/hal/x86/system.c +++ b/src/hal/x86/system.c @@ -18,7 +18,14 @@ void hal_system_reboot(void) { while (good & 0x02) good = inb(0x64); outb(0x64, 0xFE); } + +void hal_system_shutdown(void) { + /* QEMU ACPI shutdown: write 0x2000 to port 0x604 */ + outw(0x604, 0x2000); +} #else void hal_system_reboot(void) { } +void hal_system_shutdown(void) { +} #endif diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index 405f9e99..693072c5 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -673,6 +673,8 @@ struct process* process_fork_create(uintptr_t child_as, const void* child_regs) proc->gid = current_process ? current_process->gid : 0; proc->euid = current_process ? current_process->euid : 0; proc->egid = current_process ? current_process->egid : 0; + proc->suid = current_process ? current_process->suid : 0; + proc->sgid = current_process ? current_process->sgid : 0; proc->priority = current_process ? current_process->priority : SCHED_DEFAULT_PRIO; proc->nice = current_process ? current_process->nice : 0; proc->state = PROCESS_READY; @@ -874,6 +876,8 @@ struct process* process_clone_create(uint32_t clone_flags, proc->gid = current_process->gid; proc->euid = current_process->euid; proc->egid = current_process->egid; + proc->suid = current_process->suid; + proc->sgid = current_process->sgid; proc->heap_start = current_process->heap_start; proc->heap_break = current_process->heap_break; memcpy(proc->rlimits, current_process->rlimits, sizeof(proc->rlimits)); diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 51a6f5f3..c48e193c 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -34,6 +34,7 @@ #include "hal/mm.h" #include "hal/cpu.h" +#include "hal/system.h" #include "arch_signal.h" #include "arch_syscall.h" #include "arch_process.h" @@ -830,7 +831,7 @@ static int path_resolve_user(const char* user_path, char* out, size_t out_sz); static int fd_alloc(struct file* f); static int fd_close(int fd); static struct file* fd_get(int fd); -static void socket_syscall_dispatch(struct registers* regs, uint32_t syscall_no); +static void extended_syscall_dispatch(struct registers* regs, uint32_t syscall_no); static void posix_ext_syscall_dispatch(struct registers* regs, uint32_t syscall_no); /* ------------------------------------------------------------------ */ @@ -3948,7 +3949,8 @@ void syscall_handler(struct registers* regs) { if (current_process->euid == 0) { current_process->uid = new_uid; current_process->euid = new_uid; - } else if (new_uid == current_process->uid) { + current_process->suid = new_uid; + } else if (new_uid == current_process->uid || new_uid == current_process->suid) { current_process->euid = new_uid; } else { sc_ret(regs) = (uint32_t)-EPERM; @@ -3964,7 +3966,8 @@ void syscall_handler(struct registers* regs) { if (current_process->euid == 0) { current_process->gid = new_gid; current_process->egid = new_gid; - } else if (new_gid == current_process->gid) { + current_process->sgid = new_gid; + } else if (new_gid == current_process->gid || new_gid == current_process->sgid) { current_process->egid = new_gid; } else { sc_ret(regs) = (uint32_t)-EPERM; @@ -3987,7 +3990,9 @@ void syscall_handler(struct registers* regs) { if (syscall_no == SYSCALL_SETEUID) { if (!current_process) { sc_ret(regs) = (uint32_t)-EINVAL; return; } uint32_t new_euid = sc_arg0(regs); - if (current_process->euid == 0 || new_euid == current_process->uid) { + if (current_process->euid == 0 || new_euid == current_process->uid + || new_euid == current_process->suid) { + current_process->suid = current_process->euid; current_process->euid = new_euid; sc_ret(regs) = 0; } else { @@ -3999,7 +4004,9 @@ void syscall_handler(struct registers* regs) { if (syscall_no == SYSCALL_SETEGID) { if (!current_process) { sc_ret(regs) = (uint32_t)-EINVAL; return; } uint32_t new_egid = sc_arg0(regs); - if (current_process->euid == 0 || new_egid == current_process->gid) { + if (current_process->euid == 0 || new_egid == current_process->gid + || new_egid == current_process->sgid) { + current_process->sgid = current_process->egid; current_process->egid = new_egid; sc_ret(regs) = 0; } else { @@ -4214,6 +4221,24 @@ void syscall_handler(struct registers* regs) { return; } + if (syscall_no == SYSCALL_REBOOT) { + /* reboot(cmd): cmd 0 = halt, 1 = reboot, 2 = poweroff. Root-only. */ + if (!current_process || current_process->euid != 0) { + sc_ret(regs) = (uint32_t)-EPERM; return; + } + int cmd = (int)sc_arg0(regs); + if (cmd == 1) { + hal_system_reboot(); + } else if (cmd == 2) { + hal_system_shutdown(); + } + /* halt or unknown: just loop */ + hal_cpu_disable_interrupts(); + for (;;) hal_cpu_idle(); + sc_ret(regs) = 0; /* unreachable */ + return; + } + if (syscall_no == SYSCALL_MPROTECT) { uintptr_t addr = (uintptr_t)sc_arg0(regs); uint32_t len = sc_arg1(regs); @@ -4272,7 +4297,7 @@ void syscall_handler(struct registers* regs) { } /* ---- Socket syscalls ---- */ - socket_syscall_dispatch(regs, syscall_no); + extended_syscall_dispatch(regs, syscall_no); /* If socket dispatch handled it, the return register is set and we return. If not, it sets ENOSYS. Either way, return. */ return; @@ -4662,7 +4687,7 @@ static int syscall_recvmsg_impl(int sockfd, void* user_msg, int flags) { /* Separate function to keep socket locals off syscall_handler's stack frame */ __attribute__((noinline)) -static void socket_syscall_dispatch(struct registers* regs, uint32_t syscall_no) { +static void extended_syscall_dispatch(struct registers* regs, uint32_t syscall_no) { if (syscall_no == SYSCALL_SOCKET) { int domain = (int)sc_arg0(regs); int type = (int)sc_arg1(regs); diff --git a/user/ulibc/include/syscall.h b/user/ulibc/include/syscall.h index 9c583d21..06a8f880 100644 --- a/user/ulibc/include/syscall.h +++ b/user/ulibc/include/syscall.h @@ -153,6 +153,7 @@ enum { SYS_WAIT4 = 139, SYS_MADVISE = 140, SYS_EXECVEAT = 141, + SYS_REBOOT = 142, }; /* Raw syscall wrappers — up to 5 args via INT 0x80 */