為什麼我的系統上沒有 rootfs 文件系統?
linux核心文件聲稱:
Rootfs 是 ramfs(或 tmpfs,如果已啟用)的一個特殊實例,它始終存在於 2.6 系統中。您無法解除安裝 rootfs …
在我測試的所有 linux 系統上(核心 > 2.6 和 afaik 正常啟動過程,例如 ubuntu 12.04),
mount
沒有顯示rootfs
條目。但是,在使用外部存檔引導時使用buildroot映像,它存在。
.cpio
在什麼情況下有
rootfs
入口mount
?
- 在舊系統上,
mount
可能不同意/proc/mounts
- 大多數時候您不會在 中看到
rootfs
,/proc/mounts
但它仍然已安裝。- 我們能證明 rootfs 仍然掛載嗎?
1.在舊系統上,
mount
可能不同意/proc/mounts
man mount
說:“程序mount
和umount
傳統上維護文件中目前安裝的文件系統的列表/etc/mtab
。”舊方法實際上不適用於根文件系統。根文件系統可能已被核心掛載,而不是
mount
./
因此, in 中的條目/etc/mtab
可能非常做作,並且不一定與核心目前的掛載列表同步。我還沒有確定,但實際上我認為任何使用舊方案的系統都不會初始化
mtab
以顯示帶有rootfs
. (理論上,是否mount
顯示rootfs
取決於首先安裝mtab
文件的軟體)。
man mount
繼續說:“仍然支持真正的 mtab 文件,但在目前的 Linux 系統上,最好將其設為 /proc/mounts 的符號連結,因為在使用者空間中維護的正常 mtab 文件無法可靠地與命名空間、容器和其他高級 Linux 一起使用特徵。”mtab 在 Debian 7 和 Ubuntu 15.04 中被轉換為符號連結。
1.1 來源
Debian 報告#494001 - “debian-installer: /etc/mtab 必須是 /proc/mounts 的符號連結,Linux >= 2.6.26”
#494001 在 sysvinit-2.88dsf-14 中得到解決。請參閱2011 年 12 月 14 日 的結束消息。該更改包含在2013 年 5 月 4 日發布的 Debian 7 “Wheezy” 中。(它使用 sysvinit-2.88dsf-41)。
Ubuntu 將此更改延遲到sysvinit_2.88dsf-53.2ubuntu1。該更改日誌頁面顯示更改輸入“vivid”,這是 Ubuntu 15.04 的代號。
2.大多數時候你不會看到
rootfs
,/proc/mounts
但它仍然是掛載的從 Linux v4.17 開始,這個核心文件仍然是最新的。rootfs 始終存在,並且永遠無法解除安裝。但大多數時候你在 /proc/mounts 中看不到它。
如果您啟動到 initramfs shell,您可以看到 rootfs。如果您的 initramfs 是
dracut
,就像在 Fedora Linux 中一樣,您可以通過將選項添加rd.break
到核心命令行來執行此操作。(例如在 GRUB 引導載入程序中)。switch_root:/# grep rootfs /proc/mounts rootfs / rootfs rw 0 0
當 dracut 將系統切換到真正的根文件系統時,您將無法在 /proc/mounts 中看到 rootfs。dracut 可以使用
switch_root
或systemd
來執行此操作。這兩個都遵循相同的操作順序,在連結的核心文件中建議。在其他一些文章中,人們可以在切換出 initramfs 後在 /proc/mounts 中看到 rootfs。例如在 Debian 7 上:’我如何才能找到有關“rootfs”的資訊’。我認為這一定是因為核心在 Debian 7 的核心版本和我目前的核心 v4.17 之間的某個時間點改變了它顯示 /proc/mounts 的方式。通過進一步的搜尋,我認為 rootfs顯示在 Ubuntu 14.04 上,但未顯示在Ubuntu 核心 4.4.0-28-generic 的 Ubuntu 16.04 上。
即使我不使用 initramfs,而是讓核心掛載根文件系統,我也無法在 /proc/mounts 中看到 rootfs。這是有道理的,因為核心程式碼似乎也遵循相同的操作序列。
隱藏 rootfs 的操作是
chroot
.switch_root:/# cd /sysroot switch_root:/sysroot# mount --bind /proc proc switch_root:/sysroot# grep rootfs proc/mounts rootfs / rootfs rw 0 0 switch_root:/sysroot# chroot . sh-4.4# cat proc/mounts /dev/sda3 / ext4 ro,relatime 0 0 proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
3、能不能證明rootfs還是掛載了?
眾所周知,
chroot
當您以特權使用者身份執行時,可以逃脫一個簡單的。如果switch_root
只是chroot
,我們可以將其反轉並再次查看 rootfs。sh-4.4# python3 ... >>> import os >>> os.system('mount --bind / /mnt') >>> os.system('cat proc/mounts') /dev/sda3 / ext4 ro,relatime 0 0 proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 /dev/sda3 /mnt ext4 ro,relatime 0 0 >>> os.chroot('/mnt') >>> >>> # now the root, "/", is the old "/mnt"... >>> # but the current directory, ".", is outside the root :-) >>> >>> os.system('cat proc/mounts') /dev/sda3 / ext4 ro,relatime 0 0 >>> os.chdir('..') >>> os.system('bash') shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory bash-4.4# chroot . sh-4.4# grep rootfs proc/mounts rootfs / rootfs rw 0 0
switch_root
但是,這種技術不能顛倒整個序列。完整的序列確實
- 將目前工作目錄(如 中
/proc/self/cwd
)更改為新文件系統的掛載點:cd /newmount
- 移動新文件系統,即更改其掛載點,使其直接位於根目錄的頂部。
mount --move . /
- 更改目前根目錄(如 中
/proc/self/root
)以匹配目前工作目錄。chroot .
在上面的 chroot 轉義中,我們能夠從文件系統的根目錄遍歷
ext4
回rootfs
using..
,因為ext4
文件系統安裝在rootfs
.ext4
當文件系統掛載到 rootfs的根目錄時,轉義方法不起作用。我能夠找到
rootfs
使用不同的方法。(至少一位重要的核心開發人員認為這是 Linux 中的一個錯誤)。/* CURSED.c - DO NOT RUN THIS PROGRAM INSIDE YOUR MAIN MOUNT NAMESPACE */ #define _GNU_SOURCE #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> /* open() */ #include <sys/mount.h> #include <sched.h> /* setns() */ #include <sys/statfs.h> int main() { int fd = open("/proc/self/ns/mnt", O_RDONLY); /* "umount -l /" - lazy unmount everything we can see */ umount2("/", MNT_DETACH); /* reset root, by re-entering our mount namespace */ setns(fd, CLONE_NEWNS); /* "stat -f /" - inspect the root */ struct statfs fs; statfs("/", &fs); }
在 Linux 4.17.3-200.fc28.x86_64 上測試:
$ make CURSED cc CURSED.c -o CURSED $ sudo unshare -m strace ./CURSED ... openat(AT_FDCWD, "/proc/self/ns/mnt", O_RDONLY) = 3 umount2("/", MNT_DETACH) = 0 setns(3, CLONE_NEWNS) = 0 statfs("/", {f_type=RAMFS_MAGIC, f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID}) = 0 ^ ^ result: rootfs uses ramfs code on this system
(我還確認這個文件系統是空的,並且是可寫的)。