Почему обычный пользователь не может удалить подраздел btrfs

12

Используя смонтированную пользователем петлю файловую систему btrfs, с правильно установленными разрешениями, пользователь может свободно создавать подобъемы btrfs:

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

Тем не менее, попытка удалить только что созданный подобъем приводит к ошибке:

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'

Пользователь root, конечно, может удалить его:

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

Эта разница в поведении между операциями создания и удаления кажется немного странной. Может кто-нибудь пролить некоторый свет на это?

Вот точная последовательность команд:

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

Вот разрешения:

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

И соответствующая строка на df -T:

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

Дистрибутив - это Debian Wheezy, 3.2.0-4-686-paeядро, v0.19btrfs-tools. Ситуация все еще происходит на Ubuntu Saucy, 3.11.0-4-genericядре, v0.20-rc1btrfs-tools.

goncalopp
источник
Насколько я понимаю, этот тип файловой системы все еще экспериментален и не готов к работе.
MDPC
Можете ли вы добавить вывод df -Tи btrfs version? Когда я попробовал то же самое, я получил следующую ошибку «ОШИБКА: невозможно создать подраздел - В доступе отказано»
BSD
@mdpc Хотя это правда, btrfs существует уже несколько лет, и ожидается, что он будет несколько стабильным на данном этапе. На этом этапе может быть полезно понять, является ли это ошибкой или «особенностью».
goncalopp
@bdowning Я добавил точную последовательность команд, df и версии, которые я использовал.
goncalopp
Ядру 3.2 уже более полутора лет. Если вы хотите поиграть с экспериментальными файловыми системами, вы можете запустить более современное ядро.
psusi

Ответы:

14

Ну, это был опыт обучения для меня, но я в конце концов понял это. Я объясню здесь свой процесс, чтобы было проще понять, как самому разобраться в этом (документация BTRFS, как я уверен, вы узнали, относительно неполна в настоящее время).

Сначала я подумал, что создание подобъема было ioctlс обработчиком, который не делал никакой проверки возможностей (что могло или не могло быть проблемой безопасности в зависимости от того, была ли в нем какая-то логика), в то время как удаление его приводило к непосредственному изменению метаданных. (и, следовательно, пользователю может потребоваться CAP_SYS_RAWIOработать должным образом).

Чтобы проверить, я взломал btrfs-utilsисходный код, и вот что я нашел:

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

Ну, это не полезно, они оба ioctl (интересное примечание: «снимок» часто используется взаимозаменяемо в исходном коде с «subvolume» по некоторым причинам). Поэтому я пошел к исходному коду ядра и нашел оба обработчика fs/btrfs/ioctl.c.

В конце концов, я проследил это до btrfs_ioctl_snap_destroy()строки 2116:

     if (!capable(CAP_SYS_ADMIN)){

В частности, это проверка, если у них нет возможности, но если она есть, логика сразу переходит к выполнению операции. Тело оператора if проверяет, является ли обычный пользователь владельцем USER_SUBVOL_RM_ALLOWEDузла in-sub, и опция BTRFS позволяет ему продолжать выполнение обработчика. Если их нет, обработчик ioctl завершается с ошибкой.

Таким образом, похоже на то, что для уничтожения «снимка» (он же «подобъем») обычно требуется пользователь, который имеет CAP_SYS_ADMIN(или USER_SUBVOL_RM_ALLOWEDдолжен быть включен, а пользователь «владеет» данным подобъемом). Отлично, а как насчет создания снимка / тома?

Обработчик для ioctl выглядит так, как будто btrfs_ioctl_snap_create()этот обработчик не содержит вызовов capable()прямо или косвенно. Так как это основной способ доступа, я принимаю это, чтобы означать, что создание subvolume всегда успешно. На функциональном уровне это объясняет, почему вы видите то, что видите.

Я не могу сказать, почему это считается желательным, за исключением того, что основной сценарий использования BTRFS связан с сервером с ограниченным доступом пользователей. Этого недостаточно, но я не вижу никакого кода, чтобы фактически остановить операцию. Если вы не можете найти ответ на вопрос, почему это так (и вам это нужно), вам, возможно, придется спросить его в списке рассылки ядра.

Вывод

Похоже, мое исследование показывает, что любой может создавать подобъемы, но для того, чтобы удалить подобъем, вам нужно либо иметь, CAP_SYS_ADMINлибо истину, и то, что вызывающий пользователь является владельцем подузла inode и USER_SUBVOL_RM_ALLOWEDвключен.

Создание подобъема не имеет смысла, поэтому я, вероятно, упускаю какой-то косвенный способ отказа в операции, поскольку это кажется простым способом DoS системы.

Примечание: я не в том месте, где я могу проверить эту функциональность, но как только я вернусь домой, я могу установить, setcapработает ли магия так, как это предсказывает.

Bratchley
источник
Это имеет смысл (в отношении вашей озабоченности DoS), если rmdirэто разрешено на пустых подобъемах. Тогда rm -rбудет работать прозрачно. К сожалению, код просто не был разработан (пока). Похоже, что кто-то сделал три попытки в 2010 году, а затем сдался :(. Spinics.net/lists/linux-btrfs/msg06499.html
sourcejedi
5

Удаление подобъема позволяет кому-то отсоединить файлы, которые ему не принадлежат. На мой взгляд, файлы, которые привилегированный пользователь пишет в месте, выбранном менее привилегированным пользователем, являются честной игрой, но человек, который предоставил функцию удаления без полномочий root, вероятно, не был достаточно уверен в том, насколько безопасна эта семантика и была ли она контентом. представить их как новый параметр монтирования ( mount -o user_subvol_rm_allowed).

Габриель
источник
1
Что удивительно, в UNIX® вы можете легко отсоединить файл, который вам не принадлежит, - вам просто нужно иметь разрешение на запись в его каталог.
Пой
У меня такая же проблема на fedora 20, у меня / home в подобъеме, я использую пользовательский root, но все равно я не могу удалить / home
c4f4t0r
poige, если рассматриваемый файл находится в папке, которой вы не владеете, вы не можете отсоединить его и не можете отсоединить саму папку, так как она по-прежнему содержит содержимое. Вы можете выполнять только неразрушающие операции с этой папкой, например перемещать или переименовывать ее.
sleblanc
-1

"Невозможно удалить / home" (который является @home).

Почему вы хотите удалить подобъем, в котором находится ваша / home / учетная запись, если вы не создали снимок / home_snapshot_yymmdd для замены / home?

Я новичок в использовании btrfs, но вот что я обнаружил: @ / и @home (/ и / home) создаются btrfs, когда они установлены на вашем HD как файловая система. Если вы не делаете восстановление / home из предыдущего снимка, насколько я понимаю, вы отрежете себе колени.

Тем не менее, вы можете смонтировать устройство, на котором находится / home, AS ROOT, используя mount / dev / sa / mnt / (или любое другое устройство, на котором установлена ​​ваша система btrfs). Затем перейдите к / mnt / и оттуда выполните команду delete для @дом. Затем вы можете использовать команду mv, чтобы переместить @home_snapshot_yymmdd (или как вы его назвали) в @home. Перемещение может занять несколько часов, в зависимости от размера @home. Затем верните компакт-диск в свою учетную запись и выполните команду sudo umount / mnt /. Вы никогда не выходили из системы и не выключали свою систему. Это красота btrfs.

GreyGeek
источник
Кажется, они уже сделали это. Btrfs не создает @ и @home, если вы не скажете им об этом (или ваш дистрибутив, как Ubuntu, сделает это за вас).
Anthon