概要
go言語でコンテナランタイムを自作する際にこのページを参考に書いていた所、pivot rootが動かない
エラー
$ sudo ./main run /bin/sh
2022/08/14 18:38:44 mkdir newroot/putold
2022/08/14 18:38:44 bind mount to ./newroot
2022/08/14 18:38:44 run pivot_root
panic: pivot root: invalid argument
原因
元々のrootとnewrootがshared mountであった為、pivot root: invalid argumentが起こった。
https://tenforward.hatenablog.com/entry/2017/06/28/021019
より
元々のLinuxのデフォルトの挙動では、privateであるがsystemdがsharedに書き換えている為このようなエラーが起こった。
解決策
名前空間を分けたプロセスでbind mountを行う前にsharedを外す必要がある
runcのrootfsより
https://github.com/opencontainers/runc/blob/480e1298d8848f5a38518468161cf2620d76720c/libcontainer/rootfs_linux.go#L772
// sharedを外す
if err := syscall.Mount("", "/", "", syscall.MS_SLAVE|syscall.MS_REC, ""); err != nil {
return fmt.Errorf("prepare RootFS: %w", err)
}
// 古いrootfsを置く場所を作る
if err := os.MkdirAll("newroot/putold", 0755); err != nil {
return fmt.Errorf("creating directory: %w", err)
}
// bind mountを行いmountポイントを作る
if err := syscall.Mount("newroot", "newroot", "", syscall.MS_BIND|syscall.MS_REC, ""); err != nil {
return fmt.Errorf("bind mounting newroot: %w", err)
}
//pivot rootを行う
if err := syscall.PivotRoot("newroot", "newroot/putold"); err != nil {
return fmt.Errorf("pivot root: %w", err)
}
参考サイトとなぜ違いがあったのか?
参考サイトでは、特権コンテナ上で行っておりコンテナを作る際に既にsharedを外されていため
参考文献