diff --git a/config/kernel-idmap_mnt_api.m4 b/config/kernel-idmap_mnt_api.m4 index 47ddc5702fb7..d1bdd053203e 100644 --- a/config/kernel-idmap_mnt_api.m4 +++ b/config/kernel-idmap_mnt_api.m4 @@ -23,3 +23,28 @@ AC_DEFUN([ZFS_AC_KERNEL_IDMAP_MNT_API], [ ]) ]) +dnl # +dnl # 6.8 decouples mnt_idmap from user_namespace. This is all internal +dnl # to mnt_idmap so we can't detect it directly, but we detect a related +dnl # change as use that as a signal. +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SRC_IDMAP_NO_USERNS], [ + ZFS_LINUX_TEST_SRC([idmap_no_userns], [ + #include + ], [ + struct uid_gid_map *map = NULL; + map_id_down(map, 0); + ]) +]) + + +AC_DEFUN([ZFS_AC_KERNEL_IDMAP_NO_USERNS], [ + AC_MSG_CHECKING([whether idmapped mounts have a user namespace]) + ZFS_LINUX_TEST_RESULT([idmap_no_userns], [ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_IDMAP_NO_USERNS, 1, + [mnt_idmap does not have user_namespace]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index 30bdd6579523..e3f8645774c5 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -158,6 +158,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ ZFS_AC_KERNEL_SRC___COPY_FROM_USER_INATOMIC ZFS_AC_KERNEL_SRC_USER_NS_COMMON_INUM ZFS_AC_KERNEL_SRC_IDMAP_MNT_API + ZFS_AC_KERNEL_SRC_IDMAP_NO_USERNS ZFS_AC_KERNEL_SRC_IATTR_VFSID ZFS_AC_KERNEL_SRC_FILEMAP ZFS_AC_KERNEL_SRC_WRITEPAGE_T @@ -305,6 +306,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ ZFS_AC_KERNEL___COPY_FROM_USER_INATOMIC ZFS_AC_KERNEL_USER_NS_COMMON_INUM ZFS_AC_KERNEL_IDMAP_MNT_API + ZFS_AC_KERNEL_IDMAP_NO_USERNS ZFS_AC_KERNEL_IATTR_VFSID ZFS_AC_KERNEL_FILEMAP ZFS_AC_KERNEL_WRITEPAGE_T diff --git a/include/os/linux/spl/sys/cred.h b/include/os/linux/spl/sys/cred.h index 7fd5f644863f..c19c3c0719ff 100644 --- a/include/os/linux/spl/sys/cred.h +++ b/include/os/linux/spl/sys/cred.h @@ -73,13 +73,25 @@ static inline struct user_namespace *zfs_i_user_ns(struct inode *inode) static inline boolean_t zfs_no_idmapping(struct user_namespace *mnt_userns, struct user_namespace *fs_userns) { - return (zfs_is_init_userns(mnt_userns) || mnt_userns == fs_userns); + return (zfs_is_init_userns(mnt_userns) || + mnt_userns == fs_userns); } static inline uid_t zfs_uid_to_vfsuid(zidmap_t *mnt_userns, struct user_namespace *fs_userns, uid_t uid) { - struct user_namespace *owner = idmap_owner(mnt_userns); + struct user_namespace *owner; +#ifdef HAVE_IOPS_CREATE_IDMAP + if (mnt_userns == zfs_init_idmap) + return (uid); +#endif +#ifdef HAVE_IDMAP_NO_USERNS + struct user_namespace ns; + ns.uid_map = mnt_userns->uid_map; + owner = &ns; +#else + owner = idmap_owner(mnt_userns); +#endif if (zfs_no_idmapping(owner, fs_userns)) return (uid); if (!zfs_is_init_userns(fs_userns)) @@ -92,7 +104,18 @@ static inline uid_t zfs_uid_to_vfsuid(zidmap_t *mnt_userns, static inline gid_t zfs_gid_to_vfsgid(zidmap_t *mnt_userns, struct user_namespace *fs_userns, gid_t gid) { - struct user_namespace *owner = idmap_owner(mnt_userns); + struct user_namespace *owner; +#ifdef HAVE_IOPS_CREATE_IDMAP + if (mnt_userns == zfs_init_idmap) + return (gid); +#endif +#ifdef HAVE_IDMAP_NO_USERNS + struct user_namespace ns; + ns.gid_map = mnt_userns->gid_map; + owner = &ns; +#else + owner = idmap_owner(mnt_userns); +#endif if (zfs_no_idmapping(owner, fs_userns)) return (gid); if (!zfs_is_init_userns(fs_userns)) @@ -105,7 +128,18 @@ static inline gid_t zfs_gid_to_vfsgid(zidmap_t *mnt_userns, static inline uid_t zfs_vfsuid_to_uid(zidmap_t *mnt_userns, struct user_namespace *fs_userns, uid_t uid) { - struct user_namespace *owner = idmap_owner(mnt_userns); + struct user_namespace *owner; +#ifdef HAVE_IOPS_CREATE_IDMAP + if (mnt_userns == zfs_init_idmap) + return (uid); +#endif +#ifdef HAVE_IDMAP_NO_USERNS + struct user_namespace ns; + ns.uid_map = mnt_userns->uid_map; + owner = &ns; +#else + owner = idmap_owner(mnt_userns); +#endif if (zfs_no_idmapping(owner, fs_userns)) return (uid); uid = from_kuid(owner, KUIDT_INIT(uid)); @@ -119,7 +153,18 @@ static inline uid_t zfs_vfsuid_to_uid(zidmap_t *mnt_userns, static inline gid_t zfs_vfsgid_to_gid(zidmap_t *mnt_userns, struct user_namespace *fs_userns, gid_t gid) { - struct user_namespace *owner = idmap_owner(mnt_userns); + struct user_namespace *owner; +#ifdef HAVE_IOPS_CREATE_IDMAP + if (mnt_userns == zfs_init_idmap) + return (gid); +#endif +#ifdef HAVE_IDMAP_NO_USERNS + struct user_namespace ns; + ns.gid_map = mnt_userns->gid_map; + owner = &ns; +#else + owner = idmap_owner(mnt_userns); +#endif if (zfs_no_idmapping(owner, fs_userns)) return (gid); gid = from_kgid(owner, KGIDT_INIT(gid)); diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h index d89a91c36f92..20ba457f7efe 100644 --- a/include/os/linux/spl/sys/types.h +++ b/include/os/linux/spl/sys/types.h @@ -57,12 +57,23 @@ typedef int minor_t; struct user_namespace; #ifdef HAVE_IOPS_CREATE_IDMAP #include +#ifdef HAVE_IDMAP_NO_USERNS +#include +struct mnt_idmap { + struct uid_gid_map uid_map; + struct uid_gid_map gid_map; + refcount_t count; +}; +typedef struct mnt_idmap zidmap_t; +#define idmap_owner(p) (NULL) +#else 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) +#endif #else typedef struct user_namespace zidmap_t; #define idmap_owner(p) ((struct user_namespace *)p)