unshare隔离mount namespace后父子进程均可访问挂载文件问题咨询
你遇到的双进程都能读取目标文件的问题,来自两个核心的机制认知偏差和代码逻辑错误:
1. 挂载传播机制默认会跨命名空间同步挂载事件
Linux 2.6.15 版本后引入挂载传播机制,目前绝大多数主流发行版默认把根目录/的挂载属性设置为MS_SHARED(共享挂载):
- 调用
unshare(CLONE_NEWNS)创建新挂载命名空间时,新namespace会完整拷贝原namespace的挂载点条目,且这些挂载点默认和原namespace的对应挂载点属于同一个peer对等组。 - 只要挂载点是共享类型,新namespace内执行的mount/umount操作会自动同步到同组的所有挂载点,也就是原namespace里也能看到新挂载的文件系统,自然可以读取挂载点下写入的文件。
2. unshare调用位置错误,未实现父子进程的命名空间隔离
从你的代码顺序看,unshare(CLONE_NEWNS)写在fork调用之前,由父进程触发调用:
- unshare执行后,进入新挂载命名空间的是父进程本身
- fork生成的子进程会直接继承父进程的挂载命名空间,也就是说父子进程从一开始就处在同一个隔离后的namespace中,完全没有实现你预期的「子进程挂载对父进程不可见」的隔离效果。
修正方法
要得到你预期的运行结果,需要做两处核心修改,再加一处笔误修正:
- 调整unshare调用位置:把
unshare(CLONE_NEWNS)移动到子进程分支(pid == 0判断块)的最开头,保证只有子进程进入独立的新挂载命名空间,父进程留在原命名空间。 - 显式设置私有挂载属性:子进程调用unshare后、执行mount操作前,先递归把当前namespace下所有挂载点的传播属性设为私有,阻断挂载事件跨namespace传播,参考代码:
// 递归设置所有挂载点为私有,不向对等组传播挂载事件 mount("none", "/", NULL, MS_REC | MS_PRIVATE, NULL);
- 修正笔误:你代码里父进程分支的两个判断分支都打印了
parent proc failed to read file,需要把打开成功的分支打印内容改成parent proc ok to read file才能得到正确的日志输出。
内容的提问来源于stack exchange,提问作者YAKOVM
相关产品推荐
相关产品推荐

