From 938cfeb0f27303721081223816d4f251ffeb1767 Mon Sep 17 00:00:00 2001 From: Nikolay Borisov Date: Wed, 3 Aug 2016 20:19:04 +0300 Subject: [PATCH] Linux 4.8 compat: new s_user_ns member of struct super_block Kernel 4.8 paved the way to enabling mounting a file system inside a non-init user namespace. To facilitate this a s_user_ns member was added holding the userns in which the filesystem's instance was mounted. This enables doing the uid/gid translation relative to this particular username space and not the default init_user_ns. Signed-off-by: Nikolay Borisov Signed-off-by: Chunwei Chen Signed-off-by: Brian Behlendorf Closes #4928 --- config/kernel-super-userns.m4 | 21 +++++++++++++++++++++ config/kernel.m4 | 1 + include/linux/vfs_compat.h | 17 +++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 config/kernel-super-userns.m4 diff --git a/config/kernel-super-userns.m4 b/config/kernel-super-userns.m4 new file mode 100644 index 000000000..de94ad967 --- /dev/null +++ b/config/kernel-super-userns.m4 @@ -0,0 +1,21 @@ +dnl # +dnl # 4.8 API change +dnl # struct user_namespace was added to struct super_block as +dnl # super->s_user_ns member +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SUPER_USER_NS], [ + AC_MSG_CHECKING([whether super_block->s_user_ns exists]) + ZFS_LINUX_TRY_COMPILE([ + #include + #include + ],[ + struct super_block super; + super.s_user_ns = (struct user_namespace *)NULL; + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SUPER_USER_NS, 1, + [super_block->s_user_ns exists]) + ],[ + AC_MSG_RESULT(no) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index 7edafee0f..2fa04706b 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -8,6 +8,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [ ZFS_AC_KERNEL_CONFIG ZFS_AC_KERNEL_DECLARE_EVENT_CLASS ZFS_AC_KERNEL_CURRENT_BIO_TAIL + ZFS_AC_KERNEL_SUPER_USER_NS ZFS_AC_KERNEL_SUBMIT_BIO ZFS_AC_KERNEL_BDEV_BLOCK_DEVICE_OPERATIONS ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID diff --git a/include/linux/vfs_compat.h b/include/linux/vfs_compat.h index 97220c2fe..fa12ba95a 100644 --- a/include/linux/vfs_compat.h +++ b/include/linux/vfs_compat.h @@ -356,7 +356,11 @@ static inline struct inode *file_inode(const struct file *f) #ifdef HAVE_KUID_HELPERS static inline uid_t zfs_uid_read_impl(struct inode *ip) { +#ifdef HAVE_SUPER_USER_NS + return (from_kuid(ip->i_sb->s_user_ns, ip->i_uid)); +#else return (from_kuid(kcred->user_ns, ip->i_uid)); +#endif } static inline uid_t zfs_uid_read(struct inode *ip) @@ -366,7 +370,11 @@ static inline uid_t zfs_uid_read(struct inode *ip) static inline gid_t zfs_gid_read_impl(struct inode *ip) { +#ifdef HAVE_SUPER_USER_NS + return (from_kgid(ip->i_sb->s_user_ns, ip->i_gid)); +#else return (from_kgid(kcred->user_ns, ip->i_gid)); +#endif } static inline gid_t zfs_gid_read(struct inode *ip) @@ -376,13 +384,22 @@ static inline gid_t zfs_gid_read(struct inode *ip) static inline void zfs_uid_write(struct inode *ip, uid_t uid) { +#ifdef HAVE_SUPER_USER_NS + ip->i_uid = make_kuid(ip->i_sb->s_user_ns, uid); +#else ip->i_uid = make_kuid(kcred->user_ns, uid); +#endif } static inline void zfs_gid_write(struct inode *ip, gid_t gid) { +#ifdef HAVE_SUPER_USER_NS + ip->i_gid = make_kgid(ip->i_sb->s_user_ns, gid); +#else ip->i_gid = make_kgid(kcred->user_ns, gid); +#endif } + #else static inline uid_t zfs_uid_read(struct inode *ip) {