Skip to content

Commit 200c63a

Browse files
youzhongyangandrewc12
authored andcommitted
Support idmapped mount
Adds support for idmapped mounts. Supported as of Linux 5.12 this functionality allows user and group IDs to be remapped without changing their state on disk. This can be useful for portable home directories and a variety of container related use cases. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Youzhong Yang <[email protected]> Closes openzfs#12923 Closes openzfs#13671
1 parent f4dc7f9 commit 200c63a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1636
-166
lines changed

config/kernel-idmap_mnt_api.m4

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
dnl #
2+
dnl # 5.12 API
3+
dnl #
4+
dnl # Check if APIs for idmapped mount are available
5+
dnl #
6+
AC_DEFUN([ZFS_AC_KERNEL_SRC_IDMAP_MNT_API], [
7+
ZFS_LINUX_TEST_SRC([idmap_mnt_api], [
8+
#include <linux/fs.h>
9+
],[
10+
int fs_flags = 0;
11+
fs_flags |= FS_ALLOW_IDMAP;
12+
])
13+
])
14+
15+
AC_DEFUN([ZFS_AC_KERNEL_IDMAP_MNT_API], [
16+
AC_MSG_CHECKING([whether APIs for idmapped mount are present])
17+
ZFS_LINUX_TEST_RESULT([idmap_mnt_api], [
18+
AC_MSG_RESULT([yes])
19+
AC_DEFINE(HAVE_IDMAP_MNT_API, 1,
20+
[APIs for idmapped mount are present])
21+
],[
22+
AC_MSG_RESULT([no])
23+
])
24+
])
25+

config/kernel.m4

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
147147
ZFS_AC_KERNEL_SRC_ZERO_PAGE
148148
ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC
149149
ZFS_AC_KERNEL_SRC_USER_NS_COMMON_INUM
150+
ZFS_AC_KERNEL_SRC_IDMAP_MNT_API
150151
151152
AC_MSG_CHECKING([for available kernel interfaces])
152153
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
@@ -267,6 +268,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
267268
ZFS_AC_KERNEL_ZERO_PAGE
268269
ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC
269270
ZFS_AC_KERNEL_USER_NS_COMMON_INUM
271+
ZFS_AC_KERNEL_IDMAP_MNT_API
270272
])
271273

272274
dnl #

include/os/freebsd/spl/sys/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,7 @@ typedef u_longlong_t len_t;
105105

106106
typedef longlong_t diskaddr_t;
107107

108+
typedef void zuserns_t;
109+
108110
#include <sys/debug.h>
109111
#endif /* !_OPENSOLARIS_SYS_TYPES_H_ */

include/os/freebsd/zfs/sys/zfs_vnops_os.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,22 @@ int dmu_read_pages(objset_t *os, uint64_t object, vm_page_t *ma, int count,
3535
int *rbehind, int *rahead, int last_size);
3636
extern int zfs_remove(znode_t *dzp, const char *name, cred_t *cr, int flags);
3737
extern int zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap,
38-
znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp);
38+
znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns);
3939
extern int zfs_rmdir(znode_t *dzp, const char *name, znode_t *cwd,
4040
cred_t *cr, int flags);
41-
extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr);
41+
extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr,
42+
zuserns_t *mnt_ns);
4243
extern int zfs_rename(znode_t *sdzp, const char *snm, znode_t *tdzp,
43-
const char *tnm, cred_t *cr, int flags);
44+
const char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns);
4445
extern int zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
45-
const char *link, znode_t **zpp, cred_t *cr, int flags);
46+
const char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns);
4647
extern int zfs_link(znode_t *tdzp, znode_t *sp,
4748
const char *name, cred_t *cr, int flags);
4849
extern int zfs_space(znode_t *zp, int cmd, struct flock *bfp, int flag,
4950
offset_t offset, cred_t *cr);
5051
extern int zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl,
51-
int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp);
52+
int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp,
53+
zuserns_t *mnt_ns);
5254
extern int zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag,
5355
cred_t *cr);
5456
extern int zfs_write_simple(znode_t *zp, const void *data, size_t len,

include/os/linux/spl/sys/cred.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,34 @@ typedef struct cred cred_t;
4545
#define SGID_TO_KGID(x) (KGIDT_INIT(x))
4646
#define KGIDP_TO_SGIDP(x) (&(x)->val)
4747

48+
static inline uid_t zfs_uid_into_mnt(struct user_namespace *mnt_ns, uid_t uid)
49+
{
50+
if (mnt_ns)
51+
return (__kuid_val(make_kuid(mnt_ns, uid)));
52+
return (uid);
53+
}
54+
55+
static inline gid_t zfs_gid_into_mnt(struct user_namespace *mnt_ns, gid_t gid)
56+
{
57+
if (mnt_ns)
58+
return (__kgid_val(make_kgid(mnt_ns, gid)));
59+
return (gid);
60+
}
61+
62+
static inline uid_t zfs_uid_from_mnt(struct user_namespace *mnt_ns, uid_t uid)
63+
{
64+
if (mnt_ns)
65+
return (from_kuid(mnt_ns, KUIDT_INIT(uid)));
66+
return (uid);
67+
}
68+
69+
static inline gid_t zfs_gid_from_mnt(struct user_namespace *mnt_ns, gid_t gid)
70+
{
71+
if (mnt_ns)
72+
return (from_kgid(mnt_ns, KGIDT_INIT(gid)));
73+
return (gid);
74+
}
75+
4876
extern void crhold(cred_t *cr);
4977
extern void crfree(cred_t *cr);
5078
extern uid_t crgetuid(const cred_t *cr);

include/os/linux/spl/sys/types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,7 @@ typedef ulong_t pgcnt_t;
5454
typedef int major_t;
5555
typedef int minor_t;
5656

57+
struct user_namespace;
58+
typedef struct user_namespace zuserns_t;
59+
5760
#endif /* _SPL_TYPES_H */

include/os/linux/zfs/sys/policy.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ int secpolicy_vnode_create_gid(const cred_t *);
4747
int secpolicy_vnode_remove(const cred_t *);
4848
int secpolicy_vnode_setdac(const cred_t *, uid_t);
4949
int secpolicy_vnode_setid_retain(struct znode *, const cred_t *, boolean_t);
50-
int secpolicy_vnode_setids_setgids(const cred_t *, gid_t);
50+
int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zuserns_t *);
5151
int secpolicy_zinject(const cred_t *);
5252
int secpolicy_zfs(const cred_t *);
5353
int secpolicy_zfs_proc(const cred_t *, proc_t *);
5454
void secpolicy_setid_clear(vattr_t *, cred_t *);
5555
int secpolicy_setid_setsticky_clear(struct inode *, vattr_t *,
56-
const vattr_t *, cred_t *);
56+
const vattr_t *, cred_t *, zuserns_t *);
5757
int secpolicy_xvattr(xvattr_t *, uid_t, cred_t *, mode_t);
5858
int secpolicy_vnode_setattr(cred_t *, struct inode *, struct vattr *,
5959
const struct vattr *, int, int (void *, int, cred_t *), void *);

include/os/linux/zfs/sys/zfs_vnops_os.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,25 @@ extern int zfs_write_simple(znode_t *zp, const void *data, size_t len,
4545
extern int zfs_lookup(znode_t *dzp, char *nm, znode_t **zpp, int flags,
4646
cred_t *cr, int *direntflags, pathname_t *realpnp);
4747
extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl,
48-
int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp);
48+
int mode, znode_t **zpp, cred_t *cr, int flag, vsecattr_t *vsecp,
49+
zuserns_t *mnt_ns);
4950
extern int zfs_tmpfile(struct inode *dip, vattr_t *vapzfs, int excl,
50-
int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp);
51+
int mode, struct inode **ipp, cred_t *cr, int flag, vsecattr_t *vsecp,
52+
zuserns_t *mnt_ns);
5153
extern int zfs_remove(znode_t *dzp, char *name, cred_t *cr, int flags);
5254
extern int zfs_mkdir(znode_t *dzp, char *dirname, vattr_t *vap,
53-
znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp);
55+
znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zuserns_t *mnt_ns);
5456
extern int zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd,
5557
cred_t *cr, int flags);
5658
extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr);
5759
extern int zfs_getattr_fast(struct user_namespace *, struct inode *ip,
5860
struct kstat *sp);
59-
extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr);
61+
extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr,
62+
zuserns_t *mnt_ns);
6063
extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp,
61-
char *tnm, cred_t *cr, int flags);
64+
char *tnm, cred_t *cr, int flags, zuserns_t *mnt_ns);
6265
extern int zfs_symlink(znode_t *dzp, char *name, vattr_t *vap,
63-
char *link, znode_t **zpp, cred_t *cr, int flags);
66+
char *link, znode_t **zpp, cred_t *cr, int flags, zuserns_t *mnt_ns);
6467
extern int zfs_readlink(struct inode *ip, zfs_uio_t *uio, cred_t *cr);
6568
extern int zfs_link(znode_t *tdzp, znode_t *szp,
6669
char *name, cred_t *cr, int flags);

include/os/linux/zfs/sys/zpl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
/* zpl_inode.c */
4141
extern void zpl_vap_init(vattr_t *vap, struct inode *dir,
42-
umode_t mode, cred_t *cr);
42+
umode_t mode, cred_t *cr, zuserns_t *mnt_ns);
4343

4444
extern const struct inode_operations zpl_inode_operations;
4545
extern const struct inode_operations zpl_dir_inode_operations;

include/sys/zfs_acl.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ struct zfsvfs;
206206

207207
#ifdef _KERNEL
208208
int zfs_acl_ids_create(struct znode *, int, vattr_t *,
209-
cred_t *, vsecattr_t *, zfs_acl_ids_t *);
209+
cred_t *, vsecattr_t *, zfs_acl_ids_t *, zuserns_t *);
210210
void zfs_acl_ids_free(zfs_acl_ids_t *);
211211
boolean_t zfs_acl_ids_overquota(struct zfsvfs *, zfs_acl_ids_t *, uint64_t);
212212
int zfs_getacl(struct znode *, vsecattr_t *, boolean_t, cred_t *);
@@ -215,15 +215,16 @@ void zfs_acl_rele(void *);
215215
void zfs_oldace_byteswap(ace_t *, int);
216216
void zfs_ace_byteswap(void *, size_t, boolean_t);
217217
extern boolean_t zfs_has_access(struct znode *zp, cred_t *cr);
218-
extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *);
218+
extern int zfs_zaccess(struct znode *, int, int, boolean_t, cred_t *,
219+
zuserns_t *);
219220
int zfs_fastaccesschk_execute(struct znode *, cred_t *);
220-
extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *);
221+
extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *, zuserns_t *);
221222
extern int zfs_zaccess_unix(struct znode *, mode_t, cred_t *);
222223
extern int zfs_acl_access(struct znode *, int, cred_t *);
223224
int zfs_acl_chmod_setattr(struct znode *, zfs_acl_t **, uint64_t);
224-
int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *);
225+
int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *, zuserns_t *);
225226
int zfs_zaccess_rename(struct znode *, struct znode *,
226-
struct znode *, struct znode *, cred_t *cr);
227+
struct znode *, struct znode *, cred_t *cr, zuserns_t *mnt_ns);
227228
void zfs_acl_free(zfs_acl_t *);
228229
int zfs_vsec_2_aclp(struct zfsvfs *, umode_t, vsecattr_t *, cred_t *,
229230
struct zfs_fuid_info **, zfs_acl_t **);

module/os/freebsd/zfs/zfs_acl.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,7 +1619,7 @@ zfs_acl_inherit(zfsvfs_t *zfsvfs, vtype_t vtype, zfs_acl_t *paclp,
16191619
*/
16201620
int
16211621
zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
1622-
vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids)
1622+
vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids, zuserns_t *mnt_ns)
16231623
{
16241624
int error;
16251625
zfsvfs_t *zfsvfs = dzp->z_zfsvfs;
@@ -1789,7 +1789,7 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
17891789
if (mask == 0)
17901790
return (SET_ERROR(ENOSYS));
17911791

1792-
if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr)))
1792+
if ((error = zfs_zaccess(zp, ACE_READ_ACL, 0, skipaclchk, cr, NULL)))
17931793
return (error);
17941794

17951795
mutex_enter(&zp->z_acl_lock);
@@ -1952,7 +1952,7 @@ zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
19521952
if (zp->z_pflags & ZFS_IMMUTABLE)
19531953
return (SET_ERROR(EPERM));
19541954

1955-
if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr)))
1955+
if ((error = zfs_zaccess(zp, ACE_WRITE_ACL, 0, skipaclchk, cr, NULL)))
19561956
return (error);
19571957

19581958
error = zfs_vsec_2_aclp(zfsvfs, ZTOV(zp)->v_type, vsecp, cr, &fuidp,
@@ -2341,7 +2341,8 @@ zfs_fastaccesschk_execute(znode_t *zdp, cred_t *cr)
23412341
* can define any form of access.
23422342
*/
23432343
int
2344-
zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
2344+
zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr,
2345+
zuserns_t *mnt_ns)
23452346
{
23462347
uint32_t working_mode;
23472348
int error;
@@ -2471,9 +2472,11 @@ zfs_zaccess(znode_t *zp, int mode, int flags, boolean_t skipaclchk, cred_t *cr)
24712472
* NFSv4-style ZFS ACL format and call zfs_zaccess()
24722473
*/
24732474
int
2474-
zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr)
2475+
zfs_zaccess_rwx(znode_t *zp, mode_t mode, int flags, cred_t *cr,
2476+
zuserns_t *mnt_ns)
24752477
{
2476-
return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr));
2478+
return (zfs_zaccess(zp, zfs_unix_to_v4(mode >> 6), flags, B_FALSE, cr,
2479+
mnt_ns));
24772480
}
24782481

24792482
/*
@@ -2484,7 +2487,7 @@ zfs_zaccess_unix(znode_t *zp, mode_t mode, cred_t *cr)
24842487
{
24852488
int v4_mode = zfs_unix_to_v4(mode >> 6);
24862489

2487-
return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr));
2490+
return (zfs_zaccess(zp, v4_mode, 0, B_FALSE, cr, NULL));
24882491
}
24892492

24902493
static int
@@ -2540,7 +2543,7 @@ zfs_delete_final_check(znode_t *zp, znode_t *dzp,
25402543
*
25412544
*/
25422545
int
2543-
zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
2546+
zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr, zuserns_t *mnt_ns)
25442547
{
25452548
uint32_t dzp_working_mode = 0;
25462549
uint32_t zp_working_mode = 0;
@@ -2627,7 +2630,7 @@ zfs_zaccess_delete(znode_t *dzp, znode_t *zp, cred_t *cr)
26272630

26282631
int
26292632
zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
2630-
znode_t *tzp, cred_t *cr)
2633+
znode_t *tzp, cred_t *cr, zuserns_t *mnt_ns)
26312634
{
26322635
int add_perm;
26332636
int error;
@@ -2647,7 +2650,8 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
26472650
* to another.
26482651
*/
26492652
if (ZTOV(szp)->v_type == VDIR && ZTOV(sdzp) != ZTOV(tdzp)) {
2650-
if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr)))
2653+
if ((error = zfs_zaccess(szp, ACE_WRITE_DATA, 0, B_FALSE, cr,
2654+
mnt_ns)))
26512655
return (error);
26522656
}
26532657

@@ -2657,19 +2661,19 @@ zfs_zaccess_rename(znode_t *sdzp, znode_t *szp, znode_t *tdzp,
26572661
* If that succeeds then check for add_file/add_subdir permissions
26582662
*/
26592663

2660-
if ((error = zfs_zaccess_delete(sdzp, szp, cr)))
2664+
if ((error = zfs_zaccess_delete(sdzp, szp, cr, mnt_ns)))
26612665
return (error);
26622666

26632667
/*
26642668
* If we have a tzp, see if we can delete it?
26652669
*/
2666-
if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr)))
2670+
if (tzp && (error = zfs_zaccess_delete(tdzp, tzp, cr, mnt_ns)))
26672671
return (error);
26682672

26692673
/*
26702674
* Now check for add permissions
26712675
*/
2672-
error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr);
2676+
error = zfs_zaccess(tdzp, add_perm, 0, B_FALSE, cr, mnt_ns);
26732677

26742678
return (error);
26752679
}

module/os/freebsd/zfs/zfs_dir.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ zfs_make_xattrdir(znode_t *zp, vattr_t *vap, znode_t **xvpp, cred_t *cr)
809809
*xvpp = NULL;
810810

811811
if ((error = zfs_acl_ids_create(zp, IS_XATTR, vap, cr, NULL,
812-
&acl_ids)) != 0)
812+
&acl_ids, NULL)) != 0)
813813
return (error);
814814
if (zfs_acl_ids_overquota(zfsvfs, &acl_ids, 0)) {
815815
zfs_acl_ids_free(&acl_ids);
@@ -955,7 +955,7 @@ zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
955955

956956
if ((uid = crgetuid(cr)) == downer || uid == fowner ||
957957
(ZTOV(zp)->v_type == VREG &&
958-
zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0))
958+
zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr, NULL) == 0))
959959
return (0);
960960
else
961961
return (secpolicy_vnode_remove(ZTOV(zp), cr));

0 commit comments

Comments
 (0)