Skip to content

Commit

Permalink
Support idmapped mount
Browse files Browse the repository at this point in the history
Signed-off-by: Youzhong Yang <yyang@mathworks.com>
  • Loading branch information
Youzhong Yang committed Sep 15, 2022
1 parent 6f8602a commit 2f99a88
Show file tree
Hide file tree
Showing 26 changed files with 313 additions and 162 deletions.
25 changes: 25 additions & 0 deletions config/kernel-idmap_mnt_api.m4
Original file line number Diff line number Diff line change
@@ -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 <linux/fs.h>
],[
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])
])
])

2 changes: 2 additions & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand Down Expand Up @@ -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 #
Expand Down
2 changes: 2 additions & 0 deletions include/os/freebsd/spl/sys/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,7 @@ typedef u_longlong_t len_t;

typedef longlong_t diskaddr_t;

typedef void zuserns_t;

#include <sys/debug.h>
#endif /* !_OPENSOLARIS_SYS_TYPES_H_ */
12 changes: 7 additions & 5 deletions include/os/freebsd/zfs/sys/zfs_vnops_os.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
28 changes: 28 additions & 0 deletions include/os/linux/spl/sys/cred.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions include/os/linux/spl/sys/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
4 changes: 2 additions & 2 deletions include/os/linux/zfs/sys/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
15 changes: 9 additions & 6 deletions include/os/linux/zfs/sys/zfs_vnops_os.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion include/os/linux/zfs/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 6 additions & 5 deletions include/sys/zfs_acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand All @@ -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 **);
Expand Down
30 changes: 17 additions & 13 deletions module/os/freebsd/zfs/zfs_acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}

/*
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand All @@ -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);
}
4 changes: 2 additions & 2 deletions module/os/freebsd/zfs/zfs_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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));
Expand Down
Loading

0 comments on commit 2f99a88

Please sign in to comment.