[PATCH] kernel/groups.c: Code simplifications

From: Eric Biggers
Date: Sun Oct 12 2014 - 12:20:43 EST


Reduce nesting and simplify the control flow, remove redundant
'gidsetsize < 0' check in sys_getgroups(), and inline groups_to_user().

This patch reduces the length of kernel/groups.c by 27 lines.

Signed-off-by: Eric Biggers <ebiggers3@xxxxxxxxx>
---
kernel/groups.c | 69 ++++++++++++++++++---------------------------------------
1 file changed, 21 insertions(+), 48 deletions(-)

diff --git a/kernel/groups.c b/kernel/groups.c
index 451698f..fae9d11 100644
--- a/kernel/groups.c
+++ b/kernel/groups.c
@@ -62,23 +62,6 @@ void groups_free(struct group_info *group_info)

EXPORT_SYMBOL(groups_free);

-/* export the group_info to a user-space array */
-static int groups_to_user(gid_t __user *grouplist,
- const struct group_info *group_info)
-{
- struct user_namespace *user_ns = current_user_ns();
- int i;
- unsigned int count = group_info->ngroups;
-
- for (i = 0; i < count; i++) {
- gid_t gid;
- gid = from_kgid_munged(user_ns, GROUP_AT(group_info, i));
- if (put_user(gid, grouplist+i))
- return -EFAULT;
- }
- return 0;
-}
-
/* fill a group_info from a user-space array - it must be allocated already */
static int groups_from_user(struct group_info *group_info,
gid_t __user *grouplist)
@@ -191,26 +174,23 @@ EXPORT_SYMBOL(set_current_groups);

SYSCALL_DEFINE2(getgroups, int, gidsetsize, gid_t __user *, grouplist)
{
- const struct cred *cred = current_cred();
+ /* no need to grab task_lock here; our group_info cannot change */
+ const struct group_info *group_info = current_cred()->group_info;
+ int ngroups = group_info->ngroups;
+ struct user_namespace *user_ns = current_user_ns();
int i;
+ gid_t gid;

- if (gidsetsize < 0)
+ if (!gidsetsize)
+ return ngroups;
+ if (gidsetsize < ngroups)
return -EINVAL;
-
- /* no need to grab task_lock here; it cannot change */
- i = cred->group_info->ngroups;
- if (gidsetsize) {
- if (i > gidsetsize) {
- i = -EINVAL;
- goto out;
- }
- if (groups_to_user(grouplist, cred->group_info)) {
- i = -EFAULT;
- goto out;
- }
+ for (i = 0; i < ngroups; i++) {
+ gid = from_kgid_munged(user_ns, GROUP_AT(group_info, i));
+ if (put_user(gid, grouplist + i))
+ return -EFAULT;
}
-out:
- return i;
+ return ngroups;
}

/*
@@ -232,14 +212,9 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
if (!group_info)
return -ENOMEM;
retval = groups_from_user(group_info, grouplist);
- if (retval) {
- put_group_info(group_info);
- return retval;
- }
-
- retval = set_current_groups(group_info);
+ if (!retval)
+ retval = set_current_groups(group_info);
put_group_info(group_info);
-
return retval;
}

@@ -249,11 +224,10 @@ SYSCALL_DEFINE2(setgroups, int, gidsetsize, gid_t __user *, grouplist)
int in_group_p(kgid_t grp)
{
const struct cred *cred = current_cred();
- int retval = 1;

- if (!gid_eq(grp, cred->fsgid))
- retval = groups_search(cred->group_info, grp);
- return retval;
+ if (gid_eq(grp, cred->fsgid))
+ return 1;
+ return groups_search(cred->group_info, grp);
}

EXPORT_SYMBOL(in_group_p);
@@ -261,11 +235,10 @@ EXPORT_SYMBOL(in_group_p);
int in_egroup_p(kgid_t grp)
{
const struct cred *cred = current_cred();
- int retval = 1;

- if (!gid_eq(grp, cred->egid))
- retval = groups_search(cred->group_info, grp);
- return retval;
+ if (gid_eq(grp, cred->egid))
+ return 1;
+ return groups_search(cred->group_info, grp);
}

EXPORT_SYMBOL(in_egroup_p);
--
2.1.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/