Warum kann ein normaler Benutzer ein btrfs-Subvolume nicht löschen?

12

Unter Verwendung eines vom Benutzer in einer Schleife erstellten btrfs-Dateisystems kann ein Benutzer mit den richtigen Berechtigungen frei btrfs-Subvolumes erstellen:

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

Der Versuch, das neu erstellte Subvolume zu löschen, führt jedoch zu einem Fehler:

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'

Der Root-Benutzer kann es natürlich löschen:

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

Dieser Unterschied im Verhalten zwischen den Erstellungs- und Löschvorgängen scheint etwas seltsam. Kann jemand etwas Licht ins Dunkel bringen?

Hier ist die genaue Reihenfolge der Befehle:

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

Hier sind die Berechtigungen:

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

Und die entsprechende Zeile auf df -T:

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

Die Distribution ist ein Debian Wheezy, 3.2.0-4-686-paeKernel, v0.19Btrfs-Tools. Die Situation tritt immer noch bei Ubuntu Saucy, 3.11.0-4-genericKernel, v0.20-rc1btrfs-tools auf.

Goncalopp
quelle
Nach meinem Verständnis ist dieser Dateisystemtyp noch experimentell und nicht produktionsbereit.
MDPC
Können Sie die Ausgabe von df -Tund hinzufügen btrfs version? Als ich das Gleiche versuchte, wurde der folgende Fehler angezeigt: "
FEHLER
@mdpc Obwohl dies zutrifft, gibt es btrfs schon seit einigen Jahren und es wird erwartet, dass es zu diesem Zeitpunkt etwas stabil ist. Es kann immer noch nützlich sein, zu verstehen, ob es sich an dieser Stelle um einen Fehler oder eine Funktion handelt.
Goncalopp
@bdowning Ich habe die genaue Reihenfolge der Befehle, df und die von mir verwendeten Versionen hinzugefügt.
Goncalopp
Der 3.2-Kernel ist jetzt über anderthalb Jahre alt. Wenn Sie mit experimentellen Dateisystemen spielen möchten, möchten Sie möglicherweise einen aktuelleren Kernel ausführen.
Psusi

Antworten:

14

Nun, das war eine Lernerfahrung für mich, aber ich habe es schließlich herausgefunden. Ich erkläre meinen Prozess hier, damit Sie leichter selbst herausfinden können, wie man diese Dinge macht (die BTRFS-Dokumentation ist, wie Sie sicher herausgefunden haben, vorerst relativ unvollständig).

Zuerst dachte ich, dass das Erstellen des Subvolumes ioctlmit einem Handler durchgeführt wurde, der keine Funktionsprüfung durchführte (was möglicherweise ein Sicherheitsproblem war, abhängig davon, ob eine Logik vorhanden war), während das Löschen die Metadaten direkt änderte (und daher muss der Benutzer möglicherweise CAP_SYS_RAWIOordnungsgemäß arbeiten).

Zur Überprüfung habe ich den btrfs-utilsQuellcode geknackt und Folgendes gefunden:

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

Nun, das ist nicht hilfreich, sie sind beide ioctls (interessante Randnotiz: "snapshot" wird aus irgendeinem Grund im Quellcode häufig austauschbar mit "subvolume" verwendet). Also ging ich zum Kernel-Quellcode und fand beide Handler in fs/btrfs/ioctl.c.

Irgendwann habe ich es auf btrfs_ioctl_snap_destroy()und in Zeile 2116 zurückgeführt:

     if (!capable(CAP_SYS_ADMIN)){

Insbesondere ist dies eine Überprüfung, ob sie nicht über die Fähigkeit verfügen. jedoch über die Fähigkeit verfügen, springt die Logik direkt zur Ausführung der Operation. Der Hauptteil der if-Anweisung prüft, ob der reguläre Benutzer der Eigentümer des Inodes des Subvolumes ist und USER_SUBVOL_RM_ALLOWEDob die BTRFS-Option aktiviert ist, damit der Handler weiterhin ausgeführt wird. Ist dies nicht der Fall, wird der ioctl-Handler mit einem Fehler beendet.

Es sieht also so aus, als ob zum Zerstören eines "Snapshot" (auch "Subvolume" genannt) im Allgemeinen ein Benutzer erforderlich ist, der das angegebene Subvolume hat CAP_SYS_ADMIN(oder dafür USER_SUBVOL_RM_ALLOWEDaktiviert sein muss und dem der Benutzer "gehört"). Großartig, was ist mit dem Erstellen eines Schnappschusses / Volumes?

Der Handler für das ioctl scheint btrfs_ioctl_snap_create()dieser Handler zu sein, der weder capable()direkt noch indirekt einen Aufruf von enthält . Da dies die Hauptmethode für die Vermittlung des Zugriffs ist, meine ich damit die Erstellung eines Subvolumes immer erfolgreich ist. Dies erklärt auf funktionaler Ebene, warum Sie das sehen, was Sie sehen.

Ich kann nicht sprechen , warum dies wünschenswert außerhalb mit einem Server mit eingeschränktem Benutzerzugriff Hauptanwendungsfall Wesens BTRFS betrachtet wird. Das reicht nicht aus, aber ich sehe keinen Code, um den Vorgang tatsächlich zu stoppen. Wenn Sie keine Antwort darauf finden, warum das so ist (und Sie möchten es haben), müssen Sie möglicherweise auf der Kernel-Mailingliste nachfragen.

Fazit

Meine Nachforschungen scheinen darauf hinzudeuten, dass jeder Subvolumes erstellen kann, aber um ein Subvolume zu löschen, müssen Sie entweder Subvolumes haben CAP_SYS_ADMINoder es muss true sein, dass der aufrufende Benutzer der Eigentümer des Subvolumes inode und istUSER_SUBVOL_RM_ALLOWED aktiviert ist.

Die Erstellung des Subvolumes macht keinen Sinn, daher fehlt mir wahrscheinlich eine indirekte Möglichkeit, die Operation zu verweigern, da dies eine einfache Möglichkeit zu sein scheint, ein System zu tun.

Hinweis: Ich bin nicht an einem Ort, an dem ich diese Funktionalität überprüfen kann, aber wenn ich zu Hause bin, kann ich festlegen, ob setcapMagie funktioniert, wie dies vorhergesagt wird.

Bratchley
quelle
In Bezug auf Ihr DoS-Anliegen ist es sinnvoll, wenn dies rmdirauf leeren Subvolumes zulässig ist. Dann rm -rwird transparent gearbeitet. Leider wurde der Code (noch) nicht entwickelt. Es sieht so aus, als hätte jemand 2010 drei Versuche unternommen und dann aufgegeben :(. Spinics.net/lists/linux-btrfs/msg06499.html
sourcejedi
5

Durch Löschen eines Subvolumes kann eine Person die Verknüpfung von Dateien aufheben, deren Eigentümer sie nicht ist. Meiner Meinung nach sind die Dateien, die ein privilegierter Benutzer an einem von einem weniger privilegierten Benutzer ausgewählten Ort schreibt, fair, aber die Person, die die Nicht-Root-Löschfunktion beigesteuert hat, hat sich wahrscheinlich nicht sicher genug gefühlt, wie sicher diese Semantik war und war um sie als neue Mount-Option einzureichen ( mount -o user_subvol_rm_allowed).

Gabriel
quelle
1
Überraschenderweise können Sie in UNIX® die Verknüpfung einer Datei, die Sie nicht besitzen, auf einfache Weise aufheben. Sie benötigen lediglich Schreibrechte in ihrem Verzeichnis.
Poige
Ich habe das gleiche Problem auf Fedora 20, ich habe / home in einem Subvolume, ich verwende den Benutzer root, aber trotzdem kann ich / home nicht löschen
c4f4t0r
Wenn sich die betreffende Datei in einem Ordner befindet, dessen Eigentümer Sie nicht sind, können Sie die Verknüpfung nicht aufheben und die Verknüpfung des Ordners selbst nicht aufheben, da er noch Inhalte enthält. Sie können diesen Ordner nur zerstörungsfrei bearbeiten, z. B. verschieben oder umbenennen.
Sleblanc
-1

"Kann / home nicht löschen" (das ist @home).

Warum sollten Sie das Subvolume löschen, auf dem sich Ihr / home / -Konto befindet, es sei denn, Sie haben einen / home_snapshot_yymmdd-Snapshot erstellt, durch den / home ersetzt werden soll?

Ich bin neu in der Verwendung von btrfs, aber Folgendes habe ich herausgefunden: @ / und @home (/ und / home) werden von btrfs erstellt, wenn es auf Ihrer Festplatte als Dateisystem installiert wird. Wenn Sie nicht eine Wiederherstellung von / home von einem vorherigen Schnappschuss durchführen, wie ich es verstehe, würden Sie sich an den Knien abschneiden.

Sie können jedoch das Gerät, auf dem sich / home befindet, AS ROOT mit mount / dev / sa / mnt / (oder dem Gerät, auf dem Ihr btrfs-System ausgeführt wird) mounten. Wechseln Sie dann mit cd zu / mnt / und geben Sie von dort den Befehl delete für aus @Zuhause. Dann können Sie mit dem Befehl mv @home_snapshot_yymmdd (oder wie auch immer Sie es genannt haben) nach @home verschieben. Der Umzug kann abhängig von der Größe von @home Stunden dauern. Dann kehren Sie auf Ihr eigenes Konto zurück und geben sudo umount / mnt / aus. Sie haben Ihr System nie wirklich abgemeldet oder heruntergefahren. Das ist eine Schönheit von btrfs.

GreyGeek
quelle
Scheint, dass sie das schon getan haben. Btrfs macht @ und @home nur, wenn Sie es ihnen mitteilen (oder Ihre Distribution wie Ubuntu erledigt das für Sie).
Anthon