mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
Support idmapped mount in user namespace
Linux 5.17 commit torvalds/linux@5dfbfe71e enables "the idmapping infrastructure to support idmapped mounts of filesystems mounted with an idmapping". Update the OpenZFS accordingly to improve the idmapped mount support. This pull request contains the following changes: - xattr setter functions are fixed to take mnt_ns argument. Without this, cp -p would fail for an idmapped mount in a user namespace. - idmap_util is enhanced/fixed for its use in a user ns context. - One test case added to test idmapped mount in a user ns. Reviewed-by: Christian Brauner <christian@brauner.io> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Youzhong Yang <yyang@mathworks.com> Closes #14097
This commit is contained in:
@@ -26,11 +26,14 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/cred.h>
|
||||
#include <linux/sched.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vfs.h>
|
||||
|
||||
typedef struct cred cred_t;
|
||||
|
||||
extern struct task_struct init_task;
|
||||
|
||||
#define kcred ((cred_t *)(init_task.cred))
|
||||
#define CRED() ((cred_t *)current_cred())
|
||||
|
||||
@@ -45,32 +48,80 @@ typedef struct cred cred_t;
|
||||
#define SGID_TO_KGID(x) (KGIDT_INIT(x))
|
||||
#define KGIDP_TO_SGIDP(x) (&(x)->val)
|
||||
|
||||
static inline uid_t zfs_uid_into_mnt(struct user_namespace *mnt_ns, uid_t uid)
|
||||
/* Check if the user ns is the initial one */
|
||||
static inline boolean_t
|
||||
zfs_is_init_userns(struct user_namespace *user_ns)
|
||||
{
|
||||
if (mnt_ns)
|
||||
return (__kuid_val(make_kuid(mnt_ns, uid)));
|
||||
return (uid);
|
||||
#if defined(CONFIG_USER_NS)
|
||||
return (user_ns == kcred->user_ns);
|
||||
#else
|
||||
return (B_FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline gid_t zfs_gid_into_mnt(struct user_namespace *mnt_ns, gid_t gid)
|
||||
static inline struct user_namespace *zfs_i_user_ns(struct inode *inode)
|
||||
{
|
||||
if (mnt_ns)
|
||||
return (__kgid_val(make_kgid(mnt_ns, gid)));
|
||||
return (gid);
|
||||
#ifdef HAVE_SUPER_USER_NS
|
||||
return (inode->i_sb->s_user_ns);
|
||||
#else
|
||||
return (kcred->user_ns);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uid_t zfs_uid_from_mnt(struct user_namespace *mnt_ns, uid_t uid)
|
||||
static inline boolean_t zfs_no_idmapping(struct user_namespace *mnt_userns,
|
||||
struct user_namespace *fs_userns)
|
||||
{
|
||||
if (mnt_ns)
|
||||
return (from_kuid(mnt_ns, KUIDT_INIT(uid)));
|
||||
return (uid);
|
||||
return (zfs_is_init_userns(mnt_userns) || mnt_userns == fs_userns);
|
||||
}
|
||||
|
||||
static inline gid_t zfs_gid_from_mnt(struct user_namespace *mnt_ns, gid_t gid)
|
||||
static inline uid_t zfs_uid_to_vfsuid(struct user_namespace *mnt_userns,
|
||||
struct user_namespace *fs_userns, uid_t uid)
|
||||
{
|
||||
if (mnt_ns)
|
||||
return (from_kgid(mnt_ns, KGIDT_INIT(gid)));
|
||||
return (gid);
|
||||
if (zfs_no_idmapping(mnt_userns, 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)));
|
||||
}
|
||||
|
||||
static inline gid_t zfs_gid_to_vfsgid(struct user_namespace *mnt_userns,
|
||||
struct user_namespace *fs_userns, gid_t gid)
|
||||
{
|
||||
if (zfs_no_idmapping(mnt_userns, 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)));
|
||||
}
|
||||
|
||||
static inline uid_t zfs_vfsuid_to_uid(struct user_namespace *mnt_userns,
|
||||
struct user_namespace *fs_userns, uid_t uid)
|
||||
{
|
||||
if (zfs_no_idmapping(mnt_userns, fs_userns))
|
||||
return (uid);
|
||||
uid = from_kuid(mnt_userns, KUIDT_INIT(uid));
|
||||
if (uid == (uid_t)-1)
|
||||
return (uid);
|
||||
if (zfs_is_init_userns(fs_userns))
|
||||
return (uid);
|
||||
return (__kuid_val(make_kuid(fs_userns, uid)));
|
||||
}
|
||||
|
||||
static inline gid_t zfs_vfsgid_to_gid(struct user_namespace *mnt_userns,
|
||||
struct user_namespace *fs_userns, gid_t gid)
|
||||
{
|
||||
if (zfs_no_idmapping(mnt_userns, fs_userns))
|
||||
return (gid);
|
||||
gid = from_kgid(mnt_userns, KGIDT_INIT(gid));
|
||||
if (gid == (gid_t)-1)
|
||||
return (gid);
|
||||
if (zfs_is_init_userns(fs_userns))
|
||||
return (gid);
|
||||
return (__kgid_val(make_kgid(fs_userns, gid)));
|
||||
}
|
||||
|
||||
extern void crhold(cred_t *cr);
|
||||
@@ -81,5 +132,4 @@ extern gid_t crgetgid(const cred_t *cr);
|
||||
extern int crgetngroups(const cred_t *cr);
|
||||
extern gid_t *crgetgroups(const cred_t *cr);
|
||||
extern int groupmember(gid_t gid, const cred_t *cr);
|
||||
|
||||
#endif /* _SPL_CRED_H */
|
||||
|
||||
Reference in New Issue
Block a user