diff --git a/kernel/src/syscall/shmctl.rs b/kernel/src/syscall/shmctl.rs index f471cc893..07741b2d4 100644 --- a/kernel/src/syscall/shmctl.rs +++ b/kernel/src/syscall/shmctl.rs @@ -35,4 +35,67 @@ bitflags! { } pub fn sys_shmctl(id: i32, cmd: i32, buf: u64, _ctx: &Context) -> Result { + debug!("[sys_shmctl] id = {}, cmd = {}, buf = {:#x}", id, cmd, buf); + + if id < 0 { + return_errno!(Errno::EINVAL); + } + + let manager = SHM_OBJ_MANAGER.get().ok_or(Errno::EINVAL)?; + let shm_obj = { + let guard = manager.read(); + match guard.get_shm_obj(id as u64) { + Some(shm_obj) => shm_obj, + None => return_errno!(Errno::EINVAL), + } + }; + + let cmd = ShmCtlCmd::from_bits(cmd).ok_or(Errno::EINVAL)?; + + match cmd { + ShmCtlCmd::IPC_RMID => { + let mut guard = manager.write(); + + // Remove key mapping immediately to block further lookups by key + if let Some(key) = shm_obj.key() { + guard.remove_key_mapping(key); + } + + // Mark the segment to be destroyed + shm_obj.set_deleted(); + + // Try to delete the shared memory object when no process is attached + guard.try_delete_shm_obj(id as u64)?; + + Ok(SyscallReturn::Return(0)) + } + ShmCtlCmd::IPC_SET => { + let shm_ds: ShmidDs = current_userspace!().read_val(buf as usize)?; + + // FIXME: Check if the current process has the permission to set + // the attributes + + // Update the attributes of the shared memory object + shm_obj.set_attributes( + InodeMode::from_bits_truncate(shm_ds.shm_perm.mode), + shm_ds.shm_perm.uid, + shm_ds.shm_perm.gid, + )?; + + Ok(SyscallReturn::Return(0)) + } + ShmCtlCmd::IPC_STAT => { + // Get the attributes of the shared memory object + let shm_ds = shm_obj.get_attributes()?; + + // Write the attributes to the user space + current_userspace!().write_val(buf as usize, &shm_ds)?; + + Ok(SyscallReturn::Return(0)) + } + _ => { + warn!("Unsupported shmctl command: {:?}", cmd); + return_errno!(Errno::EINVAL); + } + } }