From f7fd6ddd96fae173d64bf2982ba4ceda28db56e2 Mon Sep 17 00:00:00 2001 From: Richard Yao Date: Sat, 13 Jul 2013 16:34:56 -0400 Subject: [PATCH] Linux 3.8 compat: Use kuid_t/kgid_t when required When CONFIG_UIDGID_STRICT_TYPE_CHECKS is enabled uid_t/git_t are replaced by kuid_t/kgid_t, which are structures instead of integral types. This causes any code that uses an integral type to fail to build. The User Namespace functionality introduced in Linux 3.8 requires CONFIG_UIDGID_STRICT_TYPE_CHECKS, so we could not build against any kernel that supported it. We resolve this by converting between the new kuid_t/kgid_t structures and the original uid_t/gid_t types. Original-patch-by: DHE Rewrite-by: Richard Yao Signed-off-by: Brian Behlendorf Closes #260 --- config/spl-build.m4 | 38 ++++++++++++++++++++++++++++++++++++++ include/sys/cred.h | 30 ++++++++++++++++++++++++++++++ module/spl/spl-cred.c | 28 ++++++++++++++++------------ 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 da179e3..f54c5b1 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 + ], [ + kuid_t userid = KUIDT_INIT(0); + kgid_t groupid = KGIDT_INIT(0); + ],[ + SPL_LINUX_TRY_COMPILE([ + #include + ], [ + 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 + #ifdef HAVE_KUIDGID_T + #include + #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 6c90588..3ba5c14 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 + #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 e669cbf..0ed6572 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 4f56f10..0784ff2 100644 --- a/module/spl/spl-vnode.c +++ b/module/spl/spl-vnode.c @@ -24,6 +24,7 @@ * Solaris Porting Layer (SPL) Vnode Implementation. \*****************************************************************************/ +#include #include #include #include @@ -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; -- 2.40.0