#include <linux/export.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/user_namespace.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
struct group_info *groups_alloc(int gidsetsize)
len = sizeof(struct group_info) + sizeof(kgid_t) * gidsetsize;
gi = kmalloc(len, GFP_KERNEL_ACCOUNT|__GFP_NOWARN|__GFP_NORETRY);
gi = __vmalloc(len, GFP_KERNEL_ACCOUNT, PAGE_KERNEL);
atomic_set(&gi->usage, 1);
gi->ngroups = gidsetsize;
EXPORT_SYMBOL(groups_alloc);
void groups_free(struct group_info *group_info)
EXPORT_SYMBOL(groups_free);
static int groups_to_user(gid_t __user *grouplist,
const struct group_info *group_info)
struct user_namespace *user_ns = current_user_ns();
unsigned int count = group_info->ngroups;
for (i = 0; i < count; i++) {
gid = from_kgid_munged(user_ns, group_info->gid[i]);
if (put_user(gid, grouplist+i))
static int groups_from_user(struct group_info *group_info,
struct user_namespace *user_ns = current_user_ns();