一般ユーザーがbtrfsサブボリュームを削除できない理由

一般ユーザーがbtrfsサブボリュームを削除できない理由

ループにマウントされたユーザーの作成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カーネル、btrfs-toolsで発生します。v0.20-rc1

ベストアンサー1

まあ、それは私にとって学習経験でしたが、ついにそれを得ました。これらの問題を直接解決する方法をより簡単に理解できるように、ここで私のプロセスを説明します。 (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(興味深い注意:何らかの理由で、「スナップショット」はソースコードで「サブボリューム」と同じ意味で使用されることが多いです)。だからカーネルのソースコードをよりfs/btrfs/ioctl.c

btrfs_ioctl_snap_destroy()最後に2116行まで追跡しました。

     if (!capable(CAP_SYS_ADMIN)){

具体的には、いいえ能力があるが能力がある場合、論理はすぐにタスクの実行に進みます。 ifステートメントの本文では、サブボリュームinodeの所有者が通常のユーザーであることを確認し、USER_SUBVOL_RM_ALLOWEDBTRFSオプションが有効になってもハンドラーの実行が続行されます。何もない場合、ioctlハンドラはエラーで終了します。

CAP_SYS_ADMINしたがって、「スナップショット」(別名「サブボリューム」)を削除するには、通常、ユーザーの所有権(または特定のサブボリュームをアクティブにし、ユーザーが「所有」)を必要とするようですUSER_SUBVOL_RM_ALLOWED。いいですね。スナップショット/ボリュームを作成してみてはいかがですか?

ioctlハンドラはbtrfs_ioctl_snap_create()直接または間接呼び出しを含まないようですcapable()。これがプロキシアクセスが行われる基本的な方法なので、サブボリュームの作成を意味すると仮定します。いつも効果がありました。これは、機能レベルであなたが見るものを見る理由を説明します。

話せないなぜこれは、BTRFSの主なユースケース(つまり、ユーザーアクセスが制限されたサーバー)を除いて望ましいと考えられています。十分ではありませんが、実際にタスクを停止するコードは表示されません。理由に対する答えが見つからない場合(そしてそれを得たい場合)、カーネルメーリングリストに尋ねることもできます。

結論として

私の研究では、誰でもサブボリュームを作成できますが、サブボリュームを削除するには、サブボリュームを所有またはCAP_SYS_ADMIN呼び出すユーザーがサブボリュームinodeの所有者になり、USER_SUBVOL_RM_ALLOWEDそれを有効にする必要があります。

サブボリュームを作成することは意味がないため、操作を拒否する間接的な方法が欠落している可能性があります。これはシステムにDoSを実行する簡単な方法のようです。

注:この機能を確認することはできませんが、家に着いたらsetcap期待通りに動作するように魔法を設定できます。

おすすめ記事