diff options
author | youzhongyang <[email protected]> | 2023-04-10 17:15:36 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2023-04-10 14:15:36 -0700 |
commit | d4dc53dad2f6c3a2d107f1ba0e8d66228c845e00 (patch) | |
tree | c6a1946e83a1c95c622e97af6f0b4939aa7719f9 /include | |
parent | d0cbd9feaf5b82130f2e679256c71e0c7413aae9 (diff) |
Linux 6.3 compat: idmapped mount API changes
Linux kernel 6.3 changed a bunch of APIs to use the dedicated idmap
type for mounts (struct mnt_idmap), we need to detect these changes
and make zfs work with the new APIs.
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Youzhong Yang <[email protected]>
Closes #14682
Diffstat (limited to 'include')
-rw-r--r-- | include/os/freebsd/spl/sys/types.h | 2 | ||||
-rw-r--r-- | include/os/freebsd/zfs/sys/zfs_vnops_os.h | 10 | ||||
-rw-r--r-- | include/os/linux/kernel/linux/vfs_compat.h | 21 | ||||
-rw-r--r-- | include/os/linux/kernel/linux/xattr_compat.h | 17 | ||||
-rw-r--r-- | include/os/linux/spl/sys/cred.h | 30 | ||||
-rw-r--r-- | include/os/linux/spl/sys/types.h | 15 | ||||
-rw-r--r-- | include/os/linux/zfs/sys/policy.h | 6 | ||||
-rw-r--r-- | include/os/linux/zfs/sys/zfs_vnops_os.h | 15 | ||||
-rw-r--r-- | include/os/linux/zfs/sys/zpl.h | 13 | ||||
-rw-r--r-- | include/sys/zfs_acl.h | 10 |
10 files changed, 97 insertions, 42 deletions
diff --git a/include/os/freebsd/spl/sys/types.h b/include/os/freebsd/spl/sys/types.h index 558843dca..ebc93f4f4 100644 --- a/include/os/freebsd/spl/sys/types.h +++ b/include/os/freebsd/spl/sys/types.h @@ -105,7 +105,7 @@ typedef u_longlong_t len_t; typedef longlong_t diskaddr_t; -typedef void zuserns_t; +typedef void zidmap_t; #include <sys/debug.h> #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 839ee629a..eddcab575 100644 --- a/include/os/freebsd/zfs/sys/zfs_vnops_os.h +++ b/include/os/freebsd/zfs/sys/zfs_vnops_os.h @@ -35,23 +35,23 @@ 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, zuserns_t *mnt_ns); + znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_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, - zuserns_t *mnt_ns); + zidmap_t *mnt_ns); extern int zfs_rename(znode_t *sdzp, const char *snm, znode_t *tdzp, const char *tnm, cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap, - zuserns_t *mnt_ns); + zidmap_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, zuserns_t *mnt_ns); + const char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_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, - zuserns_t *mnt_ns); + zidmap_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/kernel/linux/vfs_compat.h b/include/os/linux/kernel/linux/vfs_compat.h index fd0b9e8e1..e156ed41c 100644 --- a/include/os/linux/kernel/linux/vfs_compat.h +++ b/include/os/linux/kernel/linux/vfs_compat.h @@ -341,7 +341,8 @@ static inline void zfs_gid_write(struct inode *ip, gid_t gid) * 4.9 API change */ #if !(defined(HAVE_SETATTR_PREPARE_NO_USERNS) || \ - defined(HAVE_SETATTR_PREPARE_USERNS)) + defined(HAVE_SETATTR_PREPARE_USERNS) || \ + defined(HAVE_SETATTR_PREPARE_IDMAP)) static inline int setattr_prepare(struct dentry *dentry, struct iattr *ia) { @@ -396,6 +397,15 @@ func(struct user_namespace *user_ns, const struct path *path, \ return (func##_impl(user_ns, path, stat, request_mask, \ query_flags)); \ } +#elif defined(HAVE_IDMAP_IOPS_GETATTR) +#define ZPL_GETATTR_WRAPPER(func) \ +static int \ +func(struct mnt_idmap *user_ns, const struct path *path, \ + struct kstat *stat, u32 request_mask, unsigned int query_flags) \ +{ \ + return (func##_impl(user_ns, path, stat, request_mask, \ + query_flags)); \ +} #else #error #endif @@ -447,8 +457,15 @@ zpl_is_32bit_api(void) * 5.12 API change * To support id-mapped mounts, generic_fillattr() was modified to * accept a new struct user_namespace* as its first arg. + * + * 6.3 API change + * generic_fillattr() first arg is changed to struct mnt_idmap * + * */ -#ifdef HAVE_GENERIC_FILLATTR_USERNS +#ifdef HAVE_GENERIC_FILLATTR_IDMAP +#define zpl_generic_fillattr(idmap, ip, sp) \ + generic_fillattr(idmap, ip, sp) +#elif defined(HAVE_GENERIC_FILLATTR_USERNS) #define zpl_generic_fillattr(user_ns, ip, sp) \ generic_fillattr(user_ns, ip, sp) #else diff --git a/include/os/linux/kernel/linux/xattr_compat.h b/include/os/linux/kernel/linux/xattr_compat.h index ff80fbb06..bcc7289ad 100644 --- a/include/os/linux/kernel/linux/xattr_compat.h +++ b/include/os/linux/kernel/linux/xattr_compat.h @@ -134,12 +134,27 @@ fn(const struct xattr_handler *handler, struct dentry *dentry, \ #endif /* + * 6.3 API change, + * The xattr_handler->set() callback was changed to take the + * struct mnt_idmap* as the first arg, to support idmapped + * mounts. + */ +#if defined(HAVE_XATTR_SET_IDMAP) +#define ZPL_XATTR_SET_WRAPPER(fn) \ +static int \ +fn(const struct xattr_handler *handler, struct mnt_idmap *user_ns, \ + struct dentry *dentry, struct inode *inode, const char *name, \ + const void *buffer, size_t size, int flags) \ +{ \ + return (__ ## fn(user_ns, inode, name, buffer, size, flags)); \ +} +/* * 5.12 API change, * The xattr_handler->set() callback was changed to take the * struct user_namespace* as the first arg, to support idmapped * mounts. */ -#if defined(HAVE_XATTR_SET_USERNS) +#elif defined(HAVE_XATTR_SET_USERNS) #define ZPL_XATTR_SET_WRAPPER(fn) \ static int \ fn(const struct xattr_handler *handler, struct user_namespace *user_ns, \ diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h index 75ad400d3..7fd5f6448 100644 --- a/include/os/linux/spl/sys/cred.h +++ b/include/os/linux/spl/sys/cred.h @@ -48,6 +48,8 @@ extern struct task_struct init_task; #define SGID_TO_KGID(x) (KGIDT_INIT(x)) #define KGIDP_TO_SGIDP(x) (&(x)->val) +extern zidmap_t *zfs_get_init_idmap(void); + /* Check if the user ns is the initial one */ static inline boolean_t zfs_is_init_userns(struct user_namespace *user_ns) @@ -74,36 +76,39 @@ static inline boolean_t zfs_no_idmapping(struct user_namespace *mnt_userns, return (zfs_is_init_userns(mnt_userns) || mnt_userns == fs_userns); } -static inline uid_t zfs_uid_to_vfsuid(struct user_namespace *mnt_userns, +static inline uid_t zfs_uid_to_vfsuid(zidmap_t *mnt_userns, struct user_namespace *fs_userns, uid_t uid) { - if (zfs_no_idmapping(mnt_userns, fs_userns)) + struct user_namespace *owner = idmap_owner(mnt_userns); + if (zfs_no_idmapping(owner, fs_userns)) return (uid); if (!zfs_is_init_userns(fs_userns)) uid = from_kuid(fs_userns, KUIDT_INIT(uid)); if (uid == (uid_t)-1) return (uid); - return (__kuid_val(make_kuid(mnt_userns, uid))); + return (__kuid_val(make_kuid(owner, uid))); } -static inline gid_t zfs_gid_to_vfsgid(struct user_namespace *mnt_userns, +static inline gid_t zfs_gid_to_vfsgid(zidmap_t *mnt_userns, struct user_namespace *fs_userns, gid_t gid) { - if (zfs_no_idmapping(mnt_userns, fs_userns)) + struct user_namespace *owner = idmap_owner(mnt_userns); + if (zfs_no_idmapping(owner, fs_userns)) return (gid); if (!zfs_is_init_userns(fs_userns)) gid = from_kgid(fs_userns, KGIDT_INIT(gid)); if (gid == (gid_t)-1) return (gid); - return (__kgid_val(make_kgid(mnt_userns, gid))); + return (__kgid_val(make_kgid(owner, gid))); } -static inline uid_t zfs_vfsuid_to_uid(struct user_namespace *mnt_userns, +static inline uid_t zfs_vfsuid_to_uid(zidmap_t *mnt_userns, struct user_namespace *fs_userns, uid_t uid) { - if (zfs_no_idmapping(mnt_userns, fs_userns)) + struct user_namespace *owner = idmap_owner(mnt_userns); + if (zfs_no_idmapping(owner, fs_userns)) return (uid); - uid = from_kuid(mnt_userns, KUIDT_INIT(uid)); + uid = from_kuid(owner, KUIDT_INIT(uid)); if (uid == (uid_t)-1) return (uid); if (zfs_is_init_userns(fs_userns)) @@ -111,12 +116,13 @@ static inline uid_t zfs_vfsuid_to_uid(struct user_namespace *mnt_userns, return (__kuid_val(make_kuid(fs_userns, uid))); } -static inline gid_t zfs_vfsgid_to_gid(struct user_namespace *mnt_userns, +static inline gid_t zfs_vfsgid_to_gid(zidmap_t *mnt_userns, struct user_namespace *fs_userns, gid_t gid) { - if (zfs_no_idmapping(mnt_userns, fs_userns)) + struct user_namespace *owner = idmap_owner(mnt_userns); + if (zfs_no_idmapping(owner, fs_userns)) return (gid); - gid = from_kgid(mnt_userns, KGIDT_INIT(gid)); + gid = from_kgid(owner, KGIDT_INIT(gid)); if (gid == (gid_t)-1) return (gid); if (zfs_is_init_userns(fs_userns)) diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h index cae1bbddf..a7666187e 100644 --- a/include/os/linux/spl/sys/types.h +++ b/include/os/linux/spl/sys/types.h @@ -55,6 +55,19 @@ typedef int major_t; typedef int minor_t; struct user_namespace; -typedef struct user_namespace zuserns_t; +#ifdef HAVE_IOPS_CREATE_IDMAP +#include <linux/refcount.h> +struct mnt_idmap { + struct user_namespace *owner; + refcount_t count; +}; +typedef struct mnt_idmap zidmap_t; +#define idmap_owner(p) (((struct mnt_idmap *)p)->owner) +#else +typedef struct user_namespace zidmap_t; +#define idmap_owner(p) ((struct user_namespace *)p) +#endif + +extern zidmap_t *zfs_init_idmap; #endif /* _SPL_TYPES_H */ diff --git a/include/os/linux/zfs/sys/policy.h b/include/os/linux/zfs/sys/policy.h index b182da95b..0c265db78 100644 --- a/include/os/linux/zfs/sys/policy.h +++ b/include/os/linux/zfs/sys/policy.h @@ -47,14 +47,14 @@ 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, zuserns_t *, - zuserns_t *); +int secpolicy_vnode_setids_setgids(const cred_t *, gid_t, zidmap_t *, + struct user_namespace *); 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 *, zuserns_t *, zuserns_t *); + const vattr_t *, cred_t *, zidmap_t *, struct user_namespace *); 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 1caec0ef4..7a1db7dee 100644 --- a/include/os/linux/zfs/sys/zfs_vnops_os.h +++ b/include/os/linux/zfs/sys/zfs_vnops_os.h @@ -46,25 +46,24 @@ 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, - zuserns_t *mnt_ns); + zidmap_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, - zuserns_t *mnt_ns); + zidmap_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, zuserns_t *mnt_ns); + znode_t **zpp, cred_t *cr, int flags, vsecattr_t *vsecp, zidmap_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_getattr_fast(zidmap_t *, struct inode *ip, struct kstat *sp); extern int zfs_setattr(znode_t *zp, vattr_t *vap, int flag, cred_t *cr, - zuserns_t *mnt_ns); + zidmap_t *mnt_ns); extern int zfs_rename(znode_t *sdzp, char *snm, znode_t *tdzp, char *tnm, cred_t *cr, int flags, uint64_t rflags, vattr_t *wo_vap, - zuserns_t *mnt_ns); + zidmap_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, zuserns_t *mnt_ns); + char *link, znode_t **zpp, cred_t *cr, int flags, zidmap_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 ac1f01a86..2b302e9da 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, zuserns_t *mnt_ns); + umode_t mode, cred_t *cr, zidmap_t *mnt_ns); extern const struct inode_operations zpl_inode_operations; #ifdef HAVE_RENAME2_OPERATIONS_WRAPPER @@ -68,7 +68,10 @@ extern int zpl_xattr_security_init(struct inode *ip, struct inode *dip, const struct qstr *qstr); #if defined(CONFIG_FS_POSIX_ACL) #if defined(HAVE_SET_ACL) -#if defined(HAVE_SET_ACL_USERNS) +#if defined(HAVE_SET_ACL_IDMAP_DENTRY) +extern int zpl_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, + struct posix_acl *acl, int type); +#elif defined(HAVE_SET_ACL_USERNS) extern int zpl_set_acl(struct user_namespace *userns, struct inode *ip, struct posix_acl *acl, int type); #elif defined(HAVE_SET_ACL_USERNS_DENTRY_ARG2) @@ -189,13 +192,15 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx) #if defined(HAVE_INODE_OWNER_OR_CAPABLE) #define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ip) -#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_IDMAPPED) +#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_USERNS) #define zpl_inode_owner_or_capable(ns, ip) inode_owner_or_capable(ns, ip) +#elif defined(HAVE_INODE_OWNER_OR_CAPABLE_IDMAP) +#define zpl_inode_owner_or_capable(idmap, ip) inode_owner_or_capable(idmap, ip) #else #error "Unsupported kernel" #endif -#ifdef HAVE_SETATTR_PREPARE_USERNS +#if defined(HAVE_SETATTR_PREPARE_USERNS) || defined(HAVE_SETATTR_PREPARE_IDMAP) #define zpl_setattr_prepare(ns, dentry, ia) setattr_prepare(ns, dentry, ia) #else /* diff --git a/include/sys/zfs_acl.h b/include/sys/zfs_acl.h index e5c570c47..e19288528 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 *, zuserns_t *); + cred_t *, vsecattr_t *, zfs_acl_ids_t *, zidmap_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 *); @@ -216,15 +216,15 @@ 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 *, - zuserns_t *); + zidmap_t *); int zfs_fastaccesschk_execute(struct znode *, cred_t *); -extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *, zuserns_t *); +extern int zfs_zaccess_rwx(struct znode *, mode_t, int, cred_t *, zidmap_t *); extern int zfs_zaccess_unix(void *, int, 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 *, zuserns_t *); +int zfs_zaccess_delete(struct znode *, struct znode *, cred_t *, zidmap_t *); int zfs_zaccess_rename(struct znode *, struct znode *, - struct znode *, struct znode *, cred_t *cr, zuserns_t *mnt_ns); + struct znode *, struct znode *, cred_t *cr, zidmap_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 **); |