2016-12-13 197 views
2

我試圖實施以下情形:安裝文件系統

  1. clone()CLONE_NEWNS標誌主要過程(這意味着新坐騎命名空間)
  2. mount()新的文件系統中的子進程
  3. 子進程完成,並在此過程中創建的所有文件系統都卸載

但它不工作,因爲我預期和我仍然在主進程中看到已掛載的文件系統。我究竟做錯了什麼?

來源是這裏https://github.com/dmitrievanthony/sprat/blob/master/src/container.c#L47

系統是默認AWS的Ubuntu,

[email protected]:~/sprat$ uname -a 
Linux ip-172-31-31-112 4.4.0-53-generiC#74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux 

回答

2

簡短的回答:它看起來像的mount propagation類型設置不正確。


說明

起初,你的根掛載點的傳播類型,應該是MS_SHARED,作爲啓動設置由systemd。 這可以通過查看/proc/$PID/mountinfo可選字段來觀察。 例如,像這樣可以預料:

$ cat /proc/self/mountinfo 
    . . . 
25 0 8:6// rw,relatime shared:1 - ext4 /dev/sda6 rw,errors=remount-ro,data=ordered 
         ^^^^^^ 
    . . . 

通知的加下劃線(由我)shared:1場以上,表明/當前傳播類型掛載點是MS_SHARED,並且對等體組 ID是1(在我們的例子中,我們根本不會在乎同伴組ID)。

當使用clone(2)上的CLONE_NEWNS標誌時,會創建一個新的掛載名稱空間,該空間將初始化爲調用者的掛載名稱空間的副本。 新名稱空間的新複製掛載點將與其在調用程序的掛載名稱空間中各自的原始掛載點加入同一對等組。

其父傳播類型爲MS_SHARED的新安裝點的傳播類型也爲MS_SHARED。因此,當您的「包含」進程mount()是循環設備上的文件系統時,安裝程​​序默認爲MS_SHARED。之後,它下面的所有掛載也會傳播到「主」進程的命名空間,這就是「主」進程可以看到它們的原因。

對於你的要求得到滿足(爲「主」過程中沒有看見「載」進程的掛載點),你所尋求的掛載傳播類型是MS_SLAVEMS_PRIVATE,這取決於你是否希望你的「載」進程的根掛載點分別接收來自其他對等體的傳播事件。 顯然,MS_PRIVATE提供比MS_SLAVE更大的隔離度。

因此,在你的情況下,它應該是足以改變「載」進程的根的傳播類型,掛載點MS_PRIVATEMS_SLAVE之前掛載文件系統的其餘部分,所以坐騎將不會傳播到「主」進程的名字空間。


代碼

起初,一會嘗試來正確設置傳播類型當「包含」的過程產生其根掛載點。

不過,我注意到在man 8 mount以下(引用):

注意的是,Linux內核不允許更改多個 傳播標誌使用單個安裝(2)系統調用和標誌 不能與其他安裝選項混合使用。

由於util-linux 2.23的安裝命令允許使用幾個 傳播標誌一起,並與其他安裝 操作一起使用。此功能是實驗性的。當前面的安裝 操作成功時,傳播標誌是 由附加安裝(2)系統調用應用。

看你的代碼中,「載」的過程,之後mount()■循環設備上的文件系統,它會發出chroot()它。在這一點上,你可以通過注射這種mount(2)呼叫建立其傳播類型:

if (chroot(".") < 0) { 
    // handle error 
} 

if (mount("/", "/", c->fstype, MS_PRIVATE, "") < 0) { 
    // handle error 
} 

if (mkdir(...)) { 
    // handle error 
} 

現在傳播類型設置爲MS_PRIVATE,所有後續坐騎「載」過程/下確實將不會傳播,因此在「主」進程的名稱空間中不可見,正如您在/proc/mounts/proc/$PID/mountinfo中觀察到的那樣。


資源

+0

這是一個很好的答案,謝謝! – dmitrievanthony