proc->parent_pid = current_process ? current_process->pid : 0;
proc->session_id = current_process ? current_process->session_id : proc->pid;
proc->pgrp_id = current_process ? current_process->pgrp_id : proc->pid;
+ proc->uid = current_process ? current_process->uid : 0;
+ 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->priority = current_process ? current_process->priority : SCHED_DEFAULT_PRIO;
proc->nice = current_process ? current_process->nice : 0;
proc->state = PROCESS_READY;
proc->uid = current_process->uid;
proc->gid = current_process->gid;
+ proc->euid = current_process->euid;
+ proc->egid = current_process->egid;
proc->heap_start = current_process->heap_start;
proc->heap_break = current_process->heap_break;
return (int)f->offset;
}
+/*
+ * Check if the current process has the requested access to a file node.
+ * want: bitmask of 4 (read), 2 (write), 1 (execute).
+ * Returns 0 if allowed, -EACCES if denied.
+ */
+static int vfs_check_permission(fs_node_t* node, int want) {
+ if (!current_process) return 0; /* kernel context — allow all */
+ if (current_process->euid == 0) return 0; /* root — allow all */
+ if (node->mode == 0) return 0; /* mode not set — permissive */
+
+ uint32_t mode = node->mode;
+ uint32_t perm;
+
+ if (current_process->euid == node->uid) {
+ perm = (mode >> 6) & 7; /* owner bits */
+ } else if (current_process->egid == node->gid) {
+ perm = (mode >> 3) & 7; /* group bits */
+ } else {
+ perm = mode & 7; /* other bits */
+ }
+
+ if ((want & perm) != (uint32_t)want) return -EACCES;
+ return 0;
+}
+
static int syscall_open_impl(const char* user_path, uint32_t flags) {
if (!user_path) return -EFAULT;
if (!node) return -ENOENT;
}
+ /* Permission check based on open flags */
+ {
+ int want = 4; /* default: read */
+ uint32_t acc = flags & 3U; /* O_RDONLY=0, O_WRONLY=1, O_RDWR=2 */
+ if (acc == 1) want = 2; /* write only */
+ else if (acc == 2) want = 6; /* read + write */
+ int perm_rc = vfs_check_permission(node, want);
+ if (perm_rc < 0) return perm_rc;
+ }
+
struct file* f = (struct file*)kmalloc(sizeof(*f));
if (!f) return -ENOMEM;
f->node = node;
fs_node_t* node = vfs_lookup(path);
if (!node) return -ENOENT;
+ /* Only root or file owner can chmod */
+ if (current_process && current_process->euid != 0 &&
+ current_process->euid != node->uid) {
+ return -EPERM;
+ }
+
node->mode = mode & 07777;
return 0;
}
fs_node_t* node = vfs_lookup(path);
if (!node) return -ENOENT;
+ /* Only root can chown */
+ if (current_process && current_process->euid != 0) {
+ return -EPERM;
+ }
+
node->uid = uid;
node->gid = gid;
return 0;
if (syscall_no == SYSCALL_SETUID) {
if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; }
- current_process->uid = regs->ebx;
+ uint32_t new_uid = regs->ebx;
+ if (current_process->euid == 0) {
+ current_process->uid = new_uid;
+ current_process->euid = new_uid;
+ } else if (new_uid == current_process->uid) {
+ current_process->euid = new_uid;
+ } else {
+ regs->eax = (uint32_t)-EPERM;
+ return;
+ }
regs->eax = 0;
return;
}
if (syscall_no == SYSCALL_SETGID) {
if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; }
- current_process->gid = regs->ebx;
+ uint32_t new_gid = regs->ebx;
+ if (current_process->euid == 0) {
+ current_process->gid = new_gid;
+ current_process->egid = new_gid;
+ } else if (new_gid == current_process->gid) {
+ current_process->egid = new_gid;
+ } else {
+ regs->eax = (uint32_t)-EPERM;
+ return;
+ }
regs->eax = 0;
return;
}
+ if (syscall_no == SYSCALL_GETEUID) {
+ regs->eax = current_process ? current_process->euid : 0;
+ return;
+ }
+
+ if (syscall_no == SYSCALL_GETEGID) {
+ regs->eax = current_process ? current_process->egid : 0;
+ return;
+ }
+
+ if (syscall_no == SYSCALL_SETEUID) {
+ if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; }
+ uint32_t new_euid = regs->ebx;
+ if (current_process->euid == 0 || new_euid == current_process->uid) {
+ current_process->euid = new_euid;
+ regs->eax = 0;
+ } else {
+ regs->eax = (uint32_t)-EPERM;
+ }
+ return;
+ }
+
+ if (syscall_no == SYSCALL_SETEGID) {
+ if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; }
+ uint32_t new_egid = regs->ebx;
+ if (current_process->euid == 0 || new_egid == current_process->gid) {
+ current_process->egid = new_egid;
+ regs->eax = 0;
+ } else {
+ regs->eax = (uint32_t)-EPERM;
+ }
+ return;
+ }
+
if (syscall_no == SYSCALL_FLOCK) {
int fd = (int)regs->ebx;
if (!current_process || fd < 0 || fd >= PROCESS_MAX_FILES || !current_process->files[fd]) {
return __syscall_ret(_syscall2(SYS_ACCESS, (int)path, mode));
}
+int getuid(void) {
+ return _syscall0(SYS_GETUID);
+}
+
+int getgid(void) {
+ return _syscall0(SYS_GETGID);
+}
+
+int geteuid(void) {
+ return _syscall0(SYS_GETEUID);
+}
+
+int getegid(void) {
+ return _syscall0(SYS_GETEGID);
+}
+
int setuid(int uid) {
return __syscall_ret(_syscall1(SYS_SETUID, uid));
}
return __syscall_ret(_syscall1(SYS_SETGID, gid));
}
+int seteuid(int euid) {
+ return __syscall_ret(_syscall1(SYS_SETEUID, euid));
+}
+
+int setegid(int egid) {
+ return __syscall_ret(_syscall1(SYS_SETEGID, egid));
+}
+
int truncate(const char* path, int length) {
return __syscall_ret(_syscall2(SYS_TRUNCATE, (int)path, length));
}