]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
shm: implement SHM_RDONLY flag for read-only attach
authorTulio A M Mendes <[email protected]>
Thu, 11 Jun 2026 02:11:18 +0000 (23:11 -0300)
committerTulio A M Mendes <[email protected]>
Thu, 11 Jun 2026 02:11:18 +0000 (23:11 -0300)
Implement H3: SHM permissions complete with SHM_RDONLY attach.

Added SHM_RDONLY flag (0x1000) to shm.h for shmat syscall.
Modified shm_at() to accept shmflg parameter and:
- Check write permission only if SHM_RDONLY is not set
- Map pages without VMM_FLAG_RW when SHM_RDONLY is set
- This allows read-only shared memory segments for POSIX compliance

Updated syscall handler to pass shmflg from sc_arg2 to shm_at().

Test: make test-battery PASS (157/157), make analyzer PASS

include/shm.h
src/kernel/shm.c
src/kernel/syscall.c

index 09facf4ba8435128b9b45b8425e4bb3f782c75ed..a4772c1985c1ee1abc0a21e3a8e023b77d93fbf4 100644 (file)
@@ -20,6 +20,9 @@
 #define IPC_CREAT   0x0200
 #define IPC_EXCL    0x0400
 
+/* Flags for shmat */
+#define SHM_RDONLY  0x1000  /* Attach read-only */
+
 /* Commands for shmctl */
 #define IPC_RMID    0
 #define IPC_STAT    1
@@ -41,7 +44,7 @@ struct shmid_ds {
 
 /* Kernel API */
 int    shm_get(uint32_t key, uint32_t size, int flags);
-void*  shm_at(int shmid, uintptr_t shmaddr);
+void*  shm_at(int shmid, uintptr_t shmaddr, int shmflg);
 int    shm_dt(const void* shmaddr);
 int    shm_ctl(int shmid, int cmd, struct shmid_ds* buf);
 
index 67124c41287abe8867d39aa87e020e3284d1c8fe..9e4cab27a315d6cde591b81a98dfb038c89fe321 100644 (file)
@@ -145,7 +145,7 @@ int shm_get(uint32_t key, uint32_t size, int flags) {
     return slot;
 }
 
-void* shm_at(int shmid, uintptr_t shmaddr) {
+void* shm_at(int shmid, uintptr_t shmaddr, int shmflg) {
     if (shmid < 0 || shmid >= SHM_MAX_SEGMENTS) return (void*)(uintptr_t)-EINVAL;
 
     uintptr_t irqf = spin_lock_irqsave(&shm_lock);
@@ -166,12 +166,20 @@ void* shm_at(int shmid, uintptr_t shmaddr) {
         return (void*)(uintptr_t)-EINVAL;
     }
 
-    /* Check POSIX read permission */
+    /* Check POSIX read permission (always required) */
     if (!shm_perm_check(seg, 04)) {  /* R_OK = 4 */
         spin_unlock_irqrestore(&shm_lock, irqf);
         return (void*)(uintptr_t)-EACCES;
     }
 
+    /* If not SHM_RDONLY, also check write permission */
+    if (!(shmflg & SHM_RDONLY)) {
+        if (!shm_perm_check(seg, 02)) {  /* W_OK = 2 */
+            spin_unlock_irqrestore(&shm_lock, irqf);
+            return (void*)(uintptr_t)-EACCES;
+        }
+    }
+
     /* Find a free mmap slot (always needed to track the mapping) */
     int mslot = -1;
     for (int i = 0; i < PROCESS_MAX_MMAPS; i++) {
@@ -211,11 +219,16 @@ void* shm_at(int shmid, uintptr_t shmaddr) {
 
     /* Map physical pages into user address space.
      * vmm_map_page signature: (phys, virt, flags)
-     * NX by default - IA32_EFER.NXE MSR is now enabled (A01 completed) */
+     * NX by default - IA32_EFER.NXE MSR is now enabled (A01 completed)
+     * H3: If SHM_RDONLY is set, map without VMM_FLAG_RW for read-only access */
+    uint64_t map_flags = VMM_FLAG_PRESENT | VMM_FLAG_USER | VMM_FLAG_NX;
+    if (!(shmflg & SHM_RDONLY)) {
+        map_flags |= VMM_FLAG_RW;
+    }
     for (uint32_t i = 0; i < seg->npages; i++) {
         vmm_map_page((uint64_t)seg->pages[i],
                      (uint64_t)(vaddr + i * PAGE_SIZE),
-                     VMM_FLAG_PRESENT | VMM_FLAG_RW | VMM_FLAG_USER | VMM_FLAG_NX);
+                     map_flags);
     }
 
     /* Record mapping in process mmap table with shmid for detach lookup */
index 4e7237895b7b9c29d4185ee4ac545e751c84035e..7bdce47145c2ff8c4f98d5641ca083c10aeeee1d 100644 (file)
@@ -3974,7 +3974,8 @@ void syscall_handler(struct registers* regs) {
     if (syscall_no == SYSCALL_SHMAT) {
         int shmid = (int)sc_arg0(regs);
         uintptr_t shmaddr = (uintptr_t)sc_arg1(regs);
-        sc_ret(regs) = (uint32_t)(uintptr_t)shm_at(shmid, shmaddr);
+        int shmflg = (int)sc_arg2(regs);
+        sc_ret(regs) = (uint32_t)(uintptr_t)shm_at(shmid, shmaddr, shmflg);
         return;
     }