feat(ipc): 实现IPC命名空间初步支持 (#1288)
* feat(ipc): 实现IPC命名空间第一阶段支持 - 添加IpcNamespace结构体并集成到NsProxy中 - 将全局SHM_MANAGER重构为per-ns ShmManager - 修改shm相关系统调用以支持命名空间隔离 - 添加VMA的shm_id字段用于精确维护映射计数 - 新增IPC命名空间测试用例 - 更新相关文档 Signed-off-by: longjin <longjin@DragonOS.org> * fmt Signed-off-by: longjin <longjin@DragonOS.org> --------- Signed-off-by: longjin <longjin@DragonOS.org>
This commit is contained in:
parent
509ee34586
commit
ef296a34e1
|
|
@ -8,3 +8,4 @@
|
|||
:maxdepth: 1
|
||||
|
||||
signal
|
||||
ipc_namespace
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
# IPC Namespace
|
||||
|
||||
:::{note}
|
||||
|
||||
Author: longjin <longjin@dragonos.org>
|
||||
|
||||
:::
|
||||
|
||||
本页描述 DragonOS 对 IPC 命名空间(IPC namespace)的当前支持状态与后续计划。目标是对用户暴露与 Linux 一致的语义,并在 DragonOS 现有框架上逐步完善。
|
||||
|
||||
## 已支持功能
|
||||
- IpcNamespace 对象与 NsProxy 集成:
|
||||
- 新增 `IpcNamespace` 并接入 `NsProxy`,每个任务通过 `nsproxy.ipc_ns` 访问所属 IPC 命名空间。
|
||||
- 命名空间的创建/继承遵循 `clone/unshare` 语义:
|
||||
- 未包含 `CLONE_NEWIPC` 时继承父命名空间;
|
||||
- 包含 `CLONE_NEWIPC` 时创建独立 IPC 命名空间;
|
||||
- 与 `CLONE_SYSVSEM` 互斥,行为与 Linux 一致。
|
||||
|
||||
- SysV SHM(共享内存)按命名空间隔离:
|
||||
- 将原全局 `SHM_MANAGER` 重构为 per-ns `ShmManager`,所有 `shmget/shmat/shmdt/shmctl` 均在 `current.nsproxy.ipc_ns` 下生效。
|
||||
- `shmat`/`shmdt`:VMA 记录 `ShmId`,解除映射时精确维护 `map_count`;`IPC_RMID` 后当 `SHM_DEST && map_count==0` 即完成物理回收。
|
||||
- 基本语义与错误码对齐:`IPC_CREAT|IPC_EXCL`、`ENOENT`、拒绝 `SHM_HUGETLB` 等。
|
||||
|
||||
- 基础测试用例:(在 `test_ipc_ns_shm.rs` 中)
|
||||
|
||||
- `unshare(CLONE_NEWIPC)` 后父/子命名空间的 key 不可见;
|
||||
- 跨命名空间相同 key 不冲突;
|
||||
- `IPC_RMID` 后可重新创建同 key;
|
||||
- 输出 PASS/FAIL 与汇总结果。
|
||||
|
||||
## 暂未实现/计划中
|
||||
- `/proc/[pid]/ns/ipc` 与 `setns`:
|
||||
- 暂缓,仅规划只读占位与最简 `setns` 路径;后续版本补齐权限校验与切换时序。
|
||||
|
||||
- SysV IPC 其它子系统:
|
||||
- `msg/sem` 框架尚未纳入;`sem` 的 UNDO 列表与 `unshare/setns` 的协同需在引入时同步实现。
|
||||
|
||||
- POSIX mqueue:
|
||||
- 尚未提供 per-ns mqueuefs 内核挂载、限额与 sysctl。
|
||||
|
||||
- 权限与配额:
|
||||
- `ipcperms()`、`ns_capable(user_ns, CAP_IPC_OWNER)`;
|
||||
- ucounts/RLIMIT 与 `/proc/sys/kernel/shm*` 等 per-ns sysctl。
|
||||
|
||||
## 兼容性与注意事项
|
||||
- 当前阶段仅对 SysV SHM 提供命名空间隔离;其它 IPC 类型仍按全局语义工作。
|
||||
- 代码按模块化方式演进:后续加入 `msg/sem/mqueue` 时,保持对用户侧语义的稳定与一致。
|
||||
|
||||
## 参考
|
||||
- 代码位置:
|
||||
- `kernel/src/process/namespace/ipc_namespace.rs`
|
||||
- `kernel/src/process/namespace/nsproxy.rs`
|
||||
- `kernel/src/ipc/syscall/` 内的 `sys_shm*`
|
||||
- `kernel/src/mm/ucontext.rs`(VMA 与 SHM 计数维护)
|
||||
|
||||
|
||||
|
|
@ -1,10 +1,7 @@
|
|||
use crate::{
|
||||
arch::mm::LockedFrameAllocator,
|
||||
filesystem::vfs::syscall::ModeType,
|
||||
libs::{
|
||||
align::page_align_up,
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
},
|
||||
libs::align::page_align_up,
|
||||
mm::{
|
||||
allocator::page_frame::{FrameAllocator, PageFrameCount, PhysPageFrame},
|
||||
page::{page_manager_lock_irqsave, PageFlags, PageType},
|
||||
|
|
@ -15,33 +12,14 @@ use crate::{
|
|||
time::PosixTimeSpec,
|
||||
};
|
||||
use core::fmt;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use hashbrown::HashMap;
|
||||
use ida::IdAllocator;
|
||||
use log::info;
|
||||
use num::ToPrimitive;
|
||||
use system_error::SystemError;
|
||||
pub static mut SHM_MANAGER: Option<SpinLock<ShmManager>> = None;
|
||||
|
||||
/// 用于创建新的私有IPC对象
|
||||
pub const IPC_PRIVATE: ShmKey = ShmKey::new(0);
|
||||
|
||||
/// 初始化SHM_MANAGER
|
||||
pub fn shm_manager_init() {
|
||||
info!("shm_manager_init");
|
||||
let shm_manager = SpinLock::new(ShmManager::new());
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe { SHM_MANAGER = Some(shm_manager) };
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
info!("shm_manager_init done");
|
||||
}
|
||||
|
||||
pub fn shm_manager_lock() -> SpinLockGuard<'static, ShmManager> {
|
||||
unsafe { SHM_MANAGER.as_ref().unwrap().lock() }
|
||||
}
|
||||
|
||||
int_like!(ShmId, usize);
|
||||
int_like!(ShmKey, usize);
|
||||
|
||||
|
|
@ -138,6 +116,12 @@ pub struct ShmManager {
|
|||
key2id: HashMap<ShmKey, ShmId>,
|
||||
}
|
||||
|
||||
impl Default for ShmManager {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ShmManager {
|
||||
pub fn new() -> Self {
|
||||
ShmManager {
|
||||
|
|
@ -178,7 +162,7 @@ impl ShmManager {
|
|||
// 创建共享内存page,并添加到PAGE_MANAGER中
|
||||
let mut page_manager_guard = page_manager_lock_irqsave();
|
||||
let (paddr, _page) = page_manager_guard.create_pages(
|
||||
PageType::Shm(shm_id),
|
||||
PageType::Shm,
|
||||
PageFlags::PG_UNEVICTABLE,
|
||||
&mut LockedFrameAllocator,
|
||||
page_count,
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@ use crate::syscall::table::FormattedSyscallParam;
|
|||
use crate::{
|
||||
arch::syscall::nr::SYS_SHMAT,
|
||||
arch::MMArch,
|
||||
ipc::shm::{shm_manager_lock, ShmFlags, ShmId},
|
||||
ipc::shm::{ShmFlags, ShmId},
|
||||
libs::align::page_align_up,
|
||||
mm::{
|
||||
allocator::page_frame::{PageFrameCount, PhysPageFrame, VirtPageFrame},
|
||||
page::{page_manager_lock_irqsave, EntryFlags, PageFlushAll},
|
||||
syscall::ProtFlags,
|
||||
ucontext::{AddressSpace, VMA},
|
||||
ucontext::{AddressSpace, PhysmapParams, VMA},
|
||||
VirtAddr, VmFlags,
|
||||
},
|
||||
process::ProcessManager,
|
||||
syscall::{table::Syscall, user_access::UserBufferReader},
|
||||
};
|
||||
use syscall_table_macros::declare_syscall;
|
||||
|
|
@ -36,7 +37,8 @@ pub(super) fn do_kernel_shmat(
|
|||
vaddr: VirtAddr,
|
||||
shmflg: ShmFlags,
|
||||
) -> Result<usize, SystemError> {
|
||||
let mut shm_manager_guard = shm_manager_lock();
|
||||
let ipcns = ProcessManager::current_ipcns();
|
||||
let mut shm_manager_guard = ipcns.shm.lock();
|
||||
let current_address_space = AddressSpace::current()?;
|
||||
let mut address_write_guard = current_address_space.write();
|
||||
|
||||
|
|
@ -59,15 +61,15 @@ pub(super) fn do_kernel_shmat(
|
|||
let flusher: PageFlushAll<MMArch> = PageFlushAll::new();
|
||||
|
||||
// 将共享内存映射到对应虚拟区域
|
||||
let vma = VMA::physmap(
|
||||
let params = PhysmapParams {
|
||||
phys,
|
||||
destination,
|
||||
count,
|
||||
vm_flags,
|
||||
page_flags,
|
||||
&mut address_write_guard.user_mapper.utable,
|
||||
flusher,
|
||||
)?;
|
||||
flags: page_flags,
|
||||
shm_id: Some(id),
|
||||
};
|
||||
let vma = VMA::physmap(params, &mut address_write_guard.user_mapper.utable, flusher)?;
|
||||
|
||||
// 将VMA加入到当前进程的VMA列表中
|
||||
address_write_guard.mappings.insert_vma(vma);
|
||||
|
|
@ -125,7 +127,10 @@ pub(super) fn do_kernel_shmat(
|
|||
}
|
||||
|
||||
// 更新vma的映射状态
|
||||
vma.lock_irqsave().set_mapped(true);
|
||||
let mut vma_guard = vma.lock_irqsave();
|
||||
vma_guard.set_mapped(true);
|
||||
vma_guard.set_shm_id(Some(id));
|
||||
drop(vma_guard);
|
||||
|
||||
vaddr.data()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ use crate::alloc::vec::Vec;
|
|||
use crate::arch::interrupt::TrapFrame;
|
||||
use crate::{
|
||||
arch::syscall::nr::SYS_SHMCTL,
|
||||
ipc::shm::{shm_manager_lock, ShmCtlCmd, ShmId},
|
||||
ipc::shm::{ShmCtlCmd, ShmId},
|
||||
process::ProcessManager,
|
||||
syscall::table::{FormattedSyscallParam, Syscall},
|
||||
};
|
||||
use syscall_table_macros::declare_syscall;
|
||||
|
|
@ -28,7 +29,9 @@ pub(super) fn do_kernel_shmctl(
|
|||
user_buf: *const u8,
|
||||
from_user: bool,
|
||||
) -> Result<usize, SystemError> {
|
||||
let mut shm_manager_guard = shm_manager_lock();
|
||||
// per-ns 管理器
|
||||
let ipcns = ProcessManager::current_ipcns();
|
||||
let mut shm_manager_guard = ipcns.shm.lock();
|
||||
|
||||
match cmd {
|
||||
// 查看共享内存元信息
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ use crate::arch::interrupt::TrapFrame;
|
|||
use crate::syscall::table::FormattedSyscallParam;
|
||||
use crate::{
|
||||
arch::syscall::nr::SYS_SHMGET,
|
||||
ipc::shm::{shm_manager_lock, ShmFlags, ShmKey, IPC_PRIVATE},
|
||||
ipc::shm::{ShmFlags, ShmKey, IPC_PRIVATE},
|
||||
process::ProcessManager,
|
||||
syscall::table::Syscall,
|
||||
};
|
||||
use log::error;
|
||||
|
|
@ -34,7 +35,9 @@ pub(super) fn do_kernel_shmget(
|
|||
return Err(SystemError::ENOSYS);
|
||||
}
|
||||
|
||||
let mut shm_manager_guard = shm_manager_lock();
|
||||
// 从当前进程的 IPC 命名空间获取 per-ns SHM 管理器
|
||||
let ipcns = ProcessManager::current_ipcns();
|
||||
let mut shm_manager_guard = ipcns.shm.lock();
|
||||
match key {
|
||||
// 创建共享内存段
|
||||
IPC_PRIVATE => shm_manager_guard.add(key, size, shmflg),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ use crate::{
|
|||
arch::MMArch,
|
||||
driver::serial::serial8250::send_to_default_serial8250_port,
|
||||
filesystem::procfs::kmsg::kmsg_init,
|
||||
ipc::shm::shm_manager_init,
|
||||
libs::printk::PrintkWriter,
|
||||
mm::{
|
||||
allocator::slab::slab_init,
|
||||
|
|
@ -59,8 +58,6 @@ pub unsafe fn mm_init() {
|
|||
kmsg_init();
|
||||
// enable PAGE_MANAGER
|
||||
page_manager_init();
|
||||
// enable SHM_MANAGER
|
||||
shm_manager_init();
|
||||
// enable PAGE_RECLAIMER
|
||||
page_reclaimer_init();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ use crate::{
|
|||
exception::ipi::{IpiKind, IpiTarget},
|
||||
filesystem::{page_cache::PageCache, vfs::FilePrivateData},
|
||||
init::initcall::INITCALL_CORE,
|
||||
ipc::shm::ShmId,
|
||||
libs::{
|
||||
rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
|
||||
spinlock::{SpinLock, SpinLockGuard},
|
||||
|
|
@ -672,7 +671,7 @@ pub enum PageType {
|
|||
/// 文件映射页,含文件映射相关信息
|
||||
File(FileMapInfo),
|
||||
/// 共享内存页,记录ShmId
|
||||
Shm(ShmId),
|
||||
Shm,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use crate::{
|
|||
arch::{mm::PageMapper, CurrentIrqArch, MMArch},
|
||||
exception::InterruptArch,
|
||||
filesystem::vfs::file::File,
|
||||
ipc::shm::{shm_manager_lock, ShmFlags},
|
||||
ipc::shm::{ShmFlags, ShmId},
|
||||
libs::{
|
||||
align::page_align_up,
|
||||
rwlock::RwLock,
|
||||
|
|
@ -36,7 +36,7 @@ use super::{
|
|||
allocator::page_frame::{
|
||||
deallocate_page_frames, PageFrameCount, PhysPageFrame, VirtPageFrame, VirtPageFrameIter,
|
||||
},
|
||||
page::{EntryFlags, Flusher, InactiveFlusher, PageFlushAll, PageType},
|
||||
page::{EntryFlags, Flusher, InactiveFlusher, PageFlushAll},
|
||||
syscall::{MadvFlags, MapFlags, MremapFlags, ProtFlags},
|
||||
MemoryManagementArch, PageTableKind, VirtAddr, VirtRegion, VmFlags,
|
||||
};
|
||||
|
|
@ -1202,10 +1202,11 @@ impl LockedVMA {
|
|||
if let Some((paddr, _flags)) = mapper.translate(guard.region().start()) {
|
||||
// 如果是共享页,执行释放操作
|
||||
let page = page_manager_guard.get(&paddr).unwrap();
|
||||
let page_guard = page.read_irqsave();
|
||||
if let PageType::Shm(shm_id) = page_guard.page_type() {
|
||||
let mut shm_manager_guard = shm_manager_lock();
|
||||
if let Some(kernel_shm) = shm_manager_guard.get_mut(shm_id) {
|
||||
let _page_guard = page.read_irqsave();
|
||||
if let Some(shm_id) = guard.shm_id {
|
||||
let ipcns = ProcessManager::current_ipcns();
|
||||
let mut shm_manager_guard = ipcns.shm.lock();
|
||||
if let Some(kernel_shm) = shm_manager_guard.get_mut(&shm_id) {
|
||||
// 更新最后一次断开连接时间
|
||||
kernel_shm.update_dtim();
|
||||
|
||||
|
|
@ -1215,7 +1216,7 @@ impl LockedVMA {
|
|||
// 释放shm_id
|
||||
if kernel_shm.map_count() == 0 && kernel_shm.mode().contains(ShmFlags::SHM_DEST)
|
||||
{
|
||||
shm_manager_guard.free_id(shm_id);
|
||||
shm_manager_guard.free_id(&shm_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1405,6 +1406,17 @@ impl VMASplitResult {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parameters for physmap operation
|
||||
#[derive(Debug)]
|
||||
pub struct PhysmapParams {
|
||||
pub phys: PhysPageFrame,
|
||||
pub destination: VirtPageFrame,
|
||||
pub count: PageFrameCount,
|
||||
pub vm_flags: VmFlags,
|
||||
pub flags: EntryFlags<MMArch>,
|
||||
pub shm_id: Option<ShmId>,
|
||||
}
|
||||
|
||||
/// @brief 虚拟内存区域
|
||||
#[derive(Debug)]
|
||||
pub struct VMA {
|
||||
|
|
@ -1425,6 +1437,8 @@ pub struct VMA {
|
|||
file_pgoff: Option<usize>,
|
||||
|
||||
provider: Provider,
|
||||
/// 关联的 SysV SHM 标识(当此 VMA 来自 shmat 时设置)
|
||||
shm_id: Option<ShmId>,
|
||||
}
|
||||
|
||||
impl core::hash::Hash for VMA {
|
||||
|
|
@ -1461,6 +1475,7 @@ impl VMA {
|
|||
provider: Provider::Allocated,
|
||||
vm_file: file,
|
||||
file_pgoff: pgoff,
|
||||
shm_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1496,6 +1511,11 @@ impl VMA {
|
|||
self.flags = MMArch::vm_get_page_prot(self.vm_flags);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set_shm_id(&mut self, shm: Option<ShmId>) {
|
||||
self.shm_id = shm;
|
||||
}
|
||||
|
||||
/// # 拷贝当前VMA的内容
|
||||
///
|
||||
/// ### 安全性
|
||||
|
|
@ -1512,6 +1532,7 @@ impl VMA {
|
|||
provider: Provider::Allocated,
|
||||
file_pgoff: self.file_pgoff,
|
||||
vm_file: self.vm_file.clone(),
|
||||
shm_id: self.shm_id,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1526,6 +1547,7 @@ impl VMA {
|
|||
provider: Provider::Allocated,
|
||||
file_pgoff: self.file_pgoff,
|
||||
vm_file: self.vm_file.clone(),
|
||||
shm_id: self.shm_id,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -1589,31 +1611,29 @@ impl VMA {
|
|||
|
||||
/// 把物理地址映射到虚拟地址
|
||||
///
|
||||
/// @param phys 要映射的物理地址
|
||||
/// @param destination 要映射到的虚拟地址
|
||||
/// @param count 要映射的页帧数量
|
||||
/// @param flags 页面标志位
|
||||
/// @param params 物理映射参数
|
||||
/// @param mapper 页表映射器
|
||||
/// @param flusher 页表项刷新器
|
||||
///
|
||||
/// @return 返回映射后的虚拟内存区域
|
||||
pub fn physmap(
|
||||
phys: PhysPageFrame,
|
||||
destination: VirtPageFrame,
|
||||
count: PageFrameCount,
|
||||
vm_flags: VmFlags,
|
||||
flags: EntryFlags<MMArch>,
|
||||
params: PhysmapParams,
|
||||
mapper: &mut PageMapper,
|
||||
mut flusher: impl Flusher<MMArch>,
|
||||
) -> Result<Arc<LockedVMA>, SystemError> {
|
||||
let mut cur_phy = phys;
|
||||
let mut cur_dest = destination;
|
||||
let mut cur_phy = params.phys;
|
||||
let mut cur_dest = params.destination;
|
||||
|
||||
for _ in 0..count.data() {
|
||||
for _ in 0..params.count.data() {
|
||||
// 将物理页帧映射到虚拟页帧
|
||||
let r =
|
||||
unsafe { mapper.map_phys(cur_dest.virt_address(), cur_phy.phys_address(), flags) }
|
||||
.expect("Failed to map phys, may be OOM error");
|
||||
let r = unsafe {
|
||||
mapper.map_phys(
|
||||
cur_dest.virt_address(),
|
||||
cur_phy.phys_address(),
|
||||
params.flags,
|
||||
)
|
||||
}
|
||||
.expect("Failed to map phys, may be OOM error");
|
||||
|
||||
// todo: 增加OOM处理
|
||||
|
||||
|
|
@ -1625,18 +1645,24 @@ impl VMA {
|
|||
}
|
||||
|
||||
let r: Arc<LockedVMA> = LockedVMA::new(VMA::new(
|
||||
VirtRegion::new(destination.virt_address(), count.data() * MMArch::PAGE_SIZE),
|
||||
vm_flags,
|
||||
flags,
|
||||
VirtRegion::new(
|
||||
params.destination.virt_address(),
|
||||
params.count.data() * MMArch::PAGE_SIZE,
|
||||
),
|
||||
params.vm_flags,
|
||||
params.flags,
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
));
|
||||
if let Some(id) = params.shm_id {
|
||||
r.lock_irqsave().set_shm_id(Some(id));
|
||||
}
|
||||
|
||||
// 将VMA加入到anon_vma中
|
||||
let mut page_manager_guard = page_manager_lock_irqsave();
|
||||
cur_phy = phys;
|
||||
for _ in 0..count.data() {
|
||||
cur_phy = params.phys;
|
||||
for _ in 0..params.count.data() {
|
||||
let paddr = cur_phy.phys_address();
|
||||
let page = page_manager_guard.get_unwrap(&paddr);
|
||||
page.write_irqsave().insert_vma(r.clone());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
use alloc::sync::{Arc, Weak};
|
||||
|
||||
use crate::ipc::shm::ShmManager;
|
||||
use crate::libs::spinlock::SpinLock;
|
||||
use crate::process::namespace::{
|
||||
nsproxy::NsCommon, user_namespace::UserNamespace, NamespaceOps, NamespaceType,
|
||||
};
|
||||
use crate::process::ProcessManager;
|
||||
|
||||
// 根 IPC 命名空间
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref INIT_IPC_NAMESPACE: Arc<IpcNamespace> = IpcNamespace::new_root();
|
||||
}
|
||||
|
||||
/// DragonOS 的 IPC 命名空间
|
||||
pub struct IpcNamespace {
|
||||
ns_common: NsCommon,
|
||||
self_ref: Weak<IpcNamespace>,
|
||||
/// 关联的 user namespace (权限判断使用)
|
||||
pub user_ns: Arc<UserNamespace>,
|
||||
|
||||
/// SysV SHM 管理器(阶段一:仅支持 per-ns shm)
|
||||
pub shm: SpinLock<ShmManager>,
|
||||
}
|
||||
|
||||
impl NamespaceOps for IpcNamespace {
|
||||
fn ns_common(&self) -> &NsCommon {
|
||||
&self.ns_common
|
||||
}
|
||||
}
|
||||
|
||||
impl IpcNamespace {
|
||||
fn new_root() -> Arc<Self> {
|
||||
Arc::new_cyclic(|weak_self| Self {
|
||||
ns_common: NsCommon::new(0, NamespaceType::Ipc),
|
||||
self_ref: weak_self.clone(),
|
||||
user_ns: crate::process::namespace::user_namespace::INIT_USER_NAMESPACE.clone(),
|
||||
shm: SpinLock::new(ShmManager::new()),
|
||||
})
|
||||
}
|
||||
|
||||
/// 复制/创建 IPC 命名空间
|
||||
pub fn copy_ipc_ns(
|
||||
&self,
|
||||
clone_flags: &crate::process::fork::CloneFlags,
|
||||
user_ns: Arc<UserNamespace>,
|
||||
) -> Arc<IpcNamespace> {
|
||||
use crate::process::fork::CloneFlags;
|
||||
if !clone_flags.contains(CloneFlags::CLONE_NEWIPC) {
|
||||
return self.self_ref.upgrade().unwrap();
|
||||
}
|
||||
// 创建新的 IPC 命名空间,SHM 空间独立
|
||||
Arc::new_cyclic(|weak_self| IpcNamespace {
|
||||
ns_common: NsCommon::new(self.ns_common.level + 1, NamespaceType::Ipc),
|
||||
self_ref: weak_self.clone(),
|
||||
user_ns,
|
||||
shm: SpinLock::new(ShmManager::new()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcessManager {
|
||||
pub fn current_ipcns() -> Arc<IpcNamespace> {
|
||||
if Self::initialized() {
|
||||
ProcessManager::current_pcb().nsproxy.read().ipc_ns.clone()
|
||||
} else {
|
||||
INIT_IPC_NAMESPACE.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
pub mod ipc_namespace;
|
||||
pub mod mnt;
|
||||
pub mod nsproxy;
|
||||
pub mod pid_namespace;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use crate::process::{
|
|||
};
|
||||
use core::{fmt::Debug, intrinsics::likely};
|
||||
|
||||
use super::ipc_namespace::{IpcNamespace, INIT_IPC_NAMESPACE};
|
||||
use super::{pid_namespace::PidNamespace, user_namespace::UserNamespace, NamespaceType};
|
||||
|
||||
/// A structure containing references to all per-process namespaces (filesystem/mount, UTS, network, etc.).
|
||||
|
|
@ -28,9 +29,10 @@ pub struct NsProxy {
|
|||
/// mount namespace(挂载命名空间)
|
||||
pub mnt_ns: Arc<MntNamespace>,
|
||||
pub uts_ns: Arc<UtsNamespace>,
|
||||
/// ipc namespace(SysV IPC、POSIX mqueue 等)
|
||||
pub ipc_ns: Arc<IpcNamespace>,
|
||||
// 其他namespace(为未来扩展预留)
|
||||
// pub net_ns: Option<Arc<NetNamespace>>,
|
||||
// pub ipc_ns: Option<Arc<IpcNamespace>>,
|
||||
// pub cgroup_ns: Option<Arc<CgroupNamespace>>,
|
||||
// pub time_ns: Option<Arc<TimeNamespace>>,
|
||||
}
|
||||
|
|
@ -47,10 +49,12 @@ impl NsProxy {
|
|||
let root_pid_ns = super::pid_namespace::INIT_PID_NAMESPACE.clone();
|
||||
let root_mnt_ns = root_mnt_namespace();
|
||||
let root_uts_ns = INIT_UTS_NAMESPACE.clone();
|
||||
let root_ipc_ns = INIT_IPC_NAMESPACE.clone();
|
||||
Arc::new(Self {
|
||||
pid_ns_for_children: root_pid_ns,
|
||||
mnt_ns: root_mnt_ns,
|
||||
uts_ns: root_uts_ns,
|
||||
ipc_ns: root_ipc_ns,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -69,6 +73,7 @@ impl NsProxy {
|
|||
pid_ns_for_children: self.pid_ns_for_children.clone(),
|
||||
mnt_ns: self.mnt_ns.clone(),
|
||||
uts_ns: self.uts_ns.clone(),
|
||||
ipc_ns: self.ipc_ns.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,10 +154,12 @@ pub(super) fn create_new_namespaces(
|
|||
let mnt_ns = nsproxy.mnt_ns.copy_mnt_ns(clone_flags, user_ns.clone())?;
|
||||
|
||||
let uts_ns = nsproxy.uts_ns.copy_uts_ns(clone_flags, user_ns.clone())?;
|
||||
let ipc_ns = nsproxy.ipc_ns.copy_ipc_ns(clone_flags, user_ns.clone());
|
||||
let result = NsProxy {
|
||||
pid_ns_for_children,
|
||||
mnt_ns,
|
||||
uts_ns,
|
||||
ipc_ns,
|
||||
};
|
||||
|
||||
let result = Arc::new(result);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ dependencies = [
|
|||
"futures-sink",
|
||||
"log",
|
||||
"pin-project 0.4.30",
|
||||
"tokio 0.2.25",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
]
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"futures-util",
|
||||
"smallvec",
|
||||
"tokio 0.2.25",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -133,11 +133,11 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"futures-util",
|
||||
"log",
|
||||
"mio 0.6.23",
|
||||
"mio",
|
||||
"mio-uds",
|
||||
"num_cpus",
|
||||
"slab",
|
||||
"socket2 0.3.19",
|
||||
"socket2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -161,7 +161,7 @@ dependencies = [
|
|||
"actix-server",
|
||||
"actix-service",
|
||||
"log",
|
||||
"socket2 0.3.19",
|
||||
"socket2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -245,7 +245,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"socket2 0.3.19",
|
||||
"socket2",
|
||||
"time",
|
||||
"tinyvec",
|
||||
"url",
|
||||
|
|
@ -262,21 +262,6 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
|
|
@ -327,21 +312,6 @@ dependencies = [
|
|||
"serde_urlencoded",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.75"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if 1.0.1",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base-x"
|
||||
version = "0.2.11"
|
||||
|
|
@ -552,7 +522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -690,15 +660,9 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
|||
dependencies = [
|
||||
"cfg-if 1.0.1",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.2.7"
|
||||
|
|
@ -713,7 +677,7 @@ dependencies = [
|
|||
"http",
|
||||
"indexmap",
|
||||
"slab",
|
||||
"tokio 0.2.25",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"tracing-futures",
|
||||
|
|
@ -891,17 +855,6 @@ dependencies = [
|
|||
"cfg-if 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"cfg-if 1.0.1",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
|
|
@ -917,7 +870,7 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7"
|
||||
dependencies = [
|
||||
"socket2 0.3.19",
|
||||
"socket2",
|
||||
"widestring",
|
||||
"winapi 0.3.9",
|
||||
"winreg",
|
||||
|
|
@ -1028,15 +981,6 @@ version = "0.3.17"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.6.23"
|
||||
|
|
@ -1056,17 +1000,6 @@ dependencies = [
|
|||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-uds"
|
||||
version = "0.6.8"
|
||||
|
|
@ -1075,7 +1008,7 @@ checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0"
|
|||
dependencies = [
|
||||
"iovec",
|
||||
"libc",
|
||||
"mio 0.6.23",
|
||||
"mio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1123,15 +1056,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
|
|
@ -1285,7 +1209,6 @@ dependencies = [
|
|||
"nix",
|
||||
"sc",
|
||||
"syscalls",
|
||||
"tokio 1.46.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1388,12 +1311,6 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
|
|
@ -1601,16 +1518,6 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
|
|
@ -1828,7 +1735,7 @@ dependencies = [
|
|||
"lazy_static",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio 0.6.23",
|
||||
"mio",
|
||||
"mio-uds",
|
||||
"pin-project-lite 0.1.12",
|
||||
"signal-hook-registry",
|
||||
|
|
@ -1836,35 +1743,6 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.46.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"io-uring",
|
||||
"libc",
|
||||
"mio 1.0.4",
|
||||
"pin-project-lite 0.2.16",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"socket2 0.5.10",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.3.1"
|
||||
|
|
@ -1876,7 +1754,7 @@ dependencies = [
|
|||
"futures-sink",
|
||||
"log",
|
||||
"pin-project-lite 0.1.12",
|
||||
"tokio 0.2.25",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1925,7 +1803,7 @@ dependencies = [
|
|||
"rand",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tokio 0.2.25",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
|
@ -1944,7 +1822,7 @@ dependencies = [
|
|||
"resolv-conf",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"tokio 0.2.25",
|
||||
"tokio",
|
||||
"trust-dns-proto",
|
||||
]
|
||||
|
||||
|
|
@ -2010,12 +1888,6 @@ version = "0.9.0+wasi-snapshot-preview1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
|
|
@ -2134,47 +2006,13 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets 0.53.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm 0.52.6",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2183,106 +2021,58 @@ version = "0.53.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.53.0",
|
||||
"windows_aarch64_msvc 0.53.0",
|
||||
"windows_i686_gnu 0.53.0",
|
||||
"windows_i686_gnullvm 0.53.0",
|
||||
"windows_i686_msvc 0.53.0",
|
||||
"windows_x86_64_gnu 0.53.0",
|
||||
"windows_x86_64_gnullvm 0.53.0",
|
||||
"windows_x86_64_msvc 0.53.0",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.53.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.53.0"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,206 @@
|
|||
extern crate nix;
|
||||
|
||||
use nix::errno::Errno;
|
||||
use nix::sched::{self, CloneFlags};
|
||||
use nix::sys::wait::{waitpid, WaitStatus};
|
||||
use nix::unistd::{fork, getpid, pipe, read, write, ForkResult};
|
||||
|
||||
const IPC_CREAT: i32 = 0o1000;
|
||||
|
||||
fn shmget(key: i32, size: usize, flags: i32) -> Result<i32, i32> {
|
||||
let r = unsafe { libc::shmget(key as libc::key_t, size, flags as libc::c_int) };
|
||||
if r < 0 {
|
||||
return Err(Errno::last_raw());
|
||||
}
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn shmctl(id: i32, cmd: i32) -> Result<i32, i32> {
|
||||
let r = unsafe { libc::shmctl(id, cmd, std::ptr::null_mut()) };
|
||||
if r < 0 {
|
||||
return Err(Errno::last_raw());
|
||||
}
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn shmat(id: i32) -> Result<*mut libc::c_void, i32> {
|
||||
let r = unsafe { libc::shmat(id, std::ptr::null(), 0) };
|
||||
if (r as isize) == -1 {
|
||||
return Err(Errno::last_raw());
|
||||
}
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn shmdt(addr: *mut libc::c_void) -> Result<i32, i32> {
|
||||
let r = unsafe { libc::shmdt(addr) };
|
||||
if r < 0 {
|
||||
return Err(Errno::last_raw());
|
||||
}
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
struct Suite {
|
||||
passed: usize,
|
||||
failed: usize,
|
||||
}
|
||||
|
||||
impl Suite {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
passed: 0,
|
||||
failed: 0,
|
||||
}
|
||||
}
|
||||
fn ok(&mut self, name: &str) {
|
||||
self.passed += 1;
|
||||
println!("[PASS] {}", name);
|
||||
}
|
||||
fn fail(&mut self, name: &str, msg: &str) {
|
||||
self.failed += 1;
|
||||
println!("[FAIL] {}: {}", name, msg);
|
||||
}
|
||||
fn finish(&self) -> i32 {
|
||||
println!("Summary: passed={}, failed={}", self.passed, self.failed);
|
||||
if self.failed == 0 {
|
||||
0
|
||||
} else {
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let key_parent: i32 = 0x12345; // 仅父命名空间使用
|
||||
let key_child: i32 = 0x23456; // 仅子命名空间使用
|
||||
let size: usize = 4096;
|
||||
let mut suite = Suite::new();
|
||||
|
||||
println!("[parent:{}] create shm in parent ns", getpid());
|
||||
let id_parent = shmget(key_parent, size, IPC_CREAT | 0o600).expect("parent shmget failed");
|
||||
|
||||
let (pr, pw) = pipe().expect("pipe");
|
||||
unsafe {
|
||||
match fork() {
|
||||
Ok(ForkResult::Parent { child }) => {
|
||||
// case2: ensure child ns's shm is not visible to parent while child alive
|
||||
// wait child signals via pipe
|
||||
let mut buf = [0u8; 1];
|
||||
use std::os::fd::AsRawFd;
|
||||
let _ = read(pr.as_raw_fd(), &mut buf).expect("read pipe");
|
||||
match shmget(key_child, size, 0o600) {
|
||||
Ok(_) => suite.fail(
|
||||
"parent cannot see child's shm by key_child",
|
||||
"unexpected shm visible",
|
||||
),
|
||||
Err(e) => {
|
||||
if e == libc::ENOENT {
|
||||
suite.ok("parent cannot see child's shm by key_child");
|
||||
} else {
|
||||
suite.fail(
|
||||
"parent cannot see child's shm by key_child",
|
||||
&format!("errno={}", e),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match waitpid(child, None) {
|
||||
Ok(WaitStatus::Exited(_, status)) => {
|
||||
if status == 0 {
|
||||
suite.ok("child exited 0");
|
||||
} else {
|
||||
suite.fail("child exited 0", &format!("status={}", status));
|
||||
}
|
||||
}
|
||||
Ok(other) => suite.fail("child wait status", &format!("{:?}", other)),
|
||||
Err(e) => suite.fail("waitpid", &format!("{:?}", e)),
|
||||
}
|
||||
|
||||
// parent can still attach/detach its own segment and then remove
|
||||
match shmat(id_parent) {
|
||||
Ok(addr) => {
|
||||
let _ = shmdt(addr)
|
||||
.map_err(|e| suite.fail("parent shmdt", &format!("errno={}", e)));
|
||||
let _ = shmctl(id_parent, libc::IPC_RMID)
|
||||
.map_err(|e| suite.fail("parent IPC_RMID", &format!("errno={}", e)));
|
||||
suite.ok("parent attach/detach and remove");
|
||||
}
|
||||
Err(e) => suite.fail("parent shmat", &format!("errno={}", e)),
|
||||
}
|
||||
|
||||
std::process::exit(suite.finish());
|
||||
}
|
||||
Ok(ForkResult::Child) => {
|
||||
println!("[child:{}] unshare CLONE_NEWIPC", getpid());
|
||||
if let Err(e) = sched::unshare(CloneFlags::CLONE_NEWIPC) {
|
||||
eprintln!("unshare failed: {:?}", e);
|
||||
std::process::exit(2);
|
||||
}
|
||||
|
||||
// case1: child can't see parent's shm by key
|
||||
match shmget(key_parent, size, 0o600) {
|
||||
Ok(_) => {
|
||||
println!("[FAIL] child cannot see parent's shm by key");
|
||||
std::process::exit(3);
|
||||
}
|
||||
Err(e) => {
|
||||
if e == libc::ENOENT {
|
||||
println!("[PASS] child cannot see parent's shm by key");
|
||||
} else {
|
||||
println!("[FAIL] child cannot see parent's shm by key: errno={}", e);
|
||||
std::process::exit(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create its own shm with a different key in new ipc ns
|
||||
let id_child = match shmget(key_child, size, IPC_CREAT | 0o600) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
eprintln!("child shmget(key_child) failed errno={}", e);
|
||||
std::process::exit(4);
|
||||
}
|
||||
};
|
||||
// also create same key as parent in child ns to ensure no conflict across ns
|
||||
let _id_child_same_key = match shmget(key_parent, size, IPC_CREAT | 0o600) {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
eprintln!("child shmget(key_parent in child ns) failed errno={}", e);
|
||||
std::process::exit(4);
|
||||
}
|
||||
};
|
||||
// signal parent
|
||||
let _ = write(pw, &[1u8]).expect("write pipe");
|
||||
|
||||
// shmat + write, then mark IPC_RMID and ensure we can create new shm with the same key
|
||||
let addr = match shmat(id_child) {
|
||||
Ok(p) => p,
|
||||
Err(e) => {
|
||||
eprintln!("child shmat failed errno={}", e);
|
||||
std::process::exit(5);
|
||||
}
|
||||
};
|
||||
unsafe {
|
||||
*(addr as *mut u8) = 0xAB;
|
||||
}
|
||||
// mark to be removed
|
||||
let _ = shmctl(id_child, libc::IPC_RMID).expect("IPC_RMID failed");
|
||||
// now shmget with same key and EXCL should succeed with a new id
|
||||
let id2 = shmget(key_child, size, IPC_CREAT | 0o600 | libc::IPC_EXCL)
|
||||
.expect("child shmget recreate failed");
|
||||
if id2 == id_child {
|
||||
eprintln!("id2 should differ from id_child");
|
||||
std::process::exit(6);
|
||||
}
|
||||
// detach old mapping
|
||||
let _ = shmdt(addr).expect("child shmdt failed");
|
||||
// cleanup new one
|
||||
let addr2 = shmat(id2).expect("child shmat id2 failed");
|
||||
let _ = shmdt(addr2).expect("child shmdt id2 failed");
|
||||
let _ = shmctl(id2, libc::IPC_RMID).expect("child IPC_RMID id2 failed");
|
||||
std::process::exit(0);
|
||||
}
|
||||
Err(err) => panic!("fork failed: {:?}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue