--bind --make-private /etc/hostsを新しい名前空間にマウントし、古い名前空間でvimを使用してこのファイルを変更すると、新しいnsにも影響するのはなぜですか?

--bind --make-private /etc/hostsを新しい名前空間にマウントし、古い名前空間でvimを使用してこのファイルを変更すると、新しいnsにも影響するのはなぜですか?

別の名前空間を使用して新しい名前空間を作成したかったので、この回答で参照されているようにunshareを使用して作成してみ/etc/hostsました。mount --bindhttps://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

それから私は新しいシェル(Shell2と呼びます)を手に入れ、その中にいくつかの内容を書きました。重要ではありません。/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
(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

新しいターミナルウィンドウを起動するか、新しいSSHセッションを作成すると、システムの古い名前空間を含むシェルが作成され、これはShell1として表示されます。

Shell1の下の/ etc / hostsはマウントされているため、まだ古いバージョンです--make-private。しかし、`vimを使ってShell1の下の/etc/hostsを変更すると、Shell2の下の/etc/hostsも変更され、マウントが消えます。

# 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

/etc/hostsしかし、新しい名前空間のshell1で/etc/hostsを変更する段階では、echo '127.0.0.1 aaaa' >> /etc/hostseditvim救う

もしそうなら、私の質問は、古い名前空間のファイルを変更すると、vim新しい名前空間のファイルも影響を受けるのですか?シェルリダイレクトを使用するときの動作が異なるのはなぜですか?以前の名前空間でvimによる変更を防ぐために、またはunshareオプションを変更できますか?mount

答え1

これは、ファイルが所定の位置で編集されないためですvim。ファイルを保存すると、vimは同じディレクトリに一時ファイルを作成し、名前を元のファイルに変更します。

cp /etc/hosts{,~}; mv /etc/hosts{~,}を使用するか、またはを使用してsed -i同じ効果を得ることができますvim。あるファイルの名前を別のファイルに変更することは、以前のディレクトリエントリのリンクを解除してからその場所に別のファイルを作成することと同じです(ただし、単一のアトミックステップで)。

切断部分は、別の名前空間からマウントを削除することです。

detach_mountsこれは予想される動作です。 in呼び出しを参照してください。fs/namei.cからvfs_{unlink,rename,rmdir}()。マウントは1つだけ同じ名前空間が原因で失敗して表示されますEBUSY

やや概略的に感じますが、これがないと、すべてのプロセスが個人の名前空間のファイルやディレクトリにマウントされ、削除されるのを防ぎ、これをサービス拒否攻撃に変えることができます。

次のファイルをマウントすると、同じ恥ずかしい動作が発生します。/proc/PID/プロセスが終了すると、マウントは明示的PIDにアンマウントされずに消えます。


[1] これは実際に次のものです。犯罪これにより2013年にも行動が変わりました。マウントネームスペース(7)マンページ:

以前は(Linux 3.18より前)、他のマウントネームスペースのマウントポイントであったファイルまたはディレクトリをリンク解除したり、名前を変更または削除しようとしたときにエラーが発生しましたEBUSY。この動作には技術的な実装の問題(NFSなど)があり、より多くの権限を持つユーザーに対するサービス拒否攻撃が許可されます。 (つまり、マウントをバンドルすることで個々のファイルが更新されるのを防ぎます)。

関連情報