Dlaczego zwykły użytkownik nie może usunąć podobjętości btrfs

12

Korzystając z systemu plików btrfs montowanego w pętli, z odpowiednio ustawionymi uprawnieniami, użytkownik może swobodnie tworzyć podwoluminy btrfs:

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

Jednak próba usunięcia nowo utworzonego podwoluminu powoduje błąd:

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'

Użytkownik root oczywiście może go usunąć:

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

Ta różnica w zachowaniu między operacjami tworzenia i usuwania wydaje się nieco dziwna. Czy ktoś może rzucić na to trochę światła?

Oto dokładna sekwencja poleceń:

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

Oto uprawnienia:

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

I odpowiedni wiersz na df -T:

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

Distro to Debian Wheezy, 3.2.0-4-686-paejądro, v0.19btrfs-tools. Sytuacja nadal występuje w Ubuntu Saucy, 3.11.0-4-genericjądrze, v0.20-rc1narzędziach btrfs.

goncalopp
źródło
Z mojego zrozumienia, ten typ systemu plików jest wciąż eksperymentalny i nie jest gotowy do produkcji.
mdpc,
Czy możesz dodać dane wyjściowe df -Ti btrfs version? Kiedy spróbowałem tego samego, otrzymałem następujący błąd „BŁĄD: nie można utworzyć objętości cząstkowej - Odmowa zezwolenia”
bsd
@mdpc Chociaż to prawda, btrfs istnieje już od kilku lat i na tym etapie oczekuje się, że będzie nieco stabilny. W tym momencie nadal przydatne może być zrozumienie, czy jest to błąd, czy „funkcja”.
goncalopp
@bdowning Dodałem dokładną sekwencję poleceń, df i używanych wersji.
goncalopp,
Jądro 3.2 ma już ponad półtora roku. Jeśli chcesz grać z eksperymentalnymi systemami plików, możesz chcieć uruchomić bardziej aktualne jądro.
psusi

Odpowiedzi:

14

To było dla mnie doświadczenie uczenia się, ale w końcu to rozgryzłem. Wyjaśnię tutaj mój proces, aby łatwiej było dowiedzieć się, jak samodzielnie to rozwiązać (dokumentacja BTRFS, jak jestem pewien, że się dowiedziałeś, jest na razie stosunkowo niekompletna).

Na początku myślałem, że utworzenie podobjętości było za ioctlpomocą programu obsługi, który nie przeprowadzał żadnej kontroli zdolności (co mogło być, lub nie, problemem bezpieczeństwa w zależności od tego, czy była w tym jakaś logika), podczas gdy usunięcie go bezpośrednio modyfikowało metadane (a zatem użytkownik może wymagać CAP_SYS_RAWIOpoprawnej pracy).

Aby to sprawdzić, otworzyłem btrfs-utilskod źródłowy i oto, co znalazłem:

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

Cóż, to nie jest pomocne, oba są ioctl (ciekawa uwaga: „migawka” jest często używana zamiennie w kodzie źródłowym z „podobjętością” z jakiegoś powodu). Więc poszedłem do kodu źródłowego jądra i znalazłem oba programy obsługi fs/btrfs/ioctl.c.

W końcu prześledziłem go z powrotem do btrfs_ioctl_snap_destroy()linii 2116:

     if (!capable(CAP_SYS_ADMIN)){

W szczególności jest to sprawdzenie, czy nie mają możliwości, ale jeśli ją mają, logika przeskakuje prosto do wykonania operacji. Treść instrukcji if sprawdza, czy to zwykły użytkownik, który jest właścicielem i-węzła USER_SUBVOL_RM_ALLOWEDpodwolumny, a opcja BTRFS umożliwia kontynuowanie wykonywania procedury obsługi. Jeśli nie mają obsługi ioctl, program kończy działanie z błędem.

Wygląda więc na to, że zniszczenie „migawki” (inaczej „objętości podrzędnej”) wymaga na ogół użytkownika, który ma CAP_SYS_ADMIN(lub USER_SUBVOL_RM_ALLOWEDmusi być włączony, a użytkownik „jest właścicielem” podanej objętości). Świetnie, a co z tworzeniem migawki / woluminu?

Wygląda na btrfs_ioctl_snap_create()to, że moduł obsługi ioctl nie zawiera żadnego wywołania capable()bezpośrednio lub pośrednio. Ponieważ jest to główny sposób pośrednictwa dostępu, rozumiem, że tworzenie podobjętości zawsze kończy się powodzeniem. To wyjaśnia na poziomie funkcjonalnym, dlaczego widzisz to, co widzisz.

Nie mogę powiedzieć, dlaczego jest to pożądane poza głównym przypadkiem użycia BTRFS z serwerem z ograniczonym dostępem użytkownika. To nie wystarcza, ale nie widzę żadnego kodu, który by faktycznie zatrzymał operację. Jeśli nie możesz znaleźć odpowiedzi na pytanie, dlaczego tak jest (i zależy ci na tym), być może będziesz musiał zapytać na liście mailingowej jądra.

Wniosek

Moje badania wydają się wskazywać, że każdy może tworzyć podwoluminy, ale aby usunąć podwolumeny, musisz je mieć CAP_SYS_ADMINalbo musi być prawdziwe, że wywołujący użytkownik jest właścicielem i-węzła podwolumny i USER_SUBVOL_RM_ALLOWEDwłączony.

Tworzenie podobjętości nie ma sensu, więc prawdopodobnie brakuje mi jakiegoś pośredniego sposobu, aby odmówić operacji, ponieważ wydaje się to łatwym sposobem na DoS systemu.

Uwaga: Nie jestem w miejscu, w którym mogę zweryfikować tę funkcjonalność, ale kiedy wrócę do domu, mogę ustawić, czy setcapmagia działa tak, jak to przewiduje.

Bratchley
źródło
Ma to sens (w odniesieniu do twojego problemu DoS), jeśli rmdirjest dozwolone w pustych podwoluminach. Wtedy rm -rbędzie działał transparentnie. Niestety kod po prostu nie został jeszcze opracowany. Wygląda na to, że ktoś w 2010 roku wykonał trzy próby, a potem się poddał :(. Spinics.net/lists/linux-btrfs/msg06499.html
sourcejedi
5

Usunięcie podwolumny pozwala komuś odłączyć pliki, których nie jest właścicielem. Moim zdaniem pliki, które uprzywilejowany użytkownik zapisuje w miejscu wybranym przez mniej uprzywilejowanego użytkownika, są uczciwą grą, ale osoba, która przyczyniła się do usunięcia funkcji rootowania, prawdopodobnie nie była wystarczająco pewna, jak bezpieczna jest ta semantyka aby przesłać je jako nową opcję montowania ( mount -o user_subvol_rm_allowed).

Gabriel
źródło
1
O dziwo, w systemie UNIX® można łatwo odłączyć plik, którego nie posiadasz - wystarczy mieć uprawnienia do zapisu w jego katalogu.
poige
Mam ten sam problem na Fedorze 20, mam / home w objętości cząstkowej, używam root użytkownika, ale w każdym razie nie mogę usunąć / home
c4f4t0r
poige, jeśli dany plik znajduje się w folderze, którego nie jesteś właścicielem, nie możesz go odłączyć i nie możesz odłączyć samego folderu, ponieważ nadal zawiera on rzeczy. Możesz wykonywać nieniszczące operacje na tym folderze, takie jak przenoszenie go lub zmiana jego nazwy.
sleblanc
-1

„Nie można usunąć / home” (czyli @home).

Dlaczego chcesz usunąć podwolumnę, na której znajduje się Twoje konto / home /, chyba że utworzyłeś migawkę / home_snapshot_yymmdd w celu zastąpienia / home?

Jestem nowy w używaniu btrfs, ale oto, co się dowiedziałem: @ / i @home (/ i / home) są tworzone przez btrfs, gdy jest zainstalowany na twoim HD jako system plików. Chyba że przywracasz / home z poprzedniej migawki, tak jak rozumiem, odcinałbyś się na kolana.

Możesz jednak zamontować urządzenie, na którym / home jest włączone, AS ROOT, używając mount / dev / sa / mnt / (lub na jakimkolwiek innym urządzeniu, na którym działa Twój system btrfs). Następnie cd na / mnt /, a stamtąd wydaj polecenie delete dla @Dom. Następnie możesz użyć komendy mv, aby przenieść @home_snapshot_yymmdd (lub cokolwiek, jak ją nazwałeś) do @home. Przeniesienie może potrwać kilka godzin, w zależności od wielkości @home. Następnie wróć z powrotem na swoje konto i wydaj sudo umount / mnt / Nigdy tak naprawdę się nie wylogowujesz ani nie zamykasz systemu. To jest piękno btrfs.

GreyGeek
źródło
Wygląda na to, że już to zrobili. Btrfs nie tworzy @ i @home, chyba że im to powiesz (lub Twoja dystrybucja taka jak Ubuntu zrobi to za Ciebie).
Anthon