Debian 12 + LXD/LXC security.idmap.isolated falla

Debian 12 + LXD/LXC security.idmap.isolated falla

Debian 12.1 (6.1.0-11-amd64) que ejecuta LXD/LXC y en una configuración de contenedor sin privilegios security.idmap.isolated=trueparece no poder actualizar el propietario/grupo de los archivos del contenedor.

Aquí hay un ejemplo:

# lxc launch images:debian/12 debian
(...)

# lxc config get debian volatile.idmap.base
296608

# lxc stop debian
Error: The instance is already stopped

# lxc config set debian security.idmap.isolated true

# lxc config get debian security.idmap.isolated
true

# lxc start debian

Ahora, si enumero los archivos en el volumen contenedor, obtendré que todos son propiedad del rootusuario host:

# ls -la /mnt/NVME1/lxd/containers/debian/rootfs/
total 24
drwxr-xr-x 1 root   root  154 Sep  5 06:28 .
d--x------ 1 296608 root   78 Sep  5 15:59 ..
lrwxrwxrwx 1 root   root    7 Sep  5 06:25 bin -> usr/bin
drwxr-xr-x 1 root   root    0 Jul 14 17:00 boot
drwxr-xr-x 1 root   root    0 Sep  5 06:28 dev
drwxr-xr-x 1 root   root 1570 Sep  5 06:28 etc

Probé varias versiones de LXD/LXC. Esto sucede tanto con la versión 5.0.2 aptcomo con la 4.0 y 5.17 (la más reciente) desde snap.

Curiosamente, tengo otro Debian 10 (4.19.0-25-amd64) ejecutándose y un LXD 4 anterior a partir de snapahí, las cosas funcionan como se esperaba:

# ls -la /mnt/NVME1/lxd/containers/debian/rootfs/
total 0
drwxr-xr-x 1 1065536 1065536  138 Oct 29  2020 .
d--x------ 1 1065536 root      78 Oct 14  2020 ..
drwxr-xr-x 1 1065536 1065536 1328 Jul 24 19:07 bin
drwxr-xr-x 1 1065536 1065536    0 Sep 19  2020 boot
drwxr-xr-x 1 1065536 1065536    0 Oct 14  2020 dev
drwxr-xr-x 1 1065536 1065536 1716 Jul 24 19:08 etc

Como puede ver en estos sistemas, todos los archivos son propiedad de 1065536:1065536.


Actualizar:

Intenté explorar los mapas lxc config show debianen ambas máquinas y vi esto:

Máquina que ejecuta Debian 10:

security.idmap.isolated: "true"
(...)
volatile.idmap.base: "1065536"
volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1065536,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1065536,"Nsid":0,"Maprange":65536}]'
volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1065536,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1065536,"Nsid":0,"Maprange":65536}]'
volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1065536,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":1065536,"Nsid":0,"Maprange":65536}]'

Máquina que ejecuta Debian 12:

security.idmap.isolated: "true"
(...)
volatile.idmap.base: "231072"
volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":231072,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":231072,"Nsid":0,"Maprange":65536}]'
volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":231072,"Nsid":0,"Maprange":65536},{"Isuid":false,"Isgid":true,"Hostid":231072,"Nsid":0,"Maprange":65536}]'
volatile.last_state.idmap: '[]'

Actualizar:

También probé una nueva instalación deDebian 11 (5.10.0-25-amd64) y funciona como se esperaba:

root@vm-debian-11-cli:~# ls -la /mnt/NVME1/lxd/containers/debian/rootfs/
total 24
drwxr-xr-x 1 1065536 1065536  154 Sep  6 06:28 .
d--x------ 1 1065536 root      78 Sep  6 15:31 ..
lrwxrwxrwx 1 1065536 1065536    7 Sep  6 06:25 bin -> usr/bin
drwxr-xr-x 1 1065536 1065536    0 Jul 14 17:00 boot
drwxr-xr-x 1 1065536 1065536    0 Sep  6 06:28 dev
drwxr-xr-x 1 1065536 1065536 1570 Sep  6 06:28 etc

¿Por qué no se pobló volatile.last_state.idmap: '[]'? Al igual que con Debian 10 y 11, aparentemente esto puede estar relacionado con el nuevo kernel y/o su configuración.

¿Cómo puedo arreglarlo? Gracias.

Respuesta1

Aparentemente, esto es por diseño una característica de los núcleos más nuevos. Aquí hay una buena explicación de Stéphane Graber, mantenedor de LXC:

Antes de que VFS idmap estuviera disponible, necesitábamos solucionar la propiedad de los archivos haciendo que LXD reescribiera manualmente el propietario de cada archivo en el disco. Eso es lo que estás mostrando aquí en un kernel más antiguo.

En los kernels más nuevos, esto ya no es necesario ya que podemos hacer que el kernel mantenga los permisos en el disco sin cambios y simplemente los cambie dentro del kernel para que la propiedad se vea correcta dentro del contenedor.

Lo que estás mostrando arriba parece una configuración que funciona perfectamente en un kernel que admite VFS idmap.

De hecho, podría configurar esto en la máquina host:

root@vm-debian-12-cli:~# lxc info | grep 'shift\|idmap'
- storage_shifted
    idmapped_mounts: "true"
    shiftfs: "false"
    idmapped_mounts_v2: "true"

Y dentro de los contenedores, el punto de montaje raíz también se muestra como idmapped(última línea):

root@debian:~# cat /proc/self/uid_map
         0     231072      65536

root@debian:~# cat /proc/self/gid_map
         0     231072      65536

root@debian:~# cat /proc/self/mountinfo
490 460 0:24 /@rootfs/mnt/NVME1/lxd/containers/debian/rootfs / rw,relatime,idmapped shared:251 master:1 - btrfs /dev/sda1 rw,space_cache=v2,user_subvol_rm_allowed,subvolid=259,subvol=/@rootfs/mnt/NVME1/lxd/containers/debian

Para desactivar esto se puede:

Hay una variable de entorno que se puede pasar a LXD agregando una anulación en su unidad systemd. LXD_IDMAPPED_MOUNTS_DISABLE=1

Sin embargo, y según el señor Graber no deberíamos hacer eso:

Bien, entonces su sistema está funcionando perfectamente normalmente y con la menor sobrecarga posible en este momento, no hay nada de qué preocuparse.

El antiguo método de cambio previo al inicio era muy lento y muy riesgoso, ya que una falla o falla al cambiar un bit particular de metadatos (ACL, xattr,…) podría generar un problema de seguridad con el contenedor. También fue horrible para los sistemas de archivos CoW, ya que efectivamente hacía que pareciera que cada archivo en el contenedor había sido modificado, duplicando potencialmente GB de datos.

shiftfs (que era un truco específico de Ubuntu) y ahora el cambio de mapa de id de VFS adecuado, simplemente haga que el kernel aplique el uidmap/gidmap inverso en cualquier operación del sistema de archivos a un montaje que esté marcado como idmapped. Es una operación extremadamente trivial de realizar, permite cambios dinámicos en los mapas de contenedores (muy útil para aislados), permite compartir datos entre contenedores y admite adecuadamente todo lo que pueda contener un uid/gid (ioctl, xattr, acl,…), por lo que eliminando el riesgo de haber pasado por alto algo.

información relacionada