]> 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 69f131f344cc115210c29aa025be063dbebe37bf..0be6a6900004a5bd48e29e504f99b9b499e17022 100644 (file)
@@ -93,6 +93,7 @@ struct process {
     uintptr_t heap_break;
 
     char cwd[128];
+    uint32_t umask;
 
     int waiting;
     int wait_pid;
index 3f4b10f230f137554c5a6f01358c3c09ee1a575f..8fab4e38a744737caf0420c8cdcb6119a79eacce 100644 (file)
@@ -76,6 +76,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;
@@ -2214,6 +2215,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]) {
@@ -2224,6 +2237,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.
@@ -2231,6 +2272,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 290a1572c21c3677bf872e7c2451de12afb0f3c2..d551bddf8ce52dc52e2bb16ff1ecb21d80d45a0d 100644 (file)
@@ -59,5 +59,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 ecc6a43a1f6b1b0661f357105c631536a6396865..8404b67d34722d891e38b3e7c72221027de140dd 100644 (file)
@@ -62,6 +62,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 e7cbbbccbd1e5d1d04ecde3a9a9b97b76b3c5e06..356780c91728bf76fd0985e9e9a2adc4442e522b 100644 (file)
@@ -44,6 +44,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 cd5e71cfb08f1d6d6d49c4213559a8424f0b69d4..5e45fb4dd56b86a1a26f861e8a427f7713f8920e 100644 (file)
@@ -22,3 +22,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 f1f16601319eceb8ab8c22e00fdeb8891e9b82c8..8e2e0d297d88eabedbce4232a942218cc5902417 100644 (file)
@@ -103,6 +103,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);
 }