Add credential-related syscalls

This commit is contained in:
Jianfeng Jiang 2023-11-29 11:42:53 +00:00 committed by Tate, Hongliang Tian
parent c99e6b4ced
commit 90be8038e0
23 changed files with 563 additions and 56 deletions

View File

@ -1,7 +1,7 @@
use super::posix_thread::{PosixThread, PosixThreadBuilder, PosixThreadExt, ThreadName};
use super::process_vm::ProcessVm;
use super::signal::sig_disposition::SigDispositions;
use super::{process_table, Process, ProcessBuilder};
use super::{credentials, process_table, Credentials, Process, ProcessBuilder};
use crate::current_thread;
use crate::fs::file_table::FileTable;
use crate::fs::fs_resolver::FsResolver;
@ -176,7 +176,13 @@ fn clone_child_thread(parent_context: UserContext, clone_args: CloneArgs) -> Res
let child_tid = allocate_tid();
let child_thread = {
let is_main_thread = child_tid == current.pid();
let thread_builder = PosixThreadBuilder::new(child_tid, child_user_space)
let credentials = {
let credentials = credentials();
Credentials::new_from(&credentials)
};
let thread_builder = PosixThreadBuilder::new(child_tid, child_user_space, credentials)
.process(Arc::downgrade(&current))
.sig_mask(sig_mask)
.is_main_thread(is_main_thread);
@ -255,7 +261,13 @@ fn clone_child_process(parent_context: UserContext, clone_args: CloneArgs) -> Re
let child_elf_path = current.executable_path();
let child_thread_builder = {
let child_thread_name = ThreadName::new_from_executable_path(&child_elf_path)?;
PosixThreadBuilder::new(child_tid, child_user_space)
let credentials = {
let credentials = credentials();
Credentials::new_from(&credentials)
};
PosixThreadBuilder::new(child_tid, child_user_space, credentials)
.thread_name(Some(child_thread_name))
.sig_mask(child_sig_mask)
};

View File

@ -5,7 +5,7 @@ use crate::{
process::{
posix_thread::name::ThreadName,
signal::{sig_mask::SigMask, sig_queues::SigQueues},
Process,
Credentials, Process,
},
thread::{status::ThreadStatus, task::create_new_user_task, thread_table, Thread, Tid},
};
@ -18,6 +18,7 @@ pub struct PosixThreadBuilder {
tid: Tid,
user_space: Arc<UserSpace>,
process: Weak<Process>,
credentials: Credentials,
// Optional part
thread_name: Option<ThreadName>,
@ -29,11 +30,12 @@ pub struct PosixThreadBuilder {
}
impl PosixThreadBuilder {
pub fn new(tid: Tid, user_space: Arc<UserSpace>) -> Self {
pub fn new(tid: Tid, user_space: Arc<UserSpace>, credentials: Credentials) -> Self {
Self {
tid,
user_space,
process: Weak::new(),
credentials,
thread_name: None,
set_child_tid: 0,
clear_child_tid: 0,
@ -79,6 +81,7 @@ impl PosixThreadBuilder {
tid,
user_space,
process,
credentials,
thread_name,
set_child_tid,
clear_child_tid,
@ -96,6 +99,7 @@ impl PosixThreadBuilder {
name: Mutex::new(thread_name),
set_child_tid: Mutex::new(set_child_tid),
clear_child_tid: Mutex::new(clear_child_tid),
credentials,
sig_mask: Mutex::new(sig_mask),
sig_queues: Mutex::new(sig_queues),
sig_context,

View File

@ -1,21 +1,18 @@
use crate::{
events::Observer,
prelude::*,
process::{
do_exit_group,
posix_thread::{futex::futex_wake, robust_list::wake_robust_futex},
TermStatus,
},
thread::{thread_table, Tid},
util::write_val_to_user,
};
use super::{
signal::{
sig_mask::SigMask, sig_queues::SigQueues, signals::Signal, SigEvents, SigEventsFilter,
},
Process,
};
use super::kill::SignalSenderIds;
use super::signal::sig_mask::SigMask;
use super::signal::sig_num::SigNum;
use super::signal::sig_queues::SigQueues;
use super::signal::signals::Signal;
use super::signal::{SigEvents, SigEventsFilter};
use super::{do_exit_group, Credentials, Process, TermStatus};
use crate::events::Observer;
use crate::prelude::*;
use crate::process::signal::constants::SIGCONT;
use crate::thread::{thread_table, Tid};
use crate::util::write_val_to_user;
use futex::futex_wake;
use jinux_rights::{ReadOp, WriteOp};
use robust_list::wake_robust_futex;
mod builder;
pub mod futex;
@ -43,6 +40,9 @@ pub struct PosixThread {
robust_list: Mutex<Option<RobustListHead>>,
/// Process credentials. At the kernel level, credentials are a per-thread attribute.
credentials: Credentials,
// signal
/// blocked signals
sig_mask: Mutex<SigMask>,
@ -78,7 +78,57 @@ impl PosixThread {
!self.sig_queues.lock().is_empty()
}
pub fn enqueue_signal(&self, signal: Box<dyn Signal>) {
/// Returns whether the signal is blocked by the thread.
pub(in crate::process) fn has_signal_blocked(&self, signal: &dyn Signal) -> bool {
let mask = self.sig_mask.lock();
mask.contains(signal.num())
}
/// Checks whether the signal can be delivered to the thread.
///
/// For a signal can be delivered to the thread, the sending thread must either
/// be privileged, or the real or effective user ID of the sending thread must equal
/// the real or saved set-user-ID of the target thread.
///
/// For SIGCONT, the sending and receiving processes should belong to the same session.
pub(in crate::process) fn check_signal_perm(
&self,
signum: Option<&SigNum>,
sender: &SignalSenderIds,
) -> Result<()> {
if sender.euid().is_root() {
return Ok(());
}
if let Some(signum) = signum && *signum == SIGCONT {
let receiver_sid = self.process().session().unwrap().sid();
if receiver_sid == sender.sid() {
return Ok(())
} else {
return_errno_with_message!(Errno::EPERM, "sigcont requires that sender and receiver belongs to the same session");
}
}
let (receiver_ruid, receiver_suid) = {
let credentials = self.credentials();
(credentials.ruid(), credentials.suid())
};
// FIXME: further check the below code to ensure the behavior is same as Linux. According
// to man(2) kill, the real or effective user ID of the sending process must equal the
// real or saved set-user-ID of the target process.
if sender.ruid() == receiver_ruid
|| sender.ruid() == receiver_suid
|| sender.euid() == receiver_ruid
|| sender.euid() == receiver_suid
{
return Ok(());
}
return_errno_with_message!(Errno::EPERM, "sending signal to the thread is not allowed.");
}
pub(in crate::process) fn enqueue_signal(&self, signal: Box<dyn Signal>) {
self.sig_queues.lock().enqueue(signal);
}
@ -177,4 +227,14 @@ impl PosixThread {
futex_wake(Arc::as_ptr(&self.process()) as Vaddr, 1)?;
Ok(())
}
/// Gets the read-only credentials of the thread.
pub(in crate::process) fn credentials(&self) -> Credentials<ReadOp> {
self.credentials.dup().restrict()
}
/// Gets the write-only credentials of the thread.
pub(in crate::process) fn credentials_mut(&self) -> Credentials<WriteOp> {
self.credentials.dup().restrict()
}
}

View File

@ -3,15 +3,17 @@ use jinux_frame::{cpu::UserContext, user::UserSpace};
use crate::{
fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD},
prelude::*,
process::{process_vm::ProcessVm, program_loader::load_program_to_vm, Process},
process::{process_vm::ProcessVm, program_loader::load_program_to_vm, Credentials, Process},
thread::{Thread, Tid},
};
use super::{builder::PosixThreadBuilder, name::ThreadName, PosixThread};
pub trait PosixThreadExt {
fn as_posix_thread(&self) -> Option<&PosixThread>;
#[allow(clippy::too_many_arguments)]
fn new_posix_thread_from_executable(
tid: Tid,
credentials: Credentials,
process_vm: &ProcessVm,
fs_resolver: &FsResolver,
executable_path: &str,
@ -25,6 +27,7 @@ impl PosixThreadExt for Thread {
/// This function should only be called when launch shell()
fn new_posix_thread_from_executable(
tid: Tid,
credentials: Credentials,
process_vm: &ProcessVm,
fs_resolver: &FsResolver,
executable_path: &str,
@ -45,7 +48,7 @@ impl PosixThreadExt for Thread {
cpu_ctx.set_rsp(elf_load_info.user_stack_top() as _);
let user_space = Arc::new(UserSpace::new(vm_space, cpu_ctx));
let thread_name = Some(ThreadName::new_from_executable_path(executable_path)?);
let thread_builder = PosixThreadBuilder::new(tid, user_space)
let thread_builder = PosixThreadBuilder::new(tid, user_space, credentials)
.thread_name(thread_name)
.process(process);
Ok(thread_builder.build())

View File

@ -1,4 +1,5 @@
use jinux_frame::cpu::UserContext;
use jinux_rights::WriteOp;
use super::{constants::*, SyscallReturn};
use crate::fs::file_table::FileDescripter;
@ -7,7 +8,9 @@ use crate::fs::utils::{Dentry, InodeType};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::posix_thread::{PosixThreadExt, ThreadName};
use crate::process::{check_executable_file, load_program_to_vm};
use crate::process::{
check_executable_file, credentials_mut, load_program_to_vm, Credentials, Gid, Uid,
};
use crate::syscall::{SYS_EXECVE, SYS_EXECVEAT};
use crate::util::{read_cstring_from_user, read_val_from_user};
@ -100,9 +103,14 @@ fn do_execve(
let (new_executable_path, elf_load_info) = {
let fs_resolver = &*current.fs().read();
let process_vm = current.vm();
load_program_to_vm(process_vm, elf_file, argv, envp, fs_resolver, 1)?
load_program_to_vm(process_vm, elf_file.clone(), argv, envp, fs_resolver, 1)?
};
debug!("load elf in execve succeeds");
let credentials = credentials_mut();
set_uid_from_elf(&credentials, &elf_file);
set_gid_from_elf(&credentials, &elf_file);
// set executable path
current.set_executable_path(new_executable_path);
// set signal disposition to default
@ -157,3 +165,25 @@ fn read_cstring_vec(
}
Ok(res)
}
/// Sets uid for credentials as the same of uid of elf file if elf file has `set_uid` bit.
fn set_uid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) {
if elf_file.inode_mode().has_set_uid() {
let uid = Uid::new(elf_file.inode_metadata().uid as u32);
credentials.set_euid(uid);
}
// No matter whether the elf_file has `set_uid` bit, suid should be reset.
credentials.reset_suid();
}
/// Sets gid for credentials as the same of gid of elf file if elf file has `set_gid` bit.
fn set_gid_from_elf(credentials: &Credentials<WriteOp>, elf_file: &Arc<Dentry>) {
if elf_file.inode_mode().has_set_gid() {
let gid = Gid::new(elf_file.inode_metadata().gid as u32);
credentials.set_egid(gid);
}
// No matter whether the the elf file has `set_gid` bit, sgid should be reset.
credentials.reset_sgid();
}

View File

@ -1,9 +1,16 @@
use crate::{log_syscall_entry, prelude::*, syscall::SYS_GETEGID};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::credentials;
use super::SyscallReturn;
use super::{SyscallReturn, SYS_GETEGID};
pub fn sys_getegid() -> Result<SyscallReturn> {
log_syscall_entry!(SYS_GETEGID);
// TODO: getegid only return a fake egid now
Ok(SyscallReturn::Return(0))
let egid = {
let credentials = credentials();
credentials.egid()
};
Ok(SyscallReturn::Return(egid.as_u32() as _))
}

View File

@ -1,9 +1,15 @@
use crate::{log_syscall_entry, prelude::*, syscall::SYS_GETEUID};
use super::SyscallReturn;
use super::{SyscallReturn, SYS_GETEUID};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::credentials;
pub fn sys_geteuid() -> Result<SyscallReturn> {
log_syscall_entry!(SYS_GETEUID);
// TODO: geteuid only return a fake euid now"
Ok(SyscallReturn::Return(0))
let euid = {
let credentials = credentials();
credentials.euid()
};
Ok(SyscallReturn::Return(euid.as_u32() as _))
}

View File

@ -1,9 +1,15 @@
use crate::{log_syscall_entry, prelude::*, syscall::SYS_GETGID};
use super::SyscallReturn;
use super::{SyscallReturn, SYS_GETGID};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::credentials;
pub fn sys_getgid() -> Result<SyscallReturn> {
log_syscall_entry!(SYS_GETGID);
// TODO: getgid only return a fake gid now"
Ok(SyscallReturn::Return(0))
let gid = {
let credentials = credentials();
credentials.rgid()
};
Ok(SyscallReturn::Return(gid.as_u32() as _))
}

View File

@ -0,0 +1,35 @@
use super::{SyscallReturn, SYS_GETGROUPS};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::credentials;
use crate::util::write_val_to_user;
pub fn sys_getgroups(size: i32, group_list_addr: Vaddr) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_GETGROUPS);
debug!("size = {}, group_list_addr = 0x{:x}", size, group_list_addr);
if size < 0 {
return_errno_with_message!(Errno::EINVAL, "size cannot be negative");
}
let credentials = credentials();
let groups = credentials.groups();
if size == 0 {
return Ok(SyscallReturn::Return(groups.len() as _));
}
if groups.len() > size as usize {
return_errno_with_message!(
Errno::EINVAL,
"size is less than the number of supplementary group IDs"
);
}
for (idx, gid) in groups.iter().enumerate() {
let addr = group_list_addr + idx * core::mem::size_of_val(gid);
write_val_to_user(addr, gid)?;
}
Ok(SyscallReturn::Return(groups.len() as _))
}

View File

@ -0,0 +1,23 @@
use super::{SyscallReturn, SYS_GETRESGID};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::credentials;
use crate::util::write_val_to_user;
pub fn sys_getresgid(rgid_ptr: Vaddr, egid_ptr: Vaddr, sgid_ptr: Vaddr) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_GETRESGID);
debug!("rgid_ptr = 0x{rgid_ptr:x}, egid_ptr = 0x{egid_ptr:x}, sgid_ptr = 0x{sgid_ptr:x}");
let credentials = credentials();
let rgid = credentials.rgid();
write_val_to_user(rgid_ptr, &rgid)?;
let egid = credentials.egid();
write_val_to_user(egid_ptr, &egid)?;
let sgid = credentials.sgid();
write_val_to_user(sgid_ptr, &sgid)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -0,0 +1,23 @@
use super::{SyscallReturn, SYS_GETRESUID};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::credentials;
use crate::util::write_val_to_user;
pub fn sys_getresuid(ruid_ptr: Vaddr, euid_ptr: Vaddr, suid_ptr: Vaddr) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_GETRESUID);
debug!("ruid_ptr = 0x{ruid_ptr:x}, euid_ptr = 0x{euid_ptr:x}, suid_ptr = 0x{suid_ptr:x}");
let credentials = credentials();
let ruid = credentials.ruid();
write_val_to_user(ruid_ptr, &ruid)?;
let euid = credentials.euid();
write_val_to_user(euid_ptr, &euid)?;
let suid = credentials.suid();
write_val_to_user(suid_ptr, &suid)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -1,9 +1,15 @@
use crate::{log_syscall_entry, prelude::*, syscall::SYS_GETUID};
use super::SyscallReturn;
use super::{SyscallReturn, SYS_GETUID};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::credentials;
pub fn sys_getuid() -> Result<SyscallReturn> {
log_syscall_entry!(SYS_GETUID);
// TODO: getuid only return a fake uid now;
Ok(SyscallReturn::Return(0))
let uid = {
let credentials = credentials();
credentials.ruid()
};
Ok(SyscallReturn::Return(uid.as_u32() as _))
}

View File

@ -75,8 +75,11 @@ use self::accept::sys_accept;
use self::bind::sys_bind;
use self::connect::sys_connect;
use self::execve::sys_execveat;
use self::getgroups::sys_getgroups;
use self::getpeername::sys_getpeername;
use self::getrandom::sys_getrandom;
use self::getresgid::sys_getresgid;
use self::getresuid::sys_getresuid;
use self::getsid::sys_getsid;
use self::getsockname::sys_getsockname;
use self::getsockopt::sys_getsockopt;
@ -84,8 +87,17 @@ use self::listen::sys_listen;
use self::pread64::sys_pread64;
use self::recvfrom::sys_recvfrom;
use self::sendto::sys_sendto;
use self::setfsgid::sys_setfsgid;
use self::setfsuid::sys_setfsuid;
use self::setgid::sys_setgid;
use self::setgroups::sys_setgroups;
use self::setregid::sys_setregid;
use self::setresgid::sys_setresgid;
use self::setresuid::sys_setresuid;
use self::setreuid::sys_setreuid;
use self::setsid::sys_setsid;
use self::setsockopt::sys_setsockopt;
use self::setuid::sys_setuid;
use self::shutdown::sys_shutdown;
use self::socket::sys_socket;
use self::socketpair::sys_socketpair;
@ -116,11 +128,14 @@ mod getdents64;
mod getegid;
mod geteuid;
mod getgid;
mod getgroups;
mod getpeername;
mod getpgrp;
mod getpid;
mod getppid;
mod getrandom;
mod getresgid;
mod getresuid;
mod getsid;
mod getsockname;
mod getsockopt;
@ -157,9 +172,18 @@ mod select;
mod sendto;
mod set_robust_list;
mod set_tid_address;
mod setfsgid;
mod setfsuid;
mod setgid;
mod setgroups;
mod setpgid;
mod setregid;
mod setresgid;
mod setresuid;
mod setreuid;
mod setsid;
mod setsockopt;
mod setuid;
mod shutdown;
mod socket;
mod socketpair;
@ -273,12 +297,24 @@ define_syscall_nums!(
SYS_GETTIMEOFDAY = 96,
SYS_GETUID = 102,
SYS_GETGID = 104,
SYS_SETUID = 105,
SYS_SETGID = 106,
SYS_GETEUID = 107,
SYS_GETEGID = 108,
SYS_SETPGID = 109,
SYS_GETPPID = 110,
SYS_GETPGRP = 111,
SYS_SETSID = 112,
SYS_SETREUID = 113,
SYS_SETREGID = 114,
SYS_GETGROUPS = 115,
SYS_SETGROUPS = 116,
SYS_SETRESUID = 117,
SYS_GETRESUID = 118,
SYS_SETRESGID = 119,
SYS_GETRESGID = 120,
SYS_SETFSUID = 122,
SYS_SETFSGID = 123,
SYS_GETSID = 124,
SYS_STATFS = 137,
SYS_FSTATFS = 138,
@ -436,12 +472,24 @@ pub fn syscall_dispatch(
SYS_GETTIMEOFDAY => syscall_handler!(1, sys_gettimeofday, args),
SYS_GETUID => syscall_handler!(0, sys_getuid),
SYS_GETGID => syscall_handler!(0, sys_getgid),
SYS_SETUID => syscall_handler!(1, sys_setuid, args),
SYS_SETGID => syscall_handler!(1, sys_setgid, args),
SYS_GETEUID => syscall_handler!(0, sys_geteuid),
SYS_GETEGID => syscall_handler!(0, sys_getegid),
SYS_SETPGID => syscall_handler!(2, sys_setpgid, args),
SYS_GETPPID => syscall_handler!(0, sys_getppid),
SYS_GETPGRP => syscall_handler!(0, sys_getpgrp),
SYS_SETSID => syscall_handler!(0, sys_setsid),
SYS_SETREUID => syscall_handler!(2, sys_setreuid, args),
SYS_SETREGID => syscall_handler!(2, sys_setregid, args),
SYS_GETGROUPS => syscall_handler!(2, sys_getgroups, args),
SYS_SETGROUPS => syscall_handler!(2, sys_setgroups, args),
SYS_SETRESUID => syscall_handler!(3, sys_setresuid, args),
SYS_GETRESUID => syscall_handler!(3, sys_getresuid, args),
SYS_SETRESGID => syscall_handler!(3, sys_setresgid, args),
SYS_GETRESGID => syscall_handler!(3, sys_getresgid, args),
SYS_SETFSUID => syscall_handler!(1, sys_setfsuid, args),
SYS_SETFSGID => syscall_handler!(1, sys_setfsgid, args),
SYS_GETSID => syscall_handler!(1, sys_getsid, args),
SYS_STATFS => syscall_handler!(2, sys_statfs, args),
SYS_FSTATFS => syscall_handler!(2, sys_fstatfs, args),
@ -487,6 +535,11 @@ pub fn syscall_dispatch(
macro_rules! log_syscall_entry {
($syscall_name: tt) => {
let syscall_name_str = stringify!($syscall_name);
info!("[SYSCALL][id={}][{}]", $syscall_name, syscall_name_str);
let pid = $crate::current!().pid();
let tid = $crate::current_thread!().tid();
info!(
"[pid={}][tid={}][id={}][{}]",
pid, tid, $syscall_name, syscall_name_str
);
};
}

View File

@ -1,13 +1,10 @@
use jinux_frame::vm::VmIo;
use super::{SyscallReturn, SYS_RT_SIGPROCMASK};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::posix_thread::PosixThreadExt;
use crate::process::signal::constants::{SIGKILL, SIGSTOP};
use crate::{
log_syscall_entry,
prelude::*,
process::signal::sig_mask::SigMask,
syscall::{SyscallReturn, SYS_RT_SIGPROCMASK},
};
use crate::process::signal::sig_mask::SigMask;
use jinux_frame::vm::VmIo;
pub fn sys_rt_sigprocmask(
how: u32,

View File

@ -0,0 +1,23 @@
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Gid};
use super::{SyscallReturn, SYS_SETFSGID};
pub fn sys_setfsgid(gid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETFSGID);
debug!("gid = {}", gid);
let fsgid = if gid < 0 {
None
} else {
Some(Gid::new(gid as u32))
};
let old_fsgid = {
let credentials = credentials_mut();
credentials.set_fsgid(fsgid)?
};
Ok(SyscallReturn::Return(old_fsgid.as_u32() as _))
}

View File

@ -0,0 +1,23 @@
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Uid};
use super::{SyscallReturn, SYS_SETFSUID};
pub fn sys_setfsuid(uid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETFSUID);
debug!("uid = {}", uid);
let fsuid = if uid < 0 {
None
} else {
Some(Uid::new(uid as u32))
};
let old_fsuid = {
let credentials = credentials_mut();
credentials.set_fsuid(fsuid)?
};
Ok(SyscallReturn::Return(old_fsuid.as_u32() as _))
}

View File

@ -0,0 +1,22 @@
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Gid};
use super::{SyscallReturn, SYS_SETGID};
pub fn sys_setgid(gid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETGID);
debug!("gid = {}", gid);
if gid < 0 {
return_errno_with_message!(Errno::EINVAL, "gid cannot be negative");
}
let gid = Gid::new(gid as u32);
let credentials = credentials_mut();
credentials.set_gid(gid);
Ok(SyscallReturn::Return(0))
}

View File

@ -0,0 +1,30 @@
use super::{SyscallReturn, SYS_SETGROUPS};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Gid};
use crate::util::read_val_from_user;
pub fn sys_setgroups(size: usize, group_list_addr: Vaddr) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETGROUPS);
debug!("size = {}, group_list_addr = 0x{:x}", size, group_list_addr);
// TODO: check perm: the calling process should have the CAP_SETGID capability
if size > NGROUPS_MAX {
return_errno_with_message!(Errno::EINVAL, "size cannot be greater than NGROUPS_MAX");
}
let mut new_groups = BTreeSet::new();
for idx in 0..size {
let addr = group_list_addr + idx * core::mem::size_of::<Gid>();
let gid = read_val_from_user(addr)?;
new_groups.insert(gid);
}
let credentials = credentials_mut();
*credentials.groups_mut() = new_groups;
Ok(SyscallReturn::Return(0))
}
const NGROUPS_MAX: usize = 65536;

View File

@ -0,0 +1,27 @@
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Gid};
use super::{SyscallReturn, SYS_SETREGID};
pub fn sys_setregid(rgid: i32, egid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETREGID);
debug!("rgid = {}, egid = {}", rgid, egid);
let rgid = if rgid > 0 {
Some(Gid::new(rgid as u32))
} else {
None
};
let egid = if egid > 0 {
Some(Gid::new(egid as u32))
} else {
None
};
let credentials = credentials_mut();
credentials.set_regid(rgid, egid)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -0,0 +1,34 @@
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Gid};
use super::{SyscallReturn, SYS_SETRESGID};
pub fn sys_setresgid(rgid: i32, egid: i32, sgid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETRESGID);
let rgid = if rgid > 0 {
Some(Gid::new(rgid as u32))
} else {
None
};
let egid = if egid > 0 {
Some(Gid::new(egid as u32))
} else {
None
};
let sgid = if sgid > 0 {
Some(Gid::new(sgid as u32))
} else {
None
};
debug!("rgid = {:?}, egid = {:?}, sgid = {:?}", rgid, egid, sgid);
let credentials = credentials_mut();
credentials.set_resgid(rgid, egid, sgid)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -0,0 +1,35 @@
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Uid};
use super::{SyscallReturn, SYS_SETRESUID};
pub fn sys_setresuid(ruid: i32, euid: i32, suid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETRESUID);
let ruid = if ruid > 0 {
Some(Uid::new(ruid as u32))
} else {
None
};
let euid = if euid > 0 {
Some(Uid::new(euid as u32))
} else {
None
};
let suid = if suid > 0 {
Some(Uid::new(suid as u32))
} else {
None
};
debug!("ruid = {:?}, euid = {:?}, suid = {:?}", ruid, euid, suid);
let credentials = credentials_mut();
credentials.set_resuid(ruid, euid, suid)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -0,0 +1,27 @@
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Uid};
use super::{SyscallReturn, SYS_SETREUID};
pub fn sys_setreuid(ruid: i32, euid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETREUID);
debug!("ruid = {}, euid = {}", ruid, euid);
let ruid = if ruid > 0 {
Some(Uid::new(ruid as u32))
} else {
None
};
let euid = if euid > 0 {
Some(Uid::new(euid as u32))
} else {
None
};
let credentials = credentials_mut();
credentials.set_reuid(ruid, euid)?;
Ok(SyscallReturn::Return(0))
}

View File

@ -0,0 +1,21 @@
use super::{SyscallReturn, SYS_SETUID};
use crate::log_syscall_entry;
use crate::prelude::*;
use crate::process::{credentials_mut, Uid};
pub fn sys_setuid(uid: i32) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_SETUID);
debug!("uid = {}", uid);
if uid < 0 {
return_errno_with_message!(Errno::EINVAL, "uid cannot be negative");
}
let uid = Uid::new(uid as u32);
let credentials = credentials_mut();
credentials.set_uid(uid);
Ok(SyscallReturn::Return(0))
}