asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist) { gid_t groups[NGROUPS]; int retval; if (!capable(CAP_SETGID)) return -EPERM; if ((unsigned) gidsetsize > NGROUPS) return -EINVAL; if (copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t))) return -EFAULT; retval = security_task_setgroups(gidsetsize, groups); if (retval) return retval; memcpy(current->groups, groups, gidsetsize * sizeof(gid_t)); current->ngroups = gidsetsize; return 0; }
asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t *grouplist) { old_gid_t groups[NGROUPS]; gid_t new_groups[NGROUPS]; int i; if (!capable(CAP_SETGID)) return -EPERM; if ((unsigned) gidsetsize > NGROUPS) return -EINVAL; if (copy_from_user(groups, grouplist, gidsetsize * sizeof(old_gid_t))) return -EFAULT; for (i = 0 ; i < gidsetsize ; i++) new_groups[i] = (gid_t)groups[i]; if ((i = security_task_setgroups(gidsetsize, new_groups))) return i; memcpy(current->groups, new_groups, gidsetsize * sizeof(gid_t)); current->ngroups = gidsetsize; return 0; }
/* validate and set current->group_info */ int set_current_groups(struct group_info *group_info) { int retval; struct group_info *old_info; retval = security_task_setgroups(group_info); if (retval) return retval; groups_sort(group_info); get_group_info(group_info); task_lock(current); old_info = current->group_info; current->group_info = group_info; task_unlock(current); put_group_info(old_info); return 0; }