为什么我的系统上没有 rootfs 文件系统?

为什么我的系统上没有 rootfs 文件系统?

Linux内核文档索赔:

Rootfs 是 ramfs(或 tmpfs,如果启用的话)的一个特殊实例,它始终存在于 2.6 系统中。您无法卸载 rootfs ...

在我测试的所有 Linux 系统上(内核 > 2.6 和据我所知正常启动过程,例如 ubuntu 12.04),mount不显示rootfs条目。

然而,随着构建根目录使用外部.cpio存档启动时的映像,它是存在的。

什么情况下会有rootfs条目mount

答案1

  1. 在旧系统上,mount可能不同意/proc/mounts
  2. 大多数时候您不会看到rootfsin /proc/mounts,但它仍然已安装。
  3. 我们能证明 rootfs 仍然挂载吗?

1. 在旧系统上,mount可能不同意/proc/mounts

man mount说:“程序mount通常umount在文件中维护当前安装的文件系统的列表/etc/mtab。”

旧方法实际上不适用于根文件系统。根文件系统可能已由内核安装,而不是由mount.因此,/中的条目/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 日。该更改包含在 Debian 7“Wheezy”中, 2013 年 5 月 4 日发布。 (它使用 sysvinit-2.88dsf-41)。

Ubuntu 推迟了这一更改,直到sysvinit_2.88dsf-53.2ubuntu1。该变更日志页面显示更改进入“生动”,这是 Ubuntu 15.04 的代号

2. 大多数时候你不会看到rootfsin /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
    
  2. 移动新的文件系统,即更改其安装点,以便它直接位于根目录的顶部。

    mount --move . /
    
  3. 更改当前根目录(如 中/proc/self/root)以匹配当前工作目录。

    chroot .
    

在上面的 chroot 转义中,我们能够从ext4文件系统的根目录遍历回rootfsusing ..,因为ext4文件系统安装在rootfs.当ext4文件系统安装在rootfs 的目录。

我能够rootfs使用不同的方法找到它。 (至少一位重要的内核开发人员认为这是 Linux 中的一个错误)。

http://archive.today/2018.07.22-161140/https://lore.kernel.org/lkml/[电子邮件受保护]/

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

(我还确认该文件系统是空的正如预期的那样,并且可写)。

相关内容