GNU/Linux >> Linux の 問題 >  >> Linux

Linux –システムにRootfsファイルシステムが存在しないのはなぜですか?

Linuxカーネルのドキュメントによると:

Rootfsは、ramfs(または、有効になっている場合はtmpfs)の特別なインスタンスです。
これは、2.6システムに常に存在します。 rootfsをアンマウントすることはできません…

テストしたすべてのLinuxシステム(カーネル> 2.6およびafaikの通常の起動手順(ubuntu 12.04など))、mount rootfsは表示されません エントリ。

ただし、外部の.cpioで起動する場合のbuildrootイメージの場合 アーカイブ、それは存在します。

どのような場合にrootfsがありますか mountのエントリ ?

承認された回答:

  1. 古いシステムでは、mount /proc/mountsと一致しない場合があります
  2. ほとんどの場合、rootfsは表示されません /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は、Debian7およびUbuntu15.04でシンボリックリンクに変換されます。

1.1ソース

Debianレポート#494001 –「debian-installer:/ etc / mtabは、Linux>=2.6.26で/proc/mountsへのシンボリックリンクである必要があります」

#494001はsysvinit-2.88dsf-14で解決されています。 2011年12月14日付けのクロージングメッセージを参照してください。この変更は、2013年5月4日にリリースされたDebian 7「Wheezy」に含まれています(sysvinit-2.88dsf-41を使用しています)。

Ubuntuはこの変更をsysvinit_2.88dsf-53.2ubuntu1まで延期しました。その変更ログページには、Ubuntu15.04のコードネームである「vivid」に変更が入力されていることが示されています。

2。ほとんどの場合、rootfsは表示されません /proc/mountsにあります 、しかしそれはまだマウントされています

Linux v4.17の時点で、このカーネルのドキュメントはまだ最新です。 rootfsは常に存在し、アンマウントすることはできません。ただし、ほとんどの場合、/ proc/mountsには表示されません。

initramfsシェルを起動すると、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」について知るにはどうすればよいですか?」これは、Debian7のカーネルバージョンと現在のカーネルv4.17の間のある時点で、カーネルが/ proc/mountsの表示方法を変更したためだと思います。さらに検索すると、rootfsはUbuntu 14.04に表示されていると思いますが、Ubuntuカーネル4.4.0-28-genericを搭載したUbuntu16.04には表示されていません。

関連:Linux – / dev / urandomの文字「u」はどういう意味ですか?

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のルートディレクトリからトラバースできました。 ファイルシステムをrootfsに戻す ..を使用する 、ext4 ファイルシステムはrootfsのサブディレクトリにマウントされました 。 ext4の場合、escapeメソッドは機能しません ファイルシステムはルートにマウントされています rootfsのディレクトリ。

rootfsを見つけることができました 別の方法を使用します。 (少なくとも1人の重要なカーネル開発者はこれを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

(また、このファイルシステムは期待どおりに空であり、書き込み可能であることを確認しました。)


Linux
  1. Linux カーネルの `struct file_operations` で close 関数が release と呼ばれるのはなぜですか?

  2. Linux でシステム コール テーブルを変更する必要があるのはなぜですか?

  3. Linux のカーネルがモノリシックであるのに、なぜ Linux は Unix に似ているのですか?

  1. Linux – Linuxカーネルシステムコールの実装を見つける方法は?

  2. Linux – LinuxでProcファイルシステムはどのくらいの頻度で更新されますか?

  3. ファイルがそこにあり、PATH にあるにもかかわらず、Linux 実行可能ファイルが File not found で失敗する

  1. Linux –ユーザースペースを決して壊さないLinuxカーネルポリシーがあるのはなぜですか?

  2. Linux の <conio.h> ヘッダー ファイルはどこにありますか? <conio.h> が見つからないのはなぜですか?

  3. Linux カーネルの pr_debug が何も出力しないのはなぜですか?