Skip to content
This repository has been archived by the owner on Feb 26, 2020. It is now read-only.

Commit

Permalink
Linux 4.9 compat: group_info changes
Browse files Browse the repository at this point in the history
In Linux 4.9, torvalds/linux@81243ea, group_info changed from 2d array via
->blocks to 1d array via ->gid. We change the spl cred functions accordingly.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Chunwei Chen <david.chen@osnexus.com>
Closes #581
  • Loading branch information
Chunwei Chen authored and behlendorf committed Oct 20, 2016
1 parent 87063d7 commit ae7eda1
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 2 deletions.
23 changes: 23 additions & 0 deletions config/spl-build.m4
Expand Up @@ -49,6 +49,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
SPL_AC_WAIT_ON_BIT
SPL_AC_MUTEX_OWNER
SPL_AC_INODE_LOCK
SPL_AC_GROUP_INFO_GID
])

AC_DEFUN([SPL_AC_MODULE_SYMVERS], [
Expand Down Expand Up @@ -1574,3 +1575,25 @@ AC_DEFUN([SPL_AC_INODE_LOCK], [
])
EXTRA_KCFLAGS="$tmp_flags"
])

dnl #
dnl # 4.9 API change
dnl # group_info changed from 2d array via >blocks to 1d array via ->gid
dnl #
AC_DEFUN([SPL_AC_GROUP_INFO_GID], [
AC_MSG_CHECKING([whether group_info->gid exists])
tmp_flags="$EXTRA_KCFLAGS"
EXTRA_KCFLAGS="-Werror"
SPL_LINUX_TRY_COMPILE([
#include <linux/cred.h>
],[
struct group_info *gi = groups_alloc(1);
gi->gid[0] = KGIDT_INIT(0);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GROUP_INFO_GID, 1, [group_info->gid exists])
],[
AC_MSG_RESULT(no)
])
EXTRA_KCFLAGS="$tmp_flags"
])
5 changes: 5 additions & 0 deletions include/sys/cred.h
Expand Up @@ -34,6 +34,11 @@ typedef struct cred cred_t;
#define kcred ((cred_t *)(init_task.cred))
#define CRED() ((cred_t *)current_cred())

/* Linux 4.9 API change, GROUP_AT was removed */
#ifndef GROUP_AT
#define GROUP_AT(gi, i) ((gi)->gid[i])
#endif

#ifdef HAVE_KUIDGID_T

#define KUID_TO_SUID(x) (__kuid_val(x))
Expand Down
10 changes: 10 additions & 0 deletions module/spl/spl-cred.c
Expand Up @@ -85,20 +85,26 @@ crgetngroups(const cred_t *cr)

gi = cr->group_info;
rc = gi->ngroups;
#ifndef HAVE_GROUP_INFO_GID
/*
* For Linux <= 4.8,
* crgetgroups will only returns gi->blocks[0], which contains only
* the first NGROUPS_PER_BLOCK groups.
*/
if (rc > NGROUPS_PER_BLOCK) {
WARN_ON_ONCE(1);
rc = NGROUPS_PER_BLOCK;
}
#endif
return rc;
}

/*
* Return an array of supplemental gids. The returned address is safe
* to use as long as the caller has taken a reference with crhold().
*
* Linux 4.9 API change, group_info changed from 2d array via ->blocks to 1d
* array via ->gid.
*/
gid_t *
crgetgroups(const cred_t *cr)
Expand All @@ -107,8 +113,12 @@ crgetgroups(const cred_t *cr)
gid_t *gids = NULL;

gi = cr->group_info;
#ifdef HAVE_GROUP_INFO_GID
gids = KGIDP_TO_SGIDP(gi->gid);
#else
if (gi->nblocks > 0)
gids = KGIDP_TO_SGIDP(gi->blocks[0]);
#endif
return gids;
}

Expand Down
5 changes: 3 additions & 2 deletions module/splat/splat-cred.c
Expand Up @@ -166,6 +166,7 @@ splat_cred_test2(struct file *file, void *arg)
return 0;
} /* splat_cred_test2() */

#define SPLAT_NGROUPS 32
/*
* Verify the groupmember() works correctly by constructing an interesting
* CRED() and checking that the expected gids are part of it.
Expand All @@ -188,15 +189,15 @@ splat_cred_test3(struct file *file, void *arg)
* 1:(NGROUPS_MAX-1). Gid 0 is explicitly avoided so we can reliably
* test for its absence in the test cases.
*/
gi = groups_alloc(NGROUPS_SMALL);
gi = groups_alloc(SPLAT_NGROUPS);
if (gi == NULL) {
splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed create "
"group_info for known gids: %d\n", -ENOMEM);
rc = -ENOMEM;
goto show_groups;
}

for (i = 0, tmp_gid = known_gid; i < NGROUPS_SMALL; i++) {
for (i = 0, tmp_gid = known_gid; i < SPLAT_NGROUPS; i++) {
splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Adding gid %d "
"to current CRED() (%d/%d)\n", tmp_gid, i, gi->ngroups);
#ifdef HAVE_KUIDGID_T
Expand Down

0 comments on commit ae7eda1

Please sign in to comment.