Чому звичайний користувач не може видалити підручник 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-інструменти. Ситуація все ще виникає з Ubuntu Saucy, 3.11.0-4-genericядром, v0.20-rc1btrfs-інструментами.


Наскільки я розумію, цей тип файлової системи ще експериментальний і не готовий до виробництва.
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 (цікава сторона зауваження: "Знімок" часто використовується беззмінно у вихідному коді з "subvolum" чомусь). Тому я перейшов до вихідного коду ядра і знайшов обох обробників в fs/btrfs/ioctl.c.

Врешті-решт я простежив це назад до btrfs_ioctl_snap_destroy()лінії 2116:

     if (!capable(CAP_SYS_ADMIN)){

Зокрема, це перевірка, якщо вони не мають можливості, але якщо вони є, логіка пропускає безпосередньо до виконання операції. Тіло оператора if перевіряє, чи є звичайним користувачем, хто є власником inode USER_SUBVOL_RM_ALLOWEDпідпотоку, а параметр BTRFS увімкнено, він продовжує виконувати обробник. Якщо у них немає жодного обробника ioctl, виходить із помилкою.

Так виглядає, що для знищення "знімка" (він же "підпункт") зазвичай потрібен користувач, який має CAP_SYS_ADMIN(або для того, USER_SUBVOL_RM_ALLOWEDщоб його було ввімкнено, і користувач "володіє" даним підпунктом). Чудово, а як щодо створення знімка / обсягу?

Схоже, цей обробник для ioctl, як btrfs_ioctl_snap_create()видається, не містить capable()прямого або опосередкованого виклику . Оскільки це основний спосіб посередництва доступу, я маю на увазі, що створення підмножини завжди вдається. Це пояснює на функціональному рівні, чому ви бачите те, що бачите.

Я не можу говорити, чому це вважається бажаним за межами основного випадку використання BTRFS з сервером з обмеженим доступом користувачів. Цього недостатньо, але я не бачу жодного коду, щоб фактично зупинити операцію. Якщо ви не можете знайти відповідь, чому це так (і ви хочете це зробити), можливо, вам доведеться запитати у списку розсилки ядра.

Висновок

Моє дослідження, схоже, вказує на те, що кожен може створювати підпункти, але для того, щоб видалити підпункт, який вам або потрібно мати, CAP_SYS_ADMINабо він потрібен істинним, і те, що користувач, що викликає, є власником inode subvolume та USER_SUBVOL_RM_ALLOWEDувімкнено.

Створення підтомника не має сенсу, тому я, мабуть, пропускаю якийсь непрямий спосіб відмови в роботі, оскільки це здається простим способом DoS до системи.

Примітка: я не в тому місці, де я можу перевірити цю функціональність, але як тільки я повернусь додому, я можу встановити, чи setcapмагія працює, як це передбачає.


То, як це має сенс (щодо вашого питання щодо DoS), якщо rmdirце дозволено на порожніх підтомниках. Тоді rm -rбуде працювати прозоро. На жаль, код просто ще не був розроблений. Схоже, хтось зробив три спроби в 2010 році, а потім відмовився :(. Spinics.net/lists/linux-btrfs/msg06499.html
sourcejedi

5

Видалення підтомника дозволяє комусь від’єднати файли, якими він не володіє. На мою думку, файли, які привілейований користувач пише у місці, вибраному менш привілейованим користувачем, є чесною грою, але людина, яка внесла внесок у кореневу функцію видалення, напевно, не відчувала себе достатньо впевнено щодо того, наскільки безпечна ця семантика була та вміст надіслати їх як новий варіант монтажу ( mount -o user_subvol_rm_allowed).


1
Добре, що в UNIX® ви можете легко від’єднати файл, яким ви не володієте - вам просто потрібно мати дозвіл на запис у його каталог.
poige

У мене така ж проблема у fedora 20, у мене є / home в підпункті, я використовую root користувача, але все одно я не можу видалити / home
c4f4t0r

poige, якщо відповідний файл знаходиться у папці, у якій ви не є власником, ви не можете від’єднати його, і ви не можете від’єднати саму папку, оскільки вона все ще містить у собі матеріали. Ви можете виконувати в цій папці неруйнівні дії, наприклад переміщення або перейменування.
sleblanc

-1

"Неможливо видалити / додому" (це @home).

Чому ви хочете видалити підтомник, у якому перебуває ваш / home / account, якщо ви не створили / home_snapshot_yymmdd знімок для заміни / home?

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

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


Здається, вони вже зробили це. Btrfs не робить @ і @home, якщо ви не скажете їм (або ваш дистрибутив, подібний Ubuntu, робить це для вас).
Антон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.