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:
LoGin 2025-06-28 21:20:21 +08:00 committed by GitHub
parent 2532cb74fb
commit f8f7bcf2a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 69 additions and 1324 deletions

View File

@ -4,10 +4,7 @@
这里是DragonOS中与容器化相关的说明文档。
主要包括namespaceoverlayfs和cgroup
.. toctree::
:maxdepth: 2
namespaces/index
../filesystem/unionfs/index

View File

@ -1,14 +0,0 @@
====================================
命名空间
====================================
DragonOS的namespaces目前支持pid_namespace和mnt_namespace 预计之后会继续完善
namespace是容器化实现过程中的重要组成部分
由于目前os是单用户user_namespace为全局静态
.. toctree::
:maxdepth: 1
pid_namespace
mnt_namespace

View File

@ -1,19 +0,0 @@
# 挂载命名空间
## 底层架构
pcb -> nsproxy -> mnt_namespace
每一个挂载文件系统都有自立独立的挂载点,表现在数据结构上是一个挂载的红黑树,每一个命名空间中挂载是独立的,所以文件系统的挂载和卸载不会影响别的
## 系统调用接口
- clone
- CLONE_NEWNS用于创建一个新的 MNT 命名空间。提供独立的文件系统挂载点
- unshare
- 使用 CLONE_NEWPID 标志调用 unshare() 后,后续创建的所有子进程都将在新的命名空间中运行。
- setns
- 将进程加入到指定的命名空间
- chroot
- 将当前进程的根目录更改为指定的路径,提供文件系统隔离。

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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()
}
}

View File

@ -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;

View File

@ -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(

View File

@ -67,7 +67,6 @@ mod init;
mod ipc;
mod misc;
mod mm;
mod namespaces;
mod net;
mod perf;
mod process;

View File

@ -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
}
}

View File

@ -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)
}
};
}

View File

@ -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, &current, 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); // 转移所有权
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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()),
}
}
}

View File

@ -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],
}
}
}

View File

@ -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、组长

View File

@ -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) {
// 关闭文件描述符表

View File

@ -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;