mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
Handle negative P(G)IDs via cast_(un)signed
This commit is contained in:
parent
d3e4f175cd
commit
50ba735e96
@ -14,6 +14,7 @@
|
||||
#![feature(fn_traits)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(int_roundings)]
|
||||
#![feature(integer_sign_cast)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(linked_list_cursors)]
|
||||
#![feature(linked_list_remove)]
|
||||
|
@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
#![expect(dead_code)]
|
||||
|
||||
use super::{Pgid, Pid};
|
||||
use crate::prelude::*;
|
||||
|
||||
@ -13,44 +11,50 @@ pub enum ProcessFilter {
|
||||
}
|
||||
|
||||
impl ProcessFilter {
|
||||
// used for waitid
|
||||
pub fn from_which_and_id(which: u64, id: u64) -> Result<Self> {
|
||||
// Does not support PID_FD now(which = 3)
|
||||
// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/wait.h#L20
|
||||
// For `waitpid`.
|
||||
pub fn from_which_and_id(which: u64, id: u32) -> Result<Self> {
|
||||
// Reference:
|
||||
// <https://elixir.bootlin.com/linux/v6.14.4/source/include/uapi/linux/wait.h#L16-L20>
|
||||
const P_ALL: u64 = 0;
|
||||
const P_PID: u64 = 1;
|
||||
const P_PGID: u64 = 2;
|
||||
const P_PIDFD: u64 = 3;
|
||||
|
||||
match which {
|
||||
0 => Ok(ProcessFilter::Any),
|
||||
1 => Ok(ProcessFilter::WithPid(id as Pid)),
|
||||
2 => Ok(ProcessFilter::WithPgid(id as Pgid)),
|
||||
3 => todo!(),
|
||||
_ => return_errno_with_message!(Errno::EINVAL, "invalid which"),
|
||||
P_ALL => Ok(ProcessFilter::Any),
|
||||
P_PID => Ok(ProcessFilter::WithPid(id)),
|
||||
P_PGID => Ok(ProcessFilter::WithPgid(id)),
|
||||
P_PIDFD => {
|
||||
warn!("the process filter `P_PIDFD` is not supported");
|
||||
return_errno_with_message!(
|
||||
Errno::EINVAL,
|
||||
"the process filter `P_PIDFD` is not supported"
|
||||
);
|
||||
}
|
||||
_ => return_errno_with_message!(Errno::EINVAL, "the process filter is invalid"),
|
||||
}
|
||||
}
|
||||
|
||||
// used for wait4 and kill
|
||||
// For `wait4` and `kill`.
|
||||
pub fn from_id(wait_pid: i32) -> Self {
|
||||
// https://man7.org/linux/man-pages/man2/waitpid.2.html
|
||||
// https://man7.org/linux/man-pages/man2/kill.2.html
|
||||
// Reference:
|
||||
// <https://man7.org/linux/man-pages/man2/waitpid.2.html>
|
||||
// <https://man7.org/linux/man-pages/man2/kill.2.html>
|
||||
if wait_pid < -1 {
|
||||
// process group ID is equal to the absolute value of pid.
|
||||
ProcessFilter::WithPgid((-wait_pid) as Pgid)
|
||||
// "wait for any child process whose process group ID is equal to the absolute value of
|
||||
// `pid`"
|
||||
ProcessFilter::WithPgid((-wait_pid).cast_unsigned())
|
||||
} else if wait_pid == -1 {
|
||||
// wait for any child process
|
||||
// "wait for any child process"
|
||||
ProcessFilter::Any
|
||||
} else if wait_pid == 0 {
|
||||
// wait for any child process with same process group ID
|
||||
// "wait for any child process whose process group ID is equal to that of the calling
|
||||
// process at the time of the call to `waitpid()`"
|
||||
let pgid = current!().pgid();
|
||||
ProcessFilter::WithPgid(pgid)
|
||||
} else {
|
||||
// pid > 0. wait for the child whose process ID is equal to the value of pid.
|
||||
ProcessFilter::WithPid(wait_pid as Pid)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn contains_pid(&self, pid: Pid) -> bool {
|
||||
match self {
|
||||
ProcessFilter::Any => true,
|
||||
ProcessFilter::WithPid(filter_pid) => *filter_pid == pid,
|
||||
ProcessFilter::WithPgid(_) => todo!(),
|
||||
// "wait for the child whose process ID is equal to the value of `pid`"
|
||||
ProcessFilter::WithPid(wait_pid.cast_unsigned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,10 @@ pub fn sys_setpgid(pid: Pid, pgid: Pgid, ctx: &Context) -> Result<SyscallReturn>
|
||||
// The documentation quoted below is from
|
||||
// <https://www.man7.org/linux/man-pages/man2/setpgid.2.html>.
|
||||
|
||||
if pid.cast_signed() < 0 || pgid.cast_signed() < 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "negative PIDs or PGIDs are not valid");
|
||||
}
|
||||
|
||||
// "If `pid` is zero, then the process ID of the calling process is used."
|
||||
let pid = if pid == 0 { current.pid() } else { pid };
|
||||
// "If `pgid` is zero, then the PGID of the process specified by `pid` is made the same as its
|
||||
|
@ -15,14 +15,16 @@ pub fn sys_waitid(
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
// FIXME: what does infoq and rusage use for?
|
||||
let process_filter = ProcessFilter::from_which_and_id(which, upid)?;
|
||||
let process_filter = ProcessFilter::from_which_and_id(which, upid as _)?;
|
||||
let wait_options = WaitOptions::from_bits(options as u32)
|
||||
.ok_or(Error::with_message(Errno::EINVAL, "invalid options"))?;
|
||||
|
||||
let waited_process =
|
||||
wait_child_exit(process_filter, wait_options, ctx).map_err(|err| match err.error() {
|
||||
Errno::EINTR => Error::new(Errno::ERESTARTSYS),
|
||||
_ => err,
|
||||
})?;
|
||||
|
||||
let pid = waited_process.map_or(0, |process| process.pid());
|
||||
Ok(SyscallReturn::Return(pid as _))
|
||||
}
|
||||
|
@ -32,6 +32,10 @@ END_SETUP()
|
||||
|
||||
FN_TEST(setpgid_invalid)
|
||||
{
|
||||
// Negative PIDs or PGIDs
|
||||
TEST_ERRNO(setpgid(-1, current), EINVAL);
|
||||
TEST_ERRNO(setpgid(current, -1), EINVAL);
|
||||
|
||||
// Non-present process groups
|
||||
TEST_ERRNO(setpgid(child1, child2), EPERM);
|
||||
TEST_ERRNO(setpgid(child2, child1), EPERM);
|
||||
@ -176,6 +180,9 @@ END_TEST()
|
||||
|
||||
FN_TEST(getpgid_invalid)
|
||||
{
|
||||
// Negative PIDs
|
||||
TEST_ERRNO(getpgid(-1), ESRCH);
|
||||
|
||||
// Non-present processes
|
||||
TEST_ERRNO(getpgid(0x3c3c3c3c), ESRCH);
|
||||
}
|
||||
@ -183,6 +190,9 @@ END_TEST()
|
||||
|
||||
FN_TEST(getsid_invalid)
|
||||
{
|
||||
// Negative PIDs
|
||||
TEST_ERRNO(getsid(-1), ESRCH);
|
||||
|
||||
// Non-present processes
|
||||
TEST_ERRNO(getsid(0x3c3c3c3c), ESRCH);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user