From bb570062e55ac8389aaa30c795651a4ef0c1eddc Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 20 Apr 2025 16:35:25 +0200 Subject: [PATCH] Allow making setpgid return EACCESS, e.g. after execv. --- Cargo.lock | 8 ++++---- src/procmgr.rs | 33 +++++++++++++++++++++++++-------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13ab2e20b6..7fcc3f58f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,7 +46,7 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "generic-rt" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#040009ab3d384e75d62b7e7dd3176d910203501a" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#696ae4eca1df5e3b76a57f62903ee1a94b9c6aa6" [[package]] name = "goblin" @@ -151,7 +151,7 @@ checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717" [[package]] name = "redox-rt" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#040009ab3d384e75d62b7e7dd3176d910203501a" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#696ae4eca1df5e3b76a57f62903ee1a94b9c6aa6" dependencies = [ "bitflags", "generic-rt", @@ -162,9 +162,9 @@ dependencies = [ [[package]] name = "redox-scheme" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6469e083bf650071e9a80003c53171dfccc5ef17ae1d24972396c3c792e7c709" +checksum = "a14f94bc95b388d8f40a61f25577863f1cf151aaf600a5b7778d1a2018ff7742" dependencies = [ "libredox", "redox_syscall", diff --git a/src/procmgr.rs b/src/procmgr.rs index 6d26a24a02..732df8c1bf 100644 --- a/src/procmgr.rs +++ b/src/procmgr.rs @@ -35,7 +35,7 @@ use syscall::schemev2::NewFdFlags; use syscall::{ sig_bit, ContextStatus, ContextVerb, CtxtStsBuf, Error, Event, EventFlags, FobtainFdFlags, MapFlags, ProcSchemeAttrs, Result, SenderInfo, SetSighandlerData, SigProcControl, Sigcontrol, - EAGAIN, EBADF, EBADFD, ECHILD, EEXIST, EINTR, EINVAL, EIO, ENOENT, ENOSYS, EOPNOTSUPP, + EACCES, EAGAIN, EBADF, EBADFD, ECHILD, EEXIST, EINTR, EINVAL, EIO, ENOENT, ENOSYS, EOPNOTSUPP, EOWNERDEAD, EPERM, ERESTART, ESRCH, EWOULDBLOCK, O_CLOEXEC, O_CREAT, PAGE_SIZE, }; @@ -336,6 +336,7 @@ struct Process { ens: u32, status: ProcessStatus, + disabled_setpgid: bool, awaiting_threads_term: Vec, @@ -581,6 +582,7 @@ impl<'a> ProcScheme<'a> { name: ArrayString::<32>::from_str("[init]").unwrap(), status: ProcessStatus::PossiblyRunnable, + disabled_setpgid: false, awaiting_threads_term: Vec::new(), waitpid: BTreeMap::new(), waitpid_waiting: VecDeque::new(), @@ -659,6 +661,7 @@ impl<'a> ProcScheme<'a> { name, status: ProcessStatus::PossiblyRunnable, + disabled_setpgid: false, awaiting_threads_term: Vec::new(), waitpid: BTreeMap::new(), @@ -990,6 +993,14 @@ impl<'a> ProcScheme<'a> { self.on_proc_rename(fd_pid, payload).map(|()| 0), op, )), + ProcCall::DisableSetpgid => { + if let Some(proc) = self.processes.get(&fd_pid) { + proc.borrow_mut().disabled_setpgid = true; + Response::ready_ok(0, op) + } else { + Response::ready_err(ESRCH, op) + } + } } } Handle::Ps(_) => Response::ready_err(EOPNOTSUPP, op), @@ -1114,24 +1125,30 @@ impl<'a> ProcScheme<'a> { ) }; - // Cannot change the pgid of a process in a different session. - if caller_sid != proc.sid { - return Err(Error::new(EPERM)); - } - // Session leaders cannot have their pgid changed. if proc.sid == target_pid { return Err(Error::new(EPERM)); } - if proc.pgid == new_pgid { - return Ok(()); + // Cannot change the pgid of a process in a different session. + if caller_sid != proc.sid { + return Err(Error::new(EPERM)); } + // New pgid must either already exit, or be the same as the target pid. if new_pgid != target_pid && !self.groups.contains_key(&new_pgid) { return Err(Error::new(EPERM)); } + // After execv(), i.e. ProcCall::DisableSetpgid, setpgid shall return EACCESS + if proc.disabled_setpgid { + return Err(Error::new(EACCES)); + } + + if proc.pgid == new_pgid { + return Ok(()); + } + Self::set_pgid( proc_rc, &mut *proc,