-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support idmapped mount in user namespace #14097
Changes from all commits
f104d44
ede7027
b9ee8be
36e826f
d554250
834dd73
640f11e
20b0eaf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
dnl # | ||
dnl # 6.0 API change | ||
dnl # struct iattr has two unions for the uid and gid | ||
dnl # | ||
AC_DEFUN([ZFS_AC_KERNEL_SRC_IATTR_VFSID], [ | ||
ZFS_LINUX_TEST_SRC([iattr_vfsid], [ | ||
#include <linux/fs.h> | ||
], [ | ||
struct iattr ia; | ||
ia.ia_vfsuid = (vfsuid_t){0}; | ||
ia.ia_vfsgid = (vfsgid_t){0}; | ||
]) | ||
]) | ||
|
||
AC_DEFUN([ZFS_AC_KERNEL_IATTR_VFSID], [ | ||
AC_MSG_CHECKING([whether iattr->ia_vfsuid and iattr->ia_vfsgid exist]) | ||
ZFS_LINUX_TEST_RESULT([iattr_vfsid], [ | ||
AC_MSG_RESULT(yes) | ||
AC_DEFINE(HAVE_IATTR_VFSID, 1, | ||
[iattr->ia_vfsuid and iattr->ia_vfsgid exist]) | ||
],[ | ||
AC_MSG_RESULT(no) | ||
]) | ||
]) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just so I understand, you're deliberately operating on plain There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. I see no need to massage around different types. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think security wise this isn't a good idea which is why we have raw |
||
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 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you support kernels without sb->s_user_ns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we do.