Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+26 -88
+2 -71
fs/btrfs/ioctl.c
··· 815 815 return ret; 816 816 } 817 817 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 - 887 818 /* 888 819 * Create a new subvolume below @parent. This is largely modeled after 889 820 * sys_mkdirat and vfs_mkdir, but we only do a single component lookup ··· 836 905 if (IS_ERR(dentry)) 837 906 return PTR_ERR(dentry); 838 907 839 - ret = btrfs_may_create(idmap, dir, dentry); 908 + ret = may_create_dentry(idmap, dir, dentry); 840 909 if (ret) 841 910 goto out_dput; 842 911 ··· 2351 2420 } 2352 2421 2353 2422 /* check if subvolume may be deleted by a user */ 2354 - ret = btrfs_may_delete(idmap, dir, dentry, 1); 2423 + ret = may_delete_dentry(idmap, dir, dentry, true); 2355 2424 if (ret) 2356 2425 goto out_end_removing; 2357 2426
+19 -17
fs/namei.c
··· 3613 3613 * 11. We don't allow removal of NFS sillyrenamed files; it's handled by 3614 3614 * nfs_async_unlink(). 3615 3615 */ 3616 - static int may_delete(struct mnt_idmap *idmap, struct inode *dir, 3616 + int may_delete_dentry(struct mnt_idmap *idmap, struct inode *dir, 3617 3617 struct dentry *victim, bool isdir) 3618 3618 { 3619 3619 struct inode *inode = d_backing_inode(victim); ··· 3655 3655 return -EBUSY; 3656 3656 return 0; 3657 3657 } 3658 + EXPORT_SYMBOL(may_delete_dentry); 3658 3659 3659 3660 /* Check whether we can create an object with dentry child in directory 3660 3661 * dir. ··· 3666 3665 * 4. We should have write and exec permissions on dir 3667 3666 * 5. We can't do it if dir is immutable (done in permission()) 3668 3667 */ 3669 - static inline int may_create(struct mnt_idmap *idmap, 3670 - struct inode *dir, struct dentry *child) 3668 + int may_create_dentry(struct mnt_idmap *idmap, 3669 + struct inode *dir, struct dentry *child) 3671 3670 { 3672 3671 audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); 3673 3672 if (child->d_inode) ··· 3679 3678 3680 3679 return inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC); 3681 3680 } 3681 + EXPORT_SYMBOL(may_create_dentry); 3682 3682 3683 3683 // p1 != p2, both are on the same filesystem, ->s_vfs_rename_mutex is held 3684 3684 static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2) ··· 4126 4124 struct inode *dir = d_inode(dentry->d_parent); 4127 4125 int error; 4128 4126 4129 - error = may_create(idmap, dir, dentry); 4127 + error = may_create_dentry(idmap, dir, dentry); 4130 4128 if (error) 4131 4129 return error; 4132 4130 ··· 4152 4150 void *arg) 4153 4151 { 4154 4152 struct inode *dir = dentry->d_parent->d_inode; 4155 - int error = may_create(&nop_mnt_idmap, dir, dentry); 4153 + int error = may_create_dentry(&nop_mnt_idmap, dir, dentry); 4156 4154 if (error) 4157 4155 return error; 4158 4156 ··· 4971 4969 struct delegated_inode *delegated_inode) 4972 4970 { 4973 4971 bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV; 4974 - int error = may_create(idmap, dir, dentry); 4972 + int error = may_create_dentry(idmap, dir, dentry); 4975 4973 4976 4974 if (error) 4977 4975 return error; ··· 5117 5115 unsigned max_links = dir->i_sb->s_max_links; 5118 5116 struct dentry *de; 5119 5117 5120 - error = may_create(idmap, dir, dentry); 5118 + error = may_create_dentry(idmap, dir, dentry); 5121 5119 if (error) 5122 5120 goto err; 5123 5121 ··· 5220 5218 int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir, 5221 5219 struct dentry *dentry, struct delegated_inode *delegated_inode) 5222 5220 { 5223 - int error = may_delete(idmap, dir, dentry, 1); 5221 + int error = may_delete_dentry(idmap, dir, dentry, true); 5224 5222 5225 5223 if (error) 5226 5224 return error; ··· 5355 5353 struct dentry *dentry, struct delegated_inode *delegated_inode) 5356 5354 { 5357 5355 struct inode *target = dentry->d_inode; 5358 - int error = may_delete(idmap, dir, dentry, 0); 5356 + int error = may_delete_dentry(idmap, dir, dentry, false); 5359 5357 5360 5358 if (error) 5361 5359 return error; ··· 5507 5505 { 5508 5506 int error; 5509 5507 5510 - error = may_create(idmap, dir, dentry); 5508 + error = may_create_dentry(idmap, dir, dentry); 5511 5509 if (error) 5512 5510 return error; 5513 5511 ··· 5615 5613 if (!inode) 5616 5614 return -ENOENT; 5617 5615 5618 - error = may_create(idmap, dir, new_dentry); 5616 + error = may_create_dentry(idmap, dir, new_dentry); 5619 5617 if (error) 5620 5618 return error; 5621 5619 ··· 5827 5825 if (source == target) 5828 5826 return 0; 5829 5827 5830 - error = may_delete(rd->mnt_idmap, old_dir, old_dentry, is_dir); 5828 + error = may_delete_dentry(rd->mnt_idmap, old_dir, old_dentry, is_dir); 5831 5829 if (error) 5832 5830 return error; 5833 5831 5834 5832 if (!target) { 5835 - error = may_create(rd->mnt_idmap, new_dir, new_dentry); 5833 + error = may_create_dentry(rd->mnt_idmap, new_dir, new_dentry); 5836 5834 } else { 5837 5835 new_is_dir = d_is_dir(new_dentry); 5838 5836 5839 5837 if (!(flags & RENAME_EXCHANGE)) 5840 - error = may_delete(rd->mnt_idmap, new_dir, 5841 - new_dentry, is_dir); 5838 + error = may_delete_dentry(rd->mnt_idmap, new_dir, 5839 + new_dentry, is_dir); 5842 5840 else 5843 - error = may_delete(rd->mnt_idmap, new_dir, 5844 - new_dentry, new_is_dir); 5841 + error = may_delete_dentry(rd->mnt_idmap, new_dir, 5842 + new_dentry, new_is_dir); 5845 5843 } 5846 5844 if (error) 5847 5845 return error;
+5
include/linux/fs.h
··· 2667 2667 int __check_sticky(struct mnt_idmap *idmap, struct inode *dir, 2668 2668 struct inode *inode); 2669 2669 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 + 2670 2675 static inline bool execute_ok(struct inode *inode) 2671 2676 { 2672 2677 return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode);