GNU/Linux >> Znalost Linux >  >> Linux

Linux – Proč v systému není přítomen žádný souborový systém Rootfs?

Dokumentace linuxového jádra tvrdí:

Rootfs je speciální instance ramfs (nebo tmpfs, pokud je povoleno),
který je vždy přítomen v systémech 2.6. Nemůžete odpojit rootfs…

Na všech linuxových systémech, které jsem testoval (kernel> 2.6 a afaik normální zaváděcí procedura, např. ubuntu 12.04), mount nezobrazuje rootfs vstup.

Nicméně s bitovou kopií buildroot při spouštění s externím .cpio archiv, je přítomen.

V jakých případech existuje rootfs záznam v mount ?

Přijatá odpověď:

  1. Na starých systémech mount nemusí souhlasit s /proc/mounts
  2. Většinou neuvidíte rootfs v /proc/mounts , ale je stále připojen.
  3. Můžeme dokázat, že rootfs je stále připojen?

1. Na starých systémech mount nemusí souhlasit s /proc/mounts

man mount říká:„Programy se mount a umount tradičně udržoval seznam aktuálně připojených souborových systémů v souboru /etc/mtab .“

Starý přístup ve skutečnosti nefunguje pro kořenový souborový systém. Kořenový souborový systém mohl být připojen jádrem, nikoli pomocí mount . Proto položky pro / v /etc/mtab může být docela vymyšlené a nemusí být nutně synchronizované s aktuálním seznamem připojení jádra.

S jistotou jsem to nezkontroloval, ale v praxi si nemyslím, že jakýkoli systém, který používá staré schéma, inicializuje mtab zobrazit řádek s rootfs . (Teoreticky, zda mount zobrazuje rootfs bude záviset na softwaru, který jako první nainstaloval mtab soubor).

man mount pokračuje:„skutečný soubor mtab je stále podporován, ale na současných systémech Linux je lepší z něj udělat symbolický odkaz na /proc/mounts, protože běžný soubor mtab udržovaný v uživatelském prostoru nemůže spolehlivě fungovat s jmennými prostory, kontejnery a dalšími pokročilými Linuxem funkce.“

mtab je v Debianu 7 a Ubuntu 15.04 převeden na symbolický odkaz.

Zdroje 1.1

Debian report #494001 – “debian-installer:/etc/mtab musí být symbolický odkaz na /proc/mounts s linuxem>=2.6.26”

#494001 je vyřešen v sysvinit-2.88dsf-14. Viz závěrečná zpráva ze dne 14. prosince 2011. Změna je zahrnuta v Debianu 7 „Wheezy“, vydaném 4. května 2013. (Používá sysvinit-2.88dsf-41).

Ubuntu odložilo tuto změnu až do sysvinit_2.88dsf-53.2ubuntu1. Tato stránka s protokolem změn ukazuje, že změna zadává „vivid“, což je kódové označení pro Ubuntu 15.04.

2. rootfs většinou neuvidíte v /proc/mounts , ale stále je připojen

Od Linuxu v4.17 je tato dokumentace jádra stále aktuální. rootfs je vždy přítomen a nelze jej nikdy odpojit. Ale většinou to nevidíte v /proc/mounts.

Pokud zavedete do shellu initramfs, uvidíte rootfs. Pokud je váš initramfs dracut , stejně jako ve Fedora Linux, můžete to udělat přidáním volby rd.break na příkazový řádek jádra. (Například uvnitř zavaděče GRUB).

switch_root:/# grep rootfs /proc/mounts
rootfs / rootfs rw 0 0

Když dracut přepne systém na skutečný kořenový souborový systém, nemůžete již vidět rootfs v /proc/mounts. dracut může použít buď switch_root nebo systemd udělat toto. Oba se řídí stejnou posloupností operací, které jsou doporučeny v připojeném kernel doc.

V některých dalších příspěvcích mohou lidé vidět rootfs v /proc/mounts po vypnutí initramfs. Například na Debianu 7:‚Jak mohu zjistit o „rootfs“‘. Myslím, že to musí být proto, že jádro změnilo způsob, jakým zobrazuje /proc/mounts, v určitém okamžiku mezi verzí jádra v Debianu 7 a mým aktuálním jádrem v4.17. Z dalších hledání si myslím, že rootfs je zobrazen na Ubuntu 14.04, ale není zobrazen na Ubuntu 16.04 s jádrem Ubuntu 4.4.0-28-generic.

Související:Linux – Co znamená písmeno „u“ v /dev/urandom?

I když nepoužívám initramfs a jádro místo toho připojí kořenový souborový systém, nevidím rootfs v /proc/mounts. To dává smysl, protože se zdá, že kód jádra také sleduje stejnou sekvenci operací.

Operace, která skrývá rootfs, je 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. Můžeme dokázat, že rootfs je stále připojen?

Notoricky známý jednoduchý chroot lze uniknout, když běžíte jako privilegovaný uživatel. Pokud switch_root neudělal nic víc než chroot , mohli bychom to zvrátit a znovu vidět 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

Úplný switch_root sekvenci nelze touto technikou zvrátit. Celá sekvence ano

  1. Změňte aktuální pracovní adresář (jako v /proc/self/cwd ), do bodu připojení nového souborového systému:

    cd /newmount
    
  2. Přesuňte nový souborový systém, tj. změňte jeho bod připojení tak, aby seděl přímo nad kořenovým adresářem.

    mount --move . /
    
  3. Změňte aktuální kořenový adresář (jako v /proc/self/root ), aby odpovídal aktuálnímu pracovnímu adresáři.

    chroot .
    

Ve výše uvedeném chroot escape jsme byli schopni procházet z kořenového adresáře ext4 souborový systém zpět na rootfs pomocí .. , protože ext4 souborový systém byl připojen do podadresáře rootfs . Metoda escape nefunguje, když je ext4 souborový systém je připojen k rootu adresář rootfs.

Podařilo se mi najít rootfs pomocí jiné metody. (Přinejmenším jeden důležitý vývojář jádra to považuje za chybu v Linuxu).

http://archive.today/2018.07.22-161140/https://lore.kernel.org/lkml/[e-mail chráněný]/

/* 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);
}

Testováno na Linuxu 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

(Také jsem potvrdil, že tento souborový systém je podle očekávání prázdný a lze do něj zapisovat).


Linux
  1. Linux – jak často je systém souborů Proc aktualizován v systému Linux?

  2. Linux – Proč existuje zásada jádra Linuxu, která nikdy nenaruší uživatelský prostor?

  3. Proč pr_debug linuxového jádra nedává žádný výstup?

  1. Linux - zkontrolujte, zda na konci souboru není prázdný řádek

  2. Proč je v Linuxu potřeba upravovat tabulky systémových volání?

  3. Proč je Linux NFS server implementován v jádře na rozdíl od uživatelského prostoru?

  1. Linux – Jak najít implementace systémových volání jádra Linuxu?

  2. Linux – Proč nemůže jádro spustit inicializaci?

  3. Linux:Kam umístit odkládací soubor