refactor: Remove namespace related code (#1218)
* 删除mnt namespace * 移除Namespace代码 Signed-off-by: longjin <longjin@DragonOS.org> * 删除Namespace相关文档 Signed-off-by: longjin <longjin@DragonOS.org> --------- Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
parent
2532cb74fb
commit
f8f7bcf2a3
|
@ -4,10 +4,7 @@
|
|||
|
||||
这里是DragonOS中,与容器化相关的说明文档。
|
||||
|
||||
主要包括namespace,overlayfs和cgroup
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
namespaces/index
|
||||
../filesystem/unionfs/index
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
====================================
|
||||
命名空间
|
||||
====================================
|
||||
|
||||
DragonOS的namespaces目前支持pid_namespace和mnt_namespace 预计之后会继续完善
|
||||
namespace是容器化实现过程中的重要组成部分
|
||||
|
||||
由于目前os是单用户,user_namespace为全局静态
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
pid_namespace
|
||||
mnt_namespace
|
|
@ -1,19 +0,0 @@
|
|||
# 挂载命名空间
|
||||
|
||||
## 底层架构
|
||||
|
||||
pcb -> nsproxy -> mnt_namespace
|
||||
|
||||
每一个挂载文件系统都有自立独立的挂载点,表现在数据结构上是一个挂载的红黑树,每一个命名空间中挂载是独立的,所以文件系统的挂载和卸载不会影响别的
|
||||
|
||||
## 系统调用接口
|
||||
|
||||
|
||||
- clone
|
||||
- CLONE_NEWNS用于创建一个新的 MNT 命名空间。提供独立的文件系统挂载点
|
||||
- unshare
|
||||
- 使用 CLONE_NEWPID 标志调用 unshare() 后,后续创建的所有子进程都将在新的命名空间中运行。
|
||||
- setns
|
||||
- 将进程加入到指定的命名空间
|
||||
- chroot
|
||||
- 将当前进程的根目录更改为指定的路径,提供文件系统隔离。
|
|
@ -1,23 +0,0 @@
|
|||
# 进程命名空间
|
||||
:::{note} 本文作者:操丰毅 1553389239@qq.com
|
||||
|
||||
2024年10月30日
|
||||
:::
|
||||
|
||||
pid_namespace 是内核中的一种命名空间,用于实现进程隔离,允许在不同的命名空间中运行的进程有独立的pid视图
|
||||
|
||||
## 底层架构
|
||||
|
||||
pcb -> nsproxy -> pid_namespace
|
||||
- pid_namespace 内有独立的一套进程分配器,以及孤儿进程回收器,独立管理内部的pid
|
||||
- 不同进程的详细信息都存放在proc文件系统中,里面的找到对应的pid号里面的信息都在pid中,记录的是pid_namespace中的信息
|
||||
- pid_namespace等限制由ucount来控制管理
|
||||
|
||||
## 系统调用接口
|
||||
|
||||
- clone
|
||||
- CLONE_NEWPID用于创建一个新的 PID 命名空间。使用这个标志时,子进程将在新的 PID 命名空间内运行,进程 ID 从 1 开始。
|
||||
- unshare
|
||||
- 使用 CLONE_NEWPID 标志调用 unshare() 后,后续创建的所有子进程都将在新的命名空间中运行。
|
||||
- getpid
|
||||
- 在命名空间中调用 getpid() 会返回进程在当前 PID 命名空间中的进程 ID
|
|
@ -1,28 +0,0 @@
|
|||
.. note:: AI Translation Notice
|
||||
|
||||
This document was automatically translated by `Qwen/Qwen3-8B` model, for reference only.
|
||||
|
||||
- Source document: kernel/container/namespaces/index.rst
|
||||
|
||||
- Translation time: 2025-05-19 01:41:19
|
||||
|
||||
- Translation model: `Qwen/Qwen3-8B`
|
||||
|
||||
|
||||
Please report issues via `Community Channel <https://github.com/DragonOS-Community/DragonOS/issues>`_
|
||||
|
||||
====================================
|
||||
Namespaces
|
||||
====================================
|
||||
|
||||
DragonOS's namespaces currently support pid_namespace and mnt_namespace, and more features are expected to be added in the future.
|
||||
|
||||
Namespaces are an important component in the process of containerization.
|
||||
|
||||
Since the current OS is single-user, user_namespace is globally static.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
pid_namespace
|
||||
mnt_namespace
|
|
@ -1,33 +0,0 @@
|
|||
:::{note}
|
||||
**AI Translation Notice**
|
||||
|
||||
This document was automatically translated by `Qwen/Qwen3-8B` model, for reference only.
|
||||
|
||||
- Source document: kernel/container/namespaces/mnt_namespace.md
|
||||
|
||||
- Translation time: 2025-05-19 01:41:19
|
||||
|
||||
- Translation model: `Qwen/Qwen3-8B`
|
||||
|
||||
Please report issues via [Community Channel](https://github.com/DragonOS-Community/DragonOS/issues)
|
||||
|
||||
:::
|
||||
|
||||
# Mount Namespace
|
||||
|
||||
## Underlying Architecture
|
||||
|
||||
pcb -> nsproxy -> mnt_namespace
|
||||
|
||||
Each mounted file system has its own independent mount point, which is represented in the data structure as a red-black tree of mounts. Each namespace has its own independent mounts, so mounting and unmounting file systems will not affect others.
|
||||
|
||||
## System Call Interface
|
||||
|
||||
- clone
|
||||
- CLONE_NEWNS is used to create a new MNT namespace. It provides an independent file system mount point.
|
||||
- unshare
|
||||
- After calling unshare() with the CLONE_NEWPID flag, all subsequent child processes will run in the new namespace.
|
||||
- setns
|
||||
- Adds the process to the specified namespace.
|
||||
- chroot
|
||||
- Changes the current process's root directory to the specified path, providing file system isolation.
|
|
@ -1,38 +0,0 @@
|
|||
:::{note}
|
||||
**AI Translation Notice**
|
||||
|
||||
This document was automatically translated by `Qwen/Qwen3-8B` model, for reference only.
|
||||
|
||||
- Source document: kernel/container/namespaces/pid_namespace.md
|
||||
|
||||
- Translation time: 2025-05-19 01:41:31
|
||||
|
||||
- Translation model: `Qwen/Qwen3-8B`
|
||||
|
||||
Please report issues via [Community Channel](https://github.com/DragonOS-Community/DragonOS/issues)
|
||||
|
||||
:::
|
||||
|
||||
# Process Namespace
|
||||
:::{note} Author: Cao Fengyi 1553389239@qq.com
|
||||
|
||||
October 30, 2024
|
||||
:::
|
||||
|
||||
`pid_namespace` is a type of namespace in the kernel that is used to achieve process isolation. It allows processes running in different namespaces to have independent views of process IDs (PIDs).
|
||||
|
||||
## Underlying Architecture
|
||||
|
||||
pcb -> nsproxy -> pid_namespace
|
||||
- `pid_namespace` contains an independent set of process allocators and an orphan process reaper, which independently manages PIDs within the namespace.
|
||||
- Detailed information about processes is stored in the proc file system. The information corresponding to a specific PID is located within the `pid_namespace`, recording information related to the `pid_namespace`.
|
||||
- The limitations imposed by `pid_namespace` are controlled and managed by `ucount`.
|
||||
|
||||
## System Call Interface
|
||||
|
||||
- `clone`
|
||||
- `CLONE_NEWPID` is used to create a new PID namespace. When this flag is used, the child process will run in the new PID namespace, with the process ID starting from 1.
|
||||
- `unshare`
|
||||
- After calling `unshare()` with the `CLONE_NEWPID` flag, all subsequent child processes will run within the new namespace.
|
||||
- `getpid`
|
||||
- Calling `getpid()` within a namespace returns the process ID of the process within the current PID namespace.
|
|
@ -0,0 +1,66 @@
|
|||
use alloc::sync::Arc;
|
||||
|
||||
use crate::filesystem::vfs::syscall::ModeType;
|
||||
use crate::filesystem::vfs::IndexNode;
|
||||
use crate::filesystem::vfs::ROOT_INODE;
|
||||
use crate::libs::rwlock::RwLock;
|
||||
#[derive(Debug, Clone)]
|
||||
struct PathContext {
|
||||
root: Arc<dyn IndexNode>,
|
||||
pwd: Arc<dyn IndexNode>,
|
||||
}
|
||||
|
||||
impl PathContext {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
root: ROOT_INODE(),
|
||||
pwd: ROOT_INODE(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FsStruct {
|
||||
umask: ModeType, //文件权限掩码
|
||||
path_context: RwLock<PathContext>,
|
||||
}
|
||||
|
||||
impl Clone for FsStruct {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
umask: self.umask,
|
||||
path_context: RwLock::new(self.path_context.read().clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FsStruct {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl FsStruct {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
umask: ModeType::S_IWUGO,
|
||||
path_context: RwLock::new(PathContext::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_root(&self, inode: Arc<dyn IndexNode>) {
|
||||
self.path_context.write().root = inode;
|
||||
}
|
||||
|
||||
pub fn set_pwd(&self, inode: Arc<dyn IndexNode>) {
|
||||
self.path_context.write().pwd = inode;
|
||||
}
|
||||
|
||||
pub fn pwd(&self) -> Arc<dyn IndexNode> {
|
||||
self.path_context.read().pwd.clone()
|
||||
}
|
||||
|
||||
pub fn root(&self) -> Arc<dyn IndexNode> {
|
||||
self.path_context.read().root.clone()
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ pub mod devpts;
|
|||
pub mod epoll;
|
||||
pub mod eventfd;
|
||||
pub mod fat;
|
||||
pub mod fs;
|
||||
pub mod kernfs;
|
||||
pub mod mbr;
|
||||
pub mod overlayfs;
|
||||
|
|
|
@ -10,7 +10,6 @@ use crate::{
|
|||
arch::{interrupt::TrapFrame, process::arch_switch_to_user},
|
||||
driver::net::e1000e::e1000e::e1000e_init,
|
||||
filesystem::vfs::vcore::mount_root_fs,
|
||||
namespaces::NsProxy,
|
||||
net::net_core::net_init,
|
||||
process::{
|
||||
exec::ProcInitInfo, execve::do_execve, kthread::KernelThreadMechanism, stdio::stdio_init,
|
||||
|
@ -160,7 +159,6 @@ fn run_init_process(
|
|||
trap_frame: &mut TrapFrame,
|
||||
) -> Result<(), SystemError> {
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
ProcessManager::current_pcb().set_nsproxy(NsProxy::new()); // 初始化init进程的namespace
|
||||
let path = proc_init_info.proc_name.to_str().unwrap();
|
||||
|
||||
do_execve(
|
||||
|
|
|
@ -67,7 +67,6 @@ mod init;
|
|||
mod ipc;
|
||||
mod misc;
|
||||
mod mm;
|
||||
mod namespaces;
|
||||
mod net;
|
||||
mod perf;
|
||||
mod process;
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
#![allow(dead_code, unused_variables, unused_imports)]
|
||||
use core::sync::atomic::AtomicU64;
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::ToString;
|
||||
|
||||
use alloc::string::String;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use system_error::SystemError;
|
||||
|
||||
use super::namespace::Namespace;
|
||||
use super::namespace::NsOperations;
|
||||
use super::ucount::Ucount::MntNamespaces;
|
||||
use super::{namespace::NsCommon, ucount::UCounts, user_namespace::UserNamespace};
|
||||
use crate::container_of;
|
||||
use crate::filesystem::vfs::mount::MountFSInode;
|
||||
use crate::filesystem::vfs::syscall::ModeType;
|
||||
use crate::filesystem::vfs::IndexNode;
|
||||
use crate::filesystem::vfs::InodeId;
|
||||
use crate::filesystem::vfs::MountFS;
|
||||
use crate::filesystem::vfs::ROOT_INODE;
|
||||
use crate::libs::rbtree::RBTree;
|
||||
use crate::libs::rwlock::RwLock;
|
||||
use crate::libs::wait_queue::WaitQueue;
|
||||
use crate::process::fork::CloneFlags;
|
||||
use crate::process::geteuid::do_geteuid;
|
||||
use crate::process::ProcessManager;
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
pub struct MntNamespace {
|
||||
/// namespace 共有的部分
|
||||
ns_common: Arc<NsCommon>,
|
||||
/// 关联的用户名字空间
|
||||
user_ns: Arc<UserNamespace>,
|
||||
/// 资源计数器
|
||||
ucounts: Arc<UCounts>,
|
||||
/// 根文件系统
|
||||
root: Option<Arc<MountFS>>,
|
||||
/// 红黑树用于挂载所有挂载点
|
||||
mounts: RBTree<InodeId, MountFSInode>,
|
||||
/// 等待队列
|
||||
poll: WaitQueue,
|
||||
/// 挂载序列号
|
||||
seq: AtomicU64,
|
||||
/// 挂载点的数量
|
||||
nr_mounts: u32,
|
||||
/// 待处理的挂载点
|
||||
pending_mounts: u32,
|
||||
}
|
||||
|
||||
impl Default for MntNamespace {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MntNsOperations {
|
||||
name: String,
|
||||
clone_flags: CloneFlags,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct PathContext {
|
||||
root: Arc<dyn IndexNode>,
|
||||
pwd: Arc<dyn IndexNode>,
|
||||
}
|
||||
|
||||
impl PathContext {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
root: ROOT_INODE(),
|
||||
pwd: ROOT_INODE(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FsStruct {
|
||||
umask: ModeType, //文件权限掩码
|
||||
path_context: RwLock<PathContext>,
|
||||
}
|
||||
|
||||
impl Clone for FsStruct {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
umask: self.umask,
|
||||
path_context: RwLock::new(self.path_context.read().clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FsStruct {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl FsStruct {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
umask: ModeType::S_IWUGO,
|
||||
path_context: RwLock::new(PathContext::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_root(&self, inode: Arc<dyn IndexNode>) {
|
||||
self.path_context.write().root = inode;
|
||||
}
|
||||
|
||||
pub fn set_pwd(&self, inode: Arc<dyn IndexNode>) {
|
||||
self.path_context.write().pwd = inode;
|
||||
}
|
||||
|
||||
pub fn pwd(&self) -> Arc<dyn IndexNode> {
|
||||
self.path_context.read().pwd.clone()
|
||||
}
|
||||
|
||||
pub fn root(&self) -> Arc<dyn IndexNode> {
|
||||
self.path_context.read().root.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Namespace for MntNamespace {
|
||||
fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self> {
|
||||
let ns_common_ptr = Arc::as_ptr(&ns_common);
|
||||
// container_of!(ns_common_ptr, MntNamespace, ns_common)
|
||||
panic!("not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
impl MntNsOperations {
|
||||
pub fn new(name: String) -> Self {
|
||||
Self {
|
||||
name,
|
||||
clone_flags: CloneFlags::CLONE_NEWNS,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NsOperations for MntNsOperations {
|
||||
fn get(&self, pid: crate::process::Pid) -> Option<Arc<NsCommon>> {
|
||||
let pcb = ProcessManager::find(pid);
|
||||
pcb.map(|pcb| pcb.get_nsproxy().read().mnt_namespace.ns_common.clone())
|
||||
}
|
||||
// 不存在这个方法
|
||||
fn get_parent(&self, _ns_common: Arc<NsCommon>) -> Result<Arc<NsCommon>, SystemError> {
|
||||
unreachable!()
|
||||
}
|
||||
fn install(
|
||||
&self,
|
||||
nsset: &mut super::NsSet,
|
||||
ns_common: Arc<NsCommon>,
|
||||
) -> Result<(), SystemError> {
|
||||
let nsproxy = &mut nsset.nsproxy;
|
||||
let mnt_ns = MntNamespace::ns_common_to_ns(ns_common);
|
||||
if mnt_ns.is_anon_ns() {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
nsproxy.mnt_namespace = mnt_ns;
|
||||
|
||||
let guard = nsset.fs.write();
|
||||
guard.set_pwd(ROOT_INODE());
|
||||
guard.set_root(ROOT_INODE());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn owner(&self, ns_common: Arc<NsCommon>) -> Arc<UserNamespace> {
|
||||
let mnt_ns = MntNamespace::ns_common_to_ns(ns_common);
|
||||
mnt_ns.user_ns.clone()
|
||||
}
|
||||
fn put(&self, ns_common: Arc<NsCommon>) {
|
||||
let pid_ns = MntNamespace::ns_common_to_ns(ns_common);
|
||||
}
|
||||
}
|
||||
impl MntNamespace {
|
||||
pub fn new() -> Self {
|
||||
let ns_common = Arc::new(NsCommon::new(Box::new(MntNsOperations::new(
|
||||
"mnt".to_string(),
|
||||
))));
|
||||
|
||||
Self {
|
||||
ns_common,
|
||||
user_ns: Arc::new(UserNamespace::new()),
|
||||
ucounts: Arc::new(UCounts::new()),
|
||||
root: None,
|
||||
mounts: RBTree::new(),
|
||||
poll: WaitQueue::default(),
|
||||
seq: AtomicU64::new(0),
|
||||
nr_mounts: 0,
|
||||
pending_mounts: 0,
|
||||
}
|
||||
}
|
||||
/// anon 用来判断是否是匿名的.匿名函数的问题还需要考虑
|
||||
pub fn create_mnt_namespace(
|
||||
&self,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
anon: bool,
|
||||
) -> Result<Self, SystemError> {
|
||||
let ucounts = self.inc_mnt_namespace(user_ns.clone())?;
|
||||
if ucounts.is_none() {
|
||||
return Err(SystemError::ENOSPC);
|
||||
}
|
||||
let ucounts = ucounts.unwrap();
|
||||
let ns_common = Arc::new(NsCommon::new(Box::new(MntNsOperations::new(
|
||||
"mnt".to_string(),
|
||||
))));
|
||||
let seq = AtomicU64::new(0);
|
||||
if !anon {
|
||||
seq.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
Ok(Self {
|
||||
ns_common,
|
||||
user_ns,
|
||||
ucounts,
|
||||
root: None,
|
||||
mounts: RBTree::new(),
|
||||
poll: WaitQueue::default(),
|
||||
seq,
|
||||
nr_mounts: 0,
|
||||
pending_mounts: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn inc_mnt_namespace(
|
||||
&self,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
) -> Result<Option<Arc<UCounts>>, SystemError> {
|
||||
Ok(self
|
||||
.ucounts
|
||||
.inc_ucounts(user_ns, do_geteuid()?, MntNamespaces))
|
||||
}
|
||||
|
||||
pub fn dec_mnt_namespace(&self, uc: Arc<UCounts>) {
|
||||
UCounts::dec_ucount(uc, super::ucount::Ucount::MntNamespaces)
|
||||
}
|
||||
//判断是不是匿名空间
|
||||
pub fn is_anon_ns(&self) -> bool {
|
||||
self.seq.load(Ordering::SeqCst) == 0
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
use alloc::sync::Arc;
|
||||
use mnt_namespace::{FsStruct, MntNamespace};
|
||||
use pid_namespace::PidNamespace;
|
||||
use system_error::SystemError;
|
||||
use user_namespace::UserNamespace;
|
||||
|
||||
use crate::{
|
||||
libs::rwlock::RwLock,
|
||||
process::{fork::CloneFlags, ProcessControlBlock},
|
||||
};
|
||||
|
||||
pub mod mnt_namespace;
|
||||
pub mod namespace;
|
||||
pub mod pid_namespace;
|
||||
pub mod syscall;
|
||||
pub mod ucount;
|
||||
pub mod user_namespace;
|
||||
|
||||
/// 管理 namespace,包含了所有namespace的信息
|
||||
pub struct NsSet {
|
||||
flags: u64,
|
||||
nsproxy: NsProxy,
|
||||
pub fs: RwLock<Arc<FsStruct>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct NsProxy {
|
||||
pub pid_namespace: Arc<PidNamespace>,
|
||||
pub mnt_namespace: Arc<MntNamespace>,
|
||||
}
|
||||
impl Default for NsProxy {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl NsProxy {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pid_namespace: Arc::new(PidNamespace::new()),
|
||||
mnt_namespace: Arc::new(MntNamespace::new()),
|
||||
}
|
||||
}
|
||||
pub fn set_pid_namespace(&mut self, new_pid_ns: Arc<PidNamespace>) {
|
||||
self.pid_namespace = new_pid_ns;
|
||||
}
|
||||
|
||||
pub fn set_mnt_namespace(&mut self, new_mnt_ns: Arc<MntNamespace>) {
|
||||
self.mnt_namespace = new_mnt_ns;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_new_namespaces(
|
||||
clone_flags: u64,
|
||||
pcb: &Arc<ProcessControlBlock>,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
) -> Result<NsProxy, SystemError> {
|
||||
let mut nsproxy = NsProxy::new();
|
||||
// pid_namespace
|
||||
let new_pid_ns = if (clone_flags & CloneFlags::CLONE_NEWPID.bits()) != 0 {
|
||||
Arc::new(PidNamespace::new().create_pid_namespace(
|
||||
pcb.get_nsproxy().read().pid_namespace.clone(),
|
||||
user_ns.clone(),
|
||||
)?)
|
||||
} else {
|
||||
pcb.get_nsproxy().read().pid_namespace.clone()
|
||||
};
|
||||
nsproxy.set_pid_namespace(new_pid_ns);
|
||||
|
||||
// mnt_namespace
|
||||
let new_mnt_ns = if clone_flags & CloneFlags::CLONE_NEWNS.bits() != 0 {
|
||||
Arc::new(MntNamespace::new().create_mnt_namespace(user_ns.clone(), false)?)
|
||||
} else {
|
||||
pcb.get_nsproxy().read().mnt_namespace.clone()
|
||||
};
|
||||
nsproxy.set_mnt_namespace(new_mnt_ns);
|
||||
|
||||
Ok(nsproxy)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! container_of {
|
||||
($ptr:expr, $struct:path, $field:ident) => {
|
||||
unsafe {
|
||||
let dummy = core::mem::MaybeUninit::<$struct>::uninit();
|
||||
let dummy_ptr = dummy.as_ptr();
|
||||
let field_ptr = &(*dummy_ptr).$field as *const _ as usize;
|
||||
let offset = field_ptr - dummy_ptr as usize;
|
||||
Arc::from_raw(($ptr as *const u8).wrapping_sub(offset) as *mut $struct)
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
#![allow(dead_code, unused_variables, unused_imports)]
|
||||
use core::fmt::Debug;
|
||||
|
||||
use crate::filesystem::procfs::ProcFSInode;
|
||||
use crate::filesystem::vfs::{IndexNode, ROOT_INODE};
|
||||
use crate::libs::rwlock::RwLock;
|
||||
use crate::namespaces::user_namespace::UserNamespace;
|
||||
use crate::process::fork::CloneFlags;
|
||||
use crate::process::{Pid, ProcessControlBlock, ProcessManager};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::sync::Arc;
|
||||
use system_error::SystemError;
|
||||
|
||||
// 目前无credit功能,采用全局静态的user_namespace
|
||||
lazy_static! {
|
||||
pub static ref USER_NS: Arc<UserNamespace> = Arc::new(UserNamespace::new());
|
||||
}
|
||||
use super::{create_new_namespaces, NsProxy, NsSet};
|
||||
pub trait NsOperations: Send + Sync + Debug {
|
||||
fn get(&self, pid: Pid) -> Option<Arc<NsCommon>>;
|
||||
fn put(&self, ns_common: Arc<NsCommon>);
|
||||
fn install(&self, nsset: &mut NsSet, ns_common: Arc<NsCommon>) -> Result<(), SystemError>;
|
||||
fn owner(&self, ns_common: Arc<NsCommon>) -> Arc<UserNamespace>;
|
||||
fn get_parent(&self, ns_common: Arc<NsCommon>) -> Result<Arc<NsCommon>, SystemError>;
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct NsCommon {
|
||||
ops: Box<dyn NsOperations>,
|
||||
stashed: Arc<dyn IndexNode>,
|
||||
}
|
||||
|
||||
impl NsCommon {
|
||||
pub fn new(ops: Box<dyn NsOperations>) -> Self {
|
||||
let inode = ROOT_INODE().find("proc").unwrap_or_else(|_| ROOT_INODE());
|
||||
Self {
|
||||
ops,
|
||||
stashed: inode,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum NsType {
|
||||
Pid,
|
||||
User,
|
||||
Uts,
|
||||
Ipc,
|
||||
Net,
|
||||
Mnt,
|
||||
Cgroup,
|
||||
Time,
|
||||
}
|
||||
|
||||
pub trait Namespace {
|
||||
fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self>;
|
||||
}
|
||||
|
||||
pub fn check_unshare_flags(unshare_flags: u64) -> Result<usize, SystemError> {
|
||||
let valid_flags = CloneFlags::CLONE_THREAD
|
||||
| CloneFlags::CLONE_FS
|
||||
| CloneFlags::CLONE_NEWNS
|
||||
| CloneFlags::CLONE_SIGHAND
|
||||
| CloneFlags::CLONE_VM
|
||||
| CloneFlags::CLONE_FILES
|
||||
| CloneFlags::CLONE_SYSVSEM
|
||||
| CloneFlags::CLONE_NEWUTS
|
||||
| CloneFlags::CLONE_NEWIPC
|
||||
| CloneFlags::CLONE_NEWNET
|
||||
| CloneFlags::CLONE_NEWUSER
|
||||
| CloneFlags::CLONE_NEWPID
|
||||
| CloneFlags::CLONE_NEWCGROUP;
|
||||
|
||||
if unshare_flags & !valid_flags.bits() != 0 {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
pub fn unshare_nsproxy_namespaces(unshare_flags: u64) -> Result<Option<NsProxy>, SystemError> {
|
||||
if (unshare_flags
|
||||
& (CloneFlags::CLONE_NEWNS.bits()
|
||||
| CloneFlags::CLONE_NEWUTS.bits()
|
||||
| CloneFlags::CLONE_NEWIPC.bits()
|
||||
| CloneFlags::CLONE_NEWNET.bits()
|
||||
| CloneFlags::CLONE_NEWPID.bits()
|
||||
| CloneFlags::CLONE_NEWCGROUP.bits()))
|
||||
== 0
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
let current = ProcessManager::current_pid();
|
||||
let pcb = ProcessManager::find(current).unwrap();
|
||||
let new_nsproxy = create_new_namespaces(unshare_flags, &pcb, USER_NS.clone())?;
|
||||
Ok(Some(new_nsproxy))
|
||||
}
|
||||
|
||||
pub fn switch_task_namespace(pcb: Arc<ProcessControlBlock>, new_nsproxy: NsProxy) {
|
||||
let ns = pcb.get_nsproxy();
|
||||
pcb.set_nsproxy(new_nsproxy);
|
||||
}
|
||||
|
||||
pub fn prepare_nsset(flags: u64) -> Result<NsSet, SystemError> {
|
||||
let current = ProcessManager::current_pcb();
|
||||
Ok(NsSet {
|
||||
flags,
|
||||
fs: RwLock::new(current.fs_struct()),
|
||||
nsproxy: create_new_namespaces(flags, ¤t, USER_NS.clone())?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn commit_nsset(nsset: NsSet) {
|
||||
let flags = CloneFlags::from_bits_truncate(nsset.flags);
|
||||
let current = ProcessManager::current_pcb();
|
||||
if flags.contains(CloneFlags::CLONE_NEWNS) {
|
||||
let nsset_fs = nsset.fs.read();
|
||||
let fs = current.fs_struct_mut();
|
||||
fs.set_pwd(nsset_fs.pwd());
|
||||
fs.set_root(nsset_fs.root());
|
||||
}
|
||||
switch_task_namespace(current, nsset.nsproxy); // 转移所有权
|
||||
}
|
|
@ -1,273 +0,0 @@
|
|||
#![allow(dead_code, unused_variables, unused_imports)]
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use super::namespace::Namespace;
|
||||
use super::ucount::Ucount::PidNamespaces;
|
||||
use super::NsSet;
|
||||
use super::{namespace::NsCommon, ucount::UCounts, user_namespace::UserNamespace};
|
||||
use crate::container_of;
|
||||
use crate::filesystem::vfs::{IndexNode, ROOT_INODE};
|
||||
use crate::namespaces::namespace::NsOperations;
|
||||
use crate::process::fork::CloneFlags;
|
||||
use crate::process::geteuid::do_geteuid;
|
||||
use crate::process::ProcessManager;
|
||||
use crate::{libs::rwlock::RwLock, process::Pid};
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use alloc::string::ToString;
|
||||
use alloc::sync::Arc;
|
||||
use ida::IdAllocator;
|
||||
use system_error::SystemError;
|
||||
use system_error::SystemError::ENOSPC;
|
||||
|
||||
const INT16_MAX: u32 = 32767;
|
||||
const MAX_PID_NS_LEVEL: usize = 32;
|
||||
const PIDNS_ADDING: u32 = 1 << 31;
|
||||
const PID_MAX: usize = 4096;
|
||||
static PID_IDA: ida::IdAllocator = ida::IdAllocator::new(1, usize::MAX).unwrap();
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct PidNamespace {
|
||||
id_alloctor: RwLock<IdAllocator>,
|
||||
/// 已经分配的进程数
|
||||
pid_allocated: u32,
|
||||
/// 当前的pid_namespace所在的层数
|
||||
pub level: usize,
|
||||
/// 父命名空间
|
||||
parent: Option<Arc<PidNamespace>>,
|
||||
/// 资源计数器
|
||||
ucounts: Arc<UCounts>,
|
||||
/// 关联的用户namespace
|
||||
user_ns: Arc<UserNamespace>,
|
||||
/// 回收孤儿进程的init进程
|
||||
child_reaper: Arc<RwLock<Pid>>,
|
||||
/// namespace共有部分
|
||||
pub ns_common: Arc<NsCommon>,
|
||||
}
|
||||
|
||||
impl Default for PidNamespace {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PidStrcut {
|
||||
pub level: usize,
|
||||
pub numbers: Vec<UPid>,
|
||||
pub stashed: Arc<dyn IndexNode>,
|
||||
}
|
||||
|
||||
impl Default for PidStrcut {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UPid {
|
||||
pub nr: Pid, // 在该pid_namespace 中的pid
|
||||
pub ns: Arc<PidNamespace>,
|
||||
}
|
||||
|
||||
impl PidStrcut {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
level: 0,
|
||||
numbers: vec![UPid {
|
||||
nr: Pid::new(0),
|
||||
ns: Arc::new(PidNamespace::new()),
|
||||
}],
|
||||
stashed: ROOT_INODE(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn put_pid(pid: PidStrcut) {
|
||||
let ns = pid.numbers[pid.level].ns.clone();
|
||||
let id = pid.numbers[pid.level].nr.data();
|
||||
ns.id_alloctor.write().free(id);
|
||||
}
|
||||
pub fn alloc_pid(ns: Arc<PidNamespace>, set_tid: Vec<usize>) -> Result<PidStrcut, SystemError> {
|
||||
let mut set_tid_size = set_tid.len();
|
||||
if set_tid_size > ns.level + 1 {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let mut numbers = Vec::<UPid>::with_capacity(ns.level + 1);
|
||||
let mut tid_iter = set_tid.into_iter().rev();
|
||||
let mut pid_ns = ns.clone(); // 当前正在处理的命名空间
|
||||
for i in (0..=ns.level).rev() {
|
||||
let tid = tid_iter.next().unwrap_or(0);
|
||||
if set_tid_size > 0 {
|
||||
if tid < 1 || tid > INT16_MAX as usize {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
set_tid_size -= 1;
|
||||
}
|
||||
let mut nr = tid;
|
||||
|
||||
if tid == 0 {
|
||||
nr = pid_ns
|
||||
.id_alloctor
|
||||
.write()
|
||||
.alloc()
|
||||
.expect("PID allocation failed.");
|
||||
}
|
||||
|
||||
numbers.insert(
|
||||
i,
|
||||
UPid {
|
||||
nr: Pid::from(nr),
|
||||
ns: pid_ns.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
if let Some(parent_ns) = &pid_ns.parent {
|
||||
pid_ns = parent_ns.clone();
|
||||
} else {
|
||||
break; // 根命名空间,无需继续向上。
|
||||
}
|
||||
}
|
||||
Ok(PidStrcut {
|
||||
level: ns.level,
|
||||
numbers,
|
||||
stashed: ROOT_INODE(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn ns_of_pid(&self) -> Arc<PidNamespace> {
|
||||
self.numbers[self.level].ns.clone()
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct PidNsOperations {
|
||||
name: String,
|
||||
clone_flags: CloneFlags,
|
||||
}
|
||||
impl PidNsOperations {
|
||||
pub fn new(name: String) -> Self {
|
||||
Self {
|
||||
name,
|
||||
clone_flags: CloneFlags::CLONE_NEWPID,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Namespace for PidNamespace {
|
||||
fn ns_common_to_ns(ns_common: Arc<NsCommon>) -> Arc<Self> {
|
||||
container_of!(Arc::as_ptr(&ns_common), PidNamespace, ns_common)
|
||||
}
|
||||
}
|
||||
|
||||
impl NsOperations for PidNsOperations {
|
||||
fn put(&self, ns_common: Arc<NsCommon>) {
|
||||
let _pid_ns = PidNamespace::ns_common_to_ns(ns_common);
|
||||
// pid_ns 超出作用域自动drop 同时递归drop
|
||||
}
|
||||
|
||||
fn owner(&self, ns_common: Arc<NsCommon>) -> Arc<UserNamespace> {
|
||||
let pid_ns = PidNamespace::ns_common_to_ns(ns_common);
|
||||
pid_ns.user_ns.clone()
|
||||
}
|
||||
|
||||
fn get_parent(&self, ns_common: Arc<NsCommon>) -> Result<Arc<NsCommon>, SystemError> {
|
||||
let current = ProcessManager::current_pid();
|
||||
let pcb = ProcessManager::find(current).unwrap();
|
||||
let active = pcb.pid_strcut().read().ns_of_pid();
|
||||
let mut pid_ns = &PidNamespace::ns_common_to_ns(ns_common).parent;
|
||||
|
||||
while let Some(ns) = pid_ns {
|
||||
if Arc::ptr_eq(&active, ns) {
|
||||
return Ok(ns.ns_common.clone());
|
||||
}
|
||||
pid_ns = &ns.parent;
|
||||
}
|
||||
Err(SystemError::EPERM)
|
||||
}
|
||||
|
||||
fn get(&self, pid: Pid) -> Option<Arc<NsCommon>> {
|
||||
let pcb = ProcessManager::find(pid);
|
||||
pcb.map(|pcb| pcb.get_nsproxy().read().pid_namespace.ns_common.clone())
|
||||
}
|
||||
fn install(&self, nsset: &mut NsSet, ns_common: Arc<NsCommon>) -> Result<(), SystemError> {
|
||||
let nsproxy = &mut nsset.nsproxy;
|
||||
let current = ProcessManager::current_pid();
|
||||
let pcb = ProcessManager::find(current).unwrap();
|
||||
let active = pcb.pid_strcut().read().ns_of_pid();
|
||||
let mut pid_ns = PidNamespace::ns_common_to_ns(ns_common);
|
||||
if pid_ns.level < active.level {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
while pid_ns.level > active.level {
|
||||
if let Some(ns) = &pid_ns.parent {
|
||||
pid_ns = ns.clone();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if Arc::ptr_eq(&pid_ns, &active) {
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
nsproxy.pid_namespace = pid_ns.clone();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
impl PidNamespace {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
id_alloctor: RwLock::new(IdAllocator::new(1, PID_MAX).unwrap()),
|
||||
pid_allocated: 1,
|
||||
level: 0,
|
||||
child_reaper: Arc::new(RwLock::new(Pid::from(1))),
|
||||
parent: None,
|
||||
ucounts: Arc::new(UCounts::new()),
|
||||
user_ns: Arc::new(UserNamespace::new()),
|
||||
ns_common: Arc::new(NsCommon::new(Box::new(PidNsOperations::new(
|
||||
"pid".to_string(),
|
||||
)))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_pid_namespace(
|
||||
&self,
|
||||
parent: Arc<PidNamespace>,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
) -> Result<Self, SystemError> {
|
||||
let level = parent.level + 1;
|
||||
if level > MAX_PID_NS_LEVEL {
|
||||
return Err(ENOSPC);
|
||||
}
|
||||
let ucounts = self.inc_pid_namespaces(user_ns.clone())?;
|
||||
|
||||
if ucounts.is_none() {
|
||||
return Err(SystemError::ENOSPC);
|
||||
}
|
||||
let ucounts = ucounts.unwrap();
|
||||
|
||||
let ns_common = Arc::new(NsCommon::new(Box::new(PidNsOperations::new(
|
||||
"pid".to_string(),
|
||||
))));
|
||||
let child_reaper = parent.child_reaper.clone();
|
||||
Ok(Self {
|
||||
id_alloctor: RwLock::new(IdAllocator::new(1, PID_MAX).unwrap()),
|
||||
pid_allocated: PIDNS_ADDING,
|
||||
level,
|
||||
ucounts,
|
||||
parent: Some(parent),
|
||||
user_ns,
|
||||
ns_common,
|
||||
child_reaper,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn inc_pid_namespaces(
|
||||
&self,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
) -> Result<Option<Arc<UCounts>>, SystemError> {
|
||||
Ok(self
|
||||
.ucounts
|
||||
.inc_ucounts(user_ns, do_geteuid()?, PidNamespaces))
|
||||
}
|
||||
|
||||
pub fn dec_pid_namespaces(&mut self, uc: Arc<UCounts>) {
|
||||
UCounts::dec_ucount(uc, PidNamespaces)
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
use system_error::SystemError;
|
||||
|
||||
use crate::{
|
||||
process::{fork::CloneFlags, ProcessManager},
|
||||
syscall::Syscall,
|
||||
};
|
||||
|
||||
use super::namespace::{
|
||||
check_unshare_flags, commit_nsset, prepare_nsset, unshare_nsproxy_namespaces,
|
||||
};
|
||||
|
||||
impl Syscall {
|
||||
pub fn sys_unshare(mut unshare_flags: u64) -> Result<usize, SystemError> {
|
||||
if unshare_flags & CloneFlags::CLONE_NEWUSER.bits() != 0 {
|
||||
unshare_flags |= CloneFlags::CLONE_THREAD.bits() | CloneFlags::CLONE_FS.bits();
|
||||
}
|
||||
|
||||
if unshare_flags & CloneFlags::CLONE_VM.bits() != 0 {
|
||||
unshare_flags |= CloneFlags::CLONE_SIGHAND.bits();
|
||||
}
|
||||
|
||||
if unshare_flags & CloneFlags::CLONE_SIGHAND.bits() != 0 {
|
||||
unshare_flags |= CloneFlags::CLONE_THREAD.bits();
|
||||
}
|
||||
|
||||
if unshare_flags & CloneFlags::CLONE_NEWNS.bits() != 0 {
|
||||
unshare_flags |= CloneFlags::CLONE_FS.bits();
|
||||
}
|
||||
|
||||
let check = check_unshare_flags(unshare_flags)?;
|
||||
|
||||
let current = ProcessManager::current_pcb();
|
||||
if let Some(nsproxy) = unshare_nsproxy_namespaces(unshare_flags)? {
|
||||
*current.get_nsproxy().write() = nsproxy;
|
||||
}
|
||||
|
||||
Ok(check)
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn sys_setns(_fd: i32, flags: u64) -> Result<usize, SystemError> {
|
||||
let check = check_unshare_flags(flags)?;
|
||||
|
||||
let nsset = prepare_nsset(flags)?;
|
||||
|
||||
if check == 0 {
|
||||
commit_nsset(nsset)
|
||||
};
|
||||
Ok(0)
|
||||
}
|
||||
}
|
|
@ -1,187 +0,0 @@
|
|||
#![allow(dead_code, unused_variables, unused_imports)]
|
||||
use alloc::vec::Vec;
|
||||
use core::{hash::Hash, sync::atomic::AtomicU32};
|
||||
use system_error::SystemError;
|
||||
|
||||
use alloc::sync::Arc;
|
||||
use hashbrown::HashMap;
|
||||
use log::warn;
|
||||
|
||||
use super::user_namespace::UserNamespace;
|
||||
use crate::libs::mutex::Mutex;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Ucount {
|
||||
UserNamespaces = 1,
|
||||
PidNamespaces = 2,
|
||||
UtsNamespaces = 3,
|
||||
IpcNamespaces = 4,
|
||||
NetNamespaces = 5,
|
||||
MntNamespaces = 6,
|
||||
CgroupNamespaces = 7,
|
||||
TimeNamespaces = 8,
|
||||
Counts = 9,
|
||||
}
|
||||
|
||||
pub enum UcountRlimit {
|
||||
Nproc = 1,
|
||||
Msgqueue = 2,
|
||||
Sigpending = 3,
|
||||
Memlock = 4,
|
||||
Counts = 5,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref COUNT_MANAGER: Arc<CountManager> = Arc::new(CountManager::new());
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UCounts {
|
||||
/// 对应的user_namespace
|
||||
ns: Arc<UserNamespace>,
|
||||
/// 用户标识符
|
||||
uid: usize,
|
||||
count: AtomicU32,
|
||||
ucount: Vec<AtomicU32>, //[AtomicU32; UCOUNT_COUNTS as usize],
|
||||
rlimit: Vec<AtomicU32>, //[AtomicU32; UCOUNT_RLIMIT_COUNTS as usize],
|
||||
}
|
||||
|
||||
impl Default for UCounts {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
impl UCounts {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
ns: Arc::new(UserNamespace::new()),
|
||||
uid: 0,
|
||||
count: AtomicU32::new(1),
|
||||
ucount: (0..Ucount::Counts as usize)
|
||||
.map(|_| AtomicU32::new(0))
|
||||
.collect(),
|
||||
rlimit: (0..UcountRlimit::Counts as usize)
|
||||
.map(|_| AtomicU32::new(0))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn alloc_ucounts(&self, ns: Arc<UserNamespace>, uid: usize) -> Arc<Self> {
|
||||
let mut counts = COUNT_MANAGER.counts.lock();
|
||||
let key = UKey {
|
||||
user_ns: ns.clone(),
|
||||
uid,
|
||||
};
|
||||
let uc = if let Some(uc) = counts.get(&key) {
|
||||
self.count
|
||||
.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
|
||||
uc.clone()
|
||||
} else {
|
||||
Arc::new(Self {
|
||||
ns,
|
||||
uid,
|
||||
count: AtomicU32::new(1),
|
||||
ucount: (0..Ucount::Counts as usize)
|
||||
.map(|_| AtomicU32::new(0))
|
||||
.collect(),
|
||||
rlimit: (0..UcountRlimit::Counts as usize)
|
||||
.map(|_| AtomicU32::new(0))
|
||||
.collect(),
|
||||
})
|
||||
};
|
||||
counts.insert(key, uc.clone());
|
||||
uc
|
||||
}
|
||||
|
||||
pub fn inc_ucounts(
|
||||
&self,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
uid: usize,
|
||||
ucount_type: Ucount,
|
||||
) -> Option<Arc<UCounts>> {
|
||||
let uc_type = ucount_type as usize;
|
||||
let uc = self.alloc_ucounts(user_ns, uid);
|
||||
let mut uc_iter = Some(uc.clone());
|
||||
let mut ucounts_add = vec![];
|
||||
while let Some(iter) = uc_iter {
|
||||
let num = iter.ucount[uc_type].fetch_add(1, core::sync::atomic::Ordering::SeqCst);
|
||||
ucounts_add.push(iter.clone());
|
||||
// 分配失败回滚
|
||||
if num > iter.ns.ucount_max[uc_type] {
|
||||
for add_iter in &ucounts_add {
|
||||
add_iter.ucount[uc_type].fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
uc_iter = iter.ns.ucounts.clone();
|
||||
}
|
||||
return Some(uc);
|
||||
}
|
||||
|
||||
fn find_ucounts(user_ns: Arc<UserNamespace>, uid: usize) -> Option<Arc<UCounts>> {
|
||||
let counts = COUNT_MANAGER.counts.lock();
|
||||
let key = UKey { user_ns, uid };
|
||||
counts.get(&key).cloned()
|
||||
}
|
||||
|
||||
fn get_ucounts(uc: Arc<UCounts>) {
|
||||
let mut counts = COUNT_MANAGER.counts.lock();
|
||||
let ukey = UKey {
|
||||
user_ns: uc.ns.clone(),
|
||||
uid: uc.uid,
|
||||
};
|
||||
counts.insert(ukey, uc);
|
||||
}
|
||||
|
||||
pub fn dec_ucount(uc: Arc<UCounts>, ucount_type: Ucount) {
|
||||
let mut uc_iter = Some(uc.clone());
|
||||
let uc_type = ucount_type as usize;
|
||||
while let Some(iter) = uc_iter {
|
||||
let num = iter.ucount[uc_type].fetch_sub(1, core::sync::atomic::Ordering::SeqCst);
|
||||
if num == 0 {
|
||||
warn!("count has reached zero");
|
||||
}
|
||||
uc_iter = iter.ns.ucounts.clone();
|
||||
}
|
||||
Self::put_ucounts(uc);
|
||||
}
|
||||
|
||||
fn put_ucounts(uc: Arc<UCounts>) {
|
||||
let mut counts = COUNT_MANAGER.counts.lock();
|
||||
let key = UKey {
|
||||
user_ns: uc.ns.clone(),
|
||||
uid: uc.uid,
|
||||
};
|
||||
counts.remove(&key);
|
||||
}
|
||||
}
|
||||
struct UKey {
|
||||
user_ns: Arc<UserNamespace>,
|
||||
uid: usize,
|
||||
}
|
||||
|
||||
impl Hash for UKey {
|
||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||
let user_ns_ptr = Arc::as_ptr(&self.user_ns);
|
||||
user_ns_ptr.hash(state);
|
||||
self.uid.hash(state)
|
||||
}
|
||||
}
|
||||
impl Eq for UKey {}
|
||||
impl PartialEq for UKey {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
Arc::ptr_eq(&self.user_ns, &other.user_ns) && self.uid == other.uid
|
||||
}
|
||||
}
|
||||
|
||||
struct CountManager {
|
||||
counts: Mutex<HashMap<UKey, Arc<UCounts>>>,
|
||||
}
|
||||
|
||||
impl CountManager {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
counts: Mutex::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
#![allow(dead_code, unused_variables, unused_imports)]
|
||||
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use crate::libs::rwlock::RwLock;
|
||||
use alloc::string::String;
|
||||
use alloc::string::ToString;
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use system_error::SystemError;
|
||||
|
||||
use crate::namespaces::namespace::NsCommon;
|
||||
use crate::namespaces::ucount::UCounts;
|
||||
use crate::process::fork::CloneFlags;
|
||||
use crate::process::Pid;
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use super::namespace::NsOperations;
|
||||
use super::ucount::Ucount::Counts;
|
||||
|
||||
const UID_GID_MAP_MAX_BASE_EXTENTS: usize = 5;
|
||||
const UCOUNT_MAX: u32 = 62636;
|
||||
/// 管理用户ID和组ID的映射
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Debug)]
|
||||
struct UidGidMap {
|
||||
nr_extents: u32,
|
||||
extent: Vec<UidGidExtent>,
|
||||
}
|
||||
|
||||
///区间映射
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Debug)]
|
||||
struct UidGidExtent {
|
||||
first: u32,
|
||||
lower_first: u32,
|
||||
count: u32,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct UserNamespace {
|
||||
uid_map: UidGidMap,
|
||||
gid_map: UidGidMap,
|
||||
progid_map: UidGidMap,
|
||||
///项目ID映射
|
||||
parent: Option<Arc<UserNamespace>>,
|
||||
level: u32,
|
||||
owner: usize,
|
||||
group: usize,
|
||||
ns_common: Arc<NsCommon>,
|
||||
flags: u32,
|
||||
pid: Arc<RwLock<Pid>>,
|
||||
pub ucounts: Option<Arc<UCounts>>,
|
||||
pub ucount_max: Vec<u32>, //vec![u32; UCOUNT_COUNTS as usize],
|
||||
pub rlimit_max: Vec<u32>, // vec![u32; UCOUNT_RLIMIT_COUNTS as usize],
|
||||
}
|
||||
|
||||
impl Default for UserNamespace {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct UserNsOperations {
|
||||
name: String,
|
||||
clone_flags: CloneFlags,
|
||||
}
|
||||
impl UserNsOperations {
|
||||
pub fn new(name: String) -> Self {
|
||||
Self {
|
||||
name,
|
||||
clone_flags: CloneFlags::CLONE_NEWUSER,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl NsOperations for UserNsOperations {
|
||||
fn get(&self, pid: Pid) -> Option<Arc<NsCommon>> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn get_parent(&self, ns_common: Arc<NsCommon>) -> Result<Arc<NsCommon>, SystemError> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn install(
|
||||
&self,
|
||||
nsset: &mut super::NsSet,
|
||||
ns_common: Arc<NsCommon>,
|
||||
) -> Result<(), SystemError> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn owner(&self, ns_common: Arc<NsCommon>) -> Arc<UserNamespace> {
|
||||
unimplemented!()
|
||||
}
|
||||
fn put(&self, ns_common: Arc<NsCommon>) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
impl UidGidMap {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
nr_extents: 1,
|
||||
extent: vec![UidGidExtent::new(); UID_GID_MAP_MAX_BASE_EXTENTS],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UidGidExtent {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
first: 0,
|
||||
lower_first: 0,
|
||||
count: u32::MAX,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UserNamespace {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
uid_map: UidGidMap::new(),
|
||||
gid_map: UidGidMap::new(),
|
||||
progid_map: UidGidMap::new(),
|
||||
owner: 0,
|
||||
level: 0,
|
||||
group: 0,
|
||||
flags: 1,
|
||||
parent: None,
|
||||
ns_common: Arc::new(NsCommon::new(Box::new(UserNsOperations::new(
|
||||
"User".to_string(),
|
||||
)))),
|
||||
pid: Arc::new(RwLock::new(Pid::new(1))),
|
||||
ucount_max: vec![UCOUNT_MAX; Counts as usize],
|
||||
ucounts: None,
|
||||
rlimit_max: vec![65535, 10, 32000, 64 * 1024],
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ use crate::{
|
|||
ipc::signal::flush_signal_handlers,
|
||||
libs::rwlock::RwLock,
|
||||
mm::VirtAddr,
|
||||
namespaces::{create_new_namespaces, namespace::USER_NS, pid_namespace::PidStrcut},
|
||||
process::ProcessFlags,
|
||||
sched::{sched_cgroup_fork, sched_fork},
|
||||
smp::core::smp_get_processor_id,
|
||||
|
@ -255,34 +254,6 @@ impl ProcessManager {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn copy_namespaces(
|
||||
clone_flags: &CloneFlags,
|
||||
current_pcb: &Arc<ProcessControlBlock>,
|
||||
new_pcb: &Arc<ProcessControlBlock>,
|
||||
) -> Result<(), SystemError> {
|
||||
if !clone_flags.contains(CloneFlags::CLONE_NEWNS)
|
||||
&& !clone_flags.contains(CloneFlags::CLONE_NEWUTS)
|
||||
&& !clone_flags.contains(CloneFlags::CLONE_NEWIPC)
|
||||
&& !clone_flags.contains(CloneFlags::CLONE_NEWPID)
|
||||
&& !clone_flags.contains(CloneFlags::CLONE_NEWNET)
|
||||
&& !clone_flags.contains(CloneFlags::CLONE_NEWCGROUP)
|
||||
{
|
||||
new_pcb.set_nsproxy(current_pcb.get_nsproxy().read().clone());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if clone_flags.contains(CloneFlags::CLONE_NEWIPC)
|
||||
&& clone_flags.contains(CloneFlags::CLONE_SYSVSEM)
|
||||
{
|
||||
return Err(SystemError::EINVAL);
|
||||
}
|
||||
|
||||
let new_nsproxy = create_new_namespaces(clone_flags.bits(), current_pcb, USER_NS.clone())?;
|
||||
*new_pcb.nsproxy.write() = new_nsproxy;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
fn copy_files(
|
||||
clone_flags: &CloneFlags,
|
||||
|
@ -457,11 +428,6 @@ impl ProcessManager {
|
|||
)
|
||||
});
|
||||
|
||||
Self::copy_namespaces(&clone_flags, current_pcb, pcb).unwrap_or_else(|e|{
|
||||
panic!("fork: Failed to copy namespace form current process, current pid: [{:?}], new pid: [{:?}]. Error: {:?}",
|
||||
current_pcb.pid(), pcb.pid(), e)
|
||||
});
|
||||
|
||||
// 拷贝文件描述符表
|
||||
Self::copy_files(&clone_flags, current_pcb, pcb).unwrap_or_else(|e| {
|
||||
panic!(
|
||||
|
@ -485,13 +451,6 @@ impl ProcessManager {
|
|||
current_pcb.pid(), pcb.pid(), e
|
||||
)
|
||||
});
|
||||
if current_pcb.pid() != Pid(0) {
|
||||
let new_pid = PidStrcut::alloc_pid(
|
||||
pcb.get_nsproxy().read().pid_namespace.clone(), // 获取命名空间
|
||||
clone_args.set_tid.clone(),
|
||||
)?;
|
||||
*pcb.thread_pid.write() = new_pid;
|
||||
}
|
||||
|
||||
// log::debug!("fork: clone_flags: {:?}", clone_flags);
|
||||
// 设置线程组id、组长
|
||||
|
|
|
@ -30,6 +30,7 @@ use crate::{
|
|||
driver::tty::tty_core::TtyCore,
|
||||
exception::InterruptArch,
|
||||
filesystem::{
|
||||
fs::FsStruct,
|
||||
procfs::procfs_unregister_pid,
|
||||
vfs::{file::FileDescriptorVec, FileType, IndexNode},
|
||||
},
|
||||
|
@ -56,7 +57,6 @@ use crate::{
|
|||
ucontext::AddressSpace,
|
||||
PhysAddr, VirtAddr,
|
||||
},
|
||||
namespaces::{mnt_namespace::FsStruct, pid_namespace::PidStrcut, NsProxy},
|
||||
net::socket::SocketInode,
|
||||
sched::{
|
||||
completion::Completion, cpu_rq, fair::FairSchedEntity, prio::MAX_PRIO, DequeueFlag,
|
||||
|
@ -697,8 +697,6 @@ pub struct ProcessControlBlock {
|
|||
pid: Pid,
|
||||
/// 当前进程的线程组id(这个值在同一个线程组内永远不变)
|
||||
tgid: Pid,
|
||||
/// 有关Pid的相关的信息
|
||||
thread_pid: Arc<RwLock<PidStrcut>>,
|
||||
basic: RwLock<ProcessBasicInfo>,
|
||||
/// 当前进程的自旋锁持有计数
|
||||
preempt_count: AtomicUsize,
|
||||
|
@ -745,9 +743,6 @@ pub struct ProcessControlBlock {
|
|||
/// 进程的robust lock列表
|
||||
robust_list: RwLock<Option<RobustListHead>>,
|
||||
|
||||
/// namespace的指针
|
||||
nsproxy: Arc<RwLock<NsProxy>>,
|
||||
|
||||
/// 进程作为主体的凭证集
|
||||
cred: SpinLock<Cred>,
|
||||
self_ref: Weak<ProcessControlBlock>,
|
||||
|
@ -826,7 +821,6 @@ impl ProcessControlBlock {
|
|||
let pcb = Self {
|
||||
pid,
|
||||
tgid: pid,
|
||||
thread_pid: Arc::new(RwLock::new(PidStrcut::new())),
|
||||
basic: basic_info,
|
||||
preempt_count,
|
||||
flags,
|
||||
|
@ -846,7 +840,6 @@ impl ProcessControlBlock {
|
|||
fs: RwLock::new(Arc::new(FsStruct::new())),
|
||||
alarm_timer: SpinLock::new(None),
|
||||
robust_list: RwLock::new(None),
|
||||
nsproxy: Arc::new(RwLock::new(NsProxy::new())),
|
||||
cred: SpinLock::new(cred),
|
||||
self_ref: weak.clone(),
|
||||
restart_block: SpinLock::new(None),
|
||||
|
@ -1021,11 +1014,6 @@ impl ProcessControlBlock {
|
|||
return self.pid;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn pid_strcut(&self) -> Arc<RwLock<PidStrcut>> {
|
||||
self.thread_pid.clone()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn tgid(&self) -> Pid {
|
||||
return self.tgid;
|
||||
|
@ -1207,14 +1195,6 @@ impl ProcessControlBlock {
|
|||
return self.alarm_timer.lock_irqsave();
|
||||
}
|
||||
|
||||
pub fn get_nsproxy(&self) -> Arc<RwLock<NsProxy>> {
|
||||
self.nsproxy.clone()
|
||||
}
|
||||
|
||||
pub fn set_nsproxy(&self, nsprsy: NsProxy) {
|
||||
*self.nsproxy.write() = nsprsy;
|
||||
}
|
||||
|
||||
/// Exit fd table when process exit
|
||||
fn exit_files(&self) {
|
||||
// 关闭文件描述符表
|
||||
|
|
|
@ -846,7 +846,7 @@ impl Syscall {
|
|||
let flags = args[1] as u32;
|
||||
Self::sys_eventfd(initval, flags)
|
||||
}
|
||||
SYS_UNSHARE => Self::sys_unshare(args[0] as u64),
|
||||
|
||||
SYS_BPF => {
|
||||
let cmd = args[0] as u32;
|
||||
let attr = args[1] as *mut u8;
|
||||
|
|
Loading…
Reference in New Issue