diff --git a/services/libs/jinux-std/src/process/clone.rs b/services/libs/jinux-std/src/process/clone.rs index fa38ab0c2..3f6327477 100644 --- a/services/libs/jinux-std/src/process/clone.rs +++ b/services/libs/jinux-std/src/process/clone.rs @@ -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(¤t)) .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) }; diff --git a/services/libs/jinux-std/src/process/posix_thread/builder.rs b/services/libs/jinux-std/src/process/posix_thread/builder.rs index 28cad6fe4..0f59d06df 100644 --- a/services/libs/jinux-std/src/process/posix_thread/builder.rs +++ b/services/libs/jinux-std/src/process/posix_thread/builder.rs @@ -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, process: Weak, + credentials: Credentials, // Optional part thread_name: Option, @@ -29,11 +30,12 @@ pub struct PosixThreadBuilder { } impl PosixThreadBuilder { - pub fn new(tid: Tid, user_space: Arc) -> Self { + pub fn new(tid: Tid, user_space: Arc, 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, diff --git a/services/libs/jinux-std/src/process/posix_thread/mod.rs b/services/libs/jinux-std/src/process/posix_thread/mod.rs index d7cc85fc3..24528b111 100644 --- a/services/libs/jinux-std/src/process/posix_thread/mod.rs +++ b/services/libs/jinux-std/src/process/posix_thread/mod.rs @@ -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>, + /// Process credentials. At the kernel level, credentials are a per-thread attribute. + credentials: Credentials, + // signal /// blocked signals sig_mask: Mutex, @@ -78,7 +78,57 @@ impl PosixThread { !self.sig_queues.lock().is_empty() } - pub fn enqueue_signal(&self, signal: Box) { + /// 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) { 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 { + self.credentials.dup().restrict() + } + + /// Gets the write-only credentials of the thread. + pub(in crate::process) fn credentials_mut(&self) -> Credentials { + self.credentials.dup().restrict() + } } diff --git a/services/libs/jinux-std/src/process/posix_thread/posix_thread_ext.rs b/services/libs/jinux-std/src/process/posix_thread/posix_thread_ext.rs index 9f42ba248..b093cb2c7 100644 --- a/services/libs/jinux-std/src/process/posix_thread/posix_thread_ext.rs +++ b/services/libs/jinux-std/src/process/posix_thread/posix_thread_ext.rs @@ -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()) diff --git a/services/libs/jinux-std/src/syscall/execve.rs b/services/libs/jinux-std/src/syscall/execve.rs index d67c3e865..a4b624572 100644 --- a/services/libs/jinux-std/src/syscall/execve.rs +++ b/services/libs/jinux-std/src/syscall/execve.rs @@ -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, elf_file: &Arc) { + 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, elf_file: &Arc) { + 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(); +} diff --git a/services/libs/jinux-std/src/syscall/getegid.rs b/services/libs/jinux-std/src/syscall/getegid.rs index bcdef91a8..ee29e73c0 100644 --- a/services/libs/jinux-std/src/syscall/getegid.rs +++ b/services/libs/jinux-std/src/syscall/getegid.rs @@ -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 { 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 _)) } diff --git a/services/libs/jinux-std/src/syscall/geteuid.rs b/services/libs/jinux-std/src/syscall/geteuid.rs index 48fb1dc9f..8a85b2861 100644 --- a/services/libs/jinux-std/src/syscall/geteuid.rs +++ b/services/libs/jinux-std/src/syscall/geteuid.rs @@ -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 { 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 _)) } diff --git a/services/libs/jinux-std/src/syscall/getgid.rs b/services/libs/jinux-std/src/syscall/getgid.rs index f36a804d0..7b718a60a 100644 --- a/services/libs/jinux-std/src/syscall/getgid.rs +++ b/services/libs/jinux-std/src/syscall/getgid.rs @@ -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 { 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 _)) } diff --git a/services/libs/jinux-std/src/syscall/getgroups.rs b/services/libs/jinux-std/src/syscall/getgroups.rs new file mode 100644 index 000000000..319de710b --- /dev/null +++ b/services/libs/jinux-std/src/syscall/getgroups.rs @@ -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 { + 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 _)) +} diff --git a/services/libs/jinux-std/src/syscall/getresgid.rs b/services/libs/jinux-std/src/syscall/getresgid.rs new file mode 100644 index 000000000..c2ae6b6f5 --- /dev/null +++ b/services/libs/jinux-std/src/syscall/getresgid.rs @@ -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 { + 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)) +} diff --git a/services/libs/jinux-std/src/syscall/getresuid.rs b/services/libs/jinux-std/src/syscall/getresuid.rs new file mode 100644 index 000000000..f93b4e653 --- /dev/null +++ b/services/libs/jinux-std/src/syscall/getresuid.rs @@ -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 { + 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)) +} diff --git a/services/libs/jinux-std/src/syscall/getuid.rs b/services/libs/jinux-std/src/syscall/getuid.rs index 7eb6f9444..7bd70a11a 100644 --- a/services/libs/jinux-std/src/syscall/getuid.rs +++ b/services/libs/jinux-std/src/syscall/getuid.rs @@ -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 { 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 _)) } diff --git a/services/libs/jinux-std/src/syscall/mod.rs b/services/libs/jinux-std/src/syscall/mod.rs index d3b95f503..f35d98367 100644 --- a/services/libs/jinux-std/src/syscall/mod.rs +++ b/services/libs/jinux-std/src/syscall/mod.rs @@ -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 + ); }; } diff --git a/services/libs/jinux-std/src/syscall/rt_sigprocmask.rs b/services/libs/jinux-std/src/syscall/rt_sigprocmask.rs index b49689d51..0219d104c 100644 --- a/services/libs/jinux-std/src/syscall/rt_sigprocmask.rs +++ b/services/libs/jinux-std/src/syscall/rt_sigprocmask.rs @@ -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, diff --git a/services/libs/jinux-std/src/syscall/setfsgid.rs b/services/libs/jinux-std/src/syscall/setfsgid.rs new file mode 100644 index 000000000..e8f9f2862 --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setfsgid.rs @@ -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 { + 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 _)) +} diff --git a/services/libs/jinux-std/src/syscall/setfsuid.rs b/services/libs/jinux-std/src/syscall/setfsuid.rs new file mode 100644 index 000000000..8bfc76383 --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setfsuid.rs @@ -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 { + 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 _)) +} diff --git a/services/libs/jinux-std/src/syscall/setgid.rs b/services/libs/jinux-std/src/syscall/setgid.rs new file mode 100644 index 000000000..eeb946bbb --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setgid.rs @@ -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 { + 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)) +} diff --git a/services/libs/jinux-std/src/syscall/setgroups.rs b/services/libs/jinux-std/src/syscall/setgroups.rs new file mode 100644 index 000000000..9acf79c01 --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setgroups.rs @@ -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 { + 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::(); + 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; diff --git a/services/libs/jinux-std/src/syscall/setregid.rs b/services/libs/jinux-std/src/syscall/setregid.rs new file mode 100644 index 000000000..a8b730cda --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setregid.rs @@ -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 { + 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)) +} diff --git a/services/libs/jinux-std/src/syscall/setresgid.rs b/services/libs/jinux-std/src/syscall/setresgid.rs new file mode 100644 index 000000000..8c35b4cde --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setresgid.rs @@ -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 { + 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)) +} diff --git a/services/libs/jinux-std/src/syscall/setresuid.rs b/services/libs/jinux-std/src/syscall/setresuid.rs new file mode 100644 index 000000000..0eccd29df --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setresuid.rs @@ -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 { + 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)) +} diff --git a/services/libs/jinux-std/src/syscall/setreuid.rs b/services/libs/jinux-std/src/syscall/setreuid.rs new file mode 100644 index 000000000..90612db88 --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setreuid.rs @@ -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 { + 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)) +} diff --git a/services/libs/jinux-std/src/syscall/setuid.rs b/services/libs/jinux-std/src/syscall/setuid.rs new file mode 100644 index 000000000..d1c0a609b --- /dev/null +++ b/services/libs/jinux-std/src/syscall/setuid.rs @@ -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 { + 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)) +}