每个进程私有文件系统挂载点

每个进程私有文件系统挂载点

我正在检查unshare命令,根据它的手册页,

   unshare - run program with some namespaces unshared from parent

我还看到有一种命名空间被列为,

 mount namespace
              mounting and unmounting filesystems will not affect rest of the system.

这样做的目的到底是什么挂载命名空间?我试图借助一些例子来理解这个概念。

答案1

运行为unshare -m调用进程提供了其挂载命名空间的私有副本,并且还取消共享文件系统属性,以便它不再与任何其他进程共享其根目录、当前目录或 umask 属性。

那么上面这段话到底说了什么?让我们尝试用一个简单的例子来理解。

1号航站楼:

我在第一个终端中执行以下命令。

#Creating a new process
unshare -m /bin/bash
#creating a new mount point
secret_dir=`mktemp -d --tmpdir=/tmp`
#creating a new mount point for the above created directory. 
mount -n -o size=1m -t tmpfs tmpfs $secret_dir
#checking the available mount points. 
grep /tmp /proc/mounts 

最后一个命令给我的输出为,

tmpfs /tmp/tmp.7KtrAsd9lx tmpfs rw,relatime,size=1024k 0 0

现在,我也执行了以下命令。

cd /tmp/tmp.7KtrAsd9lx
touch hello
touch helloagain
ls -lFa

该命令的输出ls是,

ls -lFa
total 4
drwxrwxrwt   2 root root   80 Sep  3 22:23 ./
drwxrwxrwt. 16 root root 4096 Sep  3 22:22 ../
-rw-r--r--   1 root root    0 Sep  3 22:23 hello
-rw-r--r--   1 root root    0 Sep  3 22:23 helloagain

那么做这一切有什么大不了的呢?我为什么要这么做?

我现在打开另一个终端(2号航站楼)并执行以下命令。

cd /tmp/tmp.7KtrAsd9lx
ls -lFa

输出如下。

ls -lFa
total 8
drwx------   2 root root 4096 Sep  3 22:22 ./
drwxrwxrwt. 16 root root 4096 Sep  3 22:22 ../

这些文件hellohelloagain可见,我什至以 root 身份登录来检查这些文件。所以优点是,此功能使我们能够创建一个私有临时文件系统,即使其他 root 拥有的进程也无法看到或浏览该文件系统。

从 的手册页来看unshare

mount 命名空间 挂载和卸载文件系统不会影响系统的其余部分(CLONE_NEWNS 标志),除非显式标记为共享的文件系统(使用 mount --make-shared;有关共享标志,请参阅 /proc/self/mountinfo)。

建议在 unshare --mount 之后使用 mount --make-rprivate 或 mount --make-rslave 以确保新命名空间中的挂载点确实与父命名空间取消共享。

命名空间使用的内存是来自内核的 VFS。而且 - 如果我们一开始就设置正确 - 我们可以创建整个虚拟环境,在其中我们是没有 root 权限的 root 用户。

参考:

该示例是使用以下详细信息构建的这篇博文。另外,这个答案的引用来自迈克的精彩解释。关于这一点的另一篇精彩读物可以从以下答案中找到这里

答案2

关于挂载命名空间的非常非常重要的一点完全被忽略了。

我不会给出详细的解释,但会给你一些味道。

当我们使用两个挂载命名空间时,并不意味着我们有两个独立的文件系统。这是完全错误的。

例子。

我们在挂载名称空间 A 中有挂载点 /01

接下来我们从 A 创建挂载命名空间 B。

现在我们在挂载命名空间 B 中有 /01。

接下来我们将 B 中的 /01 设置为私有

(namespace B) # mount --make-private /01

接下来我们在 A 中创建文件

(namespace A) # touch /01/a.txt

我们将在 B /01 中看到该文件

接下来我们在B中创建b.txt

(namespace B)# touch /01/b.txt

我们将在 A /01 中看到 b.txt

所以。挂载命名空间之间没有任何独立性。

当一个命名空间中的一个安装点是另一命名空间的另一个安装点的源时,两个安装点之间的简单文件和简单文件夹具有 100% 的透明度。您为挂载点分配什么选项(共享、私有、从属)并不重要。这根本没有帮助。

因此,如果您认为为新命名空间中的所有挂载点创建新的挂载命名空间 assgin 私有选项并获得独立的文件系统 - 这是完全错误的。

真正的独立性仅与新的子安装点相关。

此外,如果您在新的命名空间中创建新的子挂载点,通常并不意味着该子挂载点独立于另一个挂载命名空间。关键是每个安装点都有后端(例如一些真​​实的物理磁盘)。因此,如果您了解后端,则可以安装它并进行更改。

(namespace A) # mount /dev/sdb1 /mnt
(namespace A) # mount --make-private /mnt
(namespace A) # unshare -m bash
(namespace B) #

返回命名空间A

(namespace A) # mkdir /mnt/01
(namespace A) # mount /dev/sdc1 /mnt/01
(namespace A) # mount --make-private /mnt/01
(namespace A) # touch /mnt/01/a.txt

我们不会在命名空间 B 中看到 a.txt

(namespace B) # ls -1al /mnt/01

它不会显示任何内容。

所以目前一切都很好。

但是当我们知道 /mnt/01 后端是 /dev/sdc1 时,我们可以将这个后端挂载到命名空间 B 中,最后会看到 a.txt

(namespace B) # mkdir /mnt/02
(namespace B) # mount /dev/sdc1 /mnt/02
(namespace B) # ls -1al /mnt/02/a.txt

胜利

最后,作为结论 - 挂载名称空间是棘手的事情,您必须很好地理解幕后的所有细节,才能制作真正独立的文件系统或从它们中获得您想要的结果。

答案3

如果你有泡沫包装安装到您的系统上后,您只需一步即可轻松完成:

bwrap --dev-bind / / --tmpfs /tmp bash

在上面的示例中,内部 bash 将在 /tmp 上有自己的视图。

解决方案受到 @Ramesh-s 答案的启发 - 谢谢!

相关内容