当前位置: 代码迷 >> 综合 >> chroot, mount --bind and mount namespace (by quqi99)
  详细解决方案

chroot, mount --bind and mount namespace (by quqi99)

热度:79   发布时间:2023-12-13 09:26:11.0

作者:张华  发表于:2014-01-24
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明

http://blog.csdn.net/quqi99 )


  • chroot, 切换根文件系统并运行进程 (mount --rbind / /chroot && chroot /chroot $application )
  • mount --bind  /etc /tmp/test/etc 允许从任何其他位置访问任何文件或目录, 它与mount namespace的区别是, /etc仍然对所有进程可见它从Linux 2.4版本之后。
  •  mount namespace, 让挂载点在各个进程之间隔离。一个进程不能看到其他进程的挂载点,实现真正的安全。它能实现上述chroot和mount --bind的功能,但比它们更灵活。它能真正做到对真正根目录下的子目录做共享、独享(也就是将拥有一个子目录的副本)。它从Linux 3.8版本之后。net namespace是从Linux 3.0版本之后。
       clone一个进程时也会为这个进程clone一份文件系统,并且这些clone的文件系统之间是相互隔离的,也就是说,在clone的文件系统里做mount操作不会影响到其他clone里的文件系统。这种完全隔离会造成问题,如:进程克隆了系统的文件系统名称空间之后,已经运行的系统守护进程无法为这个用户自动挂载 CD-ROM,因为在原文件系统名称空间中执行的挂载无法影响用户的拷贝。为解决这个问题,也就出现了mount propagation(mount传播),即在多个mount对象之间定义关系(两个mount对象是共享关系的话,mount event就可以传播;若是slave关系的话传播则是单向的。这样就有了几个术语,传播mount event叫shared mount(mount --make-shared <mount-point|object>, 当一个挂载点下面添加或者删除挂载点的时候,其他挂载点下面也会挂载和卸载同样的挂载点, 也即bind在一起的两个目录下的子目录再挂载了设备的话,他们之间还能相互看到子目录里挂载的内容 ), 接收mount event叫slave mount, 既不传播也不接收mount event的叫private mount(默认情况),还有一个特殊的叫unbindable mount)。

例子一,为每个用户建立私有的/tmp目录
1, 为用户创建私有目录/tmp/priv/USER
   mkdir /tmp/priv
   chmod 000 /tmp/priv
   mkdir /tmp/priv/USER
   chown -R USER /tmp/priv/USER
2, 挂载它 , mount("/tmp/priv/USER", "/tmp", "none", MS_BIND, NULL)
3, 这样,USER用户可以这样使用它
   touch /tmp/ab
   ls /tmp
   这时候用root用户可以看到/tmp/priv/USER/ab

例子二,进程不能看到其他进程的挂载点,但可以看到系统的挂载点
a, 先让根/ 挂载递归共享
    mount --make-rshared /
b, 若一个进程在/myprivatetree下再挂载目录,其他进程是看不见的,因为使用了slave mount
   mount --make-rslave /myprivatetree
c, 也可以写成:
create_user_tree {
        user = $1
        mkdir /user/$user
        mount --rbind / /user/$user
        mount --make-rslave /user/$user
        mount --make-rshared /user/$user
#create a private mount. This is to facilitate pivot_root
#to temporarily place the old root here before detaching the
#entire old root tree. NOTE: pivot_root will not allow old root
#to be placed under a shared mount.
pushd /user/$user/
mkdir -p __my_private_mnt__
mount --bind __my_private_mnt__ __my_private_mnt__
mount --make-private __my_private_mnt__
popd
}

例子三,用mount --bind模拟strongswan的namespace
sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf ip netns exec qrouter-0f354519-cf33-43d8-bec2-3ce18867bcdb neutron-netns-wrapper --mount_paths=/etc:/tmp/test/etc,/var/run:/tmp/test/var/run --cmd=ipsec,status
将执行:
sudo mount -n --bind  /etc /tmp/test/etc
sudo mount -n --bind  /var /tmp/test/var
sudo umount /tmp/test/etc
一般在mount加-n参数别把挂载项写到/etc/mtab里了,/proc/mounts包含所有挂载信息,/proc/PID/mounts包括某一进程的挂载信息。

例子四,在容器共享mounts
因为容器是采用mount namespace隔离了的,所以简单的将一个目录mount到/var/lib/lxc/o1/rootfs,容器仍然看不到这个目录的。
好在mount传播,它的本质在于如果如果挂载到/shard/o1/的也同样会通过mount event让其挂载到/shared目录。
a, 创建创建/shared挂载点
mkdir /shared
mount --bind /shared /shared
mount --make-unbindable /shared
mount --make-shared /shared
mkdir /shared/o1
b, 创建容器,
lxc-create -t ubuntu -n o1
lxc-ls --fancy
lxc-start -n o1
lxc-console -n o1 -t 1
c, 在容器根目录下创建shared目录, mkdir /var/lib/lxc/o1/rootfs/shared
d, 将容器目录/var/lib/lxc/o1/rootfs/shared挂载到/shared/o1
cat >> /var/lib/lxc/o1/fstab << EOF
/shared/o1 /var/lib/lxc/o1/rootfs/shared none bind 0 0
EOF
e, 这样,通过下列命令就可以将/lib也共享到容器目录下了。
mkdir /shared/o1/lib
mount –bind /lib /shared/o1/lib

Reference
[1], http://www.ibm.com/developerworks/cn/linux/l-mount-namespaces.html
[2], http://glandium.org/blog/?p=217
[3], https://www.digitalocean.com/community/tutorials/getting-started-with-lxc-on-an-ubuntu-13-04-vps
[4], https://segmentfault.com/a/1190000006899213
  相关解决方案