¿Por qué un usuario normal no puede eliminar un subvolumen btrfs?

12

Utilizando un sistema de archivos btrfs creado por el usuario montado en bucle, con los permisos establecidos correctamente, un usuario puede crear libremente subvolúmenes btrfs:

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

Sin embargo, al intentar eliminar el subvolumen recién creado se produce un error:

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'

El usuario root, por supuesto, puede eliminarlo:

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

Esta diferencia de comportamiento entre las operaciones de creación y eliminación parece un poco extraña. ¿Alguien puede arrojar algo de luz sobre esto?

Aquí está la secuencia exacta 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

Aquí están los permisos:

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

Y la línea relevante sobre df -T:

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

La distribución es un Debian Wheezy, 3.2.0-4-686-paekernel, v0.19btrfs-tools. La situación todavía ocurre en Ubuntu Saucy, 3.11.0-4-generickernel, v0.20-rc1btrfs-tools.

goncalopp
fuente
Según tengo entendido, este tipo de sistema de archivos todavía es experimental y no está listo para la producción.
mdpc
¿Se puede agregar la salida de df -Ty btrfs version? Cuando intenté lo mismo, recibí el siguiente error "ERROR: no se puede crear subvolumen - Permiso denegado"
bsd
@mdpc Si bien es cierto, btrfs ha existido durante algunos años, y se espera que sea algo estable en esta etapa. Todavía puede ser útil entender si esto es un error o una "característica", en este momento.
goncalopp
@bdowning He agregado la secuencia exacta de comandos, df y las versiones que utilicé.
goncalopp
El kernel 3.2 tiene ahora más de un año y medio. Si desea jugar con sistemas de archivos experimentales, es posible que desee ejecutar un núcleo más actualizado.
psusi

Respuestas:

14

Bueno, esta fue una experiencia de aprendizaje para mí, pero finalmente lo descubrí. Explicaré mi proceso aquí para que sea más fácil saber cómo resolver esto usted mismo (la documentación de BTRFS, como estoy seguro de que descubrió, es relativamente incompleta por el momento).

Al principio pensé que crear el subvolumen era ioctlcon un controlador que no realizaba ninguna verificación de capacidad (lo que puede haber sido un problema de seguridad o no, dependiendo de si había alguna lógica), mientras que eliminarlo modificaba los metadatos directamente (y, por lo tanto, el usuario puede necesitar CAP_SYS_RAWIOtrabajar correctamente).

Para verificar, abrí el btrfs-utilscódigo fuente y esto es lo que encontré:

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);

Bueno, eso no es útil, son tanto (nota interesante: "instantánea" se utiliza a menudo de forma intercambiable en el código fuente con el "volumen secundario" por alguna razón) de ioctl. Así que fui al código fuente del núcleo y encontré ambos controladores en fs/btrfs/ioctl.c.

Finalmente, lo rastreé hasta btrfs_ioctl_snap_destroy()y en la línea 2116:

     if (!capable(CAP_SYS_ADMIN)){

Específicamente, esta es una verificación si no tienen la capacidad, pero si la tienen, la lógica pasa directamente a realizar la operación. El cuerpo de la instrucción if verifica si el usuario normal es el propietario del inodo del USER_SUBVOL_RM_ALLOWEDsubvolumen y si la opción BTRFS está habilitada, continúa ejecutando el controlador. Si no tienen ninguno, el controlador ioctl sale con un error.

Por lo tanto, parece que destruir una "instantánea" (también conocido como "subvolumen") generalmente requiere un usuario que tenga CAP_SYS_ADMIN(o USER_SUBVOL_RM_ALLOWEDque esté habilitado y el usuario "posea" el subvolumen dado). Genial, ¿qué hay de crear una instantánea / volumen?

El controlador para el ioctl parece ser btrfs_ioctl_snap_create()este controlador parece no contener llamadas capable()directa o indirectamente. Como esa es la forma principal en que se negocia el acceso, considero que la creación de subvolúmenes siempre tiene éxito. Esto explica a nivel funcional por qué estás viendo lo que estás viendo.

No puedo hablar de por qué esto se considera deseable fuera del caso de uso principal de BTRFS en un servidor con acceso de usuario restringido. Eso no es suficiente, pero no veo ningún código para detener la operación. Si no puede encontrar una respuesta a por qué es así (y le interesa tenerla), puede que tenga que preguntar en la lista de correo del núcleo.

Conclusión

Mi investigación parece indicar que cualquiera puede crear subvolúmenes, pero para eliminar un subvolumen es necesario tener CAP_SYS_ADMINo es cierto que el usuario que llama es el propietario del inodo de subvolumen y está USER_SUBVOL_RM_ALLOWEDhabilitado.

La creación de subvolúmenes no tiene sentido, por lo que probablemente me estoy perdiendo alguna forma indirecta de negar la operación, ya que parece una manera fácil de hacer un sistema DoS.

Nota: No estoy en un lugar donde pueda verificar esta funcionalidad, pero una vez que llegue a casa puedo configurar si la setcapmagia funciona como predice.

Bratchley
fuente
La forma en que tiene sentido (con respecto a su preocupación DoS) es si rmdirestá permitido en subvolúmenes vacíos. Entonces rm -rfuncionará de manera transparente. Lamentablemente, el código simplemente no se desarrolló (todavía). Parece que alguien hizo tres intentos en 2010 y luego se rindió :(. Spinics.net/lists/linux-btrfs/msg06499.html
sourcejedi
5

Eliminar un subvolumen permite a alguien desvincular archivos que no son de su propiedad. En mi opinión, los archivos que escribe un usuario privilegiado en una ubicación elegida por un usuario menos privilegiado son juegos justos, pero la persona que contribuyó con la funcionalidad de eliminación no root probablemente no se sintió lo suficientemente segura sobre cuán segura era esa semántica y si estaba contenta para enviarlos como una nueva opción de montaje ( mount -o user_subvol_rm_allowed).

Gabriel
fuente
1
Bueno, sorprendentemente en UNIX® puede desvincular fácilmente un archivo que no es de su propiedad; solo necesita tener permiso de escritura en su directorio.
poige
Tengo el mismo problema en fedora 20, tengo / home en un subvolumen, estoy usando la raíz del usuario, pero de todos modos, no puedo eliminar / home
c4f4t0r
Poige, si el archivo en cuestión está en una carpeta que no es de su propiedad, no puede desvincularlo y no puede desvincular la carpeta en sí, ya que todavía contiene cosas en él. Solo puede realizar operaciones no destructivas en esta carpeta, como moverla o cambiarle el nombre.
sleblanc
-1

"No se puede eliminar / inicio" (que es @home).

¿Por qué desearía eliminar el subvolumen en el que reside su / home / account, a menos que haya creado una instantánea / home_snapshot_yymmdd para reemplazar / home?

Soy nuevo en el uso de btrfs, pero esto es lo que descubrí: btrfs crea @ / y @home (/ y / home) cuando se instala en su HD como sistema de archivos. A menos que esté haciendo una restauración de / home desde una instantánea anterior, según tengo entendido, se cortaría de rodillas.

Sin embargo, puede montar el dispositivo en el que está / home, AS ROOT, usando mount / dev / sa / mnt / (o en cualquier dispositivo en el que esté funcionando su sistema btrfs) Luego, cd a / mnt / y desde allí emita el comando de eliminación para @hogar. Luego puede usar el comando mv para mover @home_snapshot_yymmdd (o lo que sea que lo haya nombrado) a @home. La mudanza puede llevar horas, dependiendo del tamaño de @home. Luego, regrese a su propia cuenta en CD y emita sudo umount / mnt / Nunca ha cerrado la sesión o apagado su sistema. Eso es una belleza de btrfs.

GreyGeek
fuente
Parece que ya lo han hecho. Btrfs no crea @ y @home a menos que se lo pidas (o tu distribución como Ubuntu lo hace por ti).
Anthon