0

I want to create a new namespace with a different /etc/hosts, so I tried to use mount --bind with unshare to create it as referenced in this answer: https://unix.stackexchange.com/a/242830/271204

# Create temp hosts
export TEMP_HOSTS=$(mktemp XXXXXXX.hosts)
trap "{ rm -f $TEMP_HOSTS; }" EXIT
cat /etc/hosts > $TEMP_HOSTS

# Create new ns
unshare -m bash
mount --make-private "$TEMP_HOSTS" /etc/hosts --bind

Then I got a new shell (denoted as Shell2), and wrote something to it. It's ok and /etc/hosts is still in mount after append or edit.

(Shell2) # cat /proc/self/mountinfo | grep /etc/hosts
218 189 8:1 /tmp/Z3flEXS.hosts /etc/hosts rw,relatime - ext4 /dev/sda1 rw,errors=remount-ro
(Shell2) # echo '127.0.0.1 aaaa' >> /etc/hosts
(Shell2) # cat /proc/self/mountinfo | grep /etc/hosts
218 189 8:1 /tmp/Z3flEXS.hosts /etc/hosts rw,relatime - ext4 /dev/sda1 rw,errors=remount-ro

When I start a new terminal window or create or new ssh session, I get a shell with old namespace of the system and denote it as Shell1.

The /etc/hosts under Shell1 is still the old version as expect because the mount is --make-private. But when I modify the /etc/hosts under Shell1 with `vim, /etc/hosts under Shell2 is also changed and the mount is disappeared.

# Append "127.0.0.1 aaaaa" with vim, or you can use vim interactively.
(Shell1) # vim -c "$ s/$/\r127.0.0.1 aaaaa/" -c "wq" /etc/hosts
(Shell1) # md5sum /etc/hosts
1580e29f05e6af70012afe37ce08cb5a  /etc/hosts
(Shell2) # cat /proc/self/mountinfo | grep /etc/hosts
* Nothing here
(Shell2) # md5sum /etc/hosts
1580e29f05e6af70012afe37ce08cb5a  /etc/hosts

But in the step of modifying /etc/hosts in shell1, /etc/hosts in new namespace will not be affected when I use echo '127.0.0.1 aaaa' >> /etc/hosts instead of using vim to edit and save.

So my question is why I modified file with vim in old namespace, the file in the new namespace is also been affected? Why the behavior is different when using shell redirection? Can I change unshare or mount options to avoid the change caused by vim in old namespace?

1
  • Thanks a lot! At when the problem occurred, I used vim to edit the file. Modification of file with shell redirection indeed can not reproduce it. I have updated the description. Commented Jan 18, 2021 at 11:33

1 Answer 1

1

That's because vim is not editing the file in place -- when saving the file, vim creates a temporary file in the same directory and then renames it to the original.

You'll probably get the same effect with cp /etc/hosts{,~}; mv /etc/hosts{~,} (or with sed -i, which does the same thing as vim); renaming a file to another is like unlinking the old dir entry and then creating another one in its place (but in a single atomical step).

The unlinking part is obliterating any mount from another namespace.

And this is intended behaviour -- see the calls to detach_mounts in fs/namei.c from vfs_{unlink,rename,rmdir}(). Only a mount in the same namespace will cause them to fail with EBUSY.

That feels a bit sketchy, but without this, any process could mount over a file or directory in a private namespace as a way to prevent it from ever being removed ----- which may turn into a denial of service attack [1]

The same puzzling behaviour happens when you mount over files under /proc/PID/ -- the mount just disappears when process PID exits, without being explicitly unmounted.


[1] This is actually the rationale from the commit which changed the behaviour in 2013, also mentioned in the mount_namespaces(7) manpage:

Previously (before Linux 3.18), attempting to unlink, rename, or remove a file or directory that was a mount point in another mount namespace would result in the error EBUSY. That behavior had technical problems of enforcement (e.g., for NFS) and permitted denial-of-service attacks against more privileged users. (i.e., preventing individual files from being updated by bind mounting on top of them).

1
  • That's it. I used strace with vim and found it rename file to name suffix with ~ and write to /etc/hosts then unlink the old file. According to man7.org/linux/man-pages/man7/mount_namespaces.7.html it would never results EBUSY when unlink mountpoint at other namespace in recent kernel versions. Commented Jan 19, 2021 at 3:20

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.