Por que um usuário comum não pode excluir um subvolume do btrfs?

11

Usando um sistema de arquivos btrfs criado pelo usuário e montado em loop, com as permissões configuradas corretamente, um usuário pode criar livremente subvolumes btrfs:

user@machine:~/btrfs/fs/snapshots$ /sbin/btrfs sub create newsubvol
Create subvolume './newsubvol'

No entanto, tentar excluir o subvolume recém-criado resulta em um erro:

user@machine:~/btrfs/fs/snapshots$ /sbin/btrfs sub del newsubvol
Delete subvolume '/home/user/btrfs/fs/snapshots/newsubvol'
ERROR: cannot delete '/home/user/btrfs/fs/snapshots/newsubvol'

O usuário root, é claro, pode excluí-lo:

root@machine:/home/user/btrfs/fs/snapshots# /sbin/btrfs sub del newsubvol
Delete subvolume '/home/user/btrfs/fs/snapshots/newsubvol'

Essa diferença de comportamento entre as operações de criação e exclusão parece um pouco estranha. Alguém pode lançar alguma luz sobre isso?

Aqui está a sequência exata de comandos:

user@machine:~$ dd if=/dev/zero of=btrfs_disk bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 1.2345 s, 84.9 MB/s
user@machine:~$ mkdir mountpoint
user@machine:~$ /sbin/mkfs.btrfs btrfs_disk

WARNING! - Btrfs Btrfs v0.19 IS EXPERIMENTAL
WARNING! - see http://btrfs.wiki.kernel.org before using

SMALL VOLUME: forcing mixed metadata/data groups
Created a data/metadata chunk of size 8388608
fs created label (null) on btrfs_disk
    nodesize 4096 leafsize 4096 sectorsize 4096 size 100.00MB
Btrfs Btrfs v0.19
user@machine:~$ sudo mount btrfs_disk mountpoint/
user@machine:~$ cd mountpoint/
user@machine:~/mountpoint$ /sbin/btrfs sub create test
Create subvolume './test'
user@machine:~/mountpoint$ /sbin/btrfs sub delete test
Delete subvolume '/home/user/mountpoint/test'
ERROR: cannot delete '/home/user/mountpoint/test' - Operation not permitted

Aqui estão as permissões:

user@machine:~/mountpoint$ ls -la
total 4
drwxr-xr-x 1 user user    8 Set  4 09:30 .
drwx------ 1 user user 4486 Set  4 09:29 ..
drwx------ 1 user user    0 Set  4 09:38 test

E a linha relevante em df -T :

Filesystem              Type     1K-blocks      Used Available Use% Mounted on
/dev/loop0              btrfs       102400        32     98284   1% /home/user/mountpoint

A distro é um Debian Wheezy, 3.2.0-4-686-pae kernel, v0.19 btrfs-tools. A situação ainda ocorre no Ubuntu Saucy, 3.11.0-4-generic kernel, v0.20-rc1 btrfs-tools.

    
por goncalopp 31.08.2013 / 01:04

3 respostas

12

Bem, esta foi uma experiência de aprendizado para mim, mas acabei descobrindo. Vou explicar meu processo aqui para que seja mais fácil saber como resolver isso sozinho (a documentação do BTRFS, como tenho certeza que você descobriu, está relativamente incompleta por enquanto).

No começo, pensei que criar o subvolume era um ioctl com um manipulador que não fazia nenhuma verificação de capacidade (que pode ou não ter sido um problema de segurança dependendo se havia alguma lógica nele), enquanto a exclusão ele estava modificando os metadados diretamente (e, portanto, o usuário pode exigir que CAP_SYS_RAWIO funcione corretamente).

Para verificar, eu abri o código-fonte btrfs-utils e foi isso que encontrei:

Create subvolume, cmds-receive.c Line 180:
         ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);

Delete subvolume, cmds-subvolume.c Line 259:
         res = ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &args);

Bem, isso não é útil, eles são ambos ioctl's (nota interessante: "snapshot" é freqüentemente usado de forma intercambiável no código fonte com "subvolume" por algum motivo). Então eu fui ao código-fonte do kernel e encontrei os dois manipuladores em fs/btrfs/ioctl.c .

Eventualmente, eu o rastreei de volta para btrfs_ioctl_snap_destroy() e na linha 2116:

     if (!capable(CAP_SYS_ADMIN)){

Especificamente, esta é uma verificação se eles não têm a capacidade, mas se eles o tiverem, a lógica irá direto para a execução da operação. O corpo da instrução if verifica se é o usuário regular quem é o proprietário do inode do subvolume e se a opção USER_SUBVOL_RM_ALLOWED BTRFS está habilitada para continuar executando o manipulador. Se eles não tiverem o manipulador ioctl, haverá um erro.

Portanto, parece que destruir um "instantâneo" (também conhecido como "subvolume") geralmente requer um usuário que tenha CAP_SYS_ADMIN (ou que USER_SUBVOL_RM_ALLOWED esteja habilitado e que o usuário "possua" o subvolume fornecido). Ótimo, que tal criar um instantâneo / volume?

O manipulador para o ioctl parece ser btrfs_ioctl_snap_create() . Esse manipulador parece não conter nenhuma chamada para capable() direta ou indiretamente. Como essa é a principal maneira de acesso é intermediado, estou tomando isso como significando que a criação de subvolume sempre é bem-sucedida. Isso explica em um nível funcional porque você está vendo o que está vendo.

Eu não posso falar com porque isso é considerado desejável fora do principal caso de uso do BTRFS estar com um servidor com acesso de usuário restrito. Isso não é suficiente, mas não estou vendo nenhum código para interromper a operação. Se você não consegue encontrar uma resposta do porquê (e você se importa em tê-lo), você pode ter que perguntar na lista de discussão do kernel.

Conclusão

Minha pesquisa parece indicar que qualquer pessoa pode criar subvolumes, mas para excluir um subvolume, é necessário ter CAP_SYS_ADMIN ou é necessário que o usuário chamador seja o proprietário do inode de subvolume e USER_SUBVOL_RM_ALLOWED ativado.

A criação de subvolume não faz sentido, então provavelmente estou perdendo alguma forma indireta de a operação ser negada, já que parece ser uma maneira fácil de fazer DoS um sistema.

Observação: não estou em um local em que possa verificar essa funcionalidade, mas quando chegar em casa, posso definir se setcap magic funciona como isso é previsto.

    
por 22.09.2013 / 20:03
4

A exclusão de um subvolume permite que alguém desvincule arquivos que não são de sua propriedade. Na minha opinião, os arquivos que um usuário privilegiado escreve em um local escolhido por um usuário menos privilegiado são um jogo justo, mas a pessoa que contribuiu com a funcionalidade de exclusão não-raiz provavelmente não se sentia confiante o suficiente sobre quão segura era a semântica para enviá-los como uma nova opção de montagem ( mount -o user_subvol_rm_allowed ).

    
por 22.09.2013 / 21:22
-1

"Não é possível excluir / home" (que é @home).

Por que você deseja excluir o subvolume no qual sua conta / home / reside, a menos que tenha criado um instantâneo / home_snapshot_yymmdd para substituir / home por?

Eu sou novo em usar o btrfs, mas foi o que descobri: @ / e @home (/ e / home) são criados pelo btrfs quando são instalados no seu HD como o sistema de arquivos. A menos que você esteja fazendo uma restauração de / home de um instantâneo anterior, pelo que entendi, você estaria se cortando de joelhos.

No entanto, você pode montar o dispositivo em que o / home está, AS ROOT, usando mount / dev / sa / mnt / (ou o que dispositivo seu sistema btrfs em execução) Em seguida, cd para / mnt / e de lá emita o comando delete para @home. Então você pode usar o comando mv para mover @home_snapshot_yymmdd (ou o que você nomeou) para @home. A mudança pode levar horas, dependendo do tamanho do @home. Em seguida, devolva o CD à sua conta e edite sudo umount / mnt / Você nunca realmente fez logout ou desligou seu sistema. Essa é uma beleza de btrfs.

    
por 28.01.2014 / 18:18

Tags