¿Cómo realizar chroot con espacios de nombres de Linux?

14

Después de leer sobre los espacios de nombres de Linux, tuve la impresión de que son, entre muchas otras características, una alternativa al chroot. Por ejemplo, en este artículo :

Otros usos [de los espacios de nombres] incluyen [...] el estilo de aislamiento chroot () de un proceso a una parte de la jerarquía de directorio único.

Sin embargo, cuando clono el espacio de nombres de montaje, por ejemplo con el siguiente comando, todavía veo todo el árbol raíz original.

unshare --mount -- /bin/bash

Entiendo que ahora puedo realizar montajes adicionales en el nuevo espacio de nombres que no se comparten con el espacio de nombres original y, por lo tanto, esto proporciona aislamiento, pero sigue siendo la misma raíz, por ejemplo, /etcsigue siendo la misma para ambos espacios de nombres. ¿Todavía necesito chrootcambiar la raíz o hay una alternativa?

Esperaba que esta pregunta proporcionara una respuesta, pero la respuesta solo usa chroot, nuevamente.

EDITAR # 1

Hubo un comentario ahora eliminado que menciona pivot_root. Como esto es realmente parte de linux/fs/namespace.c, de hecho es parte de la implementación de espacios de nombres. Esto sugiere que cambiar el directorio raíz solo con unsharey mountno es posible, pero los espacios de nombres proporcionan una versión propia, más inteligente chroot. Aún así, no entiendo la idea principal de este enfoque que lo hace fundamentalmente diferente chroot, incluso después de leer el código fuente (en el sentido de, por ejemplo, seguridad o mejor aislamiento).

EDITAR # 2

Este no es un duplicado de esta pregunta . Después de ejecutar todos los comandos de la respuesta, tengo /tmp/tmp.vyM9IwnKuY (o similar) por separado, ¡pero el directorio raíz sigue siendo el mismo!

koalo
fuente
Con respecto a la diferencia entre pivot_rooty chroot: eché un vistazo a las fuentes de Docker y descubrí que si falla la ejecución pivot_root, recurre a chroot, es decir, estos mecanismos se consideran al menos similares en funcionalidad para fines de contenedorización.
Danila Kiver

Respuestas:

13

Ingresar un espacio de nombres de montaje antes de configurar a chroot, le permite evitar abarrotar el espacio de nombres de host con montajes adicionales, por ejemplo para /proc. Puede usar chrootdentro de un espacio de nombres de montaje como un truco agradable y simple.

Creo que la comprensión tiene ventajas pivot_root, pero tiene una pequeña curva de aprendizaje. La documentación no explica todo ... aunque hay un ejemplo de uso en man 8 pivot_root(para el comando de shell). man 2 pivot_root(para la llamada al sistema) podría ser más claro si hiciera lo mismo e incluyera un programa C de ejemplo.

Cómo usar pivot_root

Inmediatamente después de ingresar al espacio de nombres de montaje, también necesita mount --make-rslave /o equivalente. De lo contrario, todos los cambios de montaje se propagan a los montajes en el espacio de nombres original, incluido el pivot_root. No quieres eso :).

Si usaste el unshare --mount comando, tenga en cuenta que está documentado para aplicar mount --make-rprivatede manera predeterminada. AFAICS este es un mal valor por defecto y no desea esto en el código de producción. Por ejemplo, en este punto, dejaría ejectde funcionar en un DVD o USB montado en el espacio de nombres del host. El DVD o USB permanecería montado dentro del árbol de montaje privado, y el núcleo no le permitiría expulsar el DVD.

Una vez que haya hecho eso, puede montar, por ejemplo, el /procdirectorio que usará. De la misma manera que lo harías para chroot.

A diferencia de cuando usas chroot , pivot_rootrequiere que su nuevo sistema de archivos raíz sea un punto de montaje. Si no lo es ya, puede satisfacer este mediante la simple aplicación de montaje en un aprieto: mount --rbind new_root new_root.

Use pivot_root- y luego umountel antiguo sistema de archivos raíz, con la opción -l/ MNT_DETACH. ( No necesitasumount -R , lo que puede llevar más tiempo ).

Técnicamente, usando pivot_root generalmente requiere involucrar el uso chroottambién; no es "uno u otro".

Según man 2 pivot_root, solo se define como el intercambio de la raíz del espacio de nombres de montaje. No está definido para cambiar a qué directorio físico apunta la raíz del proceso. O el directorio de trabajo actual ( /proc/self/cwd). Sucede que hace , pero este es un truco para manejar hilos de kernel. La página de manual dice que eso podría cambiar en el futuro.

Usualmente quieres esta secuencia:

chdir(new_root);            // cd new_root
pivot_root(".", put_old);   // pivot_root . put_old
chroot(".");                // chroot .

La posición de la chrooten esta secuencia es otro detalle sutil . Aunque el punto depivot_root es reorganizar el espacio de nombres de montaje, el código del núcleo parece encontrar el sistema de archivos raíz para moverse mirando la raíz por proceso, que es lo que chrootestablece.

Por qué usar pivot_root

En principio, tiene sentido usarlo pivot_rootpara seguridad y aislamiento. Me gusta pensar en la teoría de la seguridad basada en capacidades . Usted pasa una lista de los recursos específicos necesarios, y el proceso no puede acceder a otros recursos. En este caso, estamos hablando de los sistemas de archivos pasados ​​a un espacio de nombres de montaje. Esta idea se aplica generalmente a la función de "espacios de nombres" de Linux, aunque probablemente no la estoy expresando muy bien.

chrootsolo establece la raíz del proceso, pero el proceso aún se refiere al espacio de nombres de montaje completo. Si un proceso conserva el privilegio de realizar chroot, puede realizar una copia de seguridad del espacio de nombres del sistema de archivos. Como se detalla en man 2 chroot, "el superusuario puede escapar de una 'cárcel chroot' por ...".

Otra forma de deshacer la reflexión chrootes nsenter --mount=/proc/self/ns/mnt. Este es quizás un argumento más fuerte para el principio. nsenter/ setns()necesariamente vuelve a cargar la raíz del proceso, desde la raíz del espacio de nombres de montaje ... aunque el hecho de que esto funcione cuando los dos se refieren a directorios físicos diferentes, podría considerarse un error del kernel. (Nota técnica: podría haber varios sistemas de archivos montados uno encima del otro en la raíz; setns()usa el superior, el más reciente).

Esto ilustra una ventaja de combinar un espacio de nombres de montaje con un "espacio de nombres PID". Estar dentro de un espacio de nombres PID le impediría ingresar al espacio de nombres de montaje de un proceso no confinado. También evita que ingrese a la raíz de un proceso no confinado ( /proc/$PID/root). Y, por supuesto, un espacio de nombres PID también evita que elimine cualquier proceso que esté fuera de él :-).

sourcejedi
fuente
Esto ya ayuda mucho. Aún así, no estoy seguro de lo que quieres decir con "la montura en la parte superior del espacio de nombres". ¿Y hay alguna manera de cambiarlo?
koalo
1
@koalo editado :-). ps no sé por qué necesitarías fstab para "make-rslave" / "make-rprivate". systemd's switch-root.c simplemente lo hacemount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL)
sourcejedi
1
@koalo y luego los desarrolladores del kernel de Linux usaron "rootfs" cuando nombraron una cuarta cosa :-P. unix.stackexchange.com/questions/152029/…
sourcejedi
1
Esta respuesta y otras de @sourcejedi han sido excepcionalmente útiles, hubiera preguntado "pivot_root: no se puede desmontar put_old como ocupado", pero la respuesta ya estaba aquí, sé perezoso ya que la fuerza no funcionaráumount -l ./oldroot
earcam
1
Recientemente hubo una actualización de la página de manual pivot_root (2) con varias aclaraciones, y ahora incluye un programa de ejemplo. Es posible que desee actualizar su respuesta para reflejar esto? La página de manual ahora también explica el buen pivot_root(".", ".")truco, que en realidad es la forma más fácil de usar pivot_rooten la mayoría de las circunstancias (no es chrootnecesario).
Philipp Wendler