diff options
author | youzhongyang <[email protected]> | 2022-11-08 13:28:56 -0500 |
---|---|---|
committer | GitHub <[email protected]> | 2022-11-08 10:28:56 -0800 |
commit | f224eddf922a33ca4b86d83148e9e6fa155fc290 (patch) | |
tree | fbd3d2703fc4c00f0431c6e261c41b037f3f63ab /module/os/linux | |
parent | 109731cd73c56c378b4c71732b9b9d3504a7a7e1 (diff) |
Support idmapped mount in user namespace
Linux 5.17 commit torvalds/linux@5dfbfe71e enables "the idmapping
infrastructure to support idmapped mounts of filesystems mounted
with an idmapping". Update the OpenZFS accordingly to improve the
idmapped mount support.
This pull request contains the following changes:
- xattr setter functions are fixed to take mnt_ns argument. Without
this, cp -p would fail for an idmapped mount in a user namespace.
- idmap_util is enhanced/fixed for its use in a user ns context.
- One test case added to test idmapped mount in a user ns.
Reviewed-by: Christian Brauner <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Youzhong Yang <[email protected]>
Closes #14097
Diffstat (limited to 'module/os/linux')
-rw-r--r-- | module/os/linux/zfs/policy.c | 17 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_acl.c | 24 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_dir.c | 7 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_vnops_os.c | 25 | ||||
-rw-r--r-- | module/os/linux/zfs/zfs_znode.c | 2 | ||||
-rw-r--r-- | module/os/linux/zfs/zpl_ctldir.c | 2 | ||||
-rw-r--r-- | module/os/linux/zfs/zpl_file.c | 6 | ||||
-rw-r--r-- | module/os/linux/zfs/zpl_inode.c | 38 | ||||
-rw-r--r-- | module/os/linux/zfs/zpl_xattr.c | 34 |
9 files changed, 100 insertions, 55 deletions
diff --git a/module/os/linux/zfs/policy.c b/module/os/linux/zfs/policy.c index 50eb7cfaa..eaf38df86 100644 --- a/module/os/linux/zfs/policy.c +++ b/module/os/linux/zfs/policy.c @@ -214,9 +214,10 @@ secpolicy_vnode_setid_retain(struct znode *zp __maybe_unused, const cred_t *cr, * Determine that subject can set the file setgid flag. */ int -secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zuserns_t *mnt_ns) +secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zuserns_t *mnt_ns, + zuserns_t *fs_ns) { - gid = zfs_gid_into_mnt(mnt_ns, gid); + gid = zfs_gid_to_vfsgid(mnt_ns, fs_ns, gid); #if defined(CONFIG_USER_NS) if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid))) return (EPERM); @@ -285,9 +286,10 @@ secpolicy_setid_clear(vattr_t *vap, cred_t *cr) * Determine that subject can set the file setid flags. */ static int -secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zuserns_t *mnt_ns) +secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zuserns_t *mnt_ns, + zuserns_t *fs_ns) { - owner = zfs_uid_into_mnt(mnt_ns, owner); + owner = zfs_uid_to_vfsuid(mnt_ns, fs_ns, owner); if (crgetuid(cr) == owner) return (0); @@ -313,13 +315,13 @@ secpolicy_vnode_stky_modify(const cred_t *cr) int secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap, - const vattr_t *ovap, cred_t *cr, zuserns_t *mnt_ns) + const vattr_t *ovap, cred_t *cr, zuserns_t *mnt_ns, zuserns_t *fs_ns) { int error; if ((vap->va_mode & S_ISUID) != 0 && (error = secpolicy_vnode_setid_modify(cr, - ovap->va_uid, mnt_ns)) != 0) { + ovap->va_uid, mnt_ns, fs_ns)) != 0) { return (error); } @@ -337,7 +339,8 @@ secpolicy_setid_setsticky_clear(struct inode *ip, vattr_t *vap, * group-id bit. */ if ((vap->va_mode & S_ISGID) != 0 && - secpolicy_vnode_setids_setgids(cr, ovap->va_gid, mnt_ns) != 0) { + secpolicy_vnode_setids_setgids(cr, ovap->va_gid, + mnt_ns, fs_ns) != 0) { vap->va_mode &= ~S_ISGID; } diff --git a/module/os/linux/zfs/zfs_acl.c b/module/os/linux/zfs/zfs_acl.c index 437169990..7d14863c5 100644 --- a/module/os/linux/zfs/zfs_acl.c +++ b/module/os/linux/zfs/zfs_acl.c @@ -1889,7 +1889,8 @@ zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, acl_ids->z_mode |= S_ISGID; } else { if ((acl_ids->z_mode & S_ISGID) && - secpolicy_vnode_setids_setgids(cr, gid, mnt_ns) != 0) { + secpolicy_vnode_setids_setgids(cr, gid, mnt_ns, + zfs_i_user_ns(ZTOI(dzp))) != 0) { acl_ids->z_mode &= ~S_ISGID; } } @@ -1979,7 +1980,8 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) if (mask == 0) return (SET_ERROR(ENOSYS)); - if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL))) + if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, + kcred->user_ns))) return (error); mutex_enter(&zp->z_acl_lock); @@ -2138,7 +2140,8 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr) if (zp->z_pflags & ZFS_IMMUTABLE) return (SET_ERROR(EPERM)); - if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL))) + if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, + kcred->user_ns))) return (error); error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp, @@ -2301,9 +2304,9 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, uid_t fowner; if (mnt_ns) { - fowner = zfs_uid_into_mnt(mnt_ns, + fowner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), KUID_TO_SUID(ZTOI(zp)->i_uid)); - gowner = zfs_gid_into_mnt(mnt_ns, + gowner = zfs_gid_to_vfsgid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), KGID_TO_SGID(ZTOI(zp)->i_gid)); } else zfs_fuid_map_ids(zp, cr, &fowner, &gowner); @@ -2417,7 +2420,8 @@ zfs_has_access(znode_t *zp, cred_t *cr) { uint32_t have = ACE_ALL_PERMS; - if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, NULL) != 0) { + if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, + kcred->user_ns) != 0) { uid_t owner; owner = zfs_fuid_map_id(ZTOZSB(zp), @@ -2610,7 +2614,8 @@ slow: DTRACE_PROBE(zfs__fastpath__execute__access__miss); if ((error = zfs_enter(ZTOZSB(zdp), FTAG)) != 0) return (error); - error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, NULL); + error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, + kcred->user_ns); zfs_exit(ZTOZSB(zdp), FTAG); return (error); } @@ -2662,7 +2667,8 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, } } - owner = zfs_uid_into_mnt(mnt_ns, KUID_TO_SUID(ZTOI(zp)->i_uid)); + owner = zfs_uid_to_vfsuid(mnt_ns, zfs_i_user_ns(ZTOI(zp)), + KUID_TO_SUID(ZTOI(zp)->i_uid)); owner = zfs_fuid_map_id(ZTOZSB(zp), owner, cr, ZFS_OWNER); /* @@ -2786,7 +2792,7 @@ zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr) { int v4_mode = zfs_unix_to_v4(mode >> 6); - return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL)); + return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, kcred->user_ns)); } /* See zfs_zaccess_delete() */ diff --git a/module/os/linux/zfs/zfs_dir.c b/module/os/linux/zfs/zfs_dir.c index b4e4146b0..85aa94d8d 100644 --- a/module/os/linux/zfs/zfs_dir.c +++ b/module/os/linux/zfs/zfs_dir.c @@ -1113,11 +1113,11 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xzpp, cred_t *cr) *xzpp = NULL; if ((error = zfs_zaccess(zp, ACE_WRITE_NAMED_ATTRS, 0, B_FALSE, cr, - NULL))) + kcred->user_ns))) return (error); if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL, - &acl_ids, NULL)) != 0) + &acl_ids, kcred->user_ns)) != 0) return (error); if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zp->z_projid)) { zfs_acl_ids_free(&acl_ids); @@ -1265,7 +1265,8 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr) cr, ZFS_OWNER); if ((uid = crgetuid(cr)) == downer || uid == fowner || - zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL) == 0) + zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, + kcred->user_ns) == 0) return (0); else return (secpolicy_vnode_remove(cr)); diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c index 545d8ad8d..29d62837a 100644 --- a/module/os/linux/zfs/zfs_vnops_os.c +++ b/module/os/linux/zfs/zfs_vnops_os.c @@ -476,7 +476,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, */ if ((error = zfs_zaccess(*zpp, ACE_EXECUTE, 0, - B_TRUE, cr, NULL))) { + B_TRUE, cr, kcred->user_ns))) { zrele(*zpp); *zpp = NULL; } @@ -494,7 +494,8 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, * Check accessibility of directory. */ - if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, NULL))) { + if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, + kcred->user_ns))) { zfs_exit(zfsvfs, FTAG); return (error); } @@ -972,7 +973,7 @@ top: return (error); } - if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { + if ((error = zfs_zaccess_delete(dzp, zp, cr, kcred->user_ns))) { goto out; } @@ -1386,7 +1387,7 @@ top: return (error); } - if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { + if ((error = zfs_zaccess_delete(dzp, zp, cr, kcred->user_ns))) { goto out; } @@ -2024,10 +2025,10 @@ top: * Take ownership or chgrp to group we are a member of */ - uid = zfs_uid_into_mnt((struct user_namespace *)mnt_ns, - vap->va_uid); - gid = zfs_gid_into_mnt((struct user_namespace *)mnt_ns, - vap->va_gid); + uid = zfs_uid_to_vfsuid((struct user_namespace *)mnt_ns, + zfs_i_user_ns(ip), vap->va_uid); + gid = zfs_gid_to_vfsgid((struct user_namespace *)mnt_ns, + zfs_i_user_ns(ip), vap->va_gid); take_owner = (mask & ATTR_UID) && (uid == crgetuid(cr)); take_group = (mask & ATTR_GID) && zfs_groupmember(zfsvfs, gid, cr); @@ -2162,7 +2163,7 @@ top: if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, mnt_ns) == 0) { err = secpolicy_setid_setsticky_clear(ip, vap, - &oldva, cr, mnt_ns); + &oldva, cr, mnt_ns, zfs_i_user_ns(ip)); if (err) goto out3; trim_mask |= ATTR_MODE; @@ -3506,7 +3507,8 @@ zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr, return (SET_ERROR(EPERM)); } - if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, NULL))) { + if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, + kcred->user_ns))) { zfs_exit(zfsvfs, FTAG); return (error); } @@ -4132,7 +4134,8 @@ zfs_space(znode_t *zp, int cmd, flock64_t *bfp, int flag, * On Linux we can get here through truncate_range() which * operates directly on inodes, so we need to check access rights. */ - if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL))) { + if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, + kcred->user_ns))) { zfs_exit(zfsvfs, FTAG); return (error); } diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c index c8f6e02bd..662147ab4 100644 --- a/module/os/linux/zfs/zfs_znode.c +++ b/module/os/linux/zfs/zfs_znode.c @@ -1964,7 +1964,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) } VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, - cr, NULL, &acl_ids, NULL)); + cr, NULL, &acl_ids, kcred->user_ns)); zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids); ASSERT3P(zp, ==, rootzp); error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx); diff --git a/module/os/linux/zfs/zpl_ctldir.c b/module/os/linux/zfs/zpl_ctldir.c index 8bc4a9b39..f0779c81d 100644 --- a/module/os/linux/zfs/zpl_ctldir.c +++ b/module/os/linux/zfs/zpl_ctldir.c @@ -374,7 +374,7 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) #ifdef HAVE_IOPS_MKDIR_USERNS zpl_vap_init(vap, dip, mode | S_IFDIR, cr, user_ns); #else - zpl_vap_init(vap, dip, mode | S_IFDIR, cr, NULL); + zpl_vap_init(vap, dip, mode | S_IFDIR, cr, kcred->user_ns); #endif error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0); diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c index cfa03e571..c56e3691e 100644 --- a/module/os/linux/zfs/zpl_file.c +++ b/module/os/linux/zfs/zpl_file.c @@ -1085,7 +1085,7 @@ zpl_ioctl_setflags(struct file *filp, void __user *arg) crhold(cr); cookie = spl_fstrans_mark(); - err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); + err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); spl_fstrans_unmark(cookie); crfree(cr); @@ -1133,7 +1133,7 @@ zpl_ioctl_setxattr(struct file *filp, void __user *arg) crhold(cr); cookie = spl_fstrans_mark(); - err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); + err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); spl_fstrans_unmark(cookie); crfree(cr); @@ -1221,7 +1221,7 @@ zpl_ioctl_setdosflags(struct file *filp, void __user *arg) crhold(cr); cookie = spl_fstrans_mark(); - err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); + err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, kcred->user_ns); spl_fstrans_unmark(cookie); crfree(cr); diff --git a/module/os/linux/zfs/zpl_inode.c b/module/os/linux/zfs/zpl_inode.c index 64016f9ac..6f4718f7d 100644 --- a/module/os/linux/zfs/zpl_inode.c +++ b/module/os/linux/zfs/zpl_inode.c @@ -118,16 +118,16 @@ zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr, vap->va_mask = ATTR_MODE; vap->va_mode = mode; - vap->va_uid = zfs_uid_from_mnt((struct user_namespace *)mnt_ns, - crgetuid(cr)); + vap->va_uid = zfs_vfsuid_to_uid((struct user_namespace *)mnt_ns, + zfs_i_user_ns(dir), crgetuid(cr)); if (dir && dir->i_mode & S_ISGID) { vap->va_gid = KGID_TO_SGID(dir->i_gid); if (S_ISDIR(mode)) vap->va_mode |= S_ISGID; } else { - vap->va_gid = zfs_gid_from_mnt((struct user_namespace *)mnt_ns, - crgetgid(cr)); + vap->va_gid = zfs_vfsgid_to_gid((struct user_namespace *)mnt_ns, + zfs_i_user_ns(dir), crgetgid(cr)); } } @@ -145,7 +145,7 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) int error; fstrans_cookie_t cookie; #ifndef HAVE_IOPS_CREATE_USERNS - zuserns_t *user_ns = NULL; + zuserns_t *user_ns = kcred->user_ns; #endif crhold(cr); @@ -192,7 +192,7 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, int error; fstrans_cookie_t cookie; #ifndef HAVE_IOPS_MKNOD_USERNS - zuserns_t *user_ns = NULL; + zuserns_t *user_ns = kcred->user_ns; #endif /* @@ -247,7 +247,7 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) int error; fstrans_cookie_t cookie; #ifndef HAVE_TMPFILE_USERNS - zuserns_t *userns = NULL; + zuserns_t *userns = kcred->user_ns; #endif crhold(cr); @@ -325,7 +325,7 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) int error; fstrans_cookie_t cookie; #ifndef HAVE_IOPS_MKDIR_USERNS - zuserns_t *user_ns = NULL; + zuserns_t *user_ns = kcred->user_ns; #endif crhold(cr); @@ -468,8 +468,20 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); vap->va_mask = ia->ia_valid & ATTR_IATTR_MASK; vap->va_mode = ia->ia_mode; - vap->va_uid = KUID_TO_SUID(ia->ia_uid); - vap->va_gid = KGID_TO_SGID(ia->ia_gid); + if (ia->ia_valid & ATTR_UID) +#ifdef HAVE_IATTR_VFSID + vap->va_uid = zfs_vfsuid_to_uid(user_ns, zfs_i_user_ns(ip), + __vfsuid_val(ia->ia_vfsuid)); +#else + vap->va_uid = KUID_TO_SUID(ia->ia_uid); +#endif + if (ia->ia_valid & ATTR_GID) +#ifdef HAVE_IATTR_VFSID + vap->va_gid = zfs_vfsgid_to_gid(user_ns, zfs_i_user_ns(ip), + __vfsgid_val(ia->ia_vfsgid)); +#else + vap->va_gid = KGID_TO_SGID(ia->ia_gid); +#endif vap->va_size = ia->ia_size; vap->va_atime = ia->ia_atime; vap->va_mtime = ia->ia_mtime; @@ -482,7 +494,7 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) #ifdef HAVE_SETATTR_PREPARE_USERNS error = -zfs_setattr(ITOZ(ip), vap, 0, cr, user_ns); #else - error = -zfs_setattr(ITOZ(ip), vap, 0, cr, NULL); + error = -zfs_setattr(ITOZ(ip), vap, 0, cr, kcred->user_ns); #endif if (!error && (ia->ia_valid & ATTR_MODE)) error = zpl_chmod_acl(ip); @@ -510,7 +522,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, int error; fstrans_cookie_t cookie; #ifndef HAVE_IOPS_RENAME_USERNS - zuserns_t *user_ns = NULL; + zuserns_t *user_ns = kcred->user_ns; #endif crhold(cr); @@ -557,7 +569,7 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) int error; fstrans_cookie_t cookie; #ifndef HAVE_IOPS_SYMLINK_USERNS - zuserns_t *user_ns = NULL; + zuserns_t *user_ns = kcred->user_ns; #endif crhold(cr); diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c index 97b6e048c..99d9b3793 100644 --- a/module/os/linux/zfs/zpl_xattr.c +++ b/module/os/linux/zfs/zpl_xattr.c @@ -499,7 +499,7 @@ zpl_xattr_set_dir(struct inode *ip, const char *name, const void *value, vap->va_gid = crgetgid(cr); error = -zfs_create(dxzp, (char *)name, vap, 0, 0644, &xzp, - cr, 0, NULL, NULL); + cr, 0, NULL, kcred->user_ns); if (error) goto out; } @@ -738,9 +738,11 @@ __zpl_xattr_user_get(struct inode *ip, const char *name, ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get); static int -__zpl_xattr_user_set(struct inode *ip, const char *name, +__zpl_xattr_user_set(struct user_namespace *user_ns, + struct inode *ip, const char *name, const void *value, size_t size, int flags) { + (void) user_ns; int error = 0; /* xattr_resolve_name will do this for us if this is defined */ #ifndef HAVE_XATTR_HANDLER_NAME @@ -846,9 +848,11 @@ __zpl_xattr_trusted_get(struct inode *ip, const char *name, ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get); static int -__zpl_xattr_trusted_set(struct inode *ip, const char *name, +__zpl_xattr_trusted_set(struct user_namespace *user_ns, + struct inode *ip, const char *name, const void *value, size_t size, int flags) { + (void) user_ns; char *xattr_name; int error; @@ -914,9 +918,11 @@ __zpl_xattr_security_get(struct inode *ip, const char *name, ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get); static int -__zpl_xattr_security_set(struct inode *ip, const char *name, +__zpl_xattr_security_set(struct user_namespace *user_ns, + struct inode *ip, const char *name, const void *value, size_t size, int flags) { + (void) user_ns; char *xattr_name; int error; /* xattr_resolve_name will do this for us if this is defined */ @@ -940,7 +946,7 @@ zpl_xattr_security_init_impl(struct inode *ip, const struct xattr *xattrs, int error = 0; for (xattr = xattrs; xattr->name != NULL; xattr++) { - error = __zpl_xattr_security_set(ip, + error = __zpl_xattr_security_set(NULL, ip, xattr->name, xattr->value, xattr->value_len, 0); if (error < 0) @@ -1300,7 +1306,8 @@ __zpl_xattr_acl_get_default(struct inode *ip, const char *name, ZPL_XATTR_GET_WRAPPER(zpl_xattr_acl_get_default); static int -__zpl_xattr_acl_set_access(struct inode *ip, const char *name, +__zpl_xattr_acl_set_access(struct user_namespace *mnt_ns, + struct inode *ip, const char *name, const void *value, size_t size, int flags) { struct posix_acl *acl; @@ -1314,8 +1321,14 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name, if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) return (-EOPNOTSUPP); +#if defined(HAVE_XATTR_SET_USERNS) + if (!zpl_inode_owner_or_capable(mnt_ns, ip)) + return (-EPERM); +#else + (void) mnt_ns; if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) return (-EPERM); +#endif if (value) { acl = zpl_acl_from_xattr(value, size); @@ -1339,7 +1352,8 @@ __zpl_xattr_acl_set_access(struct inode *ip, const char *name, ZPL_XATTR_SET_WRAPPER(zpl_xattr_acl_set_access); static int -__zpl_xattr_acl_set_default(struct inode *ip, const char *name, +__zpl_xattr_acl_set_default(struct user_namespace *mnt_ns, + struct inode *ip, const char *name, const void *value, size_t size, int flags) { struct posix_acl *acl; @@ -1353,8 +1367,14 @@ __zpl_xattr_acl_set_default(struct inode *ip, const char *name, if (ITOZSB(ip)->z_acl_type != ZFS_ACLTYPE_POSIX) return (-EOPNOTSUPP); +#if defined(HAVE_XATTR_SET_USERNS) + if (!zpl_inode_owner_or_capable(mnt_ns, ip)) + return (-EPERM); +#else + (void) mnt_ns; if (!zpl_inode_owner_or_capable(kcred->user_ns, ip)) return (-EPERM); +#endif if (value) { acl = zpl_acl_from_xattr(value, size); |