Enable idmapped mounts for xfs. This basically just means passing down the user_namespace argument from the VFS methods down to where it is passed to the relevant helpers. Note that full-filesystem bulkstat is not supported from inside idmapped mounts as it is an administrative operation that acts on the whole file system. The limitation is not applied to the bulkstat single operation that just operates on a single inode.
Unified · Split
| @@ -253,8 +253,7 @@ xfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode, · 252 unmodified lines | ||
| 253 | 253 | return error; |
| 254 | 254 | |
| 255 | 255 | if (type == ACL_TYPE_ACCESS) { |
| 256 | − error = posix_acl_update_mode(&init_user_ns, inode, &mode, | |
| 257 | − &acl); | |
| 256 | + error = posix_acl_update_mode(mnt_userns, inode, &mode, &acl); | |
| 258 | 257 | if (error) |
| 259 | 258 | return error; |
| 260 | 259 | set_mode = true; |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/backing-dev.h> |
| 30 | 30 | #include <linux/mman.h> |
| 31 | 31 | #include <linux/fadvise.h> |
| 32 | +#include <linux/mount.h> | |
| 32 | 33 | |
| 33 | 34 | static const struct vm_operations_struct xfs_file_vm_ops; |
| 34 | 35 | |
| @@ -994,7 +995,8 @@ xfs_file_fallocate( · 959 unmodified lines | ||
| 994 | 995 | |
| 995 | 996 | iattr.ia_valid = ATTR_SIZE; |
| 996 | 997 | iattr.ia_size = new_size; |
| 997 | − error = xfs_vn_setattr_size(file_dentry(file), &iattr); | |
| 998 | + error = xfs_vn_setattr_size(file_mnt_user_ns(file), | |
| 999 | + file_dentry(file), &iattr); | |
| 998 | 1000 | if (error) |
| 999 | 1001 | goto out_unlock; |
| 1000 | 1002 | } |
| @@ -766,6 +766,7 @@ xfs_inode_inherit_flags2( · 765 unmodified lines | ||
| 766 | 766 | */ |
| 767 | 767 | static int |
| 768 | 768 | xfs_init_new_inode( |
| 769 | + struct user_namespace *mnt_userns, | |
| 769 | 770 | struct xfs_trans *tp, |
| 770 | 771 | struct xfs_inode *pip, |
| 771 | 772 | xfs_ino_t ino, |
| @@ -806,7 +807,7 @@ xfs_init_new_inode( · 34 unmodified lines | ||
| 806 | 807 | inode = VFS_I(ip); |
| 807 | 808 | inode->i_mode = mode; |
| 808 | 809 | set_nlink(inode, nlink); |
| 809 | − inode->i_uid = current_fsuid(); | |
| 810 | + inode->i_uid = fsuid_into_mnt(mnt_userns); | |
| 810 | 811 | inode->i_rdev = rdev; |
| 811 | 812 | ip->i_d.di_projid = prid; |
| 812 | 813 | |
| @@ -815,7 +816,7 @@ xfs_init_new_inode( · 2 unmodified lines | ||
| 815 | 816 | if ((VFS_I(pip)->i_mode & S_ISGID) && S_ISDIR(mode)) |
| 816 | 817 | inode->i_mode |= S_ISGID; |
| 817 | 818 | } else { |
| 818 | − inode->i_gid = current_fsgid(); | |
| 819 | + inode->i_gid = fsgid_into_mnt(mnt_userns); | |
| 819 | 820 | } |
| 820 | 821 | |
| 821 | 822 | /* |
| @@ -824,7 +825,8 @@ xfs_init_new_inode( · 2 unmodified lines | ||
| 824 | 825 | * (and only if the irix_sgid_inherit compatibility variable is set). |
| 825 | 826 | */ |
| 826 | 827 | if (irix_sgid_inherit && |
| 827 | − (inode->i_mode & S_ISGID) && !in_group_p(inode->i_gid)) | |
| 828 | + (inode->i_mode & S_ISGID) && | |
| 829 | + !in_group_p(i_gid_into_mnt(mnt_userns, inode))) | |
| 828 | 830 | inode->i_mode &= ~S_ISGID; |
| 829 | 831 | |
| 830 | 832 | ip->i_d.di_size = 0; |
| @@ -901,6 +903,7 @@ xfs_init_new_inode( · 70 unmodified lines | ||
| 901 | 903 | */ |
| 902 | 904 | int |
| 903 | 905 | xfs_dir_ialloc( |
| 906 | + struct user_namespace *mnt_userns, | |
| 904 | 907 | struct xfs_trans **tpp, |
| 905 | 908 | struct xfs_inode *dp, |
| 906 | 909 | umode_t mode, |
| @@ -933,7 +936,8 @@ xfs_dir_ialloc( · 26 unmodified lines | ||
| 933 | 936 | return error; |
| 934 | 937 | ASSERT(ino != NULLFSINO); |
| 935 | 938 | |
| 936 | − return xfs_init_new_inode(*tpp, dp, ino, mode, nlink, rdev, prid, ipp); | |
| 939 | + return xfs_init_new_inode(mnt_userns, *tpp, dp, ino, mode, nlink, rdev, | |
| 940 | + prid, ipp); | |
| 937 | 941 | } |
| 938 | 942 | |
| 939 | 943 | /* |
| @@ -973,6 +977,7 @@ xfs_bumplink( · 33 unmodified lines | ||
| 973 | 977 | |
| 974 | 978 | int |
| 975 | 979 | xfs_create( |
| 980 | + struct user_namespace *mnt_userns, | |
| 976 | 981 | xfs_inode_t *dp, |
| 977 | 982 | struct xfs_name *name, |
| 978 | 983 | umode_t mode, |
| @@ -1047,7 +1052,8 @@ xfs_create( · 68 unmodified lines | ||
| 1047 | 1052 | * entry pointing to them, but a directory also the "." entry |
| 1048 | 1053 | * pointing to itself. |
| 1049 | 1054 | */ |
| 1050 | − error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, prid, &ip); | |
| 1055 | + error = xfs_dir_ialloc(mnt_userns, &tp, dp, mode, is_dir ? 2 : 1, rdev, | |
| 1056 | + prid, &ip); | |
| 1051 | 1057 | if (error) |
| 1052 | 1058 | goto out_trans_cancel; |
| 1053 | 1059 | |
| @@ -1128,6 +1134,7 @@ xfs_create( · 74 unmodified lines | ||
| 1128 | 1134 | |
| 1129 | 1135 | int |
| 1130 | 1136 | xfs_create_tmpfile( |
| 1137 | + struct user_namespace *mnt_userns, | |
| 1131 | 1138 | struct xfs_inode *dp, |
| 1132 | 1139 | umode_t mode, |
| 1133 | 1140 | struct xfs_inode **ipp) |
| @@ -1169,7 +1176,7 @@ xfs_create_tmpfile( · 35 unmodified lines | ||
| 1169 | 1176 | if (error) |
| 1170 | 1177 | goto out_trans_cancel; |
| 1171 | 1178 | |
| 1172 | − error = xfs_dir_ialloc(&tp, dp, mode, 0, 0, prid, &ip); | |
| 1179 | + error = xfs_dir_ialloc(mnt_userns, &tp, dp, mode, 0, 0, prid, &ip); | |
| 1173 | 1180 | if (error) |
| 1174 | 1181 | goto out_trans_cancel; |
| 1175 | 1182 | |
| @@ -2977,13 +2984,15 @@ out_trans_abort: · 1801 unmodified lines | ||
| 2977 | 2984 | */ |
| 2978 | 2985 | static int |
| 2979 | 2986 | xfs_rename_alloc_whiteout( |
| 2987 | + struct user_namespace *mnt_userns, | |
| 2980 | 2988 | struct xfs_inode *dp, |
| 2981 | 2989 | struct xfs_inode **wip) |
| 2982 | 2990 | { |
| 2983 | 2991 | struct xfs_inode *tmpfile; |
| 2984 | 2992 | int error; |
| 2985 | 2993 | |
| 2986 | − error = xfs_create_tmpfile(dp, S_IFCHR | WHITEOUT_MODE, &tmpfile); | |
| 2994 | + error = xfs_create_tmpfile(mnt_userns, dp, S_IFCHR | WHITEOUT_MODE, | |
| 2995 | + &tmpfile); | |
| 2987 | 2996 | if (error) |
| 2988 | 2997 | return error; |
| 2989 | 2998 | |
| @@ -3005,6 +3014,7 @@ xfs_rename_alloc_whiteout( · 15 unmodified lines | ||
| 3005 | 3014 | */ |
| 3006 | 3015 | int |
| 3007 | 3016 | xfs_rename( |
| 3017 | + struct user_namespace *mnt_userns, | |
| 3008 | 3018 | struct xfs_inode *src_dp, |
| 3009 | 3019 | struct xfs_name *src_name, |
| 3010 | 3020 | struct xfs_inode *src_ip, |
| @@ -3036,7 +3046,7 @@ xfs_rename( · 25 unmodified lines | ||
| 3036 | 3046 | */ |
| 3037 | 3047 | if (flags & RENAME_WHITEOUT) { |
| 3038 | 3048 | ASSERT(!(flags & (RENAME_NOREPLACE | RENAME_EXCHANGE))); |
| 3039 | − error = xfs_rename_alloc_whiteout(target_dp, &wip); | |
| 3049 | + error = xfs_rename_alloc_whiteout(mnt_userns, target_dp, &wip); | |
| 3040 | 3050 | if (error) |
| 3041 | 3051 | return error; |
| 3042 | 3052 | |
| @@ -369,15 +369,18 @@ int xfs_release(struct xfs_inode *ip); · 368 unmodified lines | ||
| 369 | 369 | void xfs_inactive(struct xfs_inode *ip); |
| 370 | 370 | int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, |
| 371 | 371 | struct xfs_inode **ipp, struct xfs_name *ci_name); |
| 372 | −int xfs_create(struct xfs_inode *dp, struct xfs_name *name, | |
| 372 | +int xfs_create(struct user_namespace *mnt_userns, | |
| 373 | + struct xfs_inode *dp, struct xfs_name *name, | |
| 373 | 374 | umode_t mode, dev_t rdev, struct xfs_inode **ipp); |
| 374 | −int xfs_create_tmpfile(struct xfs_inode *dp, umode_t mode, | |
| 375 | +int xfs_create_tmpfile(struct user_namespace *mnt_userns, | |
| 376 | + struct xfs_inode *dp, umode_t mode, | |
| 375 | 377 | struct xfs_inode **ipp); |
| 376 | 378 | int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, |
| 377 | 379 | struct xfs_inode *ip); |
| 378 | 380 | int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, |
| 379 | 381 | struct xfs_name *target_name); |
| 380 | −int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name, | |
| 382 | +int xfs_rename(struct user_namespace *mnt_userns, | |
| 383 | + struct xfs_inode *src_dp, struct xfs_name *src_name, | |
| 381 | 384 | struct xfs_inode *src_ip, struct xfs_inode *target_dp, |
| 382 | 385 | struct xfs_name *target_name, |
| 383 | 386 | struct xfs_inode *target_ip, unsigned int flags); |
| @@ -407,9 +410,10 @@ void xfs_lock_two_inodes(struct xfs_inode *ip0, uint ip0_mode, · 23 unmodified lines | ||
| 407 | 410 | xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip); |
| 408 | 411 | xfs_extlen_t xfs_get_cowextsz_hint(struct xfs_inode *ip); |
| 409 | 412 | |
| 410 | −int xfs_dir_ialloc(struct xfs_trans **tpp, struct xfs_inode *dp, umode_t mode, | |
| 411 | − xfs_nlink_t nlink, dev_t dev, prid_t prid, | |
| 412 | − struct xfs_inode **ipp); | |
| 413 | +int xfs_dir_ialloc(struct user_namespace *mnt_userns, | |
| 414 | + struct xfs_trans **tpp, struct xfs_inode *dp, | |
| 415 | + umode_t mode, xfs_nlink_t nlink, dev_t dev, | |
| 416 | + prid_t prid, struct xfs_inode **ipp); | |
| 413 | 417 | |
| 414 | 418 | static inline int |
| 415 | 419 | xfs_itruncate_extents( |
| @@ -693,7 +693,8 @@ xfs_ioc_space( · 692 unmodified lines | ||
| 693 | 693 | |
| 694 | 694 | iattr.ia_valid = ATTR_SIZE; |
| 695 | 695 | iattr.ia_size = bf->l_start; |
| 696 | − error = xfs_vn_setattr_size(file_dentry(filp), &iattr); | |
| 696 | + error = xfs_vn_setattr_size(file_mnt_user_ns(filp), file_dentry(filp), | |
| 697 | + &iattr); | |
| 697 | 698 | if (error) |
| 698 | 699 | goto out_unlock; |
| 699 | 700 | |
| @@ -734,13 +735,15 @@ xfs_fsinumbers_fmt( · 34 unmodified lines | ||
| 734 | 735 | |
| 735 | 736 | STATIC int |
| 736 | 737 | xfs_ioc_fsbulkstat( |
| 737 | − xfs_mount_t *mp, | |
| 738 | + struct file *file, | |
| 738 | 739 | unsigned int cmd, |
| 739 | 740 | void __user *arg) |
| 740 | 741 | { |
| 742 | + struct xfs_mount *mp = XFS_I(file_inode(file))->i_mount; | |
| 741 | 743 | struct xfs_fsop_bulkreq bulkreq; |
| 742 | 744 | struct xfs_ibulk breq = { |
| 743 | 745 | .mp = mp, |
| 746 | + .mnt_userns = file_mnt_user_ns(file), | |
| 744 | 747 | .ocount = 0, |
| 745 | 748 | }; |
| 746 | 749 | xfs_ino_t lastino; |
| @@ -908,13 +911,15 @@ xfs_bulk_ireq_teardown( · 161 unmodified lines | ||
| 908 | 911 | /* Handle the v5 bulkstat ioctl. */ |
| 909 | 912 | STATIC int |
| 910 | 913 | xfs_ioc_bulkstat( |
| 911 | − struct xfs_mount *mp, | |
| 914 | + struct file *file, | |
| 912 | 915 | unsigned int cmd, |
| 913 | 916 | struct xfs_bulkstat_req __user *arg) |
| 914 | 917 | { |
| 918 | + struct xfs_mount *mp = XFS_I(file_inode(file))->i_mount; | |
| 915 | 919 | struct xfs_bulk_ireq hdr; |
| 916 | 920 | struct xfs_ibulk breq = { |
| 917 | 921 | .mp = mp, |
| 922 | + .mnt_userns = file_mnt_user_ns(file), | |
| 918 | 923 | }; |
| 919 | 924 | int error; |
| 920 | 925 | |
| @@ -1275,8 +1280,9 @@ xfs_ioctl_setattr_prepare_dax( · 354 unmodified lines | ||
| 1275 | 1280 | */ |
| 1276 | 1281 | static struct xfs_trans * |
| 1277 | 1282 | xfs_ioctl_setattr_get_trans( |
| 1278 | − struct xfs_inode *ip) | |
| 1283 | + struct file *file) | |
| 1279 | 1284 | { |
| 1285 | + struct xfs_inode *ip = XFS_I(file_inode(file)); | |
| 1280 | 1286 | struct xfs_mount *mp = ip->i_mount; |
| 1281 | 1287 | struct xfs_trans *tp; |
| 1282 | 1288 | int error = -EROFS; |
| @@ -1300,7 +1306,7 @@ xfs_ioctl_setattr_get_trans( · 17 unmodified lines | ||
| 1300 | 1306 | * The user ID of the calling process must be equal to the file owner |
| 1301 | 1307 | * ID, except in cases where the CAP_FSETID capability is applicable. |
| 1302 | 1308 | */ |
| 1303 | − if (!inode_owner_or_capable(&init_user_ns, VFS_I(ip))) { | |
| 1309 | + if (!inode_owner_or_capable(file_mnt_user_ns(file), VFS_I(ip))) { | |
| 1304 | 1310 | error = -EPERM; |
| 1305 | 1311 | goto out_cancel; |
| 1306 | 1312 | } |
| @@ -1428,9 +1434,11 @@ xfs_ioctl_setattr_check_projid( · 121 unmodified lines | ||
| 1428 | 1434 | |
| 1429 | 1435 | STATIC int |
| 1430 | 1436 | xfs_ioctl_setattr( |
| 1431 | − xfs_inode_t *ip, | |
| 1437 | + struct file *file, | |
| 1432 | 1438 | struct fsxattr *fa) |
| 1433 | 1439 | { |
| 1440 | + struct user_namespace *mnt_userns = file_mnt_user_ns(file); | |
| 1441 | + struct xfs_inode *ip = XFS_I(file_inode(file)); | |
| 1434 | 1442 | struct fsxattr old_fa; |
| 1435 | 1443 | struct xfs_mount *mp = ip->i_mount; |
| 1436 | 1444 | struct xfs_trans *tp; |
| @@ -1462,7 +1470,7 @@ xfs_ioctl_setattr( · 25 unmodified lines | ||
| 1462 | 1470 | |
| 1463 | 1471 | xfs_ioctl_setattr_prepare_dax(ip, fa); |
| 1464 | 1472 | |
| 1465 | − tp = xfs_ioctl_setattr_get_trans(ip); | |
| 1473 | + tp = xfs_ioctl_setattr_get_trans(file); | |
| 1466 | 1474 | if (IS_ERR(tp)) { |
| 1467 | 1475 | code = PTR_ERR(tp); |
| 1468 | 1476 | goto error_free_dquots; |
| @@ -1502,7 +1510,7 @@ xfs_ioctl_setattr( · 33 unmodified lines | ||
| 1502 | 1510 | */ |
| 1503 | 1511 | |
| 1504 | 1512 | if ((VFS_I(ip)->i_mode & (S_ISUID|S_ISGID)) && |
| 1505 | − !capable_wrt_inode_uidgid(&init_user_ns, VFS_I(ip), CAP_FSETID)) | |
| 1513 | + !capable_wrt_inode_uidgid(mnt_userns, VFS_I(ip), CAP_FSETID)) | |
| 1506 | 1514 | VFS_I(ip)->i_mode &= ~(S_ISUID|S_ISGID); |
| 1507 | 1515 | |
| 1508 | 1516 | /* Change the ownerships and register project quota modifications */ |
| @@ -1549,7 +1557,6 @@ error_free_dquots: · 40 unmodified lines | ||
| 1549 | 1557 | |
| 1550 | 1558 | STATIC int |
| 1551 | 1559 | xfs_ioc_fssetxattr( |
| 1552 | − xfs_inode_t *ip, | |
| 1553 | 1560 | struct file *filp, |
| 1554 | 1561 | void __user *arg) |
| 1555 | 1562 | { |
| @@ -1562,7 +1569,7 @@ xfs_ioc_fssetxattr( · 6 unmodified lines | ||
| 1562 | 1569 | error = mnt_want_write_file(filp); |
| 1563 | 1570 | if (error) |
| 1564 | 1571 | return error; |
| 1565 | − error = xfs_ioctl_setattr(ip, &fa); | |
| 1572 | + error = xfs_ioctl_setattr(filp, &fa); | |
| 1566 | 1573 | mnt_drop_write_file(filp); |
| 1567 | 1574 | return error; |
| 1568 | 1575 | } |
| @@ -1608,7 +1615,7 @@ xfs_ioc_setxflags( · 39 unmodified lines | ||
| 1608 | 1615 | |
| 1609 | 1616 | xfs_ioctl_setattr_prepare_dax(ip, &fa); |
| 1610 | 1617 | |
| 1611 | − tp = xfs_ioctl_setattr_get_trans(ip); | |
| 1618 | + tp = xfs_ioctl_setattr_get_trans(filp); | |
| 1612 | 1619 | if (IS_ERR(tp)) { |
| 1613 | 1620 | error = PTR_ERR(tp); |
| 1614 | 1621 | goto out_drop_write; |
| @@ -2119,10 +2126,10 @@ xfs_file_ioctl( · 504 unmodified lines | ||
| 2119 | 2126 | case XFS_IOC_FSBULKSTAT_SINGLE: |
| 2120 | 2127 | case XFS_IOC_FSBULKSTAT: |
| 2121 | 2128 | case XFS_IOC_FSINUMBERS: |
| 2122 | − return xfs_ioc_fsbulkstat(mp, cmd, arg); | |
| 2129 | + return xfs_ioc_fsbulkstat(filp, cmd, arg); | |
| 2123 | 2130 | |
| 2124 | 2131 | case XFS_IOC_BULKSTAT: |
| 2125 | − return xfs_ioc_bulkstat(mp, cmd, arg); | |
| 2132 | + return xfs_ioc_bulkstat(filp, cmd, arg); | |
| 2126 | 2133 | case XFS_IOC_INUMBERS: |
| 2127 | 2134 | return xfs_ioc_inumbers(mp, cmd, arg); |
| 2128 | 2135 | |
| @@ -2144,7 +2151,7 @@ xfs_file_ioctl( · 15 unmodified lines | ||
| 2144 | 2151 | case XFS_IOC_FSGETXATTRA: |
| 2145 | 2152 | return xfs_ioc_fsgetxattr(ip, 1, arg); |
| 2146 | 2153 | case XFS_IOC_FSSETXATTR: |
| 2147 | − return xfs_ioc_fssetxattr(ip, filp, arg); | |
| 2154 | + return xfs_ioc_fssetxattr(filp, arg); | |
| 2148 | 2155 | case XFS_IOC_GETXFLAGS: |
| 2149 | 2156 | return xfs_ioc_getxflags(ip, arg); |
| 2150 | 2157 | case XFS_IOC_SETXFLAGS: |
| @@ -209,14 +209,16 @@ xfs_fsbulkstat_one_fmt_compat( · 208 unmodified lines | ||
| 209 | 209 | /* copied from xfs_ioctl.c */ |
| 210 | 210 | STATIC int |
| 211 | 211 | xfs_compat_ioc_fsbulkstat( |
| 212 | − xfs_mount_t *mp, | |
| 212 | + struct file *file, | |
| 213 | 213 | unsigned int cmd, |
| 214 | 214 | struct compat_xfs_fsop_bulkreq __user *p32) |
| 215 | 215 | { |
| 216 | + struct xfs_mount *mp = XFS_I(file_inode(file))->i_mount; | |
| 216 | 217 | u32 addr; |
| 217 | 218 | struct xfs_fsop_bulkreq bulkreq; |
| 218 | 219 | struct xfs_ibulk breq = { |
| 219 | 220 | .mp = mp, |
| 221 | + .mnt_userns = file_mnt_user_ns(file), | |
| 220 | 222 | .ocount = 0, |
| 221 | 223 | }; |
| 222 | 224 | xfs_ino_t lastino; |
| @@ -507,7 +509,7 @@ xfs_file_compat_ioctl( · 284 unmodified lines | ||
| 507 | 509 | case XFS_IOC_FSBULKSTAT_32: |
| 508 | 510 | case XFS_IOC_FSBULKSTAT_SINGLE_32: |
| 509 | 511 | case XFS_IOC_FSINUMBERS_32: |
| 510 | − return xfs_compat_ioc_fsbulkstat(mp, cmd, arg); | |
| 512 | + return xfs_compat_ioc_fsbulkstat(filp, cmd, arg); | |
| 511 | 513 | case XFS_IOC_FD_TO_HANDLE_32: |
| 512 | 514 | case XFS_IOC_PATH_TO_HANDLE_32: |
| 513 | 515 | case XFS_IOC_PATH_TO_FSHANDLE_32: { |
| @@ -128,6 +128,7 @@ xfs_cleanup_inode( · 127 unmodified lines | ||
| 128 | 128 | |
| 129 | 129 | STATIC int |
| 130 | 130 | xfs_generic_create( |
| 131 | + struct user_namespace *mnt_userns, | |
| 131 | 132 | struct inode *dir, |
| 132 | 133 | struct dentry *dentry, |
| 133 | 134 | umode_t mode, |
| @@ -161,9 +162,10 @@ xfs_generic_create( · 27 unmodified lines | ||
| 161 | 162 | goto out_free_acl; |
| 162 | 163 | |
| 163 | 164 | if (!tmpfile) { |
| 164 | − error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip); | |
| 165 | + error = xfs_create(mnt_userns, XFS_I(dir), &name, mode, rdev, | |
| 166 | + &ip); | |
| 165 | 167 | } else { |
| 166 | − error = xfs_create_tmpfile(XFS_I(dir), mode, &ip); | |
| 168 | + error = xfs_create_tmpfile(mnt_userns, XFS_I(dir), mode, &ip); | |
| 167 | 169 | } |
| 168 | 170 | if (unlikely(error)) |
| 169 | 171 | goto out_free_acl; |
| @@ -226,7 +228,7 @@ xfs_vn_mknod( · 56 unmodified lines | ||
| 226 | 228 | umode_t mode, |
| 227 | 229 | dev_t rdev) |
| 228 | 230 | { |
| 229 | − return xfs_generic_create(dir, dentry, mode, rdev, false); | |
| 231 | + return xfs_generic_create(mnt_userns, dir, dentry, mode, rdev, false); | |
| 230 | 232 | } |
| 231 | 233 | |
| 232 | 234 | STATIC int |
| @@ -237,7 +239,7 @@ xfs_vn_create( · 4 unmodified lines | ||
| 237 | 239 | umode_t mode, |
| 238 | 240 | bool flags) |
| 239 | 241 | { |
| 240 | − return xfs_generic_create(dir, dentry, mode, 0, false); | |
| 242 | + return xfs_generic_create(mnt_userns, dir, dentry, mode, 0, false); | |
| 241 | 243 | } |
| 242 | 244 | |
| 243 | 245 | STATIC int |
| @@ -247,7 +249,8 @@ xfs_vn_mkdir( · 3 unmodified lines | ||
| 247 | 249 | struct dentry *dentry, |
| 248 | 250 | umode_t mode) |
| 249 | 251 | { |
| 250 | − return xfs_generic_create(dir, dentry, mode | S_IFDIR, 0, false); | |
| 252 | + return xfs_generic_create(mnt_userns, dir, dentry, mode | S_IFDIR, 0, | |
| 253 | + false); | |
| 251 | 254 | } |
| 252 | 255 | |
| 253 | 256 | STATIC struct dentry * |
| @@ -381,7 +384,7 @@ xfs_vn_symlink( · 127 unmodified lines | ||
| 381 | 384 | if (unlikely(error)) |
| 382 | 385 | goto out; |
| 383 | 386 | |
| 384 | − error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip); | |
| 387 | + error = xfs_symlink(mnt_userns, XFS_I(dir), &name, symname, mode, &cip); | |
| 385 | 388 | if (unlikely(error)) |
| 386 | 389 | goto out; |
| 387 | 390 | |
| @@ -436,8 +439,8 @@ xfs_vn_rename( · 48 unmodified lines | ||
| 436 | 439 | if (unlikely(error)) |
| 437 | 440 | return error; |
| 438 | 441 | |
| 439 | − return xfs_rename(XFS_I(odir), &oname, XFS_I(d_inode(odentry)), | |
| 440 | − XFS_I(ndir), &nname, | |
| 442 | + return xfs_rename(mnt_userns, XFS_I(odir), &oname, | |
| 443 | + XFS_I(d_inode(odentry)), XFS_I(ndir), &nname, | |
| 441 | 444 | new_inode ? XFS_I(new_inode) : NULL, flags); |
| 442 | 445 | } |
| 443 | 446 | |
| @@ -553,8 +556,8 @@ xfs_vn_getattr( · 109 unmodified lines | ||
| 553 | 556 | stat->dev = inode->i_sb->s_dev; |
| 554 | 557 | stat->mode = inode->i_mode; |
| 555 | 558 | stat->nlink = inode->i_nlink; |
| 556 | − stat->uid = inode->i_uid; | |
| 557 | − stat->gid = inode->i_gid; | |
| 559 | + stat->uid = i_uid_into_mnt(mnt_userns, inode); | |
| 560 | + stat->gid = i_gid_into_mnt(mnt_userns, inode); | |
| 558 | 561 | stat->ino = ip->i_ino; |
| 559 | 562 | stat->atime = inode->i_atime; |
| 560 | 563 | stat->mtime = inode->i_mtime; |
| @@ -632,8 +635,9 @@ xfs_setattr_time( · 71 unmodified lines | ||
| 632 | 635 | |
| 633 | 636 | static int |
| 634 | 637 | xfs_vn_change_ok( |
| 635 | − struct dentry *dentry, | |
| 636 | − struct iattr *iattr) | |
| 638 | + struct user_namespace *mnt_userns, | |
| 639 | + struct dentry *dentry, | |
| 640 | + struct iattr *iattr) | |
| 637 | 641 | { |
| 638 | 642 | struct xfs_mount *mp = XFS_I(d_inode(dentry))->i_mount; |
| 639 | 643 | |
| @@ -643,7 +647,7 @@ xfs_vn_change_ok( · 3 unmodified lines | ||
| 643 | 647 | if (XFS_FORCED_SHUTDOWN(mp)) |
| 644 | 648 | return -EIO; |
| 645 | 649 | |
| 646 | − return setattr_prepare(&init_user_ns, dentry, iattr); | |
| 650 | + return setattr_prepare(mnt_userns, dentry, iattr); | |
| 647 | 651 | } |
| 648 | 652 | |
| 649 | 653 | /* |
| @@ -654,6 +658,7 @@ xfs_vn_change_ok( · 4 unmodified lines | ||
| 654 | 658 | */ |
| 655 | 659 | static int |
| 656 | 660 | xfs_setattr_nonsize( |
| 661 | + struct user_namespace *mnt_userns, | |
| 657 | 662 | struct xfs_inode *ip, |
| 658 | 663 | struct iattr *iattr) |
| 659 | 664 | { |
| @@ -813,7 +818,7 @@ xfs_setattr_nonsize( · 153 unmodified lines | ||
| 813 | 818 | * Posix ACL code seems to care about this issue either. |
| 814 | 819 | */ |
| 815 | 820 | if (mask & ATTR_MODE) { |
| 816 | − error = posix_acl_chmod(&init_user_ns, inode, inode->i_mode); | |
| 821 | + error = posix_acl_chmod(mnt_userns, inode, inode->i_mode); | |
| 817 | 822 | if (error) |
| 818 | 823 | return error; |
| 819 | 824 | } |
| @@ -837,6 +842,7 @@ out_dqrele: · 17 unmodified lines | ||
| 837 | 842 | */ |
| 838 | 843 | STATIC int |
| 839 | 844 | xfs_setattr_size( |
| 845 | + struct user_namespace *mnt_userns, | |
| 840 | 846 | struct xfs_inode *ip, |
| 841 | 847 | struct iattr *iattr) |
| 842 | 848 | { |
| @@ -868,7 +874,7 @@ xfs_setattr_size( · 25 unmodified lines | ||
| 868 | 874 | * Use the regular setattr path to update the timestamps. |
| 869 | 875 | */ |
| 870 | 876 | iattr->ia_valid &= ~ATTR_SIZE; |
| 871 | − return xfs_setattr_nonsize(ip, iattr); | |
| 877 | + return xfs_setattr_nonsize(mnt_userns, ip, iattr); | |
| 872 | 878 | } |
| 873 | 879 | |
| 874 | 880 | /* |
| @@ -1037,6 +1043,7 @@ out_trans_cancel: · 162 unmodified lines | ||
| 1037 | 1043 | |
| 1038 | 1044 | int |
| 1039 | 1045 | xfs_vn_setattr_size( |
| 1046 | + struct user_namespace *mnt_userns, | |
| 1040 | 1047 | struct dentry *dentry, |
| 1041 | 1048 | struct iattr *iattr) |
| 1042 | 1049 | { |
| @@ -1045,10 +1052,10 @@ xfs_vn_setattr_size( · 2 unmodified lines | ||
| 1045 | 1052 | |
| 1046 | 1053 | trace_xfs_setattr(ip); |
| 1047 | 1054 | |
| 1048 | − error = xfs_vn_change_ok(dentry, iattr); | |
| 1055 | + error = xfs_vn_change_ok(mnt_userns, dentry, iattr); | |
| 1049 | 1056 | if (error) |
| 1050 | 1057 | return error; |
| 1051 | − return xfs_setattr_size(ip, iattr); | |
| 1058 | + return xfs_setattr_size(mnt_userns, ip, iattr); | |
| 1052 | 1059 | } |
| 1053 | 1060 | |
| 1054 | 1061 | STATIC int |
| @@ -1073,14 +1080,14 @@ xfs_vn_setattr( · 18 unmodified lines | ||
| 1073 | 1080 | return error; |
| 1074 | 1081 | } |
| 1075 | 1082 | |
| 1076 | − error = xfs_vn_setattr_size(dentry, iattr); | |
| 1083 | + error = xfs_vn_setattr_size(mnt_userns, dentry, iattr); | |
| 1077 | 1084 | xfs_iunlock(ip, XFS_MMAPLOCK_EXCL); |
| 1078 | 1085 | } else { |
| 1079 | 1086 | trace_xfs_setattr(ip); |
| 1080 | 1087 | |
| 1081 | − error = xfs_vn_change_ok(dentry, iattr); | |
| 1088 | + error = xfs_vn_change_ok(mnt_userns, dentry, iattr); | |
| 1082 | 1089 | if (!error) |
| 1083 | − error = xfs_setattr_nonsize(ip, iattr); | |
| 1090 | + error = xfs_setattr_nonsize(mnt_userns, ip, iattr); | |
| 1084 | 1091 | } |
| 1085 | 1092 | |
| 1086 | 1093 | return error; |
| @@ -1156,7 +1163,7 @@ xfs_vn_tmpfile( · 69 unmodified lines | ||
| 1156 | 1163 | struct dentry *dentry, |
| 1157 | 1164 | umode_t mode) |
| 1158 | 1165 | { |
| 1159 | − return xfs_generic_create(dir, dentry, mode, 0, true); | |
| 1166 | + return xfs_generic_create(mnt_userns, dir, dentry, mode, 0, true); | |
| 1160 | 1167 | } |
| 1161 | 1168 | |
| 1162 | 1169 | static const struct inode_operations xfs_inode_operations = { |
| @@ -14,6 +14,7 @@ extern const struct file_operations xfs_dir_file_operations; · 13 unmodified lines | ||
| 14 | 14 | extern ssize_t xfs_vn_listxattr(struct dentry *, char *data, size_t size); |
| 15 | 15 | |
| 16 | 16 | extern void xfs_setattr_time(struct xfs_inode *ip, struct iattr *iattr); |
| 17 | −extern int xfs_vn_setattr_size(struct dentry *dentry, struct iattr *vap); | |
| 17 | +int xfs_vn_setattr_size(struct user_namespace *mnt_userns, | |
| 18 | + struct dentry *dentry, struct iattr *vap); | |
| 18 | 19 | |
| 19 | 20 | #endif /* __XFS_IOPS_H__ */ |
| @@ -54,10 +54,12 @@ struct xfs_bstat_chunk { · 53 unmodified lines | ||
| 54 | 54 | STATIC int |
| 55 | 55 | xfs_bulkstat_one_int( |
| 56 | 56 | struct xfs_mount *mp, |
| 57 | + struct user_namespace *mnt_userns, | |
| 57 | 58 | struct xfs_trans *tp, |
| 58 | 59 | xfs_ino_t ino, |
| 59 | 60 | struct xfs_bstat_chunk *bc) |
| 60 | 61 | { |
| 62 | + struct user_namespace *sb_userns = mp->m_super->s_user_ns; | |
| 61 | 63 | struct xfs_icdinode *dic; /* dinode core info pointer */ |
| 62 | 64 | struct xfs_inode *ip; /* incore inode pointer */ |
| 63 | 65 | struct inode *inode; |
| @@ -86,8 +88,8 @@ xfs_bulkstat_one_int( · 22 unmodified lines | ||
| 86 | 88 | */ |
| 87 | 89 | buf->bs_projectid = ip->i_d.di_projid; |
| 88 | 90 | buf->bs_ino = ino; |
| 89 | − buf->bs_uid = i_uid_read(inode); | |
| 90 | − buf->bs_gid = i_gid_read(inode); | |
| 91 | + buf->bs_uid = from_kuid(sb_userns, i_uid_into_mnt(mnt_userns, inode)); | |
| 92 | + buf->bs_gid = from_kgid(sb_userns, i_gid_into_mnt(mnt_userns, inode)); | |
| 91 | 93 | buf->bs_size = dic->di_size; |
| 92 | 94 | |
| 93 | 95 | buf->bs_nlink = inode->i_nlink; |
| @@ -173,7 +175,8 @@ xfs_bulkstat_one( · 79 unmodified lines | ||
| 173 | 175 | if (!bc.buf) |
| 174 | 176 | return -ENOMEM; |
| 175 | 177 | |
| 176 | − error = xfs_bulkstat_one_int(breq->mp, NULL, breq->startino, &bc); | |
| 178 | + error = xfs_bulkstat_one_int(breq->mp, breq->mnt_userns, NULL, | |
| 179 | + breq->startino, &bc); | |
| 177 | 180 | |
| 178 | 181 | kmem_free(bc.buf); |
| 179 | 182 | |
| @@ -194,9 +197,10 @@ xfs_bulkstat_iwalk( · 14 unmodified lines | ||
| 194 | 197 | xfs_ino_t ino, |
| 195 | 198 | void *data) |
| 196 | 199 | { |
| 200 | + struct xfs_bstat_chunk *bc = data; | |
| 197 | 201 | int error; |
| 198 | 202 | |
| 199 | − error = xfs_bulkstat_one_int(mp, tp, ino, data); | |
| 203 | + error = xfs_bulkstat_one_int(mp, bc->breq->mnt_userns, tp, ino, data); | |
| 200 | 204 | /* bulkstat just skips over missing inodes */ |
| 201 | 205 | if (error == -ENOENT || error == -EINVAL) |
| 202 | 206 | return 0; |
| @@ -239,6 +243,11 @@ xfs_bulkstat( · 36 unmodified lines | ||
| 239 | 243 | }; |
| 240 | 244 | int error; |
| 241 | 245 | |
| 246 | + if (breq->mnt_userns != &init_user_ns) { | |
| 247 | + xfs_warn_ratelimited(breq->mp, | |
| 248 | + "bulkstat not supported inside of idmapped mounts."); | |
| 249 | + return -EINVAL; | |
| 250 | + } | |
| 242 | 251 | if (xfs_bulkstat_already_done(breq->mp, breq->startino)) |
| 243 | 252 | return 0; |
| 244 | 253 | |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | ||
| 8 | 8 | /* In-memory representation of a userspace request for batch inode data. */ |
| 9 | 9 | struct xfs_ibulk { |
| 10 | 10 | struct xfs_mount *mp; |
| 11 | + struct user_namespace *mnt_userns; | |
| 11 | 12 | void __user *ubuffer; /* user output buffer */ |
| 12 | 13 | xfs_ino_t startino; /* start with this inode */ |
| 13 | 14 | unsigned int icount; /* number of elements in ubuffer */ |
| @@ -787,7 +787,8 @@ xfs_qm_qino_alloc( · 786 unmodified lines | ||
| 787 | 787 | return error; |
| 788 | 788 | |
| 789 | 789 | if (need_alloc) { |
| 790 | − error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, ipp); | |
| 790 | + error = xfs_dir_ialloc(&init_user_ns, &tp, NULL, S_IFREG, 1, 0, | |
| 791 | + 0, ipp); | |
| 791 | 792 | if (error) { |
| 792 | 793 | xfs_trans_cancel(tp); |
| 793 | 794 | return error; |
| @@ -1912,7 +1912,7 @@ static struct file_system_type xfs_fs_type = { · 1911 unmodified lines | ||
| 1912 | 1912 | .init_fs_context = xfs_init_fs_context, |
| 1913 | 1913 | .parameters = xfs_fs_parameters, |
| 1914 | 1914 | .kill_sb = kill_block_super, |
| 1915 | − .fs_flags = FS_REQUIRES_DEV, | |
| 1915 | + .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP, | |
| 1916 | 1916 | }; |
| 1917 | 1917 | MODULE_ALIAS_FS("xfs"); |
| 1918 | 1918 | |
| @@ -134,6 +134,7 @@ xfs_readlink( · 133 unmodified lines | ||
| 134 | 134 | |
| 135 | 135 | int |
| 136 | 136 | xfs_symlink( |
| 137 | + struct user_namespace *mnt_userns, | |
| 137 | 138 | struct xfs_inode *dp, |
| 138 | 139 | struct xfs_name *link_name, |
| 139 | 140 | const char *target_path, |
| @@ -223,8 +224,8 @@ xfs_symlink( · 83 unmodified lines | ||
| 223 | 224 | /* |
| 224 | 225 | * Allocate an inode for the symlink. |
| 225 | 226 | */ |
| 226 | − error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0, | |
| 227 | − prid, &ip); | |
| 227 | + error = xfs_dir_ialloc(mnt_userns, &tp, dp, S_IFLNK | (mode & ~S_IFMT), | |
| 228 | + 1, 0, prid, &ip); | |
| 228 | 229 | if (error) |
| 229 | 230 | goto out_trans_cancel; |
| 230 | 231 | |
| @@ -7,8 +7,9 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | /* Kernel only symlink definitions */ |
| 9 | 9 | |
| 10 | −int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, | |
| 11 | − const char *target_path, umode_t mode, struct xfs_inode **ipp); | |
| 10 | +int xfs_symlink(struct user_namespace *mnt_userns, struct xfs_inode *dp, | |
| 11 | + struct xfs_name *link_name, const char *target_path, | |
| 12 | + umode_t mode, struct xfs_inode **ipp); | |
| 12 | 13 | int xfs_readlink_bmap_ilocked(struct xfs_inode *ip, char *link); |
| 13 | 14 | int xfs_readlink(struct xfs_inode *ip, char *link); |
| 14 | 15 | int xfs_inactive_symlink(struct xfs_inode *ip); |