xref: /DragonOS/kernel/src/namespaces/namespace.rs (revision f5b2038871d3441e1c7f32439ff422957e7ab828)
1*f5b20388Scodeironman #![allow(dead_code, unused_variables, unused_imports)]
2*f5b20388Scodeironman use core::fmt::Debug;
3*f5b20388Scodeironman 
4*f5b20388Scodeironman use crate::filesystem::procfs::ProcFSInode;
5*f5b20388Scodeironman use crate::filesystem::vfs::{IndexNode, ROOT_INODE};
6*f5b20388Scodeironman use crate::namespaces::user_namespace::UserNamespace;
7*f5b20388Scodeironman use crate::process::fork::CloneFlags;
8*f5b20388Scodeironman use crate::process::{Pid, ProcessControlBlock, ProcessManager};
9*f5b20388Scodeironman use alloc::boxed::Box;
10*f5b20388Scodeironman use alloc::sync::Arc;
11*f5b20388Scodeironman use system_error::SystemError;
12*f5b20388Scodeironman 
13*f5b20388Scodeironman // 目前无credit功能,采用全局静态的user_namespace
14*f5b20388Scodeironman lazy_static! {
15*f5b20388Scodeironman     pub static ref USER_NS: Arc<UserNamespace> = Arc::new(UserNamespace::new());
16*f5b20388Scodeironman }
17*f5b20388Scodeironman use super::{create_new_namespaces, NsProxy, NsSet};
18*f5b20388Scodeironman pub trait NsOperations: Send + Sync + Debug {
get(&self, pid: Pid) -> Option<Arc<NsCommon>>19*f5b20388Scodeironman     fn get(&self, pid: Pid) -> Option<Arc<NsCommon>>;
put(&self, ns_common: Arc<NsCommon>)20*f5b20388Scodeironman     fn put(&self, ns_common: Arc<NsCommon>);
install(&self, nsset: &mut NsSet, ns_common: Arc<NsCommon>) -> Result<(), SystemError>21*f5b20388Scodeironman     fn install(&self, nsset: &mut NsSet, ns_common: Arc<NsCommon>) -> Result<(), SystemError>;
owner(&self, ns_common: Arc<NsCommon>) -> Arc<UserNamespace>22*f5b20388Scodeironman     fn owner(&self, ns_common: Arc<NsCommon>) -> Arc<UserNamespace>;
get_parent(&self, ns_common: Arc<NsCommon>) -> Result<Arc<NsCommon>, SystemError>23*f5b20388Scodeironman     fn get_parent(&self, ns_common: Arc<NsCommon>) -> Result<Arc<NsCommon>, SystemError>;
24*f5b20388Scodeironman }
25*f5b20388Scodeironman #[derive(Debug)]
26*f5b20388Scodeironman pub struct NsCommon {
27*f5b20388Scodeironman     ops: Box<dyn NsOperations>,
28*f5b20388Scodeironman     stashed: Arc<dyn IndexNode>,
29*f5b20388Scodeironman }
30*f5b20388Scodeironman 
31*f5b20388Scodeironman impl NsCommon {
new(ops: Box<dyn NsOperations>) -> Self32*f5b20388Scodeironman     pub fn new(ops: Box<dyn NsOperations>) -> Self {
33*f5b20388Scodeironman         let inode = ROOT_INODE().find("proc").unwrap_or_else(|_| ROOT_INODE());
34*f5b20388Scodeironman         Self {
35*f5b20388Scodeironman             ops,
36*f5b20388Scodeironman             stashed: inode,
37*f5b20388Scodeironman         }
38*f5b20388Scodeironman     }
39*f5b20388Scodeironman }
40*f5b20388Scodeironman 
41*f5b20388Scodeironman pub enum NsType {
42*f5b20388Scodeironman     Pid,
43*f5b20388Scodeironman     User,
44*f5b20388Scodeironman     Uts,
45*f5b20388Scodeironman     Ipc,
46*f5b20388Scodeironman     Net,
47*f5b20388Scodeironman     Mnt,
48*f5b20388Scodeironman     Cgroup,
49*f5b20388Scodeironman     Time,
50*f5b20388Scodeironman }
51*f5b20388Scodeironman 
52*f5b20388Scodeironman pub trait Namespace {
ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self>53*f5b20388Scodeironman     fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self>;
54*f5b20388Scodeironman }
55*f5b20388Scodeironman 
check_unshare_flags(unshare_flags: u64) -> Result<usize, SystemError>56*f5b20388Scodeironman pub fn check_unshare_flags(unshare_flags: u64) -> Result<usize, SystemError> {
57*f5b20388Scodeironman     let valid_flags = CloneFlags::CLONE_THREAD
58*f5b20388Scodeironman         | CloneFlags::CLONE_FS
59*f5b20388Scodeironman         | CloneFlags::CLONE_NEWNS
60*f5b20388Scodeironman         | CloneFlags::CLONE_SIGHAND
61*f5b20388Scodeironman         | CloneFlags::CLONE_VM
62*f5b20388Scodeironman         | CloneFlags::CLONE_FILES
63*f5b20388Scodeironman         | CloneFlags::CLONE_SYSVSEM
64*f5b20388Scodeironman         | CloneFlags::CLONE_NEWUTS
65*f5b20388Scodeironman         | CloneFlags::CLONE_NEWIPC
66*f5b20388Scodeironman         | CloneFlags::CLONE_NEWNET
67*f5b20388Scodeironman         | CloneFlags::CLONE_NEWUSER
68*f5b20388Scodeironman         | CloneFlags::CLONE_NEWPID
69*f5b20388Scodeironman         | CloneFlags::CLONE_NEWCGROUP;
70*f5b20388Scodeironman 
71*f5b20388Scodeironman     if unshare_flags & !valid_flags.bits() != 0 {
72*f5b20388Scodeironman         return Err(SystemError::EINVAL);
73*f5b20388Scodeironman     }
74*f5b20388Scodeironman     Ok(0)
75*f5b20388Scodeironman }
76*f5b20388Scodeironman 
unshare_nsproxy_namespaces(unshare_flags: u64) -> Result<Option<NsProxy>, SystemError>77*f5b20388Scodeironman pub fn unshare_nsproxy_namespaces(unshare_flags: u64) -> Result<Option<NsProxy>, SystemError> {
78*f5b20388Scodeironman     if (unshare_flags
79*f5b20388Scodeironman         & (CloneFlags::CLONE_NEWNS.bits()
80*f5b20388Scodeironman             | CloneFlags::CLONE_NEWUTS.bits()
81*f5b20388Scodeironman             | CloneFlags::CLONE_NEWIPC.bits()
82*f5b20388Scodeironman             | CloneFlags::CLONE_NEWNET.bits()
83*f5b20388Scodeironman             | CloneFlags::CLONE_NEWPID.bits()
84*f5b20388Scodeironman             | CloneFlags::CLONE_NEWCGROUP.bits()))
85*f5b20388Scodeironman         == 0
86*f5b20388Scodeironman     {
87*f5b20388Scodeironman         return Ok(None);
88*f5b20388Scodeironman     }
89*f5b20388Scodeironman     let current = ProcessManager::current_pid();
90*f5b20388Scodeironman     let pcb = ProcessManager::find(current).unwrap();
91*f5b20388Scodeironman     let new_nsproxy = create_new_namespaces(unshare_flags, &pcb, USER_NS.clone())?;
92*f5b20388Scodeironman     Ok(Some(new_nsproxy))
93*f5b20388Scodeironman }
94*f5b20388Scodeironman 
switch_task_namespace(pcb: Arc<ProcessControlBlock>, new_nsproxy: NsProxy)95*f5b20388Scodeironman pub fn switch_task_namespace(pcb: Arc<ProcessControlBlock>, new_nsproxy: NsProxy) {
96*f5b20388Scodeironman     let ns = pcb.get_nsproxy();
97*f5b20388Scodeironman     pcb.set_nsproxy(new_nsproxy);
98*f5b20388Scodeironman }
99*f5b20388Scodeironman 
prepare_nsset(flags: u64) -> Result<NsSet, SystemError>100*f5b20388Scodeironman pub fn prepare_nsset(flags: u64) -> Result<NsSet, SystemError> {
101*f5b20388Scodeironman     let current = ProcessManager::current_pcb();
102*f5b20388Scodeironman     Ok(NsSet {
103*f5b20388Scodeironman         flags,
104*f5b20388Scodeironman         fs: current.fs_struct(),
105*f5b20388Scodeironman         nsproxy: create_new_namespaces(flags, &current, USER_NS.clone())?,
106*f5b20388Scodeironman     })
107*f5b20388Scodeironman }
108*f5b20388Scodeironman 
commit_nsset(nsset: NsSet)109*f5b20388Scodeironman pub fn commit_nsset(nsset: NsSet) {
110*f5b20388Scodeironman     let flags = CloneFlags::from_bits_truncate(nsset.flags);
111*f5b20388Scodeironman     let current = ProcessManager::current_pcb();
112*f5b20388Scodeironman     if flags.contains(CloneFlags::CLONE_NEWNS) {
113*f5b20388Scodeironman         let fs = current.fs_struct();
114*f5b20388Scodeironman         let nsset_fs = nsset.fs.lock();
115*f5b20388Scodeironman         fs.lock().set_pwd(nsset_fs.pwd.clone());
116*f5b20388Scodeironman         fs.lock().set_root(nsset_fs.root.clone());
117*f5b20388Scodeironman     }
118*f5b20388Scodeironman     switch_task_namespace(current, nsset.nsproxy); // 转移所有权
119*f5b20388Scodeironman }
120