diff --git a/config/kernel-idmap_mnt_api.m4 b/config/kernel-idmap_mnt_api.m4 new file mode 100644 index 000000000000..47ddc5702fb7 --- /dev/null +++ b/config/kernel-idmap_mnt_api.m4 @@ -0,0 +1,25 @@ +dnl # +dnl # 5.12 API +dnl # +dnl # Check if APIs for idmapped mount are available +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SRC_IDMAP_MNT_API], [ + ZFS_LINUX_TEST_SRC([idmap_mnt_api], [ + #include + ],[ + int fs_flags = 0; + fs_flags |= FS_ALLOW_IDMAP; + ]) +]) + +AC_DEFUN([ZFS_AC_KERNEL_IDMAP_MNT_API], [ + AC_MSG_CHECKING([whether APIs for idmapped mount are present]) + ZFS_LINUX_TEST_RESULT([idmap_mnt_api], [ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_IDMAP_MNT_API, 1, + [APIs for idmapped mount are present]) + ],[ + AC_MSG_RESULT([no]) + ]) +]) + diff --git a/config/kernel.m4 b/config/kernel.m4 index 6aad2cf88e02..1866bbc77acc 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -148,6 +148,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ ZFS_AC_KERNEL_SRC_ZERO_PAGE ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC ZFS_AC_KERNEL_SRC_USER_NS_COMMON_INUM + ZFS_AC_KERNEL_SRC_IDMAP_MNT_API AC_MSG_CHECKING([for available kernel interfaces]) ZFS_LINUX_TEST_COMPILE_ALL([kabi]) @@ -269,6 +270,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ ZFS_AC_KERNEL_ZERO_PAGE ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC ZFS_AC_KERNEL_USER_NS_COMMON_INUM + ZFS_AC_KERNEL_IDMAP_MNT_API ]) dnl # diff --git a/include/os/freebsd/spl/sys/types.h b/include/os/freebsd/spl/sys/types.h index b1308df29503..558843dcaa74 100644 --- a/include/os/freebsd/spl/sys/types.h +++ b/include/os/freebsd/spl/sys/types.h @@ -105,5 +105,7 @@ typedef u_longlong_t len_t; typedef longlong_t diskaddr_t; +typedef void zuserns_t; + #include #endif /* !_OPENSOLARIS_SYS_TYPES_H_ */ diff --git a/include/os/freebsd/zfs/sys/zfs_vnops_os.h b/include/os/freebsd/zfs/sys/zfs_vnops_os.h index bf5e03b24c06..460aecd2e708 100644 --- a/include/os/freebsd/zfs/sys/zfs_vnops_os.h +++ b/include/os/freebsd/zfs/sys/zfs_vnops_os.h @@ -35,20 +35,22 @@ int dmu_read_pages(objset_t *os, uint64_t object, vm_page_t *ma, int count, int *rbehind, int *rahead, int last_size); extern int zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags); extern int zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, - znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp); + znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns); extern int zfs_rmdir(znode_t *dzp, const char *name, znode_t *cwd, cred_t *cr, int flags); -extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr); +extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr, + zuserns_t *mnt_ns); extern int zfs_rename(znode_t *sdzp, const char *snm, znode_t *tdzp, - const char *tnm, cred_t *cr, int flags); + const char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns); extern int zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, - const char *link, znode_t **zpp, cred_t *cr, int flags); + const char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns); extern int zfs_link(znode_t *tdzp, znode_t *sp, const char *name, cred_t *cr, int flags); extern int zfs_space(znode_t *zp, int cmd, struct flock *bfp, int flag, offset_t offset, cred_t *cr); extern int zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, - int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp); + int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, + zuserns_t *mnt_ns); extern int zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, cred_t *cr); extern int zfs_write_simple(znode_t *zp, const void *data, size_t len, diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h index b7d3f38d70bb..dc3c260dbbab 100644 --- a/include/os/linux/spl/sys/cred.h +++ b/include/os/linux/spl/sys/cred.h @@ -45,6 +45,34 @@ typedef struct cred cred_t; #define SGID_TO_KGID(x) (KGIDT_INIT(x)) #define KGIDP_TO_SGIDP(x) (&(x)->val) +static inline uid_t zfs_uid_into_mnt(struct user_namespace *mnt_ns, uid_t uid) +{ + if (mnt_ns) + return (__kuid_val(make_kuid(mnt_ns, uid))); + return (uid); +} + +static inline gid_t zfs_gid_into_mnt(struct user_namespace *mnt_ns, gid_t gid) +{ + if (mnt_ns) + return (__kgid_val(make_kgid(mnt_ns, gid))); + return (gid); +} + +static inline uid_t zfs_uid_from_mnt(struct user_namespace *mnt_ns, uid_t uid) +{ + if (mnt_ns) + return (from_kuid(mnt_ns, KUIDT_INIT(uid))); + return (uid); +} + +static inline gid_t zfs_gid_from_mnt(struct user_namespace *mnt_ns, gid_t gid) +{ + if (mnt_ns) + return (from_kgid(mnt_ns, KGIDT_INIT(gid))); + return (gid); +} + extern void crhold(cred_t *cr); extern void crfree(cred_t *cr); extern uid_t crgetuid(const cred_t *cr); diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h index b44c94518750..cae1bbddf105 100644 --- a/include/os/linux/spl/sys/types.h +++ b/include/os/linux/spl/sys/types.h @@ -54,4 +54,7 @@ typedef ulong_t pgcnt_t; typedef int major_t; typedef int minor_t; +struct user_namespace; +typedef struct user_namespace zuserns_t; + #endif /* _SPL_TYPES_H */ diff --git a/include/os/linux/zfs/sys/policy.h b/include/os/linux/zfs/sys/policy.h index 3bd7ce36b85d..ee7fda761a3b 100644 --- a/include/os/linux/zfs/sys/policy.h +++ b/include/os/linux/zfs/sys/policy.h @@ -47,13 +47,13 @@ int secpolicy_vnode_create_gid(const cred_t *); int secpolicy_vnode_remove(const cred_t *); int secpolicy_vnode_setdac(const cred_t *, uid_t); int secpolicy_vnode_setid_retain(struct znode *, const cred_t *, boolean_t); -int secpolicy_vnode_setids_setgids(const cred_t *, gid_t); +int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zuserns_t *); int secpolicy_zinject(const cred_t *); int secpolicy_zfs(const cred_t *); int secpolicy_zfs_proc(const cred_t *, proc_t *); void secpolicy_setid_clear(vattr_t *, cred_t *); int secpolicy_setid_setsticky_clear(struct inode *, vattr_t *, - const vattr_t *, cred_t *); + const vattr_t *, cred_t *, zuserns_t *); int secpolicy_xvattr(xvattr_t *, uid_t, cred_t *, mode_t); int secpolicy_vnode_setattr(cred_t *, struct inode *, struct vattr *, const struct vattr *, int, int (void *, int, cred_t *), void *); diff --git a/include/os/linux/zfs/sys/zfs_vnops_os.h b/include/os/linux/zfs/sys/zfs_vnops_os.h index 22ca625023b0..787d258e1388 100644 --- a/include/os/linux/zfs/sys/zfs_vnops_os.h +++ b/include/os/linux/zfs/sys/zfs_vnops_os.h @@ -45,22 +45,25 @@ extern int zfs_write_simple(znode_t *zp, const void *data, size_t len, extern int zfs_lookup(znode_t *dzp, char *nm, znode_t **zpp, int flags, cred_t *cr, int *direntflags, pathname_t *realpnp); extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp); + int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, + zuserns_t *mnt_ns); extern int zfs_tmpfile(struct inode *dip, vattr_t *vapzfs, int excl, - int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp); + int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp, + zuserns_t *mnt_ns); extern int zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags); extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, - znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp); + znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns); extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, cred_t *cr, int flags); extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr); extern int zfs_getattr_fast(struct user_namespace *, struct inode *ip, struct kstat *sp); -extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr); +extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr, + zuserns_t *mnt_ns); extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, - char *tnm, cred_t *cr, int flags); + char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns); extern int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, - char *link, znode_t **zpp, cred_t *cr, int flags); + char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns); extern int zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr); extern int zfs_link(znode_t *tdzp, znode_t *szp, char *name, cred_t *cr, int flags); diff --git a/include/os/linux/zfs/sys/zpl.h b/include/os/linux/zfs/sys/zpl.h index 95f08f5416d0..30d73db6b9e8 100644 --- a/include/os/linux/zfs/sys/zpl.h +++ b/include/os/linux/zfs/sys/zpl.h @@ -39,7 +39,7 @@ /* zpl_inode.c */ extern void zpl_vap_init(vattr_t *vap, struct inode *dir, - umode_t mode, cred_t *cr); + umode_t mode, cred_t *cr, zuserns_t *mnt_ns); extern const struct inode_operations zpl_inode_operations; extern const struct inode_operations zpl_dir_inode_operations; diff --git a/include/sys/zfs_acl.h b/include/sys/zfs_acl.h index c4d2dddd7b1f..82fb98c9fb89 100644 --- a/include/sys/zfs_acl.h +++ b/include/sys/zfs_acl.h @@ -206,7 +206,7 @@ struct zfsvfs; #ifdef _KERNEL int zfs_acl_ids_create(struct znode *, int, vattr_t *, - cred_t *, vsecattr_t *, zfs_acl_ids_t *); + cred_t *, vsecattr_t *, zfs_acl_ids_t *, zuserns_t *); void zfs_acl_ids_free(zfs_acl_ids_t *); boolean_t zfs_acl_ids_overquota(struct zfsvfs *, zfs_acl_ids_t *, uint64_t); int zfs_getacl(struct znode *, vsecattr_t *, boolean_t, cred_t *); @@ -215,15 +215,16 @@ void zfs_acl_rele(void *); void zfs_oldace_byteswap(ace_t *, int); void zfs_ace_byteswap(void *, size_t, boolean_t); extern boolean_t zfs_has_access(struct znode *zp, cred_t *cr); -extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *); +extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *, + zuserns_t *); int zfs_fastaccesschk_execute(struct znode *, cred_t *); -extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *); +extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *, zuserns_t *); extern int zfs_zaccess_unix(struct znode *, mode_t, cred_t *); extern int zfs_acl_access(struct znode *, int, cred_t *); int zfs_acl_chmod_setattr(struct znode *, zfs_acl_t **, uint64_t); -int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *); +int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *, zuserns_t *); int zfs_zaccess_rename(struct znode *, struct znode *, - struct znode *, struct znode *, cred_t *cr); + struct znode *, struct znode *, cred_t *cr, zuserns_t *mnt_ns); void zfs_acl_free(zfs_acl_t *); int zfs_vsec_2_aclp(struct zfsvfs *, umode_t, vsecattr_t *, cred_t *, struct zfs_fuid_info **, zfs_acl_t **); diff --git a/module/os/freebsd/zfs/zfs_acl.c b/module/os/freebsd/zfs/zfs_acl.c index ad482ee9d49b..f2d749e1c68d 100644 --- a/module/os/freebsd/zfs/zfs_acl.c +++ b/module/os/freebsd/zfs/zfs_acl.c @@ -1618,7 +1618,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp, */ int zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, - vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids) + vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zuserns_t *mnt_ns) { int error; zfsvfs_t *zfsvfs = dzp->z_zfsvfs; @@ -1788,7 +1788,7 @@ 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))) + if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL))) return (error); mutex_enter(&zp->z_acl_lock); @@ -1951,7 +1951,7 @@ 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))) + if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL))) return (error); error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp, @@ -2340,7 +2340,8 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) * can define any form of access. */ int -zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) +zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, + zuserns_t *mnt_ns) { uint32_t working_mode; int error; @@ -2470,9 +2471,11 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) * NFSv4-style ZFS ACL format and call zfs_zaccess() */ int -zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr) +zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, + zuserns_t *mnt_ns) { - return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr)); + return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr, + mnt_ns)); } /* @@ -2483,7 +2486,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)); + return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL)); } static int @@ -2539,7 +2542,7 @@ zfs_delete_final_check(znode_t *zp, znode_t *dzp, * */ int -zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) +zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns) { uint32_t dzp_working_mode = 0; uint32_t zp_working_mode = 0; @@ -2626,7 +2629,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) int zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, - znode_t *tzp, cred_t *cr) + znode_t *tzp, cred_t *cr, zuserns_t *mnt_ns) { int add_perm; int error; @@ -2646,7 +2649,8 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, * to another. */ if (ZTOV(szp)->v_type == VDIR && ZTOV(sdzp) != ZTOV(tdzp)) { - if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr))) + if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr, + mnt_ns))) return (error); } @@ -2656,19 +2660,19 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, * If that succeeds then check for add_file/add_subdir permissions */ - if ((error = zfs_zaccess_delete(sdzp, szp, cr))) + if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns))) return (error); /* * If we have a tzp, see if we can delete it? */ - if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr))) + if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns))) return (error); /* * Now check for add permissions */ - error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr); + error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns); return (error); } diff --git a/module/os/freebsd/zfs/zfs_dir.c b/module/os/freebsd/zfs/zfs_dir.c index 6321f0b532ae..fe7493fbaefa 100644 --- a/module/os/freebsd/zfs/zfs_dir.c +++ b/module/os/freebsd/zfs/zfs_dir.c @@ -810,7 +810,7 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xvpp, cred_t *cr) *xvpp = NULL; if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL, - &acl_ids)) != 0) + &acl_ids, NULL)) != 0) return (error); if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, 0)) { zfs_acl_ids_free(&acl_ids); @@ -956,7 +956,7 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr) if ((uid = crgetuid(cr)) == downer || uid == fowner || (ZTOV(zp)->v_type == VREG && - zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0)) + zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL) == 0)) return (0); else return (secpolicy_vnode_remove(ZTOV(zp), cr)); diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c index f0579626c5a9..931e5ab35cd9 100644 --- a/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/module/os/freebsd/zfs/zfs_vnops_os.c @@ -836,7 +836,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, /* * Do we have permission to get into attribute directory? */ - error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr); + error = zfs_zaccess(zp, ACE_EXECUTE, 0, B_FALSE, cr, NULL); if (error) { vrele(ZTOV(zp)); } @@ -855,7 +855,8 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, cnp->cn_flags &= ~NOEXECCHECK; } else #endif - if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, + NULL))) { ZFS_EXIT(zfsvfs); return (error); } @@ -1027,6 +1028,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, * flag - large file flag [UNUSED]. * ct - caller context * vsecp - ACL to be set + * mnt_ns - Unused on FreeBSD * * OUT: vpp - vnode of created or trunc'd entry. * @@ -1038,7 +1040,7 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp, */ int zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode, - znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp) + znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, zuserns_t *mnt_ns) { (void) excl, (void) mode, (void) flag; znode_t *zp; @@ -1101,7 +1103,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode, * Create a new file object and update the directory * to reference it. */ - if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) { goto out; } @@ -1117,7 +1119,7 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode, } if ((error = zfs_acl_ids_create(dzp, 0, vap, - cr, vsecp, &acl_ids)) != 0) + cr, vsecp, &acl_ids, NULL)) != 0) goto out; if (S_ISREG(vap->va_mode) || S_ISDIR(vap->va_mode)) @@ -1219,7 +1221,7 @@ zfs_remove_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr) xattr_obj = 0; xzp = NULL; - if ((error = zfs_zaccess_delete(dzp, zp, cr))) { + if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { goto out; } @@ -1372,6 +1374,7 @@ zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags) * ct - caller context * flags - case flags * vsecp - ACL to be set + * mnt_ns - Unused on FreeBSD * * OUT: vpp - vnode of created directory. * @@ -1383,7 +1386,7 @@ zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags) */ int zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp, - cred_t *cr, int flags, vsecattr_t *vsecp) + cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns) { (void) flags, (void) vsecp; znode_t *zp; @@ -1432,7 +1435,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp, } if ((error = zfs_acl_ids_create(dzp, 0, vap, cr, - NULL, &acl_ids)) != 0) { + NULL, &acl_ids, NULL)) != 0) { ZFS_EXIT(zfsvfs); return (error); } @@ -1453,7 +1456,8 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp, } ASSERT3P(zp, ==, NULL); - if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr, + mnt_ns))) { zfs_acl_ids_free(&acl_ids); ZFS_EXIT(zfsvfs); return (error); @@ -1567,7 +1571,7 @@ zfs_rmdir_(vnode_t *dvp, vnode_t *vp, const char *name, cred_t *cr) zilog = zfsvfs->z_log; - if ((error = zfs_zaccess_delete(dzp, zp, cr))) { + if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { goto out; } @@ -1993,7 +1997,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) if (!(zp->z_pflags & ZFS_ACL_TRIVIAL) && (vap->va_uid != crgetuid(cr))) { if ((error = zfs_zaccess(zp, ACE_READ_ATTRIBUTES, 0, - skipaclchk, cr))) { + skipaclchk, cr, NULL))) { ZFS_EXIT(zfsvfs); return (error); } @@ -2159,7 +2163,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) * flags - ATTR_UTIME set if non-default time values provided. * - ATTR_NOACLCHECK (CIFS context only). * cr - credentials of caller. - * ct - caller context + * mnt_ns - Unused on FreeBSD * * RETURN: 0 on success, error code on failure. * @@ -2167,7 +2171,7 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) * vp - ctime updated, mtime updated if size changed. */ int -zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) +zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) { vnode_t *vp = ZTOV(zp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; @@ -2339,7 +2343,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) XVA_ISSET_REQ(xvap, XAT_CREATETIME) || XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) { need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0, - skipaclchk, cr); + skipaclchk, cr, mnt_ns); } if (mask & (AT_UID|AT_GID)) { @@ -2376,7 +2380,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) ((idmask == AT_UID) && take_owner) || ((idmask == AT_GID) && take_group)) { if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0, - skipaclchk, cr) == 0) { + skipaclchk, cr, mnt_ns) == 0) { /* * Remove setuid/setgid for non-privileged users */ @@ -2485,7 +2489,8 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) } if (mask & AT_MODE) { - if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) { + if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, + mnt_ns) == 0) { err = secpolicy_setid_setsticky_clear(vp, vap, &oldva, cr); if (err) { @@ -3268,7 +3273,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp, * Note that if target and source are the same, this can be * done in a single check. */ - if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr))) + if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr, NULL))) goto out; if ((*svpp)->v_type == VDIR) { @@ -3419,7 +3424,7 @@ zfs_do_rename_impl(vnode_t *sdvp, vnode_t **svpp, struct componentname *scnp, int zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname, - cred_t *cr, int flags) + cred_t *cr, int flags, zuserns_t *mnt_ns) { struct componentname scn, tcn; vnode_t *sdvp, *tdvp; @@ -3464,6 +3469,7 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname, * cr - credentials of caller. * ct - caller context * flags - case flags + * mnt_ns - Unused on FreeBSD * * RETURN: 0 on success, error code on failure. * @@ -3472,7 +3478,7 @@ zfs_rename(znode_t *sdzp, const char *sname, znode_t *tdzp, const char *tname, */ int zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, - const char *link, znode_t **zpp, cred_t *cr, int flags) + const char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns) { (void) flags; znode_t *zp; @@ -3503,7 +3509,7 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, } if ((error = zfs_acl_ids_create(dzp, 0, - vap, cr, NULL, &acl_ids)) != 0) { + vap, cr, NULL, &acl_ids, NULL)) != 0) { ZFS_EXIT(zfsvfs); return (error); } @@ -3518,7 +3524,7 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap, return (error); } - if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) { zfs_acl_ids_free(&acl_ids); ZFS_EXIT(zfsvfs); return (error); @@ -3731,7 +3737,7 @@ zfs_link(znode_t *tdzp, znode_t *szp, const char *name, cred_t *cr, return (SET_ERROR(EPERM)); } - if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, NULL))) { ZFS_EXIT(zfsvfs); return (error); } @@ -3832,7 +3838,7 @@ 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))) { + if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL))) { ZFS_EXIT(zfsvfs); return (error); } @@ -4605,7 +4611,7 @@ zfs_freebsd_create(struct vop_create_args *ap) *ap->a_vpp = NULL; rc = zfs_create(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, 0, mode, - &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */); + &zp, cnp->cn_cred, 0 /* flag */, NULL /* vsecattr */, NULL); if (rc == 0) *ap->a_vpp = ZTOV(zp); if (zfsvfs->z_use_namecache && @@ -4655,7 +4661,7 @@ zfs_freebsd_mkdir(struct vop_mkdir_args *ap) *ap->a_vpp = NULL; rc = zfs_mkdir(VTOZ(ap->a_dvp), ap->a_cnp->cn_nameptr, vap, &zp, - ap->a_cnp->cn_cred, 0, NULL); + ap->a_cnp->cn_cred, 0, NULL, NULL); if (rc == 0) *ap->a_vpp = ZTOV(zp); @@ -4906,7 +4912,7 @@ zfs_freebsd_setattr(struct vop_setattr_args *ap) xvap.xva_vattr.va_mask |= AT_XVATTR; XVA_SET_REQ(&xvap, XAT_CREATETIME); } - return (zfs_setattr(VTOZ(vp), (vattr_t *)&xvap, 0, cred)); + return (zfs_setattr(VTOZ(vp), (vattr_t *)&xvap, 0, cred, NULL)); } #ifndef _SYS_SYSPROTO_H_ @@ -4973,7 +4979,7 @@ zfs_freebsd_symlink(struct vop_symlink_args *ap) *ap->a_vpp = NULL; rc = zfs_symlink(VTOZ(ap->a_dvp), cnp->cn_nameptr, vap, - ap->a_target, &zp, cnp->cn_cred, 0 /* flags */); + ap->a_target, &zp, cnp->cn_cred, 0 /* flags */, NULL); if (rc == 0) { *ap->a_vpp = ZTOV(zp); ASSERT_VOP_ELOCKED(ZTOV(zp), __func__); diff --git a/module/os/freebsd/zfs/zfs_znode.c b/module/os/freebsd/zfs/zfs_znode.c index 6345e9e69d30..72bff3bbb105 100644 --- a/module/os/freebsd/zfs/zfs_znode.c +++ b/module/os/freebsd/zfs/zfs_znode.c @@ -298,7 +298,7 @@ zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx) sharezp->z_is_sa = zfsvfs->z_use_sa; VERIFY0(zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr, - kcred, NULL, &acl_ids)); + kcred, NULL, &acl_ids, NULL)); zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids); ASSERT3P(zp, ==, sharezp); POINTER_INVALIDATE(&sharezp->z_zfsvfs); @@ -1773,7 +1773,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) rootzp->z_zfsvfs = zfsvfs; VERIFY0(zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr, - cr, NULL, &acl_ids)); + cr, NULL, &acl_ids, NULL)); 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/policy.c b/module/os/linux/zfs/policy.c index a69618978622..50eb7cfaa61c 100644 --- a/module/os/linux/zfs/policy.c +++ b/module/os/linux/zfs/policy.c @@ -214,8 +214,9 @@ 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) +secpolicy_vnode_setids_setgids(const cred_t *cr, gid_t gid, zuserns_t *mnt_ns) { + gid = zfs_gid_into_mnt(mnt_ns, gid); #if defined(CONFIG_USER_NS) if (!kgid_has_mapping(cr->user_ns, SGID_TO_KGID(gid))) return (EPERM); @@ -284,8 +285,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) +secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner, zuserns_t *mnt_ns) { + owner = zfs_uid_into_mnt(mnt_ns, owner); + if (crgetuid(cr) == owner) return (0); @@ -310,13 +313,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) + const vattr_t *ovap, cred_t *cr, zuserns_t *mnt_ns) { int error; if ((vap->va_mode & S_ISUID) != 0 && (error = secpolicy_vnode_setid_modify(cr, - ovap->va_uid)) != 0) { + ovap->va_uid, mnt_ns)) != 0) { return (error); } @@ -334,7 +337,7 @@ 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) != 0) { + secpolicy_vnode_setids_setgids(cr, ovap->va_gid, mnt_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 a139ee12c4d8..3bbab5d7267b 100644 --- a/module/os/linux/zfs/zfs_acl.c +++ b/module/os/linux/zfs/zfs_acl.c @@ -1801,7 +1801,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, umode_t va_mode, zfs_acl_t *paclp, */ int zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr, - vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids) + vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zuserns_t *mnt_ns) { int error; zfsvfs_t *zfsvfs = ZTOZSB(dzp); @@ -1888,8 +1888,9 @@ 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) != 0) + secpolicy_vnode_setids_setgids(cr, gid, mnt_ns) != 0) { acl_ids->z_mode &= ~S_ISGID; + } } if (acl_ids->z_aclp == NULL) { @@ -1977,7 +1978,7 @@ 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))) + if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL))) return (error); mutex_enter(&zp->z_acl_lock); @@ -2136,7 +2137,7 @@ 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))) + if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL))) return (error); error = zfs_vsec_2_aclp(zfsvfs, ZTOI(zp)->i_mode, vsecp, cr, &fuidp, @@ -2282,7 +2283,7 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode) */ static int zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, - boolean_t anyaccess, cred_t *cr) + boolean_t anyaccess, cred_t *cr, zuserns_t *mnt_ns) { zfsvfs_t *zfsvfs = ZTOZSB(zp); zfs_acl_t *aclp; @@ -2298,7 +2299,13 @@ zfs_zaccess_aces_check(znode_t *zp, uint32_t *working_mode, uid_t gowner; uid_t fowner; - zfs_fuid_map_ids(zp, cr, &fowner, &gowner); + if (mnt_ns) { + fowner = zfs_uid_into_mnt(mnt_ns, + KUID_TO_SUID(ZTOI(zp)->i_uid)); + gowner = zfs_gid_into_mnt(mnt_ns, + KGID_TO_SGID(ZTOI(zp)->i_gid)); + } else + zfs_fuid_map_ids(zp, cr, &fowner, &gowner); mutex_enter(&zp->z_acl_lock); @@ -2409,7 +2416,7 @@ 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) != 0) { + if (zfs_zaccess_aces_check(zp, &have, B_TRUE, cr, NULL) != 0) { uid_t owner; owner = zfs_fuid_map_id(ZTOZSB(zp), @@ -2439,7 +2446,8 @@ zfs_has_access(znode_t *zp, cred_t *cr) * we want to avoid that here. */ static int -zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr) +zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr, + zuserns_t *mnt_ns) { int err, mask; int unmapped = 0; @@ -2453,7 +2461,10 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr) } #if defined(HAVE_IOPS_PERMISSION_USERNS) - err = generic_permission(cr->user_ns, ZTOI(zp), mask); + if (mnt_ns) + err = generic_permission(mnt_ns, ZTOI(zp), mask); + else + err = generic_permission(cr->user_ns, ZTOI(zp), mask); #else err = generic_permission(ZTOI(zp), mask); #endif @@ -2468,7 +2479,7 @@ zfs_zaccess_trivial(znode_t *zp, uint32_t *working_mode, cred_t *cr) static int zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, - boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr) + boolean_t *check_privs, boolean_t skipaclchk, cred_t *cr, zuserns_t *mnt_ns) { zfsvfs_t *zfsvfs = ZTOZSB(zp); int err; @@ -2518,20 +2529,20 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode, } if (zp->z_pflags & ZFS_ACL_TRIVIAL) - return (zfs_zaccess_trivial(zp, working_mode, cr)); + return (zfs_zaccess_trivial(zp, working_mode, cr, mnt_ns)); - return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr)); + return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr, mnt_ns)); } static int zfs_zaccess_append(znode_t *zp, uint32_t *working_mode, boolean_t *check_privs, - cred_t *cr) + cred_t *cr, zuserns_t *mnt_ns) { if (*working_mode != ACE_WRITE_DATA) return (SET_ERROR(EACCES)); return (zfs_zaccess_common(zp, ACE_APPEND_DATA, working_mode, - check_privs, B_FALSE, cr)); + check_privs, B_FALSE, cr, mnt_ns)); } int @@ -2597,7 +2608,7 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) slow: DTRACE_PROBE(zfs__fastpath__execute__access__miss); ZFS_ENTER(ZTOZSB(zdp)); - error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr); + error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, NULL); ZFS_EXIT(ZTOZSB(zdp)); return (error); } @@ -2609,7 +2620,8 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr) * can define any form of access. */ int -zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) +zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr, + zuserns_t *mnt_ns) { uint32_t working_mode; int error; @@ -2648,8 +2660,9 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) } } - owner = zfs_fuid_map_id(ZTOZSB(zp), KUID_TO_SUID(ZTOI(zp)->i_uid), - cr, ZFS_OWNER); + owner = zfs_uid_into_mnt(mnt_ns, KUID_TO_SUID(ZTOI(zp)->i_uid)); + owner = zfs_fuid_map_id(ZTOZSB(zp), owner, cr, ZFS_OWNER); + /* * Map the bits required to the standard inode flags * S_IRUSR|S_IWUSR|S_IXUSR in the needed_bits. Map the bits @@ -2674,7 +2687,7 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) needed_bits |= S_IXUSR; if ((error = zfs_zaccess_common(check_zp, mode, &working_mode, - &check_privs, skipaclchk, cr)) == 0) { + &check_privs, skipaclchk, cr, mnt_ns)) == 0) { if (is_attr) zrele(xzp); return (secpolicy_vnode_access2(cr, ZTOI(zp), owner, @@ -2688,7 +2701,8 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) } if (error && (flags & V_APPEND)) { - error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr); + error = zfs_zaccess_append(zp, &working_mode, &check_privs, cr, + mnt_ns); } if (error && check_privs) { @@ -2755,9 +2769,11 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr) * NFSv4-style ZFS ACL format and call zfs_zaccess() */ int -zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr) +zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr, + zuserns_t *mnt_ns) { - return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr)); + return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr, + mnt_ns)); } /* @@ -2768,7 +2784,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)); + return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL)); } /* See zfs_zaccess_delete() */ @@ -2845,7 +2861,7 @@ static const boolean_t zfs_write_implies_delete_child = B_TRUE; * zfs_write_implies_delete_child */ int -zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) +zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns) { uint32_t wanted_dirperms; uint32_t dzp_working_mode = 0; @@ -2872,7 +2888,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) * (This is part of why we're checking the target first.) */ zp_error = zfs_zaccess_common(zp, ACE_DELETE, &zp_working_mode, - &zpcheck_privs, B_FALSE, cr); + &zpcheck_privs, B_FALSE, cr, mnt_ns); if (zp_error == EACCES) { /* We hit a DENY ACE. */ if (!zpcheck_privs) @@ -2894,7 +2910,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) if (zfs_write_implies_delete_child) wanted_dirperms |= ACE_WRITE_DATA; dzp_error = zfs_zaccess_common(dzp, wanted_dirperms, - &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr); + &dzp_working_mode, &dzpcheck_privs, B_FALSE, cr, mnt_ns); if (dzp_error == EACCES) { /* We hit a DENY ACE. */ if (!dzpcheck_privs) @@ -2976,7 +2992,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr) int zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, - znode_t *tzp, cred_t *cr) + znode_t *tzp, cred_t *cr, zuserns_t *mnt_ns) { int add_perm; int error; @@ -2998,21 +3014,21 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp, * If that succeeds then check for add_file/add_subdir permissions */ - if ((error = zfs_zaccess_delete(sdzp, szp, cr))) + if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns))) return (error); /* * If we have a tzp, see if we can delete it? */ if (tzp) { - if ((error = zfs_zaccess_delete(tdzp, tzp, cr))) + if ((error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns))) return (error); } /* * Now check for add permissions */ - error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr); + error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns); return (error); } diff --git a/module/os/linux/zfs/zfs_dir.c b/module/os/linux/zfs/zfs_dir.c index 6738d237b923..611a2471dd94 100644 --- a/module/os/linux/zfs/zfs_dir.c +++ b/module/os/linux/zfs/zfs_dir.c @@ -1066,11 +1066,12 @@ 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))) + if ((error = zfs_zaccess(zp, ACE_WRITE_NAMED_ATTRS, 0, B_FALSE, cr, + NULL))) return (error); if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL, - &acl_ids)) != 0) + &acl_ids, NULL)) != 0) return (error); if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, zp->z_projid)) { zfs_acl_ids_free(&acl_ids); @@ -1218,7 +1219,7 @@ 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) == 0) + zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL) == 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 0b3f7f2501ee..1998dae4d486 100644 --- a/module/os/linux/zfs/zfs_vnops_os.c +++ b/module/os/linux/zfs/zfs_vnops_os.c @@ -474,7 +474,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))) { + B_TRUE, cr, NULL))) { zrele(*zpp); *zpp = NULL; } @@ -492,7 +492,7 @@ 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))) { + if ((error = zfs_zaccess(zdp, ACE_EXECUTE, 0, B_FALSE, cr, NULL))) { ZFS_EXIT(zfsvfs); return (error); } @@ -524,6 +524,7 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, * cr - credentials of caller. * flag - file flag. * vsecp - ACL to be set + * mnt_ns - user namespace of the mount * * OUT: zpp - znode of created or trunc'd entry. * @@ -535,7 +536,8 @@ zfs_lookup(znode_t *zdp, char *nm, znode_t **zpp, int flags, cred_t *cr, */ int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, - int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp) + int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp, + zuserns_t *mnt_ns) { znode_t *zp; zfsvfs_t *zfsvfs = ZTOZSB(dzp); @@ -622,7 +624,8 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, * Create a new file object and update the directory * to reference it. */ - if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, + mnt_ns))) { if (have_acl) zfs_acl_ids_free(&acl_ids); goto out; @@ -641,7 +644,7 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, } if (!have_acl && (error = zfs_acl_ids_create(dzp, 0, vap, - cr, vsecp, &acl_ids)) != 0) + cr, vsecp, &acl_ids, mnt_ns)) != 0) goto out; have_acl = B_TRUE; @@ -736,7 +739,8 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, /* * Verify requested access to file. */ - if (mode && (error = zfs_zaccess_rwx(zp, mode, aflags, cr))) { + if (mode && (error = zfs_zaccess_rwx(zp, mode, aflags, cr, + mnt_ns))) { goto out; } @@ -780,7 +784,8 @@ zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, int zfs_tmpfile(struct inode *dip, vattr_t *vap, int excl, - int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp) + int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp, + zuserns_t *mnt_ns) { (void) excl, (void) mode, (void) flag; znode_t *zp = NULL, *dzp = ITOZ(dip); @@ -827,14 +832,14 @@ zfs_tmpfile(struct inode *dip, vattr_t *vap, int excl, * Create a new file object and update the directory * to reference it. */ - if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) { if (have_acl) zfs_acl_ids_free(&acl_ids); goto out; } if (!have_acl && (error = zfs_acl_ids_create(dzp, 0, vap, - cr, vsecp, &acl_ids)) != 0) + cr, vsecp, &acl_ids, mnt_ns)) != 0) goto out; have_acl = B_TRUE; @@ -965,7 +970,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) return (error); } - if ((error = zfs_zaccess_delete(dzp, zp, cr))) { + if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { goto out; } @@ -1145,6 +1150,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) * cr - credentials of caller. * flags - case flags. * vsecp - ACL to be set + * mnt_ns - user namespace of the mount * * OUT: zpp - znode of created directory. * @@ -1157,7 +1163,7 @@ zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags) */ int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp, - cred_t *cr, int flags, vsecattr_t *vsecp) + cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns) { znode_t *zp; zfsvfs_t *zfsvfs = ZTOZSB(dzp); @@ -1214,7 +1220,7 @@ zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp, } if ((error = zfs_acl_ids_create(dzp, 0, vap, cr, - vsecp, &acl_ids)) != 0) { + vsecp, &acl_ids, mnt_ns)) != 0) { ZFS_EXIT(zfsvfs); return (error); } @@ -1235,7 +1241,8 @@ zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap, znode_t **zpp, return (error); } - if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(dzp, ACE_ADD_SUBDIRECTORY, 0, B_FALSE, cr, + mnt_ns))) { zfs_acl_ids_free(&acl_ids); zfs_dirent_unlock(dl); ZFS_EXIT(zfsvfs); @@ -1377,7 +1384,7 @@ zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, cred_t *cr, return (error); } - if ((error = zfs_zaccess_delete(dzp, zp, cr))) { + if ((error = zfs_zaccess_delete(dzp, zp, cr, NULL))) { goto out; } @@ -1808,6 +1815,7 @@ zfs_setattr_dir(znode_t *dzp) * flags - ATTR_UTIME set if non-default time values provided. * - ATTR_NOACLCHECK (CIFS context only). * cr - credentials of caller. + * mnt_ns - user namespace of the mount * * RETURN: 0 if success * error code if failure @@ -1816,7 +1824,7 @@ zfs_setattr_dir(znode_t *dzp) * ip - ctime updated, mtime updated if size changed. */ int -zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) +zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zuserns_t *mnt_ns) { struct inode *ip; zfsvfs_t *zfsvfs = ZTOZSB(zp); @@ -1965,7 +1973,8 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) */ if (mask & ATTR_SIZE) { - err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr); + err = zfs_zaccess(zp, ACE_WRITE_DATA, 0, skipaclchk, cr, + mnt_ns); if (err) goto out3; @@ -1990,13 +1999,15 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) XVA_ISSET_REQ(xvap, XAT_CREATETIME) || XVA_ISSET_REQ(xvap, XAT_SYSTEM)))) { need_policy = zfs_zaccess(zp, ACE_WRITE_ATTRIBUTES, 0, - skipaclchk, cr); + skipaclchk, cr, mnt_ns); } if (mask & (ATTR_UID|ATTR_GID)) { int idmask = (mask & (ATTR_UID|ATTR_GID)); int take_owner; int take_group; + uid_t uid; + gid_t gid; /* * NOTE: even if a new mode is being set, @@ -2010,9 +2021,13 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) * Take ownership or chgrp to group we are a member of */ - take_owner = (mask & ATTR_UID) && (vap->va_uid == crgetuid(cr)); + 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); + take_owner = (mask & ATTR_UID) && (uid == crgetuid(cr)); take_group = (mask & ATTR_GID) && - zfs_groupmember(zfsvfs, vap->va_gid, cr); + zfs_groupmember(zfsvfs, gid, cr); /* * If both ATTR_UID and ATTR_GID are set then take_owner and @@ -2028,7 +2043,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) ((idmask == ATTR_UID) && take_owner) || ((idmask == ATTR_GID) && take_group)) { if (zfs_zaccess(zp, ACE_WRITE_OWNER, 0, - skipaclchk, cr) == 0) { + skipaclchk, cr, mnt_ns) == 0) { /* * Remove setuid/setgid for non-privileged users */ @@ -2141,12 +2156,12 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr) mutex_exit(&zp->z_lock); if (mask & ATTR_MODE) { - if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr) == 0) { + if (zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, + mnt_ns) == 0) { err = secpolicy_setid_setsticky_clear(ip, vap, - &oldva, cr); + &oldva, cr, mnt_ns); if (err) goto out3; - trim_mask |= ATTR_MODE; } else { need_policy = TRUE; @@ -2637,6 +2652,7 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) * tnm - New entry name. * cr - credentials of caller. * flags - case flags + * mnt_ns - user namespace of the mount * * RETURN: 0 on success, error code on failure. * @@ -2645,7 +2661,7 @@ zfs_rename_lock(znode_t *szp, znode_t *tdzp, znode_t *sdzp, zfs_zlock_t **zlpp) */ int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, - cred_t *cr, int flags) + cred_t *cr, int flags, zuserns_t *mnt_ns) { znode_t *szp, *tzp; zfsvfs_t *zfsvfs = ZTOZSB(sdzp); @@ -2835,7 +2851,7 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, * done in a single check. */ - if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr))) + if ((error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr, mnt_ns))) goto out; if (S_ISDIR(ZTOI(szp)->i_mode)) { @@ -3002,6 +3018,7 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, * link - Name for new symlink entry. * cr - credentials of caller. * flags - case flags + * mnt_ns - user namespace of the mount * * OUT: zpp - Znode for new symbolic link. * @@ -3012,7 +3029,7 @@ zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, */ int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link, - znode_t **zpp, cred_t *cr, int flags) + znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns) { znode_t *zp; zfs_dirlock_t *dl; @@ -3050,7 +3067,7 @@ zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link, } if ((error = zfs_acl_ids_create(dzp, 0, - vap, cr, NULL, &acl_ids)) != 0) { + vap, cr, NULL, &acl_ids, mnt_ns)) != 0) { ZFS_EXIT(zfsvfs); return (error); } @@ -3067,7 +3084,7 @@ zfs_symlink(znode_t *dzp, char *name, vattr_t *vap, char *link, return (error); } - if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr))) { + if ((error = zfs_zaccess(dzp, ACE_ADD_FILE, 0, B_FALSE, cr, mnt_ns))) { zfs_acl_ids_free(&acl_ids); zfs_dirent_unlock(dl); ZFS_EXIT(zfsvfs); @@ -3316,7 +3333,7 @@ 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))) { + if ((error = zfs_zaccess(tdzp, ACE_ADD_FILE, 0, B_FALSE, cr, NULL))) { ZFS_EXIT(zfsvfs); return (error); } @@ -3941,7 +3958,7 @@ 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))) { + if ((error = zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL))) { ZFS_EXIT(zfsvfs); return (error); } diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c index 73c21b6c00a8..7b56d377cb20 100644 --- a/module/os/linux/zfs/zfs_znode.c +++ b/module/os/linux/zfs/zfs_znode.c @@ -1960,7 +1960,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)); + cr, NULL, &acl_ids, NULL)); 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 ec8f2938598f..2430ec4889a5 100644 --- a/module/os/linux/zfs/zpl_ctldir.c +++ b/module/os/linux/zfs/zpl_ctldir.c @@ -369,7 +369,11 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode) crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); - zpl_vap_init(vap, dip, mode | S_IFDIR, cr); +#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); +#endif error = -zfsctl_snapdir_mkdir(dip, dname(dentry), vap, &ip, cr, 0); if (error == 0) { diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c index b0d9f37a3ec0..a02e82f2165d 100644 --- a/module/os/linux/zfs/zpl_file.c +++ b/module/os/linux/zfs/zpl_file.c @@ -1081,7 +1081,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); + err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); spl_fstrans_unmark(cookie); crfree(cr); @@ -1129,7 +1129,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); + err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); spl_fstrans_unmark(cookie); crfree(cr); @@ -1217,7 +1217,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); + err = -zfs_setattr(ITOZ(ip), (vattr_t *)&xva, 0, cr, NULL); 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 7578753ed8ce..8d073ff8cbd3 100644 --- a/module/os/linux/zfs/zpl_inode.c +++ b/module/os/linux/zfs/zpl_inode.c @@ -33,7 +33,6 @@ #include #include - static struct dentry * zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { @@ -112,18 +111,22 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) } void -zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr) +zpl_vap_init(vattr_t *vap, struct inode *dir, umode_t mode, cred_t *cr, + zuserns_t *mnt_ns) { vap->va_mask = ATTR_MODE; vap->va_mode = mode; - vap->va_uid = crgetuid(cr); + + vap->va_uid = zfs_uid_from_mnt((struct user_namespace *)mnt_ns, + 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 = crgetgid(cr); + vap->va_gid = zfs_gid_from_mnt((struct user_namespace *)mnt_ns, + crgetgid(cr)); } } @@ -140,14 +143,17 @@ zpl_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool flag) vattr_t *vap; int error; fstrans_cookie_t cookie; +#ifndef HAVE_IOPS_CREATE_USERNS + zuserns_t *user_ns = NULL; +#endif crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); - zpl_vap_init(vap, dir, mode, cr); + zpl_vap_init(vap, dir, mode, cr, user_ns); cookie = spl_fstrans_mark(); error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0, - mode, &zp, cr, 0, NULL); + mode, &zp, cr, 0, NULL, user_ns); if (error == 0) { error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); if (error == 0) @@ -184,6 +190,9 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, vattr_t *vap; int error; fstrans_cookie_t cookie; +#ifndef HAVE_IOPS_MKNOD_USERNS + zuserns_t *user_ns = NULL; +#endif /* * We currently expect Linux to supply rdev=0 for all sockets @@ -194,12 +203,12 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); - zpl_vap_init(vap, dir, mode, cr); + zpl_vap_init(vap, dir, mode, cr, user_ns); vap->va_rdev = rdev; cookie = spl_fstrans_mark(); error = -zfs_create(ITOZ(dir), dname(dentry), vap, 0, - mode, &zp, cr, 0, NULL); + mode, &zp, cr, 0, NULL, user_ns); if (error == 0) { error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); if (error == 0) @@ -236,6 +245,9 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) vattr_t *vap; int error; fstrans_cookie_t cookie; +#ifndef HAVE_TMPFILE_USERNS + zuserns_t *userns = NULL; +#endif crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); @@ -245,10 +257,10 @@ zpl_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) */ if (!IS_POSIXACL(dir)) mode &= ~current_umask(); - zpl_vap_init(vap, dir, mode, cr); + zpl_vap_init(vap, dir, mode, cr, userns); cookie = spl_fstrans_mark(); - error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL); + error = -zfs_tmpfile(dir, vap, 0, mode, &ip, cr, 0, NULL, userns); if (error == 0) { /* d_tmpfile will do drop_nlink, so we should set it first */ set_nlink(ip, 1); @@ -311,13 +323,17 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) znode_t *zp; int error; fstrans_cookie_t cookie; +#ifndef HAVE_IOPS_MKDIR_USERNS + zuserns_t *user_ns = NULL; +#endif crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); - zpl_vap_init(vap, dir, mode | S_IFDIR, cr); + zpl_vap_init(vap, dir, mode | S_IFDIR, cr, user_ns); cookie = spl_fstrans_mark(); - error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL); + error = -zfs_mkdir(ITOZ(dir), dname(dentry), vap, &zp, cr, 0, NULL, + user_ns); if (error == 0) { error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); if (error == 0) @@ -439,7 +455,11 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) int error; fstrans_cookie_t cookie; +#ifdef HAVE_SETATTR_PREPARE_USERNS + error = zpl_setattr_prepare(user_ns, dentry, ia); +#else error = zpl_setattr_prepare(kcred->user_ns, dentry, ia); +#endif if (error) return (error); @@ -458,7 +478,11 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia) ip->i_atime = zpl_inode_timestamp_truncate(ia->ia_atime, ip); cookie = spl_fstrans_mark(); - error = -zfs_setattr(ITOZ(ip), vap, 0, cr); +#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); +#endif if (!error && (ia->ia_valid & ATTR_MODE)) error = zpl_chmod_acl(ip); @@ -483,6 +507,9 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, cred_t *cr = CRED(); int error; fstrans_cookie_t cookie; +#ifndef HAVE_IOPS_RENAME_USERNS + zuserns_t *user_ns = NULL; +#endif /* We don't have renameat2(2) support */ if (flags) @@ -491,7 +518,7 @@ zpl_rename2(struct inode *sdip, struct dentry *sdentry, crhold(cr); cookie = spl_fstrans_mark(); error = -zfs_rename(ITOZ(sdip), dname(sdentry), ITOZ(tdip), - dname(tdentry), cr, 0); + dname(tdentry), cr, 0, user_ns); spl_fstrans_unmark(cookie); crfree(cr); ASSERT3S(error, <=, 0); @@ -521,14 +548,17 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name) znode_t *zp; int error; fstrans_cookie_t cookie; +#ifndef HAVE_IOPS_SYMLINK_USERNS + zuserns_t *user_ns = NULL; +#endif crhold(cr); vap = kmem_zalloc(sizeof (vattr_t), KM_SLEEP); - zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr); + zpl_vap_init(vap, dir, S_IFLNK | S_IRWXUGO, cr, user_ns); cookie = spl_fstrans_mark(); error = -zfs_symlink(ITOZ(dir), dname(dentry), vap, - (char *)name, &zp, cr, 0); + (char *)name, &zp, cr, 0, user_ns); if (error == 0) { error = zpl_xattr_security_init(ZTOI(zp), dir, &dentry->d_name); if (error) { diff --git a/module/os/linux/zfs/zpl_super.c b/module/os/linux/zfs/zpl_super.c index cf879a2897b3..5e932fc20fca 100644 --- a/module/os/linux/zfs/zpl_super.c +++ b/module/os/linux/zfs/zpl_super.c @@ -372,7 +372,11 @@ const struct super_operations zpl_super_operations = { struct file_system_type zpl_fs_type = { .owner = THIS_MODULE, .name = ZFS_DRIVER, +#if defined(HAVE_IDMAP_MNT_API) + .fs_flags = FS_USERNS_MOUNT | FS_ALLOW_IDMAP, +#else .fs_flags = FS_USERNS_MOUNT, +#endif .mount = zpl_mount, .kill_sb = zpl_kill_sb, }; diff --git a/module/os/linux/zfs/zpl_xattr.c b/module/os/linux/zfs/zpl_xattr.c index e7e299dcf1cd..cae324793fff 100644 --- a/module/os/linux/zfs/zpl_xattr.c +++ b/module/os/linux/zfs/zpl_xattr.c @@ -497,7 +497,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); + cr, 0, NULL, NULL); if (error) goto out; } diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c index 379e1d1a7b57..45c2fa3720cf 100644 --- a/module/zfs/zfs_replay.c +++ b/module/zfs/zfs_replay.c @@ -387,7 +387,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) } error = zfs_create(dzp, name, &xva.xva_vattr, - 0, 0, &zp, kcred, vflg, &vsec); + 0, 0, &zp, kcred, vflg, &vsec, NULL); break; case TX_MKDIR_ACL: aclstart = (caddr_t)(lracl + 1); @@ -417,7 +417,7 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) lr->lr_uid, lr->lr_gid); } error = zfs_mkdir(dzp, name, &xva.xva_vattr, - &zp, kcred, vflg, &vsec); + &zp, kcred, vflg, &vsec, NULL); break; default: error = SET_ERROR(ENOTSUP); @@ -528,7 +528,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) name = (char *)start; error = zfs_create(dzp, name, &xva.xva_vattr, - 0, 0, &zp, kcred, vflg, NULL); + 0, 0, &zp, kcred, vflg, NULL, NULL); break; case TX_MKDIR_ATTR: lrattr = (lr_attr_t *)(caddr_t)(lr + 1); @@ -546,7 +546,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) name = (char *)(lr + 1); error = zfs_mkdir(dzp, name, &xva.xva_vattr, - &zp, kcred, vflg, NULL); + &zp, kcred, vflg, NULL, NULL); break; case TX_MKXATTR: error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred); @@ -555,7 +555,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) name = (char *)(lr + 1); link = name + strlen(name) + 1; error = zfs_symlink(dzp, name, &xva.xva_vattr, - link, &zp, kcred, vflg); + link, &zp, kcred, vflg, NULL); break; default: error = SET_ERROR(ENOTSUP); @@ -667,7 +667,7 @@ zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) if (lr->lr_common.lrc_txtype & TX_CI) vflg |= FIGNORECASE; - error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg); + error = zfs_rename(sdzp, sname, tdzp, tname, kcred, vflg, NULL); zrele(tdzp); zrele(sdzp); @@ -860,7 +860,7 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); - error = zfs_setattr(zp, vap, 0, kcred); + error = zfs_setattr(zp, vap, 0, kcred, NULL); zfs_fuid_info_free(zfsvfs->z_fuid_replay); zfsvfs->z_fuid_replay = NULL; diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index b02e8283c77d..7d66b6889919 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -166,9 +166,9 @@ zfs_access(znode_t *zp, int mode, int flag, cred_t *cr) ZFS_VERIFY_ZP(zp); if (flag & V_ACE_MASK) - error = zfs_zaccess(zp, mode, flag, B_FALSE, cr); + error = zfs_zaccess(zp, mode, flag, B_FALSE, cr, NULL); else - error = zfs_zaccess_rwx(zp, mode, flag, cr); + error = zfs_zaccess_rwx(zp, mode, flag, cr, NULL); ZFS_EXIT(zfsvfs); return (error);