]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: sigpending, pread/pwrite, access, umask, setuid/setgid syscalls + ulibc wrappers
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 02:54:11 +0000 (23:54 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:20:50 +0000 (23:20 -0300)
- SYSCALL_SIGPENDING (71): returns pending & blocked signal mask
- SYSCALL_PREAD/PWRITE (72/73): positional read/write without altering file offset
- SYSCALL_ACCESS (74): checks file existence (simplified, no real perm check yet)
- SYSCALL_UMASK (75): per-process file creation mask (new umask field in struct process)
- SYSCALL_SETUID/SETGID (76/77): change process uid/gid
- Extract pread/pwrite/access into noinline posix_ext_syscall_dispatch to avoid stack bloat
- ulibc: signal.h sigpending(), unistd.h pread/pwrite/access/setuid/setgid

include/process.h
src/kernel/syscall.c
user/ulibc/include/signal.h
user/ulibc/include/syscall.h
user/ulibc/include/unistd.h
user/ulibc/src/signal.c
user/ulibc/src/unistd.c

index b89ace5cc494b1c3e7d345583d6074e220c876a3..ddc7e748db307edbfa597027af2e2016417f03ab 100644 (file)
@@ -84,6 +84,7 @@ struct process {
     uintptr_t heap_break;
 
     char cwd[128];
+    uint32_t umask;
 
     int waiting;
     int wait_pid;
index 1c0ab58c723d325d57f4dda9ee44a381b51ad106..3bb789bcf6841446feb0ddbbdae1f6f33ae5d78d 100644 (file)
@@ -67,6 +67,7 @@ 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 posix_ext_syscall_dispatch(struct registers* regs, uint32_t syscall_no);
 
 struct pollfd {
     int fd;
@@ -2205,6 +2206,18 @@ void syscall_handler(struct registers* regs) {
         return;
     }
 
+    if (syscall_no == SYSCALL_SIGPENDING) {
+        uint32_t* user_set = (uint32_t*)regs->ebx;
+        if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; }
+        uint32_t pending = current_process->sig_pending_mask & current_process->sig_blocked_mask;
+        if (copy_to_user(user_set, &pending, sizeof(pending)) < 0) {
+            regs->eax = (uint32_t)-EFAULT;
+        } else {
+            regs->eax = 0;
+        }
+        return;
+    }
+
     if (syscall_no == SYSCALL_FSYNC || syscall_no == SYSCALL_FDATASYNC) {
         int fd = (int)regs->ebx;
         if (!current_process || fd < 0 || fd >= PROCESS_MAX_FILES || !current_process->files[fd]) {
@@ -2215,6 +2228,34 @@ void syscall_handler(struct registers* regs) {
         return;
     }
 
+    if (syscall_no == SYSCALL_PREAD || syscall_no == SYSCALL_PWRITE ||
+        syscall_no == SYSCALL_ACCESS) {
+        posix_ext_syscall_dispatch(regs, syscall_no);
+        return;
+    }
+
+    if (syscall_no == SYSCALL_UMASK) {
+        if (!current_process) { regs->eax = 0; return; }
+        uint32_t old = current_process->umask;
+        current_process->umask = regs->ebx & 0777;
+        regs->eax = old;
+        return;
+    }
+
+    if (syscall_no == SYSCALL_SETUID) {
+        if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; }
+        current_process->uid = regs->ebx;
+        regs->eax = 0;
+        return;
+    }
+
+    if (syscall_no == SYSCALL_SETGID) {
+        if (!current_process) { regs->eax = (uint32_t)-EINVAL; return; }
+        current_process->gid = regs->ebx;
+        regs->eax = 0;
+        return;
+    }
+
     /* ---- Socket syscalls ---- */
     socket_syscall_dispatch(regs, syscall_no);
     /* If socket dispatch handled it, eax is set and we return.
@@ -2222,6 +2263,76 @@ void syscall_handler(struct registers* regs) {
     return;
 }
 
+/* Separate function to keep pread/pwrite/access locals off syscall_handler's stack */
+__attribute__((noinline))
+static void posix_ext_syscall_dispatch(struct registers* regs, uint32_t syscall_no) {
+    if (syscall_no == SYSCALL_PREAD) {
+        int fd = (int)regs->ebx;
+        void* buf = (void*)regs->ecx;
+        uint32_t count = regs->edx;
+        uint32_t offset = regs->esi;
+        struct file* f = fd_get(fd);
+        if (!f || !f->node) { regs->eax = (uint32_t)-EBADF; return; }
+        if (!f->node->read) { regs->eax = (uint32_t)-ESPIPE; return; }
+        if (count > 1024 * 1024) { regs->eax = (uint32_t)-EINVAL; return; }
+        uint8_t kbuf[256];
+        uint32_t total = 0;
+        while (total < count) {
+            uint32_t chunk = count - total;
+            if (chunk > sizeof(kbuf)) chunk = (uint32_t)sizeof(kbuf);
+            uint32_t rd = vfs_read(f->node, offset + total, chunk, kbuf);
+            if (rd == 0) break;
+            if (copy_to_user((uint8_t*)buf + total, kbuf, rd) < 0) {
+                regs->eax = (uint32_t)-EFAULT; return;
+            }
+            total += rd;
+            if (rd < chunk) break;
+        }
+        regs->eax = total;
+        return;
+    }
+
+    if (syscall_no == SYSCALL_PWRITE) {
+        int fd = (int)regs->ebx;
+        const void* buf = (const void*)regs->ecx;
+        uint32_t count = regs->edx;
+        uint32_t offset = regs->esi;
+        struct file* f = fd_get(fd);
+        if (!f || !f->node) { regs->eax = (uint32_t)-EBADF; return; }
+        if (!f->node->write) { regs->eax = (uint32_t)-ESPIPE; return; }
+        if (count > 1024 * 1024) { regs->eax = (uint32_t)-EINVAL; return; }
+        uint8_t kbuf[256];
+        uint32_t total = 0;
+        while (total < count) {
+            uint32_t chunk = count - total;
+            if (chunk > sizeof(kbuf)) chunk = (uint32_t)sizeof(kbuf);
+            if (copy_from_user(kbuf, (const uint8_t*)buf + total, chunk) < 0) {
+                regs->eax = (uint32_t)-EFAULT; return;
+            }
+            uint32_t wr = vfs_write(f->node, offset + total, chunk, kbuf);
+            if (wr == 0) break;
+            total += wr;
+            if (wr < chunk) break;
+        }
+        regs->eax = total;
+        return;
+    }
+
+    if (syscall_no == SYSCALL_ACCESS) {
+        const char* user_path = (const char*)regs->ebx;
+        if (!user_path) { regs->eax = (uint32_t)-EFAULT; return; }
+        char path[128];
+        int prc = path_resolve_user(user_path, path, sizeof(path));
+        if (prc < 0) { regs->eax = (uint32_t)prc; return; }
+        fs_node_t* node = vfs_lookup(path);
+        if (!node) { regs->eax = (uint32_t)-ENOENT; return; }
+        regs->eax = 0;
+        return;
+    }
+
+    regs->eax = (uint32_t)-ENOSYS;
+}
+
 /* 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) {
index dc4b5712f900da3120b0e68079636ee7cc2f4c09..02c9f94046c5f4ec6956c8df11e1ba838711cd60 100644 (file)
@@ -50,5 +50,6 @@ int raise(int sig);
 int sigaction(int signum, const struct sigaction* act,
               struct sigaction* oldact);
 int sigprocmask(int how, const uint32_t* set, uint32_t* oldset);
+int sigpending(uint32_t* set);
 
 #endif
index ec1e847fb40dd6586522624719aa02d848d493e6..586b404ea25c53fa0fc508f566b07c8c1a1f382a 100644 (file)
@@ -53,6 +53,13 @@ enum {
     SYS_GETTID = 68,
     SYS_FSYNC = 69,
     SYS_FDATASYNC = 70,
+    SYS_SIGPENDING = 71,
+    SYS_PREAD = 72,
+    SYS_PWRITE = 73,
+    SYS_ACCESS = 74,
+    SYS_UMASK = 75,
+    SYS_SETUID = 76,
+    SYS_SETGID = 77,
 };
 
 /* Raw syscall wrappers — up to 5 args via INT 0x80 */
index 70a818f5f6b85b272a37a1e935d821f22f001dd2..5d4d7128221e33ec8009ec7054790cd28c7309fa 100644 (file)
@@ -35,6 +35,11 @@ int     getpgrp(void);
 int     gettid(void);
 int     fsync(int fd);
 int     fdatasync(int fd);
+int     pread(int fd, void* buf, size_t count, int offset);
+int     pwrite(int fd, const void* buf, size_t count, int offset);
+int     access(const char* path, int mode);
+int     setuid(int uid);
+int     setgid(int gid);
 void*   brk(void* addr);
 
 void    _exit(int status) __attribute__((noreturn));
index 0bd63c1535e8c2e369e4d8bc290cb9f5df4b16c8..0eaa8d0b43cc11d76167821c7e44a6a5383b163a 100644 (file)
@@ -13,3 +13,7 @@ int raise(int sig) {
 int sigprocmask(int how, const uint32_t* set, uint32_t* oldset) {
     return __syscall_ret(_syscall3(SYS_SIGPROCMASK, how, (int)set, (int)oldset));
 }
+
+int sigpending(uint32_t* set) {
+    return __syscall_ret(_syscall1(SYS_SIGPENDING, (int)set));
+}
index 06ce1b6d5109160753a1cc089c9dbfa4a27ccf67..b27226f6110d63c95a4ccfd5b68324777c007921 100644 (file)
@@ -94,6 +94,26 @@ int fdatasync(int fd) {
     return __syscall_ret(_syscall1(SYS_FDATASYNC, fd));
 }
 
+int pread(int fd, void* buf, size_t count, int offset) {
+    return __syscall_ret(_syscall4(SYS_PREAD, fd, (int)buf, (int)count, offset));
+}
+
+int pwrite(int fd, const void* buf, size_t count, int offset) {
+    return __syscall_ret(_syscall4(SYS_PWRITE, fd, (int)buf, (int)count, offset));
+}
+
+int access(const char* path, int mode) {
+    return __syscall_ret(_syscall2(SYS_ACCESS, (int)path, mode));
+}
+
+int setuid(int uid) {
+    return __syscall_ret(_syscall1(SYS_SETUID, uid));
+}
+
+int setgid(int gid) {
+    return __syscall_ret(_syscall1(SYS_SETGID, gid));
+}
+
 void* brk(void* addr) {
     return (void*)_syscall1(SYS_BRK, (int)addr);
 }