1*f5b20388Scodeironman #![allow(dead_code, unused_variables, unused_imports)] 2*f5b20388Scodeironman use alloc::vec::Vec; 3*f5b20388Scodeironman use core::{hash::Hash, sync::atomic::AtomicU32}; 4*f5b20388Scodeironman use system_error::SystemError; 5*f5b20388Scodeironman 6*f5b20388Scodeironman use alloc::sync::Arc; 7*f5b20388Scodeironman use hashbrown::HashMap; 8*f5b20388Scodeironman use log::warn; 9*f5b20388Scodeironman 10*f5b20388Scodeironman use super::user_namespace::UserNamespace; 11*f5b20388Scodeironman use crate::libs::mutex::Mutex; 12*f5b20388Scodeironman 13*f5b20388Scodeironman #[derive(Clone, Copy)] 14*f5b20388Scodeironman pub enum Ucount { 15*f5b20388Scodeironman UserNamespaces = 1, 16*f5b20388Scodeironman PidNamespaces = 2, 17*f5b20388Scodeironman UtsNamespaces = 3, 18*f5b20388Scodeironman IpcNamespaces = 4, 19*f5b20388Scodeironman NetNamespaces = 5, 20*f5b20388Scodeironman MntNamespaces = 6, 21*f5b20388Scodeironman CgroupNamespaces = 7, 22*f5b20388Scodeironman TimeNamespaces = 8, 23*f5b20388Scodeironman Counts = 9, 24*f5b20388Scodeironman } 25*f5b20388Scodeironman 26*f5b20388Scodeironman pub enum UcountRlimit { 27*f5b20388Scodeironman Nproc = 1, 28*f5b20388Scodeironman Msgqueue = 2, 29*f5b20388Scodeironman Sigpending = 3, 30*f5b20388Scodeironman Memlock = 4, 31*f5b20388Scodeironman Counts = 5, 32*f5b20388Scodeironman } 33*f5b20388Scodeironman 34*f5b20388Scodeironman lazy_static! { 35*f5b20388Scodeironman static ref COUNT_MANAGER: Arc<CountManager> = Arc::new(CountManager::new()); 36*f5b20388Scodeironman } 37*f5b20388Scodeironman 38*f5b20388Scodeironman #[derive(Debug)] 39*f5b20388Scodeironman pub struct UCounts { 40*f5b20388Scodeironman /// 对应的user_namespace 41*f5b20388Scodeironman ns: Arc<UserNamespace>, 42*f5b20388Scodeironman /// 用户标识符 43*f5b20388Scodeironman uid: usize, 44*f5b20388Scodeironman count: AtomicU32, 45*f5b20388Scodeironman ucount: Vec<AtomicU32>, //[AtomicU32; UCOUNT_COUNTS as usize], 46*f5b20388Scodeironman rlimit: Vec<AtomicU32>, //[AtomicU32; UCOUNT_RLIMIT_COUNTS as usize], 47*f5b20388Scodeironman } 48*f5b20388Scodeironman 49*f5b20388Scodeironman impl Default for UCounts { default() -> Self50*f5b20388Scodeironman fn default() -> Self { 51*f5b20388Scodeironman Self::new() 52*f5b20388Scodeironman } 53*f5b20388Scodeironman } 54*f5b20388Scodeironman impl UCounts { new() -> Self55*f5b20388Scodeironman pub fn new() -> Self { 56*f5b20388Scodeironman Self { 57*f5b20388Scodeironman ns: Arc::new(UserNamespace::new()), 58*f5b20388Scodeironman uid: 0, 59*f5b20388Scodeironman count: AtomicU32::new(1), 60*f5b20388Scodeironman ucount: (0..Ucount::Counts as usize) 61*f5b20388Scodeironman .map(|_| AtomicU32::new(0)) 62*f5b20388Scodeironman .collect(), 63*f5b20388Scodeironman rlimit: (0..UcountRlimit::Counts as usize) 64*f5b20388Scodeironman .map(|_| AtomicU32::new(0)) 65*f5b20388Scodeironman .collect(), 66*f5b20388Scodeironman } 67*f5b20388Scodeironman } 68*f5b20388Scodeironman alloc_ucounts(&self, ns: Arc<UserNamespace>, uid: usize) -> Arc<Self>69*f5b20388Scodeironman fn alloc_ucounts(&self, ns: Arc<UserNamespace>, uid: usize) -> Arc<Self> { 70*f5b20388Scodeironman let mut counts = COUNT_MANAGER.counts.lock(); 71*f5b20388Scodeironman let key = UKey { 72*f5b20388Scodeironman user_ns: ns.clone(), 73*f5b20388Scodeironman uid, 74*f5b20388Scodeironman }; 75*f5b20388Scodeironman let uc = if let Some(uc) = counts.get(&key) { 76*f5b20388Scodeironman self.count 77*f5b20388Scodeironman .fetch_add(1, core::sync::atomic::Ordering::SeqCst); 78*f5b20388Scodeironman uc.clone() 79*f5b20388Scodeironman } else { 80*f5b20388Scodeironman Arc::new(Self { 81*f5b20388Scodeironman ns, 82*f5b20388Scodeironman uid, 83*f5b20388Scodeironman count: AtomicU32::new(1), 84*f5b20388Scodeironman ucount: (0..Ucount::Counts as usize) 85*f5b20388Scodeironman .map(|_| AtomicU32::new(0)) 86*f5b20388Scodeironman .collect(), 87*f5b20388Scodeironman rlimit: (0..UcountRlimit::Counts as usize) 88*f5b20388Scodeironman .map(|_| AtomicU32::new(0)) 89*f5b20388Scodeironman .collect(), 90*f5b20388Scodeironman }) 91*f5b20388Scodeironman }; 92*f5b20388Scodeironman counts.insert(key, uc.clone()); 93*f5b20388Scodeironman uc 94*f5b20388Scodeironman } 95*f5b20388Scodeironman inc_ucounts( &self, user_ns: Arc<UserNamespace>, uid: usize, ucount_type: Ucount, ) -> Option<Arc<UCounts>>96*f5b20388Scodeironman pub fn inc_ucounts( 97*f5b20388Scodeironman &self, 98*f5b20388Scodeironman user_ns: Arc<UserNamespace>, 99*f5b20388Scodeironman uid: usize, 100*f5b20388Scodeironman ucount_type: Ucount, 101*f5b20388Scodeironman ) -> Option<Arc<UCounts>> { 102*f5b20388Scodeironman let uc_type = ucount_type as usize; 103*f5b20388Scodeironman let uc = self.alloc_ucounts(user_ns, uid); 104*f5b20388Scodeironman let mut uc_iter = Some(uc.clone()); 105*f5b20388Scodeironman let mut ucounts_add = vec![]; 106*f5b20388Scodeironman while let Some(iter) = uc_iter { 107*f5b20388Scodeironman let num = iter.ucount[uc_type].fetch_add(1, core::sync::atomic::Ordering::SeqCst); 108*f5b20388Scodeironman ucounts_add.push(iter.clone()); 109*f5b20388Scodeironman // 分配失败回滚 110*f5b20388Scodeironman if num > iter.ns.ucount_max[uc_type] { 111*f5b20388Scodeironman for add_iter in &ucounts_add { 112*f5b20388Scodeironman add_iter.ucount[uc_type].fetch_sub(1, core::sync::atomic::Ordering::SeqCst); 113*f5b20388Scodeironman } 114*f5b20388Scodeironman return None; 115*f5b20388Scodeironman } 116*f5b20388Scodeironman uc_iter = iter.ns.ucounts.clone(); 117*f5b20388Scodeironman } 118*f5b20388Scodeironman return Some(uc); 119*f5b20388Scodeironman } 120*f5b20388Scodeironman find_ucounts(user_ns: Arc<UserNamespace>, uid: usize) -> Option<Arc<UCounts>>121*f5b20388Scodeironman fn find_ucounts(user_ns: Arc<UserNamespace>, uid: usize) -> Option<Arc<UCounts>> { 122*f5b20388Scodeironman let counts = COUNT_MANAGER.counts.lock(); 123*f5b20388Scodeironman let key = UKey { user_ns, uid }; 124*f5b20388Scodeironman counts.get(&key).cloned() 125*f5b20388Scodeironman } 126*f5b20388Scodeironman get_ucounts(uc: Arc<UCounts>)127*f5b20388Scodeironman fn get_ucounts(uc: Arc<UCounts>) { 128*f5b20388Scodeironman let mut counts = COUNT_MANAGER.counts.lock(); 129*f5b20388Scodeironman let ukey = UKey { 130*f5b20388Scodeironman user_ns: uc.ns.clone(), 131*f5b20388Scodeironman uid: uc.uid, 132*f5b20388Scodeironman }; 133*f5b20388Scodeironman counts.insert(ukey, uc); 134*f5b20388Scodeironman } 135*f5b20388Scodeironman dec_ucount(uc: Arc<UCounts>, ucount_type: Ucount)136*f5b20388Scodeironman pub fn dec_ucount(uc: Arc<UCounts>, ucount_type: Ucount) { 137*f5b20388Scodeironman let mut uc_iter = Some(uc.clone()); 138*f5b20388Scodeironman let uc_type = ucount_type as usize; 139*f5b20388Scodeironman while let Some(iter) = uc_iter { 140*f5b20388Scodeironman let num = iter.ucount[uc_type].fetch_sub(1, core::sync::atomic::Ordering::SeqCst); 141*f5b20388Scodeironman if num == 0 { 142*f5b20388Scodeironman warn!("count has reached zero"); 143*f5b20388Scodeironman } 144*f5b20388Scodeironman uc_iter = iter.ns.ucounts.clone(); 145*f5b20388Scodeironman } 146*f5b20388Scodeironman Self::put_ucounts(uc); 147*f5b20388Scodeironman } 148*f5b20388Scodeironman put_ucounts(uc: Arc<UCounts>)149*f5b20388Scodeironman fn put_ucounts(uc: Arc<UCounts>) { 150*f5b20388Scodeironman let mut counts = COUNT_MANAGER.counts.lock(); 151*f5b20388Scodeironman let key = UKey { 152*f5b20388Scodeironman user_ns: uc.ns.clone(), 153*f5b20388Scodeironman uid: uc.uid, 154*f5b20388Scodeironman }; 155*f5b20388Scodeironman counts.remove(&key); 156*f5b20388Scodeironman } 157*f5b20388Scodeironman } 158*f5b20388Scodeironman struct UKey { 159*f5b20388Scodeironman user_ns: Arc<UserNamespace>, 160*f5b20388Scodeironman uid: usize, 161*f5b20388Scodeironman } 162*f5b20388Scodeironman 163*f5b20388Scodeironman impl Hash for UKey { hash<H: core::hash::Hasher>(&self, state: &mut H)164*f5b20388Scodeironman fn hash<H: core::hash::Hasher>(&self, state: &mut H) { 165*f5b20388Scodeironman let user_ns_ptr = Arc::as_ptr(&self.user_ns); 166*f5b20388Scodeironman user_ns_ptr.hash(state); 167*f5b20388Scodeironman self.uid.hash(state) 168*f5b20388Scodeironman } 169*f5b20388Scodeironman } 170*f5b20388Scodeironman impl Eq for UKey {} 171*f5b20388Scodeironman impl PartialEq for UKey { eq(&self, other: &Self) -> bool172*f5b20388Scodeironman fn eq(&self, other: &Self) -> bool { 173*f5b20388Scodeironman Arc::ptr_eq(&self.user_ns, &other.user_ns) && self.uid == other.uid 174*f5b20388Scodeironman } 175*f5b20388Scodeironman } 176*f5b20388Scodeironman 177*f5b20388Scodeironman struct CountManager { 178*f5b20388Scodeironman counts: Mutex<HashMap<UKey, Arc<UCounts>>>, 179*f5b20388Scodeironman } 180*f5b20388Scodeironman 181*f5b20388Scodeironman impl CountManager { new() -> Self182*f5b20388Scodeironman fn new() -> Self { 183*f5b20388Scodeironman Self { 184*f5b20388Scodeironman counts: Mutex::new(HashMap::new()), 185*f5b20388Scodeironman } 186*f5b20388Scodeironman } 187*f5b20388Scodeironman } 188