一篇文章搞懂Linux 文件系统隔离:Mount Namespace 与三个挂载视图 容器安全3/7
容器安全文章3核心概念Mount Namespace挂载命名空间与文件系统视图隔离Linux 文件系统隔离Mount Namespace 与三个挂载视图为什么需要隔离一台服务器跑着网站、数据库、缓存三个服务。如果共享同一个文件系统一个服务被入侵就能读到其他服务的配置文件、数据库密码。文件系统隔离让每个服务只能看到自己的文件即使运行在同一台机器上。下面是实验证明Linux 系统debian实验能更好了解和证明一、核心概念1.1 目录是门文件系统是房间目录本身不存储数据它只是一扇门。门后面是什么房间取决于你在这扇门上挂载了什么。文件系统是独立的房间——有自己的文件、目录、权限。但不挂到门上你就进不去、看不到、用不了。# 造一扇门创建一个空目录mkdir/mnt/door# 门后面是空的ls/mnt/door# 没有任何输出# 在门后挂一个房间# mount 挂载命令# -t tmpfs 指定房间类型为 tmpfs内存文件系统存在内存里重启消失# 第一个 tmpfs 房间类型# 第二个 tmpfs 房间名字可以随便取# /mnt/door 门的位置mount-ttmpfs tmpfs /mnt/door# 现在门后就是一个独立房间了echo我在房间里/mnt/door/msg.txtcat/mnt/door/msg.txt# 我在房间里# 拆下房间门又变空了# umount 卸载把房间从门上拆下来umount/mnt/doorcat/mnt/door/msg.txt# 报错没有那个文件或目录文件系统必须挂载到目录上才能使用。目录是唯一的入口。1.2 什么是 Mount Namespace挂载视图Linux 内核有一个机制叫Mount Namespace挂载命名空间本文简称挂载视图。它的作用让每个进程拥有自己的房间清单挂载表进程之间互相独立。同一个门/mnt/data进程 A 的清单上写着通向房间 X进程 B 的清单上可能写着通向房间 Y或者什么都没写。不是房间变了是进程手里的清单不同。1.3 什么是复制一份创建新挂载视图时内核会复制一份当前的房间清单给新视图。之后两边的清单各自更新互不影响。就像你复印一份文件清单你在这份复印件上新增一条记录原件不会自动更新⚠️重要挂载视图隔离的是房间清单挂载表不是房间里的文件内容。如果两个视图都挂载了同一个房间比如都指向同一个硬盘分区修改文件会互相看到。只有新挂载的房间才是隔离的。二、第一视图宿主机的清单这是你开机后的正常 Linux。所有进程共享同一份房间清单。你在第一视图 终端ls/bin boot dev etc home lib...特点所有挂载操作全系统可见其他视图的新挂载你看不到这是根视图其他视图都从这里复制出去三、第二视图独立的清单3.1 怎么创建sudo以 root 权限执行 unshare脱离共享资源创建自己的副本--mount只脱离房间清单这一项--propagationprivate确保新视图的挂载操作不影响宿主机 systemd 默认把根文件系统的挂载传播类型设为 shared不加这句可能传播回宿主机 /bin/bash启动一个新的命令行 终端sudounshare--mount--propagationprivate /bin/bash执行后你的 shell 进入了一个新的挂载视图。这一刻内核复制了一份房间清单给你。从此你的清单和宿主机的清单各自独立。3.2 验证视图切换查看当前进程的 Mount Namespace ID 终端 readlink /proc/$$/ns/mountmnt:[4026532234]数字与之前不同说明进了新视图3.3 即时验证# 你在第二视图mkdir/mnt/room2mount-ttmpfs tmpfs /mnt/room2echo第二视图的文件/mnt/room2/secret.txtcat/mnt/room2/secret.txt# 第二视图的文件# 退出第二视图回到第一视图exit# 第一视图看不到ls/mnt/room2# 没有任何输出cat/mnt/room2/secret.txt# 报错没有那个文件或目录第二视图的新挂载只写在自己的清单上第一视图的清单没有这条记录。⚠️ 常见错误错误以为 exit 后文件还在exit只是退出视图但挂载的房间还在内存里。如果同一目录在宿主机会被用到可能冲突。解决退出前卸载在第二视图里执行 终端umount/mnt/room2exit⚠️ 安全警告第二视图里/仍然是宿主机的根文件系统只是挂载表不同。不要执行rm -rf /等危险命令会删除宿主机文件。注意清单隔离 ≠ 文件隔离如果第二视图修改了已经存在的文件如/etc/hosts第一视图能看到变化因为底层文件数据是同一个。只有新挂载的房间才是隔离的。验证# 在第二视图里echotest/etc/hosts# 退出到第一视图exitcat/etc/hosts# 能看到 test 被追加进去了四、第三视图在独立清单里再复制一份4.1 怎么创建在第二视图内部执行在第二视图的 shell 里继续输入# 确保你在第二视图里提示符可能变了或者你记得执行过 unsharesudounshare--mount--propagationprivate /bin/bash# 在第二视图里再复制一份清单创建第三视图mkdir/mnt/room2/room3mount-ttmpfs tmpfs /mnt/room2/room3echo第三视图的文件/mnt/room2/room3/deep.txt“在内部执行” 基于第二视图的清单再复制一份作为第三视图的起点。4.2 即时验证# 第三视图能看到所有内容cat/mnt/room2/secret.txt# 第二视图的文件复制时带过来的cat/mnt/room2/room3/deep.txt# 第三视图的文件自己的新挂载# 退出到第二视图exitcat/mnt/room2/secret.txt# ✅ 能看到cat/mnt/room2/room3/deep.txt# ❌ 报错第二视图看不到第三视图的新挂载# 退出到第一视图exitcat/mnt/room2/secret.txt# ❌ 报错第一视图看不到第二视图的新挂载4.3 三个视图对比查看内容第一视图第二视图第三视图/mnt/room2/secret.txt❌ 看不到✅ 能看到✅ 能看到复制时带过来的/mnt/room2/room3/deep.txt❌ 看不到❌ 看不到✅ 能看到修改/etc/hosts已存在文件✅ 能看到变化✅ 能看到变化✅ 能看到变化底层共享规律每多一个视图就多一层清单隔离。外层看不到内层的新挂载除非显式进入内层。⚠️ 常见错误错误在第二视图外创建第三视图如果你在第一视图里执行sudo unshare --mount创建的是另一个第二视图不是第三视图。第三视图必须在第二视图内部创建。五、从视图到容器换房间5.1 问题前面的视图只隔离了清单没换房间第二视图、第三视图的清单虽然独立了但根目录/里的内容还是和第一视图一样。/bin/bash、/etc/passwd都是宿主机的文件。容器需要不仅清单独立根目录/也要换成新房间。5.2 容器怎么做以文件系统隔离为例dockerrun-itubuntu /bin/bash内部三步创建 Mount Namespace第二视图清单隔离挂载容器镜像文件系统新房间不是第三视图用pivot_root把根目录/指向新房间换房间操作pivot_root把进程的根目录切换到指定目录。这是容器运行时的内部机制实验 1-4 不手动操作只理解原理。容器里ls/# bin boot dev etc home lib ...这是 Ubuntu 镜像的内容不是宿主机的cat/etc/os-release# PRETTY_NAMEUbuntu 22.04 LTS宿主机上终端cat/etc/os-release显示宿主机自己的系统如 CentOS5.3 容器的文件系统隔离容器的文件系统隔离 第二视图清单隔离 新房间 换根容器比纯 Namespace 多了一层不仅换清单视图隔离还换房间根目录替换。注意容器没有创建第三视图它复用了第二视图的 Mount Namespace在里面直接挂载新房间并换根。完整的容器还需要 PID Namespace进程隔离、Network Namespace网络隔离、User Namespace用户权限隔离等。这里只讨论文件系统隔离。5.4 安全 implications文件系统隔离机制攻击场景文件系统隔离机制标准容器容器内读取宿主机/etc/shadow✅ 换根后看不到容器内修改宿主机文件✅ 清单隔离保护注意通过 volume 显式挂载宿主机目录容器可以访问。这是配置行为不是隔离机制的绕过。实验 1-4 的理解适用于标准容器。特权容器--privileged或内核漏洞逃逸需要额外防护不在本文范围。六、核心结论第一视图宿主机 │ ├── 房间清单/bin, /etc, /home, /mnt...所有系统挂载 │ ▼ unshare --mount复制清单 第二视图容器边界 │ ├── 复制了第一视图的清单作为起点 ├── 之后独立添加新房间 ├── 第一视图看不到第二视图的新房间 │ ▼ 内部再 unshare mount再复制清单 第三视图嵌套隔离 │ ├── 在第二视图内部再创建的 Mount Namespace ├── 第二视图看不到第三视图的新房间 ├── 底层还是同一个内核 │ └── 宿主机不进入第二视图永远看不到这里 容器第二视图的应用 │ ├── 用第二视图的 Mount Namespace 做边界 ├── 在内部挂载新房间容器镜像 ├── 用 pivot_root 把根目录指向新房间 │ └── 不是第三视图是第二视图 换房间同一内核不同房间清单。跨视图不可见必须显式进入。容器多一步不仅换清单还换房间。七、完整实验带清理# 步骤1创建第二视图记录 PID sudounshare--mount--propagationprivate /bin/bashecho$$# 记下这个 PID如 1234readlink /proc/$$/ns/mount# mnt:[...]记下这个数字# 步骤2第二视图挂载 mkdir/mnt/room2mount-ttmpfs tmpfs /mnt/room2echo第二视图/mnt/room2/a.txt# 步骤3在第二视图里创建第三视图 sudounshare--mount--propagationprivate /bin/bash readlink /proc/$$/ns/mount# mnt:[...]数字与步骤1不同# 步骤4第三视图挂载嵌套在room2内部 mkdir/mnt/room2/room3mount-ttmpfs tmpfs /mnt/room2/room3echo第三视图/mnt/room2/room3/b.txt# 步骤5第三视图验证能看到所有 cat/mnt/room2/a.txt# 第二视图的文件cat/mnt/room2/room3/b.txt# 第三视图的文件# 步骤5.5在第三视图内先卸载内层必须在exit之前umount/mnt/room2/room3# 步骤6回退到第二视图 exitcat/mnt/room2/a.txt# ✅ 能看到cat/mnt/room2/room3/b.txt# ❌ 报错目录存在但为空因为room3已卸载# 步骤6.5用 nsenter 进入第二视图验证 # 需要另开终端窗口执行保持原终端不退出# 1. 保持原终端窗口不关闭第二视图的bash还在运行# 2. 新开一个终端窗口或新标签页# 3. 在新终端里执行以下命令# 4. 验证完成后在新终端里输入 exit 退出# 5. 回到原终端继续步骤7sudonsenter-t1234-m/bin/bashcat/mnt/room2/a.txt# ✅ 能看到cat/mnt/room2/room3/b.txt# ❌ 报错确认第二视图看不到第三视图exit# 回到原终端# 步骤7在第二视图内卸载外层 umount/mnt/room2# 在第二视图内卸载exit# 回退到第一视图# 步骤8第一视图验证看不到第二视图 cat/mnt/room2/a.txt# ❌ 报错# 步骤9确认回到第一视图 readlink /proc/$$/ns/mount# 与步骤1的数字对比确认一致八、清理检查实验后必做# 检查是否还有残留挂载mount|grep/mnt/room# 应该没有任何输出# 检查 room2 目录是否为空umount 后ls/mnt/room2# 没有任何输出目录存在但为空# 检查 room3 目录是否消失随 room2 的 tmpfs 一起释放ls/mnt/room2/room3# 报错没有那个文件或目录# 如果有残留手动卸载sudoumount/mnt/room2/room3sudoumount/mnt/room2# 删除空目录sudormdir/mnt/room2/room3sudormdir/mnt/room2附录 A故障排查现象原因解决umount: not mounted在当前视图里没有这条挂载记录确认你在正确的视图里或检查 mountnsenter: cannot open /proc/1234/ns/mountPID 对应的进程已退出重新执行步骤 1-2确保第二视图的 bash 没退出ls /mnt/room2显示文件可能没执行 umount或 mount 传播到宿主机检查 mount修改/etc/hosts后宿主机也变了这是正常的清单隔离 ≠ 文件隔离理解已存在文件是共享的附录 B后续学习实验 1-4 理解了 Mount Namespace文件系统视图隔离。后续内容User Namespace用户权限隔离容器内的 root 映射到宿主机普通用户附录 C延伸阅读man 2 unshare创建新 Namespace 的系统调用man 1 nsenter进入指定 Namespace 的命令man 2 pivot_root切换根目录的系统调用Linux 内核源码fs/namespace.cMount Namespace 实现

相关新闻

OpenAI开发者内容需求分析:从基础入门到高级应用全攻略

OpenAI开发者内容需求分析:从基础入门到高级应用全攻略

在技术社区中,开发者对各类技术内容的需求日益多样化,特别是像 OpenAI 这样的前沿技术平台,其相关教程、实战案例和最佳实践备受关注。本文将从社区反馈出发,系统梳理开发者对 OpenAI 技术内容的偏好类型,涵盖从基础入…

2026/10/20 4:51:41 阅读更多 →
自制动作游戏剧本编辑器:可视化编排与实时预览实践

自制动作游戏剧本编辑器:可视化编排与实时预览实践

这次我们来看一个自制的动作游戏剧本编辑器项目。这个工具的核心目标是让游戏开发者能够更高效地编写和管理动作游戏的剧情脚本、角色动作序列和关卡事件。对于独立开发者或小团队来说,这类工具能显著提升内容生产效率和游戏原型迭代速度。 从项目演示来看&#xf…

2026/10/20 12:37:21 阅读更多 →
告别抢票焦虑:95%成功率的Python大麦自动抢票神器全攻略

告别抢票焦虑:95%成功率的Python大麦自动抢票神器全攻略

告别抢票焦虑:95%成功率的Python大麦自动抢票神器全攻略 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为热门演唱会门票秒光而烦恼…

2026/10/17 14:35:43 阅读更多 →

最新新闻

Python+MySQL学生管理系统:可视化界面落地与避坑指南

Python+MySQL学生管理系统:可视化界面落地与避坑指南

简介:这是一套面向Python与数据库初学者的学生管理系统实战项目,采用Python编写客户端逻辑、MySQL负责数据存储,适合正在学习桌面应用开发或需要完成课程设计的学生参考。压缩包共2个文件,包含1个py主程序与1个sql数据库脚本&…

2026/10/20 17:19:49 阅读更多 →
MySQL反斜杠转义全解析:从字符串插入到LIKE查询的避坑指南

MySQL反斜杠转义全解析:从字符串插入到LIKE查询的避坑指南

先交代一个真实翻车现场。有天业务方发来一张截图,某张配置表里的 Windows 路径字段,原本应该是C:\Users\某应用目录\data\config.ini,结果库里存成了C:Users某应用目录dataconfig.ini,所有反斜杠集体失踪。我一开始以为是应用层写…

2026/10/20 17:19:49 阅读更多 →
电商评论情感分析实战:从数据清洗到BERT蒸馏部署全记录

电商评论情感分析实战:从数据清洗到BERT蒸馏部署全记录

这个项目标题一看就是从实战里踩出来的,数据坑、部署、硬核笔记,说明作者真刀真枪跑过完整链路,不是拿公开数据集跑个demo就完事。文本分类和情感分析在NLP里属于入门必练但做好极难的方向,难就难在数据永远是脏的、标签永远是偏的…

2026/10/20 17:19:49 阅读更多 →
TensorFlow工业级AI工程实践:从计算图到TFX流水线

TensorFlow工业级AI工程实践:从计算图到TFX流水线

1. 这不是“学个框架”那么简单:TensorFlow到底在解决什么问题?很多人第一次听说TensorFlow,是在某次技术分享会上听到“谷歌开源的深度学习框架”,或者在招聘JD里看到“熟悉TensorFlow者优先”。但如果你真去翻它的GitHub仓库、读…

2026/10/20 17:19:49 阅读更多 →
双线性插值原理与C语言实现:图像缩放算法详解

双线性插值原理与C语言实现:图像缩放算法详解

简介:这份资源围绕双线性插值方法及实现展开,面向图像处理、计算机图形学与数值计算方向的学习者,尤其适合希望用C语言理解插值数学原理并动手实现的开发者。包内共31个文件,以h头文件、cpp源文件、obj目标文件为主,辅…

2026/10/20 17:19:49 阅读更多 →
Prescan+Simulink+CarSim联仿:多工况自动驾驶避障模型搭建与标定实战

Prescan+Simulink+CarSim联仿:多工况自动驾驶避障模型搭建与标定实战

做自动驾驶避障仿真的人,迟早会跟三个名字绑在一起:Prescan、Simulink、CarSim。标题里那套“不同工况避障模型”,说白了就是让一辆装有虚拟传感器的车,在模拟道路环境里遇到静止车、前车急减速、旁边车道突然切进来、行人横穿这些…

2026/10/20 17:18:48 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →