在阅读了 Linux 命名空间之后,我的印象是,在许多其他特性中,它们是 chroot 的替代品。例如,在这篇文章中:
[命名空间] 的其他用途包括 [...] chroot() 风格的进程隔离到单个目录层次结构的一部分。
但是,当我克隆挂载命名空间时,例如使用以下命令,我仍然可以看到整个原始根树。
unshare --mount -- /bin/bash
我知道我现在能够在不与原始命名空间共享的新命名空间中执行额外的挂载,因此这提供了隔离,但它仍然是同一个根,例如/etc
对于两个命名空间来说仍然是相同的。我还需要chroot
更改根目录还是有替代方法?
我原以为这个问题会提供答案,但答案仅使用chroot
, 。
编辑#1
有一条现已删除的评论提到pivot_root
. 由于这实际上是 的一部分linux/fs/namespace.c
,因此它实际上是命名空间实现的一部分。这表明仅使用unshare
and更改根目录mount
是不可能的,但命名空间提供了一个自己的更聪明的chroot
. chroot
即使在阅读了源代码之后(例如在安全性或更好的隔离方面),我仍然不明白这种方法的主要思想,这使得它与.
编辑#2
这不是这个问题的重复。从答案中执行所有命令后,我有单独的 /tmp/tmp.vyM9IwnKuY (或类似的),但根目录仍然相同!
chroot
在设置/proc
. 您可以chroot
在挂载命名空间中使用它作为一个不错且简单的 hack。我认为理解有好处
pivot_root
,但它有一点学习曲线。该文档并没有完全解释所有内容......尽管man 8 pivot_root
(用于 shell 命令)中有一个用法示例。man 2 pivot_root
(对于系统调用)如果它做同样的事情可能会更清楚,并包含一个示例 C 程序。如何使用 pivot_root
进入挂载命名空间后,您还需要
mount --make-rslave /
或等效。否则,您的所有挂载更改都会传播到原始命名空间中的挂载,包括pivot_root
. 你不想要那个:)。如果您使用了该
unshare --mount
命令,请注意它已记录为mount --make-rprivate
默认应用。AFAICS 这是一个糟糕的默认值,您不希望在生产代码中使用它。例如,此时,它将停止eject
在主机命名空间中安装的 DVD 或 USB 上工作。DVD 或 USB 将保持挂载在私有挂载树中,并且内核不会让您弹出 DVD。完成后,您可以挂载例如
/proc
您将使用的目录。和你一样chroot
。不像你使用
chroot
,pivot_root
要求你的新根文件系统是一个挂载点。如果它还不是一个,您可以通过简单地应用绑定安装来满足这一点:mount --rbind new_root new_root
。使用
pivot_root
-,然后使用带有/选项umount
的旧根文件系统。(您不需要,这可能需要更长的时间。)。-l
MNT_DETACH
umount -R
从技术上讲,使用
pivot_root
一般也需要涉及使用chroot
;这不是“非此即彼”。根据
man 2 pivot_root
,它仅被定义为交换挂载命名空间的根。它没有被定义为更改进程根指向的物理目录。或当前工作目录 (/proc/self/cwd
)。碰巧它确实这样做了,但这是处理内核线程的一种技巧。手册页说将来可能会改变。通常你想要这个序列:
在这个
chroot
序列中的位置是另一个微妙的细节。尽管重点pivot_root
是重新排列挂载命名空间,但内核代码似乎通过查看每个进程的根目录来找到要移动的根文件系统,这是chroot
设置的。为什么要使用 pivot_root
pivot_root
原则上,用于安全和隔离是有意义的。我喜欢思考基于能力的安全理论。您传入所需特定资源的列表,并且该进程无法访问其他资源。在这种情况下,我们讨论的是传入挂载命名空间的文件系统。这个想法通常适用于 Linux “命名空间”功能,尽管我可能没有很好地表达它。chroot
只设置进程根,但进程仍然引用完整的挂载命名空间。如果一个进程保留了执行权限chroot
,那么它可以遍历备份文件系统命名空间。如 中man 2 chroot
所述,“超级用户可以通过...逃离 'chroot jail'”。撤消的另一种发人深省的方法
chroot
是nsenter --mount=/proc/self/ns/mnt
. 这也许是该原则的一个更有力的论据。nsenter
/setns()
必须从挂载命名空间的根目录重新加载进程根目录……尽管当两者引用不同的物理目录时这会起作用,这可能被认为是内核错误。(技术说明:在根目录中可能有多个文件系统相互叠加安装;setns()
使用顶部,最近安装的一个)。这说明了将挂载命名空间与“PID 命名空间”结合起来的一个优势。位于 PID 命名空间内会阻止您进入无限制进程的挂载命名空间。它还可以防止您进入不受限制的进程的根目录 (
/proc/$PID/root
)。当然,PID 命名空间也可以防止你杀死它之外的任何进程:-)。