Linux

為什麼我的系統上沒有 rootfs 文件系統?

  • July 22, 2018

linux核心文件聲稱:

Rootfs 是 ramfs(或 tmpfs,如果已啟用)的一個特殊實例,它始終存在於 2.6 系統中。您無法解除安裝 rootfs …

在我測試的所有 linux 系統上(核心 > 2.6 和 afaik 正常啟動過程,例如 ubuntu 12.04),mount沒有顯示rootfs條目。

但是,在使用外部存檔引導時使用buildroot映像,它存在。.cpio

在什麼情況下有rootfs入口mount

  1. 在舊系統上,mount可能不同意/proc/mounts
  2. 大多數時候您不會在 中看到rootfs/proc/mounts但它仍然已安裝。
  3. 我們能證明 rootfs 仍然掛載嗎?

1.在舊系統上,mount可能不同意/proc/mounts

man mount說:“程序mountumount傳統上維護文件中目前安裝的文件系統的列表/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_rootsystemd來執行此操作。這兩個都遵循相同的操作順序,在連結的核心文件中建議。

在其他一些文章中,人們可以在切換出 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但是,這種技術不能顛倒整個序列。完整的序列確實

  1. 將目前工作目錄(如 中/proc/self/cwd)更改為新文件系統的掛載點:
cd /newmount
  1. 移動新文件系統,即更改其掛載點,使其直接位於根目錄的頂部。
mount --move . /
  1. 更改目前根目錄(如 中/proc/self/root)以匹配目前工作目錄。
chroot .

在上面的 chroot 轉義中,我們能夠從文件系統的根目錄遍歷ext4rootfsusing ..,因為ext4文件系統安裝在rootfs. ext4當文件系統掛載到 rootfs的目錄時,轉義方法不起作用。

我能夠找到rootfs使用不同的方法。(至少一位重要的核心開發人員認為這是 Linux 中的一個錯誤)。

http://archive.today/2018.07.22-161140/https://lore.kernel.org/lkml/20141007133339.GH7996@ZenIV.linux.org.uk/

/* 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

(我還確認這個文件系統是空,並且是可寫的)。

引用自:https://unix.stackexchange.com/questions/152029