Bläddra i källkod

Merge branch 'master' into patch-add-file-mapping

MemoryShore 10 månader sedan
förälder
incheckning
cc19c94157

+ 2 - 2
.github/workflows/makefile.yml

@@ -2,9 +2,9 @@ name: Build Check
 
 on:
   push:
-    branches: [ "master" ]
+    branches: [ "master", "feat-*", "fix-*"]
   pull_request:
-    branches: [ "master" ]
+    branches: [ "master", "feat-*", "fix-*"]
 
 jobs:
   # ensure the toolchain is cached

+ 2 - 2
kernel/src/driver/tty/tty_ldisc/ntty.rs

@@ -388,9 +388,9 @@ impl NTtyData {
                 continue;
             }
 
-            if self.char_map.get(c as usize).unwrap() {
+            if ((c as usize) < self.char_map.size()) && self.char_map.get(c as usize).unwrap() {
                 // 特殊字符
-                self.receive_special_char(c, tty.clone(), lookahead_done)
+                self.receive_special_char(c, tty.clone(), lookahead_done);
             } else {
                 self.receive_char(c, tty.clone());
             }

+ 1 - 1
kernel/src/filesystem/vfs/core.rs

@@ -239,7 +239,7 @@ pub fn do_unlink_at(dirfd: i32, path: &str) -> Result<u64, SystemError> {
         return Err(SystemError::EPERM);
     }
 
-    let (filename, parent_path) = rsplit_path(path);
+    let (filename, parent_path) = rsplit_path(&remain_path);
     // 查找父目录
     let parent_inode: Arc<dyn IndexNode> = inode_begin
         .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;

+ 5 - 1
kernel/src/filesystem/vfs/file.rs

@@ -23,7 +23,7 @@ use crate::{
         event_poll::{EPollItem, EPollPrivateData, EventPoll},
         socket::SocketInode,
     },
-    process::ProcessManager,
+    process::{cred::Cred, ProcessManager},
 };
 
 use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
@@ -195,6 +195,8 @@ pub struct File {
     /// readdir时候用的,暂存的本次循环中,所有子目录项的名字的数组
     readdir_subdirs_name: SpinLock<Vec<String>>,
     pub private_data: SpinLock<FilePrivateData>,
+    /// 文件的凭证
+    cred: Cred,
 }
 
 impl File {
@@ -218,6 +220,7 @@ impl File {
             file_type,
             readdir_subdirs_name: SpinLock::new(Vec::default()),
             private_data: SpinLock::new(FilePrivateData::default()),
+            cred: ProcessManager::current_pcb().cred(),
         };
         f.inode.open(f.private_data.lock(), &mode)?;
 
@@ -472,6 +475,7 @@ impl File {
             file_type: self.file_type,
             readdir_subdirs_name: SpinLock::new(self.readdir_subdirs_name.lock().clone()),
             private_data: SpinLock::new(self.private_data.lock().clone()),
+            cred: self.cred.clone(),
         };
         // 调用inode的open方法,让inode知道有新的文件打开了这个inode
         if self

+ 12 - 6
kernel/src/libs/keyboard_parser.rs

@@ -313,7 +313,8 @@ impl TypeOneFSMState {
         }
 
         // shift被按下
-        if scancode_status.shift_l || scancode_status.shift_r {
+        let shift = scancode_status.shift_l || scancode_status.shift_r;
+        if shift {
             col = true;
         }
 
@@ -327,9 +328,8 @@ impl TypeOneFSMState {
 
         let mut ch = TYPE1_KEY_CODE_MAPTABLE[col as usize + 2 * index as usize];
         if key != KeyFlag::NoneFlag {
-            // debug!("EMIT: ch is '{}', keyflag is {:?}\n", ch as char, key);
             if scancode_status.ctrl_l || scancode_status.ctrl_r {
-                ch = Self::to_ctrl(ch);
+                ch = Self::to_ctrl(ch, shift);
             }
             Self::emit(ch);
         }
@@ -337,10 +337,16 @@ impl TypeOneFSMState {
     }
 
     #[inline]
-    fn to_ctrl(ch: u8) -> u8 {
+    fn to_ctrl(ch: u8, shift: bool) -> u8 {
         return match ch as char {
-            'a'..='z' => ch - 0x40,
-            'A'..='Z' => ch - 0x40,
+            'a'..='z' => ch - 0x60,
+            'A'..='Z' => {
+                if shift {
+                    ch
+                } else {
+                    ch - 0x40
+                }
+            }
             '@'..='_' => ch - 0x40,
             _ => ch,
         };

+ 1 - 1
kernel/src/net/syscall.rs

@@ -345,7 +345,7 @@ impl Syscall {
             .get_socket(fd as i32)
             .ok_or(SystemError::EBADF)?;
         let mut socket = unsafe { socket.inner_no_preempt() };
-        socket.shutdown(ShutdownType::from_bits_truncate(how as u8))?;
+        socket.shutdown(ShutdownType::from_bits_truncate((how + 1) as u8))?;
         return Ok(0);
     }
 

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

@@ -0,0 +1,170 @@
+use core::sync::atomic::AtomicUsize;
+
+use alloc::vec::Vec;
+
+const GLOBAL_ROOT_UID: Kuid = Kuid(0);
+const GLOBAL_ROOT_GID: Kgid = Kgid(0);
+pub static INIT_CRED: Cred = Cred::init();
+
+int_like!(Kuid, AtomicKuid, usize, AtomicUsize);
+int_like!(Kgid, AtomicKgid, usize, AtomicUsize);
+
+bitflags! {
+    pub struct CAPFlags:u64{
+        const CAP_EMPTY_SET = 0;
+        const CAP_FULL_SET = (1 << 41) - 1;
+    }
+}
+
+pub enum CredFsCmp {
+    Equal,
+    Less,
+    Greater,
+}
+
+/// 凭证集
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Cred {
+    /// 进程实际uid
+    pub uid: Kuid,
+    /// 进程实际gid
+    pub gid: Kgid,
+    /// 进程保存的uid
+    pub suid: Kuid,
+    /// 进程保存的gid
+    pub sgid: Kgid,
+    /// 进程有效的uid
+    pub euid: Kuid,
+    /// 进程有效的gid
+    pub egid: Kgid,
+    /// UID for VFS ops
+    pub fsuid: Kuid,
+    /// GID for VFS ops
+    pub fsgid: Kgid,
+    /// 子进程可以继承的权限
+    pub cap_inheritable: CAPFlags,
+    /// 当前进程被赋予的权限
+    pub cap_permitted: CAPFlags,
+    /// 当前进程实际使用的权限
+    pub cap_effective: CAPFlags,
+    /// capability bounding set
+    pub cap_bset: CAPFlags,
+    /// Ambient capability set
+    pub cap_ambient: CAPFlags,
+    /// supplementary groups for euid/fsgid
+    pub group_info: Option<GroupInfo>,
+}
+
+impl Cred {
+    pub const fn init() -> Self {
+        Self {
+            uid: GLOBAL_ROOT_UID,
+            gid: GLOBAL_ROOT_GID,
+            suid: GLOBAL_ROOT_UID,
+            sgid: GLOBAL_ROOT_GID,
+            euid: GLOBAL_ROOT_UID,
+            egid: GLOBAL_ROOT_GID,
+            fsuid: GLOBAL_ROOT_UID,
+            fsgid: GLOBAL_ROOT_GID,
+            cap_inheritable: CAPFlags::CAP_EMPTY_SET,
+            cap_permitted: CAPFlags::CAP_FULL_SET,
+            cap_effective: CAPFlags::CAP_FULL_SET,
+            cap_bset: CAPFlags::CAP_FULL_SET,
+            cap_ambient: CAPFlags::CAP_FULL_SET,
+            group_info: None,
+        }
+    }
+
+    #[allow(dead_code)]
+    /// Compare two credentials with respect to filesystem access.
+    pub fn fscmp(&self, other: Cred) -> CredFsCmp {
+        if *self == other {
+            return CredFsCmp::Equal;
+        }
+
+        if self.fsuid < other.fsuid {
+            return CredFsCmp::Less;
+        }
+        if self.fsuid > other.fsuid {
+            return CredFsCmp::Greater;
+        }
+
+        if self.fsgid < other.fsgid {
+            return CredFsCmp::Less;
+        }
+        if self.fsgid > other.fsgid {
+            return CredFsCmp::Greater;
+        }
+
+        if self.group_info == other.group_info {
+            return CredFsCmp::Equal;
+        }
+
+        if let (Some(ga), Some(gb)) = (&self.group_info, &other.group_info) {
+            let ga_count = ga.gids.len();
+            let gb_count = gb.gids.len();
+
+            if ga_count < gb_count {
+                return CredFsCmp::Less;
+            }
+            if ga_count > gb_count {
+                return CredFsCmp::Greater;
+            }
+
+            for i in 0..ga_count {
+                if ga.gids[i] < gb.gids[i] {
+                    return CredFsCmp::Less;
+                }
+                if ga.gids[i] > gb.gids[i] {
+                    return CredFsCmp::Greater;
+                }
+            }
+        } else {
+            if self.group_info.is_none() {
+                return CredFsCmp::Less;
+            }
+            if other.group_info.is_none() {
+                return CredFsCmp::Greater;
+            }
+        }
+
+        return CredFsCmp::Equal;
+    }
+
+    pub fn setuid(&mut self, uid: usize) {
+        self.uid.0 = uid;
+    }
+
+    pub fn seteuid(&mut self, euid: usize) {
+        self.euid.0 = euid;
+    }
+
+    pub fn setsuid(&mut self, suid: usize) {
+        self.suid.0 = suid;
+    }
+
+    pub fn setfsuid(&mut self, fsuid: usize) {
+        self.fsuid.0 = fsuid;
+    }
+
+    pub fn setgid(&mut self, gid: usize) {
+        self.gid.0 = gid;
+    }
+
+    pub fn setegid(&mut self, egid: usize) {
+        self.egid.0 = egid;
+    }
+
+    pub fn setsgid(&mut self, sgid: usize) {
+        self.sgid.0 = sgid;
+    }
+
+    pub fn setfsgid(&mut self, fsgid: usize) {
+        self.fsgid.0 = fsgid;
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct GroupInfo {
+    pub gids: Vec<Kgid>,
+}

+ 19 - 4
kernel/src/process/mod.rs

@@ -13,6 +13,7 @@ use alloc::{
     sync::{Arc, Weak},
     vec::Vec,
 };
+use cred::INIT_CRED;
 use hashbrown::HashMap;
 use log::{debug, error, info, warn};
 use system_error::SystemError;
@@ -64,10 +65,11 @@ use crate::{
 };
 use timer::AlarmTimer;
 
-use self::kthread::WorkerPrivate;
+use self::{cred::Cred, kthread::WorkerPrivate};
 
 pub mod abi;
 pub mod c_adapter;
+pub mod cred;
 pub mod exec;
 pub mod exit;
 pub mod fork;
@@ -649,6 +651,9 @@ pub struct ProcessControlBlock {
 
     /// 进程的robust lock列表
     robust_list: RwLock<Option<RobustListHead>>,
+
+    /// 进程作为主体的凭证集
+    cred: SpinLock<Cred>,
 }
 
 impl ProcessControlBlock {
@@ -687,12 +692,16 @@ impl ProcessControlBlock {
 
     #[inline(never)]
     fn do_create_pcb(name: String, kstack: KernelStack, is_idle: bool) -> Arc<Self> {
-        let (pid, ppid, cwd) = if is_idle {
-            (Pid(0), Pid(0), "/".to_string())
+        let (pid, ppid, cwd, cred) = if is_idle {
+            let cred = INIT_CRED.clone();
+            (Pid(0), Pid(0), "/".to_string(), cred)
         } else {
             let ppid = ProcessManager::current_pcb().pid();
+            let mut cred = ProcessManager::current_pcb().cred();
+            cred.cap_permitted = cred.cap_ambient;
+            cred.cap_effective = cred.cap_ambient;
             let cwd = ProcessManager::current_pcb().basic().cwd();
-            (Self::generate_pid(), ppid, cwd)
+            (Self::generate_pid(), ppid, cwd, cred)
         };
 
         let basic_info = ProcessBasicInfo::new(Pid(0), ppid, name, cwd, None);
@@ -727,6 +736,7 @@ impl ProcessControlBlock {
             thread: RwLock::new(ThreadInfo::new()),
             alarm_timer: SpinLock::new(None),
             robust_list: RwLock::new(None),
+            cred: SpinLock::new(cred),
         };
 
         // 初始化系统调用栈
@@ -879,6 +889,11 @@ impl ProcessControlBlock {
         return self.basic.read().fd_table().unwrap();
     }
 
+    #[inline(always)]
+    pub fn cred(&self) -> Cred {
+        self.cred.lock().clone()
+    }
+
     /// 根据文件描述符序号,获取socket对象的Arc指针
     ///
     /// ## 参数

+ 108 - 7
kernel/src/process/syscall.rs

@@ -6,6 +6,7 @@ use system_error::SystemError;
 
 use super::{
     abi::WaitOption,
+    cred::{Kgid, Kuid},
     exit::kernel_wait4,
     fork::{CloneFlags, KernelCloneArgs},
     resource::{RLimit64, RLimitID, RUsage, RUsageWho},
@@ -286,25 +287,125 @@ impl Syscall {
     }
 
     pub fn getuid() -> Result<usize, SystemError> {
-        // todo: 增加credit功能之后,需要修改
-        return Ok(0);
+        let pcb = ProcessManager::current_pcb();
+        return Ok(pcb.cred.lock().uid.data());
     }
 
     pub fn getgid() -> Result<usize, SystemError> {
-        // todo: 增加credit功能之后,需要修改
-        return Ok(0);
+        let pcb = ProcessManager::current_pcb();
+        return Ok(pcb.cred.lock().gid.data());
     }
 
     pub fn geteuid() -> Result<usize, SystemError> {
-        // todo: 增加credit功能之后,需要修改
-        return Ok(0);
+        let pcb = ProcessManager::current_pcb();
+        return Ok(pcb.cred.lock().euid.data());
     }
 
     pub fn getegid() -> Result<usize, SystemError> {
-        // todo: 增加credit功能之后,需要修改
+        let pcb = ProcessManager::current_pcb();
+        return Ok(pcb.cred.lock().egid.data());
+    }
+
+    pub fn setuid(uid: usize) -> Result<usize, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        let mut guard = pcb.cred.lock();
+
+        if guard.uid.data() == 0 {
+            guard.setuid(uid);
+            guard.seteuid(uid);
+            guard.setsuid(uid);
+        } else if uid == guard.uid.data() || uid == guard.suid.data() {
+            guard.seteuid(uid);
+        } else {
+            return Err(SystemError::EPERM);
+        }
+
+        return Ok(0);
+    }
+
+    pub fn setgid(gid: usize) -> Result<usize, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        let mut guard = pcb.cred.lock();
+
+        if guard.egid.data() == 0 {
+            guard.setgid(gid);
+            guard.setegid(gid);
+            guard.setsgid(gid);
+            guard.setfsgid(gid);
+        } else if guard.gid.data() == gid || guard.sgid.data() == gid {
+            guard.setegid(gid);
+            guard.setfsgid(gid);
+        } else {
+            return Err(SystemError::EPERM);
+        }
+
+        return Ok(0);
+    }
+
+    pub fn seteuid(euid: usize) -> Result<usize, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        let mut guard = pcb.cred.lock();
+
+        if euid == usize::MAX || (euid == guard.euid.data() && euid == guard.fsuid.data()) {
+            return Ok(0);
+        }
+
+        if euid != usize::MAX {
+            guard.seteuid(euid);
+        }
+
+        let euid = guard.euid.data();
+        guard.setfsuid(euid);
+
+        return Ok(0);
+    }
+
+    pub fn setegid(egid: usize) -> Result<usize, SystemError> {
+        let pcb = ProcessManager::current_pcb();
+        let mut guard = pcb.cred.lock();
+
+        if egid == usize::MAX || (egid == guard.egid.data() && egid == guard.fsgid.data()) {
+            return Ok(0);
+        }
+
+        if egid != usize::MAX {
+            guard.setegid(egid);
+        }
+
+        let egid = guard.egid.data();
+        guard.setfsgid(egid);
+
         return Ok(0);
     }
 
+    pub fn setfsuid(fsuid: usize) -> Result<usize, SystemError> {
+        let fsuid = Kuid::new(fsuid);
+
+        let pcb = ProcessManager::current_pcb();
+        let mut guard = pcb.cred.lock();
+        let old_fsuid = guard.fsuid;
+
+        if fsuid == guard.uid || fsuid == guard.euid || fsuid == guard.suid {
+            guard.setfsuid(fsuid.data());
+        }
+
+        Ok(old_fsuid.data())
+    }
+
+    pub fn setfsgid(fsgid: usize) -> Result<usize, SystemError> {
+        let fsgid = Kgid::new(fsgid);
+
+        let pcb = ProcessManager::current_pcb();
+        let mut guard = pcb.cred.lock();
+        let old_fsgid = guard.fsgid;
+
+        if fsgid == guard.gid || fsgid == guard.egid || fsgid == guard.sgid {
+            guard.setfsgid(fsgid.data());
+        }
+
+        Ok(old_fsgid.data())
+    }
+
     pub fn get_rusage(who: i32, rusage: *mut RUsage) -> Result<usize, SystemError> {
         let who = RUsageWho::try_from(who)?;
         let mut writer = UserBufferWriter::new(rusage, core::mem::size_of::<RUsage>(), true)?;

+ 13 - 12
kernel/src/syscall/mod.rs

@@ -875,7 +875,6 @@ impl Syscall {
             }
 
             SYS_GETTID => Self::gettid().map(|tid| tid.into()),
-            SYS_GETUID => Self::getuid(),
 
             SYS_SYSLOG => {
                 let syslog_action_type = args[0];
@@ -889,27 +888,29 @@ impl Syscall {
                 Self::do_syslog(syslog_action_type, user_buf, len)
             }
 
+            SYS_GETUID => Self::getuid(),
             SYS_GETGID => Self::getgid(),
-            SYS_SETUID => {
-                warn!("SYS_SETUID has not yet been implemented");
-                Ok(0)
-            }
-            SYS_SETGID => {
-                warn!("SYS_SETGID has not yet been implemented");
-                Ok(0)
-            }
+            SYS_SETUID => Self::setuid(args[0]),
+            SYS_SETGID => Self::setgid(args[0]),
+
+            SYS_GETEUID => Self::geteuid(),
+            SYS_GETEGID => Self::getegid(),
+            SYS_SETRESUID => Self::seteuid(args[1]),
+            SYS_SETRESGID => Self::setegid(args[1]),
+
+            SYS_SETFSUID => Self::setfsuid(args[0]),
+            SYS_SETFSGID => Self::setfsgid(args[0]),
+
             SYS_SETSID => {
                 warn!("SYS_SETSID has not yet been implemented");
                 Ok(0)
             }
-            SYS_GETEUID => Self::geteuid(),
-            SYS_GETEGID => Self::getegid(),
+
             SYS_GETRUSAGE => {
                 let who = args[0] as c_int;
                 let rusage = args[1] as *mut RUsage;
                 Self::get_rusage(who, rusage)
             }
-
             #[cfg(target_arch = "x86_64")]
             SYS_READLINK => {
                 let path = args[0] as *const u8;

+ 1 - 0
user/apps/test_cred/.gitignore

@@ -0,0 +1 @@
+test_cred

+ 20 - 0
user/apps/test_cred/Makefile

@@ -0,0 +1,20 @@
+ifeq ($(ARCH), x86_64)
+	CROSS_COMPILE=x86_64-linux-musl-
+else ifeq ($(ARCH), riscv64)
+	CROSS_COMPILE=riscv64-linux-musl-
+endif
+
+CC=$(CROSS_COMPILE)gcc
+
+.PHONY: all
+all: main.c
+	$(CC) -static -o test_cred main.c
+
+.PHONY: install clean
+install: all
+	mv test_cred $(DADK_CURRENT_BUILD_DIR)/test_cred
+
+clean:
+	rm test_cred *.o
+
+fmt:

+ 42 - 0
user/apps/test_cred/main.c

@@ -0,0 +1,42 @@
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <assert.h>
+
+int main()
+{
+    printf("Current uid: %d, euid: %d, gid: %d, egid: %d\n\n", getuid(), geteuid(), getgid(), getegid());
+
+    // 测试uid
+    printf("Set uid 1000\n");
+    setuid(1000);
+    int uid = getuid();
+    assert(uid == 1000);
+    printf("Current uid:%d\n\n", uid);
+
+    // 测试gid
+    printf("Set gid 1000\n");
+    setgid(1000);
+    int gid = getgid();
+    assert(gid == 1000);
+    printf("Current gid:%d\n\n", gid);
+
+    // 测试euid
+    printf("Setg euid 1000\n");
+    seteuid(1000);
+    int euid = geteuid();
+    assert(euid == 1000);
+    printf("Current euid:%d\n\n", euid);
+
+    // 测试egid
+    printf("Set egid 1000\n");
+    setegid(1000);
+    int egid = getegid();
+    assert(egid == 1000);
+    printf("Current egid:%d\n\n", egid);
+
+    // 测试uid在非root用户下无法修改
+    printf("Try to setuid for non_root.\n");
+    assert(setuid(0) < 0); // 非root用户无法修改uid
+    printf("Current uid: %d, euid: %d, gid: %d, egid: %d\n", getuid(), geteuid(), getgid(), getegid());
+}

+ 23 - 0
user/dadk/config/test_cred-0.1.0.dadk

@@ -0,0 +1,23 @@
+{
+  "name": "test_cred",
+  "version": "0.1.0",
+  "description": "测试cred",
+  "task_type": {
+    "BuildFromSource": {
+      "Local": {
+        "path": "apps/test_cred"
+      }
+    }
+  },
+  "depends": [],
+  "build": {
+    "build_command": "make install"
+  },
+  "clean": {
+    "clean_command": "make clean"
+  },
+  "install": {
+    "in_dragonos_path": "/bin"
+  },
+  "target_arch": ["x86_64"]
+}

+ 1 - 0
user/sysconfig/etc/group

@@ -0,0 +1 @@
+root::0:

+ 1 - 0
user/sysconfig/etc/gshadow

@@ -0,0 +1 @@
+root:::

+ 1 - 0
user/sysconfig/etc/passwd

@@ -0,0 +1 @@
+root::0:0:root:/root:/bin/NovaShell

+ 1 - 0
user/sysconfig/etc/shadow

@@ -0,0 +1 @@
+root:::0:99999:7:::