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

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

O Debian 12.1 (6.1.0-11-amd64) executando LXD/LXC e em uma configuração de contêiner sem privilégios security.idmap.isolated=trueparece não conseguir atualizar o proprietário/grupo dos arquivos do contêiner.

Aqui está um exemplo:

# 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

Agora, se eu listar os arquivos no volume do contêiner, todos eles pertencem ao rootusuário 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

Tentei várias versões do LXD/LXC. Isso acontece tanto com 5.0.2 quanto aptcom 4.0 e 5.17 (mais recente) de snap.

Curiosamente, tenho outro Debian 10 (4.19.0-25-amd64) em execução e um LXD 4 mais antigo a partir de snapentão, as coisas funcionam conforme o esperado:

# 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 você pode ver neste sistema todos os arquivos são de propriedade de 1065536:1065536.


Atualizar:

Tentei investigar os mapas em lxc config show debianambas as máquinas e vi isto:

Máquina rodando 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 rodando 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: '[]'

Atualizar:

Eu também tentei uma nova instalação doDebian 11 (5.10.0-25-amd64) e funciona como esperado:

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 que não povoou volatile.last_state.idmap: '[]'? Tal como acontece com o Debian 10 e 11, aparentemente isso pode estar relacionado ao novo kernel e/ou sua configuração.

Como posso consertar isso? Obrigado.

Responder1

Aparentemente, esse é um recurso intencional dos kernels mais recentes. Aqui está uma boa explicação de Stéphane Graber, mantenedor do LXC:

Antes de o idmap do VFS estar disponível, precisávamos contornar a propriedade do arquivo fazendo com que o LXD reescrevesse manualmente o proprietário de cada arquivo no disco. Isso é o que você está mostrando aqui em um kernel mais antigo.

Em kernels mais novos, isso não é mais necessário, pois podemos fazer com que o kernel mantenha as permissões no disco inalteradas e apenas mude no kernel para que a propriedade pareça correta dentro do contêiner.

O que você está mostrando acima parece uma configuração funcionando perfeitamente em um kernel que suporta idmap VFS.

De fato, eu poderia configurar isso na máquina host:

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

E dentro dos containers o ponto de montagem raiz também aparece como idmapped(última linha):

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 desabilitar isso pode-se:

Existe uma variável de ambiente que pode ser passada para o LXD adicionando uma substituição em sua unidade systemd. LXD_IDMAPPED_MOUNTS_DISABLE=1

No entanto, e de acordo com o Sr. Graber, não deveríamos fazer isso:

Ok, então seu sistema está operando perfeitamente normalmente e com a menor sobrecarga possível no momento, nada com que se preocupar.

O antigo método de mudança de pré-início era muito lento e muito arriscado, pois uma falha ou falha na mudança de um determinado bit de metadados (ACL, xattr,…) poderia permitir um problema de segurança com o contêiner. Também foi horrível para os sistemas de arquivos CoW, pois fazia com que parecesse que cada arquivo no contêiner havia sido modificado, potencialmente duplicando GBs de dados.

shiftfs (que era um hack específico do Ubuntu) e agora a mudança adequada do idmap do VFS, basta fazer com que o kernel aplique o uidmap/gidmap reverso em qualquer operação do sistema de arquivos para uma montagem marcada como idmapped. É uma operação extremamente trivial de realizar, permite alterações dinâmicas nos mapas de contêineres (muito útil para isolados), permite compartilhar dados entre contêineres e suporta adequadamente tudo que pode conter um uid/gid (ioctl, xattr, acl,…) então eliminando o risco de ter perdido alguma coisa.

informação relacionada