2024-01-03 03:22:36 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2024-05-03 20:36:19 +00:00
|
|
|
use super::SyscallReturn;
|
2024-02-25 14:09:24 +00:00
|
|
|
use crate::{
|
|
|
|
|
prelude::*,
|
2025-11-21 09:27:13 +00:00
|
|
|
process::{
|
|
|
|
|
credentials::SecureBits, posix_thread::MAX_THREAD_NAME_LEN, signal::sig_num::SigNum,
|
|
|
|
|
},
|
2024-02-25 14:09:24 +00:00
|
|
|
};
|
2024-01-08 03:36:16 +00:00
|
|
|
|
2024-08-04 06:37:50 +00:00
|
|
|
pub fn sys_prctl(
|
|
|
|
|
option: i32,
|
|
|
|
|
arg2: u64,
|
|
|
|
|
arg3: u64,
|
|
|
|
|
arg4: u64,
|
|
|
|
|
arg5: u64,
|
2024-08-11 13:35:27 +00:00
|
|
|
ctx: &Context,
|
2024-08-04 06:37:50 +00:00
|
|
|
) -> Result<SyscallReturn> {
|
2022-11-10 09:57:39 +00:00
|
|
|
let prctl_cmd = PrctlCmd::from_args(option, arg2, arg3, arg4, arg5)?;
|
2023-03-13 07:59:01 +00:00
|
|
|
debug!("prctl cmd = {:x?}", prctl_cmd);
|
2022-11-10 09:57:39 +00:00
|
|
|
match prctl_cmd {
|
2024-01-08 03:36:16 +00:00
|
|
|
PrctlCmd::PR_SET_PDEATHSIG(signum) => {
|
2024-08-11 13:35:27 +00:00
|
|
|
ctx.process.set_parent_death_signal(signum);
|
2024-01-08 03:36:16 +00:00
|
|
|
}
|
|
|
|
|
PrctlCmd::PR_GET_PDEATHSIG(write_to_addr) => {
|
|
|
|
|
let write_val = {
|
2024-08-11 13:35:27 +00:00
|
|
|
match ctx.process.parent_death_signal() {
|
2024-01-08 03:36:16 +00:00
|
|
|
None => 0i32,
|
|
|
|
|
Some(signum) => signum.as_u8() as i32,
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-11-13 15:39:10 +00:00
|
|
|
ctx.user_space().write_val(write_to_addr, &write_val)?;
|
2024-01-08 03:36:16 +00:00
|
|
|
}
|
2024-07-15 07:46:23 +00:00
|
|
|
PrctlCmd::PR_GET_DUMPABLE => {
|
|
|
|
|
// TODO: when coredump is supported, return the actual value
|
|
|
|
|
return Ok(SyscallReturn::Return(Dumpable::Disable as _));
|
|
|
|
|
}
|
|
|
|
|
PrctlCmd::PR_SET_DUMPABLE(dumpable) => {
|
|
|
|
|
if dumpable != Dumpable::Disable && dumpable != Dumpable::User {
|
|
|
|
|
return_errno!(Errno::EINVAL)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: implement coredump
|
|
|
|
|
}
|
2024-12-05 07:49:43 +00:00
|
|
|
PrctlCmd::PR_GET_KEEPCAPS => {
|
|
|
|
|
let keep_cap = {
|
|
|
|
|
let credentials = ctx.posix_thread.credentials();
|
|
|
|
|
if credentials.keep_capabilities() {
|
|
|
|
|
1
|
|
|
|
|
} else {
|
|
|
|
|
0
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return Ok(SyscallReturn::Return(keep_cap as _));
|
|
|
|
|
}
|
|
|
|
|
PrctlCmd::PR_SET_KEEPCAPS(keep_cap) => {
|
|
|
|
|
if keep_cap > 1 {
|
|
|
|
|
return_errno!(Errno::EINVAL)
|
|
|
|
|
}
|
|
|
|
|
let credentials = ctx.posix_thread.credentials_mut();
|
2025-11-21 09:27:13 +00:00
|
|
|
credentials.set_keep_capabilities(keep_cap != 0)?;
|
2024-12-05 07:49:43 +00:00
|
|
|
}
|
2022-11-10 09:57:39 +00:00
|
|
|
PrctlCmd::PR_GET_NAME(write_to_addr) => {
|
2024-08-11 14:32:47 +00:00
|
|
|
let thread_name = ctx.posix_thread.thread_name().lock();
|
2025-09-24 09:13:23 +00:00
|
|
|
ctx.user_space().write_bytes(
|
|
|
|
|
write_to_addr,
|
|
|
|
|
&mut VmReader::from(thread_name.name().to_bytes_with_nul()),
|
|
|
|
|
)?;
|
2022-11-10 09:57:39 +00:00
|
|
|
}
|
|
|
|
|
PrctlCmd::PR_SET_NAME(read_addr) => {
|
2025-09-24 09:13:23 +00:00
|
|
|
let new_thread_name = ctx
|
|
|
|
|
.user_space()
|
|
|
|
|
.read_cstring(read_addr, MAX_THREAD_NAME_LEN)?;
|
2024-08-11 14:32:47 +00:00
|
|
|
let mut thread_name = ctx.posix_thread.thread_name().lock();
|
2025-09-24 09:13:23 +00:00
|
|
|
thread_name.set_name(&new_thread_name);
|
2022-11-10 09:57:39 +00:00
|
|
|
}
|
2025-03-03 09:02:08 +00:00
|
|
|
PrctlCmd::PR_SET_CHILD_SUBREAPER(is_set) => {
|
2025-09-22 08:02:43 +00:00
|
|
|
let process = ctx.process.as_ref();
|
2025-03-03 09:02:08 +00:00
|
|
|
if is_set {
|
|
|
|
|
process.set_child_subreaper();
|
|
|
|
|
} else {
|
|
|
|
|
process.unset_child_subreaper();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
PrctlCmd::PR_GET_CHILD_SUBREAPER(write_addr) => {
|
2025-09-22 08:02:43 +00:00
|
|
|
let process = ctx.process.as_ref();
|
2025-03-03 09:02:08 +00:00
|
|
|
ctx.user_space()
|
|
|
|
|
.write_val(write_addr, &(process.is_child_subreaper() as u32))?;
|
|
|
|
|
}
|
2025-11-21 09:27:13 +00:00
|
|
|
PrctlCmd::PR_GET_SECUREBITS => {
|
|
|
|
|
let credentials = ctx.posix_thread.credentials();
|
|
|
|
|
let securebits = credentials.securebits();
|
|
|
|
|
return Ok(SyscallReturn::Return(securebits.bits() as _));
|
|
|
|
|
}
|
|
|
|
|
PrctlCmd::PR_SET_SECUREBITS(securebits) => {
|
|
|
|
|
let credentials = ctx.posix_thread.credentials_mut();
|
|
|
|
|
credentials.set_securebits(securebits)?;
|
|
|
|
|
}
|
2022-11-10 09:57:39 +00:00
|
|
|
_ => todo!(),
|
|
|
|
|
}
|
|
|
|
|
Ok(SyscallReturn::Return(0))
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-08 03:36:16 +00:00
|
|
|
const PR_SET_PDEATHSIG: i32 = 1;
|
|
|
|
|
const PR_GET_PDEATHSIG: i32 = 2;
|
2024-07-15 07:46:23 +00:00
|
|
|
const PR_GET_DUMPABLE: i32 = 3;
|
|
|
|
|
const PR_SET_DUMPABLE: i32 = 4;
|
2024-12-05 07:49:43 +00:00
|
|
|
const PR_GET_KEEPCAPS: i32 = 7;
|
|
|
|
|
const PR_SET_KEEPCAPS: i32 = 8;
|
2022-11-10 09:57:39 +00:00
|
|
|
const PR_SET_NAME: i32 = 15;
|
|
|
|
|
const PR_GET_NAME: i32 = 16;
|
2025-11-21 09:27:13 +00:00
|
|
|
const PR_GET_SECUREBITS: i32 = 27;
|
|
|
|
|
const PR_SET_SECUREBITS: i32 = 28;
|
2022-11-10 09:57:39 +00:00
|
|
|
const PR_SET_TIMERSLACK: i32 = 29;
|
|
|
|
|
const PR_GET_TIMERSLACK: i32 = 30;
|
2025-03-03 09:02:08 +00:00
|
|
|
const PR_SET_CHILD_SUBREAPER: i32 = 36;
|
|
|
|
|
const PR_GET_CHILD_SUBREAPER: i32 = 37;
|
2022-11-10 09:57:39 +00:00
|
|
|
|
2025-01-24 10:06:53 +00:00
|
|
|
#[expect(non_camel_case_types)]
|
2022-11-10 09:57:39 +00:00
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
|
pub enum PrctlCmd {
|
2024-01-08 03:36:16 +00:00
|
|
|
PR_SET_PDEATHSIG(SigNum),
|
|
|
|
|
PR_GET_PDEATHSIG(Vaddr),
|
2022-11-10 09:57:39 +00:00
|
|
|
PR_SET_NAME(Vaddr),
|
|
|
|
|
PR_GET_NAME(Vaddr),
|
2024-12-05 07:49:43 +00:00
|
|
|
PR_GET_KEEPCAPS,
|
|
|
|
|
PR_SET_KEEPCAPS(u32),
|
2025-01-24 10:06:53 +00:00
|
|
|
#[expect(dead_code)]
|
2022-11-10 09:57:39 +00:00
|
|
|
PR_SET_TIMERSLACK(u64),
|
2025-01-24 10:06:53 +00:00
|
|
|
#[expect(dead_code)]
|
2022-11-10 09:57:39 +00:00
|
|
|
PR_GET_TIMERSLACK,
|
2024-07-15 07:46:23 +00:00
|
|
|
PR_SET_DUMPABLE(Dumpable),
|
|
|
|
|
PR_GET_DUMPABLE,
|
2025-03-03 09:02:08 +00:00
|
|
|
PR_SET_CHILD_SUBREAPER(bool),
|
|
|
|
|
PR_GET_CHILD_SUBREAPER(Vaddr),
|
2025-11-21 09:27:13 +00:00
|
|
|
PR_GET_SECUREBITS,
|
|
|
|
|
PR_SET_SECUREBITS(SecureBits),
|
2024-07-15 07:46:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[repr(u64)]
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromInt)]
|
|
|
|
|
pub enum Dumpable {
|
|
|
|
|
Disable = 0, /* No setuid dumping */
|
|
|
|
|
User = 1, /* Dump as user of process */
|
|
|
|
|
Root = 2, /* Dump as root */
|
2022-11-10 09:57:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PrctlCmd {
|
2024-08-11 12:17:25 +00:00
|
|
|
fn from_args(option: i32, arg2: u64, _arg3: u64, _arg4: u64, _arg5: u64) -> Result<PrctlCmd> {
|
2022-11-10 09:57:39 +00:00
|
|
|
match option {
|
2024-01-08 03:36:16 +00:00
|
|
|
PR_SET_PDEATHSIG => {
|
|
|
|
|
let signum = SigNum::try_from(arg2 as u8)?;
|
|
|
|
|
Ok(PrctlCmd::PR_SET_PDEATHSIG(signum))
|
|
|
|
|
}
|
|
|
|
|
PR_GET_PDEATHSIG => Ok(PrctlCmd::PR_GET_PDEATHSIG(arg2 as _)),
|
2024-07-15 07:46:23 +00:00
|
|
|
PR_GET_DUMPABLE => Ok(PrctlCmd::PR_GET_DUMPABLE),
|
|
|
|
|
PR_SET_DUMPABLE => Ok(PrctlCmd::PR_SET_DUMPABLE(Dumpable::try_from(arg2)?)),
|
2022-11-10 09:57:39 +00:00
|
|
|
PR_SET_NAME => Ok(PrctlCmd::PR_SET_NAME(arg2 as _)),
|
|
|
|
|
PR_GET_NAME => Ok(PrctlCmd::PR_GET_NAME(arg2 as _)),
|
|
|
|
|
PR_GET_TIMERSLACK => todo!(),
|
|
|
|
|
PR_SET_TIMERSLACK => todo!(),
|
2024-12-05 07:49:43 +00:00
|
|
|
PR_GET_KEEPCAPS => Ok(PrctlCmd::PR_GET_KEEPCAPS),
|
|
|
|
|
PR_SET_KEEPCAPS => Ok(PrctlCmd::PR_SET_KEEPCAPS(arg2 as _)),
|
2025-03-03 09:02:08 +00:00
|
|
|
PR_SET_CHILD_SUBREAPER => Ok(PrctlCmd::PR_SET_CHILD_SUBREAPER(arg2 > 0)),
|
|
|
|
|
PR_GET_CHILD_SUBREAPER => Ok(PrctlCmd::PR_GET_CHILD_SUBREAPER(arg2 as _)),
|
2025-11-21 09:27:13 +00:00
|
|
|
PR_GET_SECUREBITS => Ok(PrctlCmd::PR_GET_SECUREBITS),
|
|
|
|
|
PR_SET_SECUREBITS => Ok(PrctlCmd::PR_SET_SECUREBITS(SecureBits::try_from(
|
|
|
|
|
arg2 as u16,
|
|
|
|
|
)?)),
|
2022-11-10 09:57:39 +00:00
|
|
|
_ => {
|
|
|
|
|
debug!("prctl cmd number: {}", option);
|
|
|
|
|
return_errno_with_message!(Errno::EINVAL, "unsupported prctl command");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|