為什麼我在新的命名空間中掛載–bind –make-private /etc/hosts,在舊的命名空間中用vim修改這個文件也會影響新的ns?
我想創建一個不同的新命名空間
/etc/hosts
,所以我嘗試使用mount --bind
unshare 來創建它,如此答案中所引用: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
然後我得到了一個新的shell(記作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 會話時,我得到一個帶有系統舊命名空間的 shell,並將其表示為 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
但是在shell1中修改/etc/hosts的步驟中,在new namespace中我使用而不是使用編輯和保存
/etc/hosts
時不會受到影響。echo '127.0.0.1 aaaa' >> /etc/hosts``vim
所以我的問題是為什麼我修改
vim
了舊命名空間中的文件,新命名空間中的文件也受到了影響?為什麼使用 shell 重定向時行為不同?我可以更改unshare
或mount
選項以避免舊命名空間中 vim 引起的更改嗎?
那是因為
vim
沒有就地編輯文件——保存文件時,vim 在同一目錄中創建一個臨時文件,然後將其重命名為原始文件。你可能會得到相同的效果
cp /etc/hosts{,~}; mv /etc/hosts{~,}
(或與sed -i
,它做同樣的事情vim
); 將文件重命名為另一個文件就像取消連結舊的 dir 條目,然後在其位置創建另一個文件(但在單個原子步驟中)。取消連結部分正在消除來自另一個命名空間的任何掛載。
這是預期的行為 - 請參閱對
detach_mounts
infs/namei.c
from的呼叫vfs_{unlink,rename,rmdir}()
。只有在同一命名空間中的掛載才會導致它們失敗並顯示EBUSY
.這感覺有點粗略,但如果沒有這個,任何程序都可以掛載在私有命名空間中的文件或目錄上,以防止它被刪除 —– 這可能會變成拒絕服務攻擊
$$ 1 $$ 當您將文件掛載到以下文件時,也會發生同樣令人費解的行為
/proc/PID/
——當程序PID
退出時,掛載就會消失,而沒有顯式解除安裝。$$ 1 $$這實際上是 2013 年改變行為的送出的基本原理,在mount_namespaces(7) 手冊頁中也提到了:
以前(在 Linux 3.18 之前),嘗試取消連結、重命名或刪除作為另一個掛載命名空間中的掛載點的文件或目錄會導致錯誤
EBUSY
。這種行為存在執行技術問題(例如,對於 NFS),並且允許對更多特權使用者進行拒絕服務攻擊。(即,通過綁定安裝在它們之上來防止單個文件被更新)。