#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
/* 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);
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);
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++) {
/* 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 */
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;
}