如何使用 Linux 命名空間執行 chroot?
在閱讀了 Linux 命名空間之後,我的印像是,在許多其他特性中,它們是 chroot 的替代品。例如,在這篇文章中:
其他用途
$$ of namespaces $$包括$$ … $$chroot() 風格的程序隔離到單個目錄層次結構的一部分。
但是,當我複製掛載命名空間時,例如使用以下命令,我仍然可以看到整個原始根樹。
unshare --mount -- /bin/bash
我知道我現在能夠在新命名空間中執行不與原始命名空間共享的額外掛載,因此這提供了隔離,但它仍然是相同的根,例如
/etc
對於兩個命名空間仍然相同。我還需要chroot
更改根目錄還是有替代方法?我原以為這個問題會提供答案,但答案僅使用
chroot
, 。編輯#1
有一條現已刪除的評論提到
pivot_root
. 由於這實際上是 的一部分linux/fs/namespace.c
,因此它實際上是命名空間實現的一部分。這表明僅使用unshare
and更改根目錄mount
是不可能的,但命名空間提供了一個自己的更聰明的chroot
.chroot
即使在閱讀了原始碼之後(例如在安全性或更好的隔離意義上),我仍然沒有理解這種方法的主要思想,這使得它與.編輯#2
這不是這個問題的重複。從答案中執行所有命令後,我有單獨的 /tmp/tmp.vyM9IwnKuY (或類似的),但根目錄仍然相同!
chroot
在設置/proc
. 您可以chroot
在掛載命名空間中使用它作為一個不錯且簡單的 hack。我認為理解有好處
pivot_root
,但它有一點學習曲線。該文件並沒有完全解釋所有內容……儘管man 8 pivot_root
(用於 shell 命令)中有一個用法範例。man 2 pivot_root
(對於系統呼叫)如果它做同樣的事情可能會更清楚,並包含一個範例 C 程序。如何使用 pivot_root
進入掛載命名空間後,您還需要
mount --make-rslave /
或等效。否則,您的所有掛載更改都會傳播到原始命名空間中的掛載,包括pivot_root
. 你不想要那個:)。如果您使用了該
unshare --mount
命令,請注意它已記錄為mount --make-rprivate
預設應用。AFAICS 這是一個糟糕的預設值,您不希望在生產程式碼中使用它。例如,此時,它將停止eject
在主機命名空間中安裝的 DVD 或 USB 上工作。DVD 或 USB 將保持掛載在私有掛載樹中,並且核心不會讓您彈出 DVD。完成後,您可以掛載例如
/proc
您將使用的目錄。和你一樣chroot
。不像你使用
chroot
,pivot_root
要求你的新根文件系統是一個掛載點。如果它還不是一個,您可以通過簡單地應用綁定安裝來滿足這一點:mount --rbind new_root new_root
。使用
pivot_root
-,然後使用帶有/選項umount
的舊根文件系統。(您不需要,這可能需要更長的時間。)。-l``MNT_DETACH
umount -R
從技術上講,使用
pivot_root
一般也需要涉及使用chroot
;這不是“非此即彼”。根據
man 2 pivot_root
,它僅被定義為交換掛載命名空間的根。它沒有被定義為更改程序根指向的物理目錄。或目前工作目錄 (/proc/self/cwd
)。碰巧它確實這樣做了,但這是處理核心執行緒的一種技巧。手冊頁說將來可能會改變。通常你想要這個序列:
chdir(new_root); // cd new_root pivot_root(".", put_old); // pivot_root . put_old chroot("."); // chroot .
在這個
chroot
序列中的位置是另一個微妙的細節。儘管重點pivot_root
是重新排列掛載命名空間,但核心程式碼似乎通過查看每個程序的根目錄來找到要移動的根文件系統,這是chroot
設置的。為什麼要使用 pivot_root
pivot_root
原則上,用於安全和隔離是有意義的。我喜歡思考基於能力的安全理論。您傳入所需特定資源的列表,並且該程序無法訪問其他資源。在這種情況下,我們討論的是傳入掛載命名空間的文件系統。這個想法通常適用於 Linux “命名空間”功能,儘管我可能沒有很好地表達它。
chroot
只設置程序根,但程序仍然引用完整的掛載命名空間。如果一個程序保留了執行權限chroot
,那麼它可以遍歷備份文件系統命名空間。如 中man 2 chroot
所述,“超級使用者可以通過…逃離 ‘chroot jail’”。撤消的另一種發人深省的方法
chroot
是nsenter --mount=/proc/self/ns/mnt
. 這也許是該原則的一個更有力的論據。nsenter
/setns()
必須從掛載命名空間的根目錄重新載入程序根目錄……儘管當兩者引用不同的物理目錄時這會起作用,這可能被認為是核心錯誤。(技術說明:在根目錄中可能有多個文件系統相互疊加安裝;setns()
使用頂部,最近安裝的一個)。這說明了將掛載命名空間與“PID 命名空間”結合起來的一個優勢。位於 PID 命名空間內會阻止您進入無限制程序的掛載命名空間。它還可以防止您進入不受限制的程序的根目錄 (
/proc/$PID/root
)。當然,PID 命名空間也可以防止你殺死它之外的任何程序:-)。