Commit f9d9ef62cd3ecbd6cbb7957a253c1e81f69d5586
1 parent
20bcd64934
Exists in
master
and in
6 other branches
btrfs: do not allow mounting non-subvolumes via subvol option
There's a missing test whether the path passed to subvol=path option during mount is a real subvolume, allowing any directory located in default subovlume to be passed and accepted for mount. (current btrfs progs prevent this early) $ btrfs subvol snapshot . p1-snap ERROR: '.' is not a subvolume (with "is subvolume?" test bypassed) $ btrfs subvol snapshot . p1-snap Create a snapshot of '.' in './p1-snap' $ btrfs subvol list -p . ID 258 parent 5 top level 5 path subvol ID 259 parent 5 top level 5 path subvol1 ID 260 parent 5 top level 5 path default-subvol1 ID 262 parent 5 top level 5 path p1/p1-snapshot ID 263 parent 259 top level 5 path subvol1/subvol1-snap The problem I see is that this makes a false impression of snapshotting the given subvolume but in fact snapshots the default one: a user expects outcome like ID 263 but in fact gets ID 262 . This patch makes mount fail with EINVAL with a message in syslog. Signed-off-by: David Sterba <dsterba@suse.cz>
Showing 1 changed file with 19 additions and 0 deletions Side-by-side Diff
fs/btrfs/super.c
... | ... | @@ -741,6 +741,16 @@ |
741 | 741 | } |
742 | 742 | |
743 | 743 | /* |
744 | + * subvolumes are identified by ino 256 | |
745 | + */ | |
746 | +static inline int is_subvolume_inode(struct inode *inode) | |
747 | +{ | |
748 | + if (inode && inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | |
749 | + return 1; | |
750 | + return 0; | |
751 | +} | |
752 | + | |
753 | +/* | |
744 | 754 | * This will strip out the subvol=%s argument for an argument string and add |
745 | 755 | * subvolid=0 to make sure we get the actual tree root for path walking to the |
746 | 756 | * subvol we want. |
... | ... | @@ -842,6 +852,15 @@ |
842 | 852 | put_mnt_ns(ns_private); |
843 | 853 | if (error) |
844 | 854 | return ERR_PTR(error); |
855 | + | |
856 | + if (!is_subvolume_inode(path.dentry->d_inode)) { | |
857 | + path_put(&path); | |
858 | + mntput(mnt); | |
859 | + error = -EINVAL; | |
860 | + printk(KERN_ERR "btrfs: '%s' is not a valid subvolume\n", | |
861 | + subvol_name); | |
862 | + return ERR_PTR(-EINVAL); | |
863 | + } | |
845 | 864 | |
846 | 865 | /* Get a ref to the sb and the dentry we found and return it */ |
847 | 866 | s = path.mnt->mnt_sb; |