Resolve `semget01` failure by fixing key limit and adding `IPC_STAT`

This commit is contained in:
Tao Su 2025-08-14 03:23:46 +00:00 committed by Tate, Hongliang Tian
parent 85f17ff159
commit 226ea2865c
5 changed files with 69 additions and 5 deletions

View File

@ -7,7 +7,7 @@ futex, set_robust_list, and get_robust_list
under this category.
-->
## `System V semaphore`
## System V semaphore
### `semget`
@ -80,10 +80,17 @@ semctl(
semnum,
cmd = GETVAL | GETPID | GETNCNT | GETZCNT
);
// Retrieve a copy of the `semid_ds` kernel structure for the specified semaphore set
semctl(
semid,
semnum,
cmd = IPC_STAT,
arg
);
```
Unsupported commands:
* `IPC_STAT`
* `IPC_INFO`
* `SEM_INFO`
* `SEM_STAT`

View File

@ -51,6 +51,37 @@ pub struct SemaphoreSet {
sem_otime: AtomicU64,
}
// https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/ipcbuf.h
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Pod)]
pub struct IpcPerm {
key: u32,
uid: u32,
gid: u32,
cuid: u32,
cgid: u32,
mode: u16,
_pad1: u16,
seq: u16,
_pad2: u16,
_unused1: u64,
_unused2: u64,
}
// https://github.com/torvalds/linux/blob/master/arch/x86/include/uapi/asm/sembuf.h
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Pod)]
pub struct SemidDs {
sem_perm: IpcPerm,
sem_otime: u64,
_unused1: u64,
sem_ctime: u64,
_unused2: u64,
sem_nsems: u64,
_unused3: u64,
_unused4: u64,
}
#[derive(Debug)]
pub(super) struct SemSetInner {
/// Semaphores
@ -196,6 +227,26 @@ impl SemaphoreSet {
}),
})
}
pub fn semid_ds(&self) -> SemidDs {
let ipc_perm = IpcPerm {
key: self.permission.key() as u32,
uid: self.permission.uid().into(),
gid: self.permission.gid().into(),
cuid: self.permission.cuid().into(),
cgid: self.permission.cguid().into(),
mode: self.permission.mode(),
..IpcPerm::default()
};
SemidDs {
sem_perm: ipc_perm,
sem_otime: self.sem_otime.load(Ordering::Relaxed),
sem_ctime: self.sem_ctime.load(Ordering::Relaxed),
sem_nsems: self.nsems as u64,
..SemidDs::default()
}
}
}
impl Drop for SemaphoreSet {

View File

@ -92,6 +92,12 @@ pub fn sys_semctl(
return Ok(SyscallReturn::Return(cnt as isize));
}
IpcControlCmd::IPC_STAT => {
check_and_ctl(semid, PermissionMode::READ, |sem_set| {
let semid_ds = sem_set.semid_ds();
ctx.user_space().write_val(arg as Vaddr, &semid_ds)
})?;
}
_ => todo!("Need to support {:?} in SYS_SEMCTL", cmd),
}

View File

@ -4,7 +4,7 @@ use super::SyscallReturn;
use crate::{
ipc::{
semaphore::system_v::{
sem_set::{check_sem, create_sem_set, create_sem_set_with_id, SEMMSL},
sem_set::{check_sem, create_sem_set, create_sem_set_with_id, SEMMNI, SEMMSL},
PermissionMode,
},
IpcFlags,
@ -32,7 +32,7 @@ pub fn sys_semget(key: i32, nsems: i32, semflags: i32, ctx: &Context) -> Result<
// Create a new semaphore set directly
const IPC_NEW: i32 = 0;
if key == IPC_NEW {
if key == IPC_NEW || (key as usize > SEMMNI && flags.contains(IpcFlags::IPC_CREAT)) {
if nsems == 0 {
return_errno!(Errno::EINVAL);
}

View File

@ -1290,7 +1290,7 @@ select03
# semctl08
# semctl09
# semget01
semget01
# semget02
# semget05