mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-19 04:56:30 +00:00
feat(cred): 初步实现Cred (#846)
* 初步实现Cred * 添加seteuid和setegid * 添加cred测试程序 * 修改Cred::fscmp返回结果为CredFsCmp枚举 * 完善root用户相关信息
This commit is contained in:
@ -20,7 +20,7 @@ use crate::{
|
||||
event_poll::{EPollItem, EPollPrivateData, EventPoll},
|
||||
socket::SocketInode,
|
||||
},
|
||||
process::ProcessManager,
|
||||
process::{cred::Cred, ProcessManager},
|
||||
};
|
||||
|
||||
use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData};
|
||||
@ -131,6 +131,8 @@ pub struct File {
|
||||
/// readdir时候用的,暂存的本次循环中,所有子目录项的名字的数组
|
||||
readdir_subdirs_name: SpinLock<Vec<String>>,
|
||||
pub private_data: SpinLock<FilePrivateData>,
|
||||
/// 文件的凭证
|
||||
cred: Cred,
|
||||
}
|
||||
|
||||
impl File {
|
||||
@ -154,6 +156,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)?;
|
||||
|
||||
@ -408,6 +411,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
|
||||
|
170
kernel/src/process/cred.rs
Normal file
170
kernel/src/process/cred.rs
Normal file
@ -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>,
|
||||
}
|
@ -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指针
|
||||
///
|
||||
/// ## 参数
|
||||
|
@ -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)?;
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user