]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Linux 6.8 compat: handle mnt_idmap user_namespace change
authorRob Norris <robn@despairlabs.com>
Tue, 23 Jan 2024 10:14:06 +0000 (21:14 +1100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 29 Jan 2024 19:36:07 +0000 (11:36 -0800)
struct mnt_idmap no longer has a struct user_namespace within it. Work
around this by creating a temporary with the copy of the map we need
taken from the idmap.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Co-authored-by: Youzhong Yang <yyang@mathworks.com>
Signed-off-by: Rob Norris <robn@despairlabs.com>
Sponsored-by: https://despairlabs.com/sponsor/
Closes #15805

config/kernel-idmap_mnt_api.m4
config/kernel.m4
include/os/linux/spl/sys/cred.h
include/os/linux/spl/sys/types.h

index 47ddc5702fb7edf3d9730da2df70fa3479656a9e..d1bdd053203eb9700e23a30dd3614ee0800f8151 100644 (file)
@@ -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 <linux/uidgid.h>
+       ], [
+               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])
+       ])
+])
index 30bdd6579523ff27646614a5a43ec395f0200dc3..e3f8645774c5323da564697562f2011ab81180fd 100644 (file)
@@ -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
index 7fd5f644863fa1143b66c51a1c61c8470ca675cd..c19c3c0719ff47b66b0226027919835fc7ad1e8e 100644 (file)
@@ -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));
index d89a91c36f92b3f591f00a0699b34907c6895b29..20ba457f7efe525b222bc749d65d6d8664c631a8 100644 (file)
@@ -57,12 +57,23 @@ typedef int                 minor_t;
 struct user_namespace;
 #ifdef HAVE_IOPS_CREATE_IDMAP
 #include <linux/refcount.h>
+#ifdef HAVE_IDMAP_NO_USERNS
+#include <linux/user_namespace.h>
+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)