Merge pull request #153 from arihant2math/prctl-updates

Implement more of prctl
This commit is contained in:
Matthew Leach
2026-01-15 12:24:27 +00:00
committed by GitHub
3 changed files with 81 additions and 10 deletions

View File

@@ -145,10 +145,18 @@ impl Capabilities {
self.ambient
}
pub fn ambient_mut(&mut self) -> &mut CapabilitiesFlags {
&mut self.ambient
}
pub fn bounding(&self) -> CapabilitiesFlags {
self.bounding
}
pub fn bounding_mut(&mut self) -> &mut CapabilitiesFlags {
&mut self.bounding
}
/// Checks if a capability is effective, as in if it can be used.
pub fn is_capable(&self, cap: CapabilitiesFlags) -> bool {
self.effective.contains(cap)

View File

@@ -471,7 +471,7 @@ pub async fn handle_syscall() {
0xa0 => sys_uname(TUA::from_value(arg1 as _)).await,
0xa3 => Err(KernelError::InvalidValue),
0xa6 => sys_umask(arg1 as _).map_err(|e| match e {}),
0xa7 => sys_prctl(arg1 as _, arg2).await,
0xa7 => sys_prctl(arg1 as _, arg2, arg3).await,
0xa9 => sys_gettimeofday(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
0xac => sys_getpid().map_err(|e| match e {}),
0xad => sys_getppid().map_err(|e| match e {}),

View File

@@ -2,23 +2,55 @@ use crate::memory::uaccess::copy_to_user_slice;
use crate::memory::uaccess::cstr::UserCStr;
use crate::process::Comm;
use crate::sched::current::current_task_shared;
use bitflags::Flags;
use core::ffi::c_char;
use libkernel::error::{KernelError, Result};
use libkernel::memory::address::TUA;
use libkernel::proc::caps::CapabilitiesFlags;
const PR_CAPBSET_READ: i32 = 23;
const PR_CAPBSET_DROP: i32 = 24;
const PR_SET_NAME: i32 = 15;
const PR_GET_NAME: i32 = 16;
const CAP_MAX: usize = 40;
const PR_GET_SECUREBITS: i32 = 27;
const PR_GET_NO_NEW_PRIVS: i32 = 39;
const PR_CAP_AMBIENT: i32 = 47;
fn pr_read_capset(what: usize) -> Result<usize> {
// Validate the argument
if what > CAP_MAX {
return Err(KernelError::InvalidValue);
#[derive(Debug)]
enum AmbientCapOp {
IsSet = 1,
Raise = 2,
Lower = 3,
ClearAll = 4,
}
impl TryFrom<u64> for AmbientCapOp {
type Error = KernelError;
fn try_from(value: u64) -> Result<Self> {
match value {
1 => Ok(AmbientCapOp::IsSet),
2 => Ok(AmbientCapOp::Raise),
3 => Ok(AmbientCapOp::Lower),
4 => Ok(AmbientCapOp::ClearAll),
_ => Err(KernelError::InvalidValue),
}
}
}
// Assume we have *all* the capabilities.
Ok(1)
fn pr_read_capbset(what: usize) -> Result<usize> {
let what = CapabilitiesFlags::from_bits(1u64 << what).ok_or(KernelError::InvalidValue)?;
let task = current_task_shared();
let creds = task.creds.lock_save_irq();
Ok(creds.caps.bounding().contains(what) as _)
}
async fn pr_drop_capbset(what: usize) -> Result<usize> {
let what = CapabilitiesFlags::from_bits(1u64 << what).ok_or(KernelError::InvalidValue)?;
let task = current_task_shared();
let mut creds = task.creds.lock_save_irq();
creds.caps.bounding_mut().remove(what);
Ok(0)
}
async fn pr_get_name(str: TUA<c_char>) -> Result<usize> {
@@ -36,11 +68,42 @@ async fn pr_set_name(str: TUA<c_char>) -> Result<usize> {
Ok(0)
}
pub async fn sys_prctl(op: i32, arg1: u64) -> Result<usize> {
async fn pr_cap_ambient(op: u64, arg1: u64) -> Result<usize> {
let op = AmbientCapOp::try_from(op)?;
let task = current_task_shared();
match op {
AmbientCapOp::ClearAll => {
let mut creds = task.creds.lock_save_irq();
creds.caps.ambient_mut().clear();
Ok(0)
}
AmbientCapOp::IsSet => {
let what =
CapabilitiesFlags::from_bits(1u64 << arg1).ok_or(KernelError::InvalidValue)?;
let creds = task.creds.lock_save_irq();
let is_set = creds.caps.ambient().contains(what);
Ok(is_set as _)
}
AmbientCapOp::Lower => {
let what =
CapabilitiesFlags::from_bits(1u64 << arg1).ok_or(KernelError::InvalidValue)?;
let mut creds = task.creds.lock_save_irq();
creds.caps.ambient_mut().remove(what);
Ok(0)
}
op => todo!("prctl PR_CAP_AMBIENT op: {:?}", op),
}
}
pub async fn sys_prctl(op: i32, arg1: u64, arg2: u64) -> Result<usize> {
match op {
PR_SET_NAME => pr_set_name(TUA::from_value(arg1 as usize)).await,
PR_GET_NAME => pr_get_name(TUA::from_value(arg1 as usize)).await,
PR_CAPBSET_READ => pr_read_capset(arg1 as usize),
PR_CAPBSET_READ => pr_read_capbset(arg1 as usize),
PR_CAPBSET_DROP => pr_drop_capbset(arg1 as usize).await,
PR_GET_SECUREBITS => Ok(0),
PR_GET_NO_NEW_PRIVS => Ok(0),
PR_CAP_AMBIENT => pr_cap_ambient(arg1, arg2).await,
_ => todo!("prctl op: {}", op),
}
}