diff options
-rw-r--r-- | config/spl-build.m4 | 38 | ||||
-rw-r--r-- | include/sys/cred.h | 30 | ||||
-rw-r--r-- | module/spl/spl-cred.c | 28 | ||||
-rw-r--r-- | module/spl/spl-vnode.c | 5 |
4 files changed, 87 insertions, 14 deletions
diff --git a/config/spl-build.m4 b/config/spl-build.m4 index da179e33d..f54c5b166 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -73,6 +73,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ SPL_AC_INODE_TRUNCATE_RANGE SPL_AC_FS_STRUCT_SPINLOCK SPL_AC_CRED_STRUCT + SPL_AC_KUIDGID_T SPL_AC_GROUPS_SEARCH SPL_AC_PUT_TASK_STRUCT SPL_AC_5ARGS_PROC_HANDLER @@ -1866,6 +1867,36 @@ AC_DEFUN([SPL_AC_CRED_STRUCT], [ ]) ]) + +dnl # +dnl # User namespaces, use kuid_t in place of uid_t +dnl # where available. Not strictly a user namespaces thing +dnl # but it should prevent surprises +dnl # +AC_DEFUN([SPL_AC_KUIDGID_T], [ + AC_MSG_CHECKING([whether kuid_t/kgid_t is available]) + SPL_LINUX_TRY_COMPILE([ + #include <linux/uidgid.h> + ], [ + kuid_t userid = KUIDT_INIT(0); + kgid_t groupid = KGIDT_INIT(0); + ],[ + SPL_LINUX_TRY_COMPILE([ + #include <linux/uidgid.h> + ], [ + kuid_t userid = 0; + kgid_t groupid = 0; + ],[ + AC_MSG_RESULT(yes; optional) + ],[ + AC_MSG_RESULT(yes; mandatory) + AC_DEFINE(HAVE_KUIDGID_T, 1, [kuid_t/kgid_t in use]) + ]) + ],[ + AC_MSG_RESULT(no) + ]) +]) + dnl # dnl # Custom SPL patch may export this symbol. dnl # @@ -1873,8 +1904,15 @@ AC_DEFUN([SPL_AC_GROUPS_SEARCH], [AC_MSG_CHECKING([whether groups_search() is available]) SPL_LINUX_TRY_COMPILE_SYMBOL([ #include <linux/cred.h> + #ifdef HAVE_KUIDGID_T + #include <linux/uidgid.h> + #endif ], [ + #ifdef HAVE_KUIDGID_T + groups_search(NULL, KGIDT_INIT(0)); + #else groups_search(NULL, 0); + #endif ], [groups_search], [], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_GROUPS_SEARCH, 1, [groups_search() is available]) diff --git a/include/sys/cred.h b/include/sys/cred.h index 6c905884b..3ba5c141b 100644 --- a/include/sys/cred.h +++ b/include/sys/cred.h @@ -45,6 +45,36 @@ typedef struct task_struct cred_t; #endif /* HAVE_CRED_STRUCT */ +#ifdef HAVE_KUIDGID_T + + /* + * Linux 3.8+ uses typedefs to redefine uid_t and gid_t. We have to rename the + * typedefs to recover the original types. We then can use them provided that + * we are careful about translating from k{g,u}id_t to the original versions + * and vice versa. + */ + #define uid_t xuid_t + #define gid_t xgid_t + #include <linux/uidgid.h> + #undef uid_t + #undef gid_t + + #define KUID_TO_SUID(x) (__kuid_val(x)) + #define KGID_TO_SGID(x) (__kgid_val(x)) + #define SUID_TO_KUID(x) (KUIDT_INIT(x)) + #define SGID_TO_KGID(x) (KGIDT_INIT(x)) + #define KGIDP_TO_SGIDP(x) (&(x)->val) + +#else /* HAVE_KUIDGID_T */ + + #define KUID_TO_SUID(x) (x) + #define KGID_TO_SGID(x) (x) + #define SUID_TO_KUID(x) (x) + #define SGID_TO_KGID(x) (x) + #define KGIDP_TO_SGIDP(x) (x) + +#endif /* HAVE_KUIDGID_T */ + extern void crhold(cred_t *cr); extern void crfree(cred_t *cr); extern uid_t crgetuid(const cred_t *cr); diff --git a/module/spl/spl-cred.c b/module/spl/spl-cred.c index e669cbf5d..0ed65725e 100644 --- a/module/spl/spl-cred.c +++ b/module/spl/spl-cred.c @@ -38,7 +38,11 @@ #else /* Implementation from 2.6.30 kernel */ static int +#ifdef HAVE_KUIDGID_T +cr_groups_search(const struct group_info *group_info, kgid_t grp) +#else cr_groups_search(const struct group_info *group_info, gid_t grp) +#endif { unsigned int left, right; @@ -49,7 +53,7 @@ cr_groups_search(const struct group_info *group_info, gid_t grp) right = group_info->ngroups; while (left < right) { unsigned int mid = (left+right)/2; - int cmp = grp - GROUP_AT(group_info, mid); + int cmp = KGID_TO_SGID(grp) - KGID_TO_SGID(GROUP_AT(group_info, mid)); if (cmp > 0) left = mid + 1; else if (cmp < 0) @@ -110,7 +114,7 @@ crgetgroups(const cred_t *cr) gid_t *gids; gi = get_group_info(cr->group_info); - gids = gi->blocks[0]; + gids = KGIDP_TO_SGIDP(gi->blocks[0]); put_group_info(gi); return gids; @@ -124,7 +128,7 @@ groupmember(gid_t gid, const cred_t *cr) int rc; gi = get_group_info(cr->group_info); - rc = cr_groups_search(cr->group_info, gid); + rc = cr_groups_search(cr->group_info, SGID_TO_KGID(gid)); put_group_info(gi); return rc; @@ -180,7 +184,7 @@ crgetgroups(const cred_t *cr) task_lock((struct task_struct *)cr); get_group_info(cr->group_info); - gids = cr->group_info->blocks[0]; + gids = KGID_TO_SGID(cr->group_info->blocks[0]); put_group_info(cr->group_info); if (lock) @@ -215,56 +219,56 @@ groupmember(gid_t gid, const cred_t *cr) uid_t crgetuid(const cred_t *cr) { - return cr->euid; + return KUID_TO_SUID(cr->euid); } /* Return the real user id */ uid_t crgetruid(const cred_t *cr) { - return cr->uid; + return KUID_TO_SUID(cr->uid); } /* Return the saved user id */ uid_t crgetsuid(const cred_t *cr) { - return cr->suid; + return KUID_TO_SUID(cr->suid); } /* Return the filesystem user id */ uid_t crgetfsuid(const cred_t *cr) { - return cr->fsuid; + return KUID_TO_SUID(cr->fsuid); } /* Return the effective group id */ gid_t crgetgid(const cred_t *cr) { - return cr->egid; + return KGID_TO_SGID(cr->egid); } /* Return the real group id */ gid_t crgetrgid(const cred_t *cr) { - return cr->gid; + return KGID_TO_SGID(cr->gid); } /* Return the saved group id */ gid_t crgetsgid(const cred_t *cr) { - return cr->sgid; + return KGID_TO_SGID(cr->sgid); } /* Return the filesystem group id */ gid_t crgetfsgid(const cred_t *cr) { - return cr->fsgid; + return KGID_TO_SGID(cr->fsgid); } EXPORT_SYMBOL(crhold); diff --git a/module/spl/spl-vnode.c b/module/spl/spl-vnode.c index 4f56f1039..0784ff261 100644 --- a/module/spl/spl-vnode.c +++ b/module/spl/spl-vnode.c @@ -24,6 +24,7 @@ * Solaris Porting Layer (SPL) Vnode Implementation. \*****************************************************************************/ +#include <sys/cred.h> #include <sys/vnode.h> #include <linux/falloc.h> #include <spl-debug.h> @@ -616,8 +617,8 @@ vn_getattr(vnode_t *vp, vattr_t *vap, int flags, void *x3, void *x4) vap->va_type = vn_mode_to_vtype(stat.mode); vap->va_mode = stat.mode; - vap->va_uid = stat.uid; - vap->va_gid = stat.gid; + vap->va_uid = KUID_TO_SUID(stat.uid); + vap->va_gid = KGID_TO_SGID(stat.gid); vap->va_fsid = 0; vap->va_nodeid = stat.ino; vap->va_nlink = stat.nlink; |