La documentación del kernel de Linux afirma:
Rootfs es una instancia especial de ramfs (o tmpfs, si está habilitado),
que siempre está presente en los sistemas 2.6. No puedes desmontar rootfs...
En todos los sistemas Linux que probé (kernel> 2.6 y procedimiento de arranque normal afaik, por ejemplo, ubuntu 12.04), mount
no muestra un rootfs
entrada.
Sin embargo, con una imagen buildroot al arrancar con un .cpio
externo archivo, está presente.
¿En qué casos hay un rootfs
entrada en mount
?
Respuesta aceptada:
- En sistemas antiguos,
mount
puede no estar de acuerdo con/proc/mounts
- La mayoría de las veces no verá
rootfs
en/proc/mounts
, pero todavía está montado. - ¿Podemos probar que rootfs todavía está montado?
1. En sistemas antiguos, mount
puede no estar de acuerdo con /proc/mounts
man mount
dice:“Los programas mount
y umount
tradicionalmente mantenía una lista de los sistemas de archivos actualmente montados en el archivo /etc/mtab
.”
El antiguo enfoque realmente no funciona para el sistema de archivos raíz. El sistema de archivos raíz puede haber sido montado por el kernel, no por mount
. Por lo tanto, entradas para /
en el /etc/mtab
puede ser bastante artificial y no estar necesariamente sincronizado con la lista actual de montajes del kernel.
No lo he comprobado con seguridad, pero en la práctica no creo que ningún sistema que utilice el esquema anterior inicialice mtab
para mostrar una línea con rootfs
. (En teoría, si mount
muestra rootfs
dependería del software que primero instaló el mtab
archivo).
man mount
continúa:“el archivo mtab real todavía es compatible, pero en los sistemas Linux actuales es mejor convertirlo en un enlace simbólico a /proc/mounts, porque un archivo mtab normal mantenido en el espacio de usuario no puede funcionar de manera confiable con espacios de nombres, contenedores y otros Linux avanzados. características.”
mtab se convierte en un enlace simbólico en Debian 7 y en Ubuntu 15.04.
1.1 Fuentes
Informe de Debian n.° 494001 – “instalador de debian:/etc/mtab debe ser un enlace simbólico a /proc/mounts con linux>=2.6.26”
#494001 se resuelve en sysvinit-2.88dsf-14. Consulte el mensaje de cierre, fechado el 14 de diciembre de 2011. El cambio está incluido en Debian 7 "Wheezy", publicado el 4 de mayo de 2013. (Utiliza sysvinit-2.88dsf-41).
Ubuntu retrasó este cambio hasta sysvinit_2.88dsf-53.2ubuntu1. Esa página de registro de cambios muestra que el cambio ingresa "vívido", que es el nombre en clave de Ubuntu 15.04.
2. La mayoría de las veces no verá rootfs
en /proc/mounts
, pero todavía está montado
A partir de Linux v4.17, esta documentación del kernel aún está actualizada. rootfs siempre está presente y nunca se puede desmontar. Pero la mayoría de las veces no puede verlo en /proc/mounts.
Puede ver rootfs si arranca en un shell initramfs. Si su initramfs es dracut
, como en Fedora Linux, puede hacer esto agregando la opción rd.break
a la línea de comandos del kernel. (Por ejemplo, dentro del cargador de arranque GRUB).
switch_root:/# grep rootfs /proc/mounts
rootfs / rootfs rw 0 0
Cuando dracut cambia el sistema al sistema de archivos raíz real, ya no puede ver rootfs en /proc/mounts. dracut puede usar switch_root
o systemd
para hacer esto. Ambos siguen la misma secuencia de operaciones, que se recomiendan en el documento del kernel vinculado.
En algunas otras publicaciones, las personas pueden ver rootfs en /proc/mounts después de desconectarse de initramfs. Por ejemplo en Debian 7:'¿Cómo puedo obtener información sobre "rootfs"'? Creo que esto debe ser porque el kernel cambió la forma en que muestra /proc/mounts, en algún momento entre la versión del kernel en Debian 7 y mi kernel v4.17 actual. De búsquedas posteriores, creo que rootfs se muestra en Ubuntu 14.04, pero no se muestra en Ubuntu 16.04 con Ubuntu kernel 4.4.0-28-generic.
Relacionado:Linux:¿Qué significa la letra 'u' en /dev/urandom?Incluso si no uso un initramfs y hago que el kernel monte el sistema de archivos raíz, no puedo ver rootfs en /proc/mounts. Esto tiene sentido ya que el código del kernel también parece seguir la misma secuencia de operaciones.
La operación que oculta rootfs es 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. ¿Podemos probar que rootfs todavía está montado?
Notoriamente, un simple chroot
se puede escapar cuando se está ejecutando como un usuario privilegiado. Si switch_root
no hizo nada más que chroot
, podríamos revertirlo y volver a ver 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
Sin embargo, el switch_root
completo la secuencia no puede ser revertida por esta técnica. La secuencia completa sí
-
Cambiar el directorio de trabajo actual (como en
/proc/self/cwd
), al punto de montaje del nuevo sistema de archivos:cd /newmount
-
Mueva el nuevo sistema de archivos, es decir, cambie su punto de montaje, para que quede directamente encima del directorio raíz.
mount --move . /
-
Cambiar el directorio raíz actual (como en
/proc/self/root
) para que coincida con el directorio de trabajo actual.chroot .
En el escape chroot anterior, pudimos atravesar desde el directorio raíz de ext4
sistema de archivos de vuelta a rootfs
usando ..
, porque el ext4
el sistema de archivos se montó en un subdirectorio de rootfs
. El método de escape no funciona cuando ext4
el sistema de archivos está montado en la raíz directorio de rootfs.
Pude encontrar el rootfs
usando un método diferente. (Al menos un importante desarrollador del kernel piensa que esto es un error en Linux).
http://archive.today/2018.07.22-161140/https://lore.kernel.org/lkml/[email protected]/
/* 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);
}
Probado en 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
(También confirmé que este sistema de archivos está vacío como se esperaba y se puede escribir).