ここのサイトで紹介されているpivot_root
の理解に時間がかかったので解説します。
pivot_rootとは?
pivot_root
はプロセスのルートファイルシステムを隔離する目的で使用されるコマンドです。仲間にchroot
がいますが挙動が異なります。pivot_root
はプロセスのルートファイルシステムそのものを入れ替えることでファイルシステムを隔離します。
またpivot_root
を使うには以下の条件があります。
【引用】
・新しいファイルシステム(new_root)と元のファイルシステムの移動先(put_old)はディレクトリでなければならない ・new_rootとput_oldは現在のrootと同じファイルシステムにあってはならない ・put_oldはnew_root配下になければならない ・他のファイルシステムがput_oldにマウントされていてはならない
試してみる
このコマンドを叩くとpivot_root
を使ってルートファイルシステムの隔離ができます。
$ ROOTFS=$(mktemp -d) $ cp -a /bin /lib /lib64 $ROOTFS $ NEW_ROOT=$ROOTFS $ mkdir $NEW_ROOT/{.put_old,proc} $ unshare -mpfr /bin/sh -c " \ mount --bind $NEW_ROOT $NEW_ROOT && \ mount -t proc proc $NEW_ROOT/proc && \ pivot_root $NEW_ROOT $NEW_ROOT/.put_old && \ umount -l /.put_old && \ cd / && \ exec /bin/sh " # ls bin lib lib64 proc
何をしているのか?
ここにフォーカスして説明します。
mount --bind $NEW_ROOT $NEW_ROOT && \ mount -t proc proc $NEW_ROOT/proc && \ pivot_root $NEW_ROOT $NEW_ROOT/.put_old && \ umount -l /.put_old && \ cd / && \ exec /bin/sh
まずmount --bind $NEW_ROOT $NEW_ROOT && \
で$NEW_ROOT
をマウントします。続いてproc
をマウントしたのち、pivot_root
コマンドによって現在のプロセスのルートファイルシステムを移動しています。
pivot_root
のmanページをみると
pivot_root moves the root file system of the current process to the directory put_old and makes new_root the new root file system.
とあり日本語に訳すと
pivot_rootは、現在のプロセスのルートファイルシステムをput_oldディレクトリを作成し、new_rootを新しいルートファイルシステムにします。
と言っています。
unshare
コマンドを叩いたプロセスでは/
を使っていました。このルートファイルシステムを$NEW_ROOT/.put_old
に移し、$NEW_ROOT
をルートファイルシステムに変更しています。
そして不要になった/.put_old
をunmount
しています。
ためしにunmountを抜いてみよう
$ unshare -mpfr /bin/sh -c " \ mount --bind $NEW_ROOT $NEW_ROOT && \ mount -t proc proc $NEW_ROOT/proc && \ pivot_root $NEW_ROOT $NEW_ROOT/.put_old && \ umount -l /.put_old && \ cd / && \ exec /bin/sh "
このコマンドからumount -l /.put_old &&
を抜いてみましょう。
root@ubuntu-bionic:~/docker# unshare -mpfr /bin/sh -c " \ mount --bind $NEW_ROOT $NEW_ROOT && \ mount -t proc proc $NEW_ROOT/proc && \ pivot_root $NEW_ROOT $NEW_ROOT/.put_old && \ cd / && \ exec /bin/sh "
# ls /.put_old
bin home lib64 opt sbin tmp vmlinuz
boot initrd.img lost+found proc snap usr vmlinuz.old
dev initrd.img.old media root srv vagrant
etc lib mnt run sys var
すると/.put_old
の下に先ほどまでは存在しなかった元々のルートファイルシステムがあることがわかります。