Browse Source

feat: add set/getgroups syscall (#1255)

Signed-off-by: Godones <chenlinfeng25@outlook.com>
linfeng 1 week ago
parent
commit
e439a66004

+ 13 - 0
kernel/src/process/cred.rs

@@ -43,6 +43,8 @@ pub struct Cred {
     pub euid: Kuid,
     pub euid: Kuid,
     /// 进程有效的gid
     /// 进程有效的gid
     pub egid: Kgid,
     pub egid: Kgid,
+    /// supplementary groups
+    pub groups: Vec<Kgid>,
     /// UID for VFS ops
     /// UID for VFS ops
     pub fsuid: Kuid,
     pub fsuid: Kuid,
     /// GID for VFS ops
     /// GID for VFS ops
@@ -74,6 +76,7 @@ impl Cred {
             egid: GLOBAL_ROOT_GID,
             egid: GLOBAL_ROOT_GID,
             fsuid: GLOBAL_ROOT_UID,
             fsuid: GLOBAL_ROOT_UID,
             fsgid: GLOBAL_ROOT_GID,
             fsgid: GLOBAL_ROOT_GID,
+            groups: Vec::new(),
             cap_inheritable: CAPFlags::CAP_EMPTY_SET,
             cap_inheritable: CAPFlags::CAP_EMPTY_SET,
             cap_permitted: CAPFlags::CAP_FULL_SET,
             cap_permitted: CAPFlags::CAP_FULL_SET,
             cap_effective: CAPFlags::CAP_FULL_SET,
             cap_effective: CAPFlags::CAP_FULL_SET,
@@ -179,6 +182,16 @@ impl Cred {
     pub fn setfsgid(&mut self, fsgid: usize) {
     pub fn setfsgid(&mut self, fsgid: usize) {
         self.fsgid.0 = fsgid;
         self.fsgid.0 = fsgid;
     }
     }
+
+    /// Set supplementary groups
+    pub fn setgroups(&mut self, groups: Vec<Kgid>) {
+        self.groups = groups;
+    }
+
+    /// Get supplementary groups
+    pub fn getgroups(&self) -> &Vec<Kgid> {
+        &self.groups
+    }
 }
 }
 
 
 #[derive(Debug, Clone, PartialEq, Eq, Default)]
 #[derive(Debug, Clone, PartialEq, Eq, Default)]

+ 1 - 0
kernel/src/process/syscall/mod.rs

@@ -13,6 +13,7 @@ mod sys_getppid;
 mod sys_getsid;
 mod sys_getsid;
 mod sys_gettid;
 mod sys_gettid;
 mod sys_getuid;
 mod sys_getuid;
+mod sys_groups;
 mod sys_prlimit64;
 mod sys_prlimit64;
 mod sys_set_tid_address;
 mod sys_set_tid_address;
 mod sys_setfsgid;
 mod sys_setfsgid;

+ 93 - 0
kernel/src/process/syscall/sys_groups.rs

@@ -0,0 +1,93 @@
+use crate::arch::interrupt::TrapFrame;
+use crate::arch::syscall::nr::SYS_GETGROUPS;
+use crate::arch::syscall::nr::SYS_SETGROUPS;
+use crate::process::cred::Cred;
+use crate::process::cred::Kgid;
+use crate::process::ProcessManager;
+use crate::syscall::table::FormattedSyscallParam;
+use crate::syscall::table::Syscall;
+use crate::syscall::user_access::UserBufferReader;
+use crate::syscall::user_access::UserBufferWriter;
+use alloc::vec::Vec;
+use system_error::SystemError;
+
+const NGROUPS_MAX: usize = 65536;
+
+/// See https://man7.org/linux/man-pages/man2/setgroups.2.html
+pub struct SysGetGroups;
+
+impl Syscall for SysGetGroups {
+    fn num_args(&self) -> usize {
+        2
+    }
+
+    fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        let cred = pcb.cred.lock();
+        let size = args[0];
+        if size == 0 {
+            return Ok(cred.getgroups().len());
+        }
+        if size < cred.getgroups().len() || size > NGROUPS_MAX {
+            return Err(SystemError::EINVAL);
+        }
+        let mut user_buffer = UserBufferWriter::new(
+            args[1] as *mut Kgid,
+            size * core::mem::size_of::<Kgid>(),
+            true,
+        )?;
+        user_buffer.copy_to_user(cred.getgroups(), 0)?;
+        Ok(size)
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![
+            FormattedSyscallParam::new("size", format!("{}", args[0])),
+            FormattedSyscallParam::new("list", format!("{:#x}", args[1])),
+        ]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_GETGROUPS, SysGetGroups);
+
+pub struct SysSetGroups;
+
+impl Syscall for SysSetGroups {
+    fn num_args(&self) -> usize {
+        2
+    }
+
+    fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result<usize, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        let mut cred = (**pcb.cred.lock()).clone();
+        let size = args[0];
+        if size == 0 {
+            // clear all supplementary groups
+            cred.setgroups(Vec::new());
+            return Ok(0);
+        }
+        if size > NGROUPS_MAX {
+            return Err(SystemError::EINVAL);
+        }
+        let user_buffer = UserBufferReader::new(
+            args[1] as *const Kgid,
+            size * core::mem::size_of::<Kgid>(),
+            true,
+        )?;
+        let mut groups = vec![Kgid::from(0); size];
+        user_buffer.copy_from_user(&mut groups, 0).unwrap();
+        // log::info!("set supplementary groups: {:?}", groups);
+        cred.setgroups(groups);
+        *pcb.cred.lock() = Cred::new_arc(cred);
+        Ok(0)
+    }
+
+    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
+        vec![
+            FormattedSyscallParam::new("size", format!("{}", args[0])),
+            FormattedSyscallParam::new("list", format!("{:#x}", args[1])),
+        ]
+    }
+}
+
+syscall_table_macros::declare_syscall!(SYS_SETGROUPS, SysSetGroups);