1 use core::sync::atomic::AtomicUsize; 2 3 use alloc::vec::Vec; 4 5 const GLOBAL_ROOT_UID: Kuid = Kuid(0); 6 const GLOBAL_ROOT_GID: Kgid = Kgid(0); 7 pub static INIT_CRED: Cred = Cred::init(); 8 9 int_like!(Kuid, AtomicKuid, usize, AtomicUsize); 10 int_like!(Kgid, AtomicKgid, usize, AtomicUsize); 11 12 bitflags! { 13 pub struct CAPFlags:u64{ 14 const CAP_EMPTY_SET = 0; 15 const CAP_FULL_SET = (1 << 41) - 1; 16 } 17 } 18 19 pub enum CredFsCmp { 20 Equal, 21 Less, 22 Greater, 23 } 24 25 /// 凭证集 26 #[derive(Debug, Clone, PartialEq, Eq)] 27 pub struct Cred { 28 /// 进程实际uid 29 pub uid: Kuid, 30 /// 进程实际gid 31 pub gid: Kgid, 32 /// 进程保存的uid 33 pub suid: Kuid, 34 /// 进程保存的gid 35 pub sgid: Kgid, 36 /// 进程有效的uid 37 pub euid: Kuid, 38 /// 进程有效的gid 39 pub egid: Kgid, 40 /// UID for VFS ops 41 pub fsuid: Kuid, 42 /// GID for VFS ops 43 pub fsgid: Kgid, 44 /// 子进程可以继承的权限 45 pub cap_inheritable: CAPFlags, 46 /// 当前进程被赋予的权限 47 pub cap_permitted: CAPFlags, 48 /// 当前进程实际使用的权限 49 pub cap_effective: CAPFlags, 50 /// capability bounding set 51 pub cap_bset: CAPFlags, 52 /// Ambient capability set 53 pub cap_ambient: CAPFlags, 54 /// supplementary groups for euid/fsgid 55 pub group_info: Option<GroupInfo>, 56 } 57 58 impl Cred { 59 pub const fn init() -> Self { 60 Self { 61 uid: GLOBAL_ROOT_UID, 62 gid: GLOBAL_ROOT_GID, 63 suid: GLOBAL_ROOT_UID, 64 sgid: GLOBAL_ROOT_GID, 65 euid: GLOBAL_ROOT_UID, 66 egid: GLOBAL_ROOT_GID, 67 fsuid: GLOBAL_ROOT_UID, 68 fsgid: GLOBAL_ROOT_GID, 69 cap_inheritable: CAPFlags::CAP_EMPTY_SET, 70 cap_permitted: CAPFlags::CAP_FULL_SET, 71 cap_effective: CAPFlags::CAP_FULL_SET, 72 cap_bset: CAPFlags::CAP_FULL_SET, 73 cap_ambient: CAPFlags::CAP_FULL_SET, 74 group_info: None, 75 } 76 } 77 78 #[allow(dead_code)] 79 /// Compare two credentials with respect to filesystem access. 80 pub fn fscmp(&self, other: Cred) -> CredFsCmp { 81 if *self == other { 82 return CredFsCmp::Equal; 83 } 84 85 if self.fsuid < other.fsuid { 86 return CredFsCmp::Less; 87 } 88 if self.fsuid > other.fsuid { 89 return CredFsCmp::Greater; 90 } 91 92 if self.fsgid < other.fsgid { 93 return CredFsCmp::Less; 94 } 95 if self.fsgid > other.fsgid { 96 return CredFsCmp::Greater; 97 } 98 99 if self.group_info == other.group_info { 100 return CredFsCmp::Equal; 101 } 102 103 if let (Some(ga), Some(gb)) = (&self.group_info, &other.group_info) { 104 let ga_count = ga.gids.len(); 105 let gb_count = gb.gids.len(); 106 107 if ga_count < gb_count { 108 return CredFsCmp::Less; 109 } 110 if ga_count > gb_count { 111 return CredFsCmp::Greater; 112 } 113 114 for i in 0..ga_count { 115 if ga.gids[i] < gb.gids[i] { 116 return CredFsCmp::Less; 117 } 118 if ga.gids[i] > gb.gids[i] { 119 return CredFsCmp::Greater; 120 } 121 } 122 } else { 123 if self.group_info.is_none() { 124 return CredFsCmp::Less; 125 } 126 if other.group_info.is_none() { 127 return CredFsCmp::Greater; 128 } 129 } 130 131 return CredFsCmp::Equal; 132 } 133 134 pub fn setuid(&mut self, uid: usize) { 135 self.uid.0 = uid; 136 } 137 138 pub fn seteuid(&mut self, euid: usize) { 139 self.euid.0 = euid; 140 } 141 142 pub fn setsuid(&mut self, suid: usize) { 143 self.suid.0 = suid; 144 } 145 146 pub fn setfsuid(&mut self, fsuid: usize) { 147 self.fsuid.0 = fsuid; 148 } 149 150 pub fn setgid(&mut self, gid: usize) { 151 self.gid.0 = gid; 152 } 153 154 pub fn setegid(&mut self, egid: usize) { 155 self.egid.0 = egid; 156 } 157 158 pub fn setsgid(&mut self, sgid: usize) { 159 self.sgid.0 = sgid; 160 } 161 162 pub fn setfsgid(&mut self, fsgid: usize) { 163 self.fsgid.0 = fsgid; 164 } 165 } 166 167 #[derive(Debug, Clone, PartialEq, Eq)] 168 pub struct GroupInfo { 169 pub gids: Vec<Kgid>, 170 } 171