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, ¤t, 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