CentOS – Bind Mount Differences Between CentOS 6 and CentOS 7

centoschrootmount

I'm mounting couple of directories (bind mount) in a chroot environment, but they behave differently on CentOS 6 and 7 – exactly the same commands.

Example:

I have my chroot env in /chroot/base.

Then I mount it on every user:

mount --bind /chroot/base /chroot/$user

Then I mount /home/$user in the same user's chroot:

mount --bind /home/$user /chroot/$user/home/$user

On CentOS 6 it works fine and it mounts exactly those directories, but on CentOS 7 I get something like this:

/dev/mapper/cl_cp-home /chroot/user1/home/user1 xfs rw,relatime,attr2,inode64,usrquota 0 0
/dev/mapper/cl_cp-home /chroot/user2/home/user1 xfs rw,relatime,attr2,inode64,usrquota 0 0
/dev/mapper/cl_cp-home /chroot/user3/home/user1 xfs rw,relatime,attr2,inode64,usrquota 0 0
/dev/mapper/cl_cp-home /chroot/user2/home/user2 xfs rw,relatime,attr2,inode64,usrquota 0 0
/dev/mapper/cl_cp-home /chroot/user3/home/user2 xfs rw,relatime,attr2,inode64,usrquota 0 0
/dev/mapper/cl_cp-home /chroot/user1/home/user2 xfs rw,relatime,attr2,inode64,usrquota 0 0
/dev/mapper/cl_cp-home /chroot/user3/home/user3 xfs rw,relatime,attr2,inode64,usrquota 0 0

Every user's homedir gets mounted in the chroot env of the other users.

Why is this happening? What changed between CentOS6/7 that could be causing this?

Edit:

Running ls on the folder for user1 for example (123user1 is a simple touch /home/user1/123user1 file):

root@server:~# ls /chroot/user1/home/user1/
123user1
root@server:~# ls /chroot/user2/home/user1/
123user1
root@server:~# ls /chroot/user3/home/user1/
123user1

Even more strange is this:

root@server:~# ls /chroot/base/home/user1/
123user1

I haven't mounted this at any stage

Best Answer

The source of the behaviour seems the changed default of the shared subtrees operation. The kernel documentation Documentation/sharedsubtree.txt mentions that private is the default, whereas actually it is shared which can be obtained by viewing /proc/self/mountinfo after mounting a directory with --bind.

root@localhost ~]# mount --bind /chroot/base /chroot/test
[root@localhost ~]# grep test /proc/self/mountinfo
234 62 253:1 /chroot/base /chroot/test rw,relatime shared:1 - xfs /dev/vda1 rw,attr2,inode64,noquota

This causes propagation of mounts under /chroot/test back to /chroot/base which then affects the other bind-mounts derived from /chroot/base.

To get back the old behaviour, one has to specifiy --make-private explicitly or private as mount option in /etc/fstab.

[root@localhost ~]# umount /chroot/test
[root@localhost ~]# mount --bind --make-private /chroot/base /chroot/test
[root@localhost ~]# grep test /proc/self/mountinfo
234 62 253:1 /chroot/base /chroot/test rw,relatime - xfs /dev/vda1 rw,attr2,inode64,noquota

I think it is save to apply the private option to any bind-mount you want the old behaviour back.


Update

The kernel default is still private but systemd is remounting the filesystems as shared due to better container support. From the systemd github site:

Mark the root directory as shared in regards to mount propagation. The kernel defaults to "private", but we think it makes more sense to have a default of "shared" so that nspawn and the container tools work out of the box. If specific setups need other settings they can reset the propagation mode to private if needed. Note that we set this only when we are invoked directly by the kernel. If we are invoked by a container manager we assume the container manager knows what it is doing (for example, because it set up some directories with different propagation modes).

Related Topic