Skip to content

Commit 6124fa4

Browse files
committed
Merge tag 'vfs-7.0-rc1.btrfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull vfs updates for btrfs from Christian Brauner: "This contains some changes for btrfs that are taken to the vfs tree to stop duplicating VFS code for subvolume/snapshot dentry Btrfs has carried private copies of the VFS may_delete() and may_create() functions in fs/btrfs/ioctl.c for permission checks during subvolume creation and snapshot destruction. These copies have drifted out of sync with the VFS originals — btrfs_may_delete() is missing the uid/gid validity check and btrfs_may_create() is missing the audit_inode_child() call. Export the VFS functions as may_{create,delete}_dentry() and switch btrfs to use them, removing ~70 lines of duplicated code" * tag 'vfs-7.0-rc1.btrfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: btrfs: use may_create_dentry() in btrfs_mksubvol() btrfs: use may_delete_dentry() in btrfs_ioctl_snap_destroy() fs: export may_create() as may_create_dentry() fs: export may_delete() as may_delete_dentry()
2 parents dd466ea + f97f020 commit 6124fa4

3 files changed

Lines changed: 26 additions & 88 deletions

File tree

fs/btrfs/ioctl.c

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -815,75 +815,6 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
815815
return ret;
816816
}
817817

818-
/* copy of may_delete in fs/namei.c()
819-
* Check whether we can remove a link victim from directory dir, check
820-
* whether the type of victim is right.
821-
* 1. We can't do it if dir is read-only (done in permission())
822-
* 2. We should have write and exec permissions on dir
823-
* 3. We can't remove anything from append-only dir
824-
* 4. We can't do anything with immutable dir (done in permission())
825-
* 5. If the sticky bit on dir is set we should either
826-
* a. be owner of dir, or
827-
* b. be owner of victim, or
828-
* c. have CAP_FOWNER capability
829-
* 6. If the victim is append-only or immutable we can't do anything with
830-
* links pointing to it.
831-
* 7. If we were asked to remove a directory and victim isn't one - ENOTDIR.
832-
* 8. If we were asked to remove a non-directory and victim isn't one - EISDIR.
833-
* 9. We can't remove a root or mountpoint.
834-
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
835-
* nfs_async_unlink().
836-
*/
837-
838-
static int btrfs_may_delete(struct mnt_idmap *idmap,
839-
struct inode *dir, struct dentry *victim, int isdir)
840-
{
841-
int ret;
842-
843-
if (d_really_is_negative(victim))
844-
return -ENOENT;
845-
846-
/* The @victim is not inside @dir. */
847-
if (d_inode(victim->d_parent) != dir)
848-
return -EINVAL;
849-
audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
850-
851-
ret = inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
852-
if (ret)
853-
return ret;
854-
if (IS_APPEND(dir))
855-
return -EPERM;
856-
if (check_sticky(idmap, dir, d_inode(victim)) ||
857-
IS_APPEND(d_inode(victim)) || IS_IMMUTABLE(d_inode(victim)) ||
858-
IS_SWAPFILE(d_inode(victim)))
859-
return -EPERM;
860-
if (isdir) {
861-
if (!d_is_dir(victim))
862-
return -ENOTDIR;
863-
if (IS_ROOT(victim))
864-
return -EBUSY;
865-
} else if (d_is_dir(victim))
866-
return -EISDIR;
867-
if (IS_DEADDIR(dir))
868-
return -ENOENT;
869-
if (victim->d_flags & DCACHE_NFSFS_RENAMED)
870-
return -EBUSY;
871-
return 0;
872-
}
873-
874-
/* copy of may_create in fs/namei.c() */
875-
static inline int btrfs_may_create(struct mnt_idmap *idmap,
876-
struct inode *dir, const struct dentry *child)
877-
{
878-
if (d_really_is_positive(child))
879-
return -EEXIST;
880-
if (IS_DEADDIR(dir))
881-
return -ENOENT;
882-
if (!fsuidgid_has_mapping(dir->i_sb, idmap))
883-
return -EOVERFLOW;
884-
return inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
885-
}
886-
887818
/*
888819
* Create a new subvolume below @parent. This is largely modeled after
889820
* sys_mkdirat and vfs_mkdir, but we only do a single component lookup
@@ -905,7 +836,7 @@ static noinline int btrfs_mksubvol(struct dentry *parent,
905836
if (IS_ERR(dentry))
906837
return PTR_ERR(dentry);
907838

908-
ret = btrfs_may_create(idmap, dir, dentry);
839+
ret = may_create_dentry(idmap, dir, dentry);
909840
if (ret)
910841
goto out_dput;
911842

@@ -2420,7 +2351,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
24202351
}
24212352

24222353
/* check if subvolume may be deleted by a user */
2423-
ret = btrfs_may_delete(idmap, dir, dentry, 1);
2354+
ret = may_delete_dentry(idmap, dir, dentry, true);
24242355
if (ret)
24252356
goto out_end_removing;
24262357

fs/namei.c

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3613,7 +3613,7 @@ EXPORT_SYMBOL(__check_sticky);
36133613
* 11. We don't allow removal of NFS sillyrenamed files; it's handled by
36143614
* nfs_async_unlink().
36153615
*/
3616-
static int may_delete(struct mnt_idmap *idmap, struct inode *dir,
3616+
int may_delete_dentry(struct mnt_idmap *idmap, struct inode *dir,
36173617
struct dentry *victim, bool isdir)
36183618
{
36193619
struct inode *inode = d_backing_inode(victim);
@@ -3655,6 +3655,7 @@ static int may_delete(struct mnt_idmap *idmap, struct inode *dir,
36553655
return -EBUSY;
36563656
return 0;
36573657
}
3658+
EXPORT_SYMBOL(may_delete_dentry);
36583659

36593660
/* Check whether we can create an object with dentry child in directory
36603661
* dir.
@@ -3665,8 +3666,8 @@ static int may_delete(struct mnt_idmap *idmap, struct inode *dir,
36653666
* 4. We should have write and exec permissions on dir
36663667
* 5. We can't do it if dir is immutable (done in permission())
36673668
*/
3668-
static inline int may_create(struct mnt_idmap *idmap,
3669-
struct inode *dir, struct dentry *child)
3669+
int may_create_dentry(struct mnt_idmap *idmap,
3670+
struct inode *dir, struct dentry *child)
36703671
{
36713672
audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
36723673
if (child->d_inode)
@@ -3678,6 +3679,7 @@ static inline int may_create(struct mnt_idmap *idmap,
36783679

36793680
return inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
36803681
}
3682+
EXPORT_SYMBOL(may_create_dentry);
36813683

36823684
// p1 != p2, both are on the same filesystem, ->s_vfs_rename_mutex is held
36833685
static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2)
@@ -4124,7 +4126,7 @@ int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mode,
41244126
struct inode *dir = d_inode(dentry->d_parent);
41254127
int error;
41264128

4127-
error = may_create(idmap, dir, dentry);
4129+
error = may_create_dentry(idmap, dir, dentry);
41284130
if (error)
41294131
return error;
41304132

@@ -4150,7 +4152,7 @@ int vfs_mkobj(struct dentry *dentry, umode_t mode,
41504152
void *arg)
41514153
{
41524154
struct inode *dir = dentry->d_parent->d_inode;
4153-
int error = may_create(&nop_mnt_idmap, dir, dentry);
4155+
int error = may_create_dentry(&nop_mnt_idmap, dir, dentry);
41544156
if (error)
41554157
return error;
41564158

@@ -4969,7 +4971,7 @@ int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
49694971
struct delegated_inode *delegated_inode)
49704972
{
49714973
bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV;
4972-
int error = may_create(idmap, dir, dentry);
4974+
int error = may_create_dentry(idmap, dir, dentry);
49734975

49744976
if (error)
49754977
return error;
@@ -5115,7 +5117,7 @@ struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
51155117
unsigned max_links = dir->i_sb->s_max_links;
51165118
struct dentry *de;
51175119

5118-
error = may_create(idmap, dir, dentry);
5120+
error = may_create_dentry(idmap, dir, dentry);
51195121
if (error)
51205122
goto err;
51215123

@@ -5218,7 +5220,7 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
52185220
int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir,
52195221
struct dentry *dentry, struct delegated_inode *delegated_inode)
52205222
{
5221-
int error = may_delete(idmap, dir, dentry, 1);
5223+
int error = may_delete_dentry(idmap, dir, dentry, true);
52225224

52235225
if (error)
52245226
return error;
@@ -5353,7 +5355,7 @@ int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir,
53535355
struct dentry *dentry, struct delegated_inode *delegated_inode)
53545356
{
53555357
struct inode *target = dentry->d_inode;
5356-
int error = may_delete(idmap, dir, dentry, 0);
5358+
int error = may_delete_dentry(idmap, dir, dentry, false);
53575359

53585360
if (error)
53595361
return error;
@@ -5505,7 +5507,7 @@ int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
55055507
{
55065508
int error;
55075509

5508-
error = may_create(idmap, dir, dentry);
5510+
error = may_create_dentry(idmap, dir, dentry);
55095511
if (error)
55105512
return error;
55115513

@@ -5613,7 +5615,7 @@ int vfs_link(struct dentry *old_dentry, struct mnt_idmap *idmap,
56135615
if (!inode)
56145616
return -ENOENT;
56155617

5616-
error = may_create(idmap, dir, new_dentry);
5618+
error = may_create_dentry(idmap, dir, new_dentry);
56175619
if (error)
56185620
return error;
56195621

@@ -5825,21 +5827,21 @@ int vfs_rename(struct renamedata *rd)
58255827
if (source == target)
58265828
return 0;
58275829

5828-
error = may_delete(rd->mnt_idmap, old_dir, old_dentry, is_dir);
5830+
error = may_delete_dentry(rd->mnt_idmap, old_dir, old_dentry, is_dir);
58295831
if (error)
58305832
return error;
58315833

58325834
if (!target) {
5833-
error = may_create(rd->mnt_idmap, new_dir, new_dentry);
5835+
error = may_create_dentry(rd->mnt_idmap, new_dir, new_dentry);
58345836
} else {
58355837
new_is_dir = d_is_dir(new_dentry);
58365838

58375839
if (!(flags & RENAME_EXCHANGE))
5838-
error = may_delete(rd->mnt_idmap, new_dir,
5839-
new_dentry, is_dir);
5840+
error = may_delete_dentry(rd->mnt_idmap, new_dir,
5841+
new_dentry, is_dir);
58405842
else
5841-
error = may_delete(rd->mnt_idmap, new_dir,
5842-
new_dentry, new_is_dir);
5843+
error = may_delete_dentry(rd->mnt_idmap, new_dir,
5844+
new_dentry, new_is_dir);
58435845
}
58445846
if (error)
58455847
return error;

include/linux/fs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,6 +2667,11 @@ static inline int path_permission(const struct path *path, int mask)
26672667
int __check_sticky(struct mnt_idmap *idmap, struct inode *dir,
26682668
struct inode *inode);
26692669

2670+
int may_delete_dentry(struct mnt_idmap *idmap, struct inode *dir,
2671+
struct dentry *victim, bool isdir);
2672+
int may_create_dentry(struct mnt_idmap *idmap,
2673+
struct inode *dir, struct dentry *child);
2674+
26702675
static inline bool execute_ok(struct inode *inode)
26712676
{
26722677
return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode);

0 commit comments

Comments
 (0)