Estoy tratando de entender los contenedores y me topé con un truco aparentemente encontrado por los desarrolladores de LXC, vereste runc PR: Puede llamar pivot_root(".", ".")
, lo que evita la necesidad de un directorio donde colocar la raíz anterior. Sin embargo, esto hace que el espacio de nombres de montaje se comporte de manera extraña:
unshare --user --map-root-user --mount bash -c "
mount --bind containerfs bindmountpoint
cd bindmountpoint
pivot_root . .
# this is fine:
ls -l /
# this is not fine:
ls -l /..
"
El padre de .
, al que se accede a través de ./..
o apunta a la raíz del espacio de nombres de montaje raíz ( /..
¡ /proc/<any>/cwd/..
todavía no he intentado anidar)! No apunta al padre de containerfs
nor bindmountpoint
, sino en realidad a la raíz del espacio de nombres de montaje raíz/externo.
De manera similar, cuando lo intento nsenter --user --preserve-credentials --mount --target=<pid>
, este nuevo proceso tiene su CWD ubicado en la raíz del espacio de nombres de montaje raíz.
Nada de esto sucede cuando yo pivot_root(".", "oldroot")
. El comportamiento también desaparece al desmontar la raíz antigua, ya sea mediante un descriptor de archivo umount -l /
o umount -l /proc/1/cwd
.
También probé esta secuencia de llamadas al sistema desde un programa C personalizado, ya que la documentación del pivot_root
único da garantías sobre el proceso actual (así que hago todo en el mismo proceso). El comportamiento es el mismo que el de los pasos multiproceso que utilizan las herramientas CLI que se muestran arriba.
Probado en un kernel 5.3.
¿Qué pasa cuando corro pivot_root(".", ".")
?
Respuesta1
pivot_root(new_root, put_old)
mueve el antiguo directorio raíz del proceso de llamada (que debe ser una raíz de un montaje) put_old
y lo coloca new_root
en su lugar. Luego establece el directorio actual y la raíz de cada proceso que se configuró en el directorio raíz anterior en new_root
.
Entonces, después de que pivot_root(".", ".")
el nuevo directorio raíz tenga el antiguo directorio raíz montado encima de él.
Siempre que ..
se resuelva en un directorio que tiene otro directorio montado, en realidad se resuelve en el directorio que está montado en la parte superior. Esto coincide con el comportamiento histórico de Unix y Linux donde ..
, excepto en el directorio raíz de un sistema de archivos, no tenía un manejo especial en el recorrido de ruta y se implementaba mediante una entrada de directorio almacenada en el disco.
Este no es un escape del espacio de nombres de montaje.
Respuesta2
Parece un error de buena fe...
Verifique el kernel más reciente de su distribución e infórmelo con todos los detalles (¡adjunte su programa de prueba!).