Commit a937b06e authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] NGROUPS 2.6.2rc2 + fixups

From: Tim Hockin <thockin@sun.com>,
      Neil Brown <neilb@cse.unsw.edu.au>,
      me

New groups infrastructure.  task->groups and task->ngroups are replaced by
task->group_info.  Group)info is a refcounted, dynamic struct with an array
of pages.  This allows for large numbers of groups.  The current limit of
32 groups has been raised to 64k groups.  It can be raised more by changing
the NGROUPS_MAX constant in limits.h
parent 7e594425
...@@ -2413,44 +2413,85 @@ sys32_lseek (unsigned int fd, int offset, unsigned int whence) ...@@ -2413,44 +2413,85 @@ sys32_lseek (unsigned int fd, int offset, unsigned int whence)
return sys_lseek(fd, offset, whence); return sys_lseek(fd, offset, whence);
} }
extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist); static int
groups16_to_user(short *grouplist, struct group_info *group_info)
{
int i;
short group;
for (i = 0; i < group_info->ngroups; i++) {
group = (short)GROUP_AT(group_info, i);
if (put_user(group, grouplist+i))
return -EFAULT;
}
return 0;
}
static int
groups16_from_user(struct group_info *group_info, short *grouplist)
{
int i;
short group;
for (i = 0; i < group_info->ngroups; i++) {
if (get_user(group, grouplist+i))
return -EFAULT;
GROUP_AT(group_info, i) = (gid_t)group;
}
return 0;
}
asmlinkage long asmlinkage long
sys32_getgroups16 (int gidsetsize, short *grouplist) sys32_getgroups16 (int gidsetsize, short *grouplist)
{ {
mm_segment_t old_fs = get_fs(); int i;
gid_t gl[NGROUPS];
int ret, i;
set_fs(KERNEL_DS); if (gidsetsize < 0)
ret = sys_getgroups(gidsetsize, gl); return -EINVAL;
set_fs(old_fs);
if (gidsetsize && ret > 0 && ret <= NGROUPS) get_group_info(current->group_info);
for (i = 0; i < ret; i++, grouplist++) i = current->group_info->ngroups;
if (put_user(gl[i], grouplist)) if (gidsetsize) {
return -EFAULT; if (i > gidsetsize) {
return ret; i = -EINVAL;
goto out;
}
if (groups16_to_user(grouplist, current->group_info)) {
i = -EFAULT;
goto out;
}
}
out:
put_group_info(current->group_info);
return i;
} }
extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist);
asmlinkage long asmlinkage long
sys32_setgroups16 (int gidsetsize, short *grouplist) sys32_setgroups16 (int gidsetsize, short *grouplist)
{ {
mm_segment_t old_fs = get_fs(); struct group_info *group_info;
gid_t gl[NGROUPS]; int retval;
int ret, i;
if ((unsigned) gidsetsize > NGROUPS) if (!capable(CAP_SETGID))
return -EPERM;
if ((unsigned)gidsetsize > NGROUPS_MAX)
return -EINVAL; return -EINVAL;
for (i = 0; i < gidsetsize; i++, grouplist++)
if (get_user(gl[i], grouplist)) group_info = groups_alloc(gidsetsize);
return -EFAULT; if (!group_info)
set_fs(KERNEL_DS); return -ENOMEM;
ret = sys_setgroups(gidsetsize, gl); retval = groups16_from_user(group_info, grouplist);
set_fs(old_fs); if (retval) {
return ret; put_group_info(group_info);
return retval;
}
retval = set_current_groups(group_info);
put_group_info(group_info);
return retval;
} }
asmlinkage long asmlinkage long
......
...@@ -368,7 +368,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs) ...@@ -368,7 +368,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
retval = HZ; retval = HZ;
goto out; goto out;
case 4: case 4:
retval = NGROUPS; retval = NGROUPS_MAX;
goto out; goto out;
case 5: case 5:
retval = NR_OPEN; retval = NR_OPEN;
......
...@@ -190,40 +190,81 @@ asmlinkage long sys32_setfsgid16(u16 gid) ...@@ -190,40 +190,81 @@ asmlinkage long sys32_setfsgid16(u16 gid)
return sys_setfsgid((gid_t)gid); return sys_setfsgid((gid_t)gid);
} }
static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
{
int i;
u16 group;
for (i = 0; i < group_info->ngroups; i++) {
group = (u16)GROUP_AT(group_info, i);
if (put_user(group, grouplist+i))
return -EFAULT;
}
return 0;
}
static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
{
int i;
u16 group;
for (i = 0; i < group_info->ngroups; i++) {
if (get_user(group, grouplist+i))
return -EFAULT;
GROUP_AT(group_info, i) = (gid_t)group;
}
return 0;
}
asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist) asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
{ {
u16 groups[NGROUPS]; int i;
int i,j;
if (gidsetsize < 0) if (gidsetsize < 0)
return -EINVAL; return -EINVAL;
i = current->ngroups;
get_group_info(current->group_info);
i = current->group_info->ngroups;
if (gidsetsize) { if (gidsetsize) {
if (i > gidsetsize) if (i > gidsetsize) {
return -EINVAL; i = -EINVAL;
for(j=0;j<i;j++) goto out;
groups[j] = current->groups[j]; }
if (copy_to_user(grouplist, groups, sizeof(u16)*i)) if (groups16_to_user(grouplist, current->group_info)) {
return -EFAULT; i = -EFAULT;
goto out;
}
} }
out:
put_group_info(current->group_info);
return i; return i;
} }
asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist) asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
{ {
u16 groups[NGROUPS]; struct group_info *group_info;
int i; int retval;
if (!capable(CAP_SETGID)) if (!capable(CAP_SETGID))
return -EPERM; return -EPERM;
if ((unsigned) gidsetsize > NGROUPS) if ((unsigned)gidsetsize > NGROUPS_MAX)
return -EINVAL; return -EINVAL;
if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
return -EFAULT; group_info = groups_alloc(gidsetsize);
for (i = 0 ; i < gidsetsize ; i++) if (!group_info)
current->groups[i] = (gid_t)groups[i]; return -ENOMEM;
current->ngroups = gidsetsize; retval = groups16_from_user(group_info, grouplist);
return 0; if (retval) {
put_group_info(group_info);
return retval;
}
retval = set_current_groups(group_info);
put_group_info(group_info);
return retval;
} }
asmlinkage long sys32_getuid16(void) asmlinkage long sys32_getuid16(void)
......
...@@ -179,40 +179,81 @@ asmlinkage long sys32_setfsgid16(u16 gid) ...@@ -179,40 +179,81 @@ asmlinkage long sys32_setfsgid16(u16 gid)
return sys_setfsgid((gid_t)gid); return sys_setfsgid((gid_t)gid);
} }
static int groups16_to_user(u16 *grouplist, struct group_info *group_info)
{
int i;
u16 group;
for (i = 0; i < group_info->ngroups; i++) {
group = (u16)GROUP_AT(group_info, i);
if (put_user(group, grouplist+i))
return -EFAULT;
}
return 0;
}
static int groups16_from_user(struct group_info *group_info, u16 *grouplist)
{
int i;
u16 group;
for (i = 0; i < group_info->ngroups; i++) {
if (get_user(group, grouplist+i))
return -EFAULT;
GROUP_AT(group_info, i) = (gid_t)group;
}
return 0;
}
asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist) asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
{ {
u16 groups[NGROUPS]; int i;
int i,j;
if (gidsetsize < 0) if (gidsetsize < 0)
return -EINVAL; return -EINVAL;
i = current->ngroups;
get_group_info(current->group_info);
i = current->group_info->ngroups;
if (gidsetsize) { if (gidsetsize) {
if (i > gidsetsize) if (i > gidsetsize) {
return -EINVAL; i = -EINVAL;
for(j=0;j<i;j++) goto out;
groups[j] = current->groups[j]; }
if (copy_to_user(grouplist, groups, sizeof(u16)*i)) if (groups16_to_user(grouplist, current->group_info)) {
return -EFAULT; i = -EFAULT;
goto out;
}
} }
out:
put_group_info(current->group_info);
return i; return i;
} }
asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist) asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
{ {
u16 groups[NGROUPS]; struct group_info *group_info;
int i; int retval;
if (!capable(CAP_SETGID)) if (!capable(CAP_SETGID))
return -EPERM; return -EPERM;
if ((unsigned) gidsetsize > NGROUPS) if ((unsigned)gidsetsize > NGROUPS_MAX)
return -EINVAL; return -EINVAL;
if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
return -EFAULT; group_info = groups_alloc(gidsetsize);
for (i = 0 ; i < gidsetsize ; i++) if (!group_info)
current->groups[i] = (gid_t)groups[i]; return -ENOMEM;
current->ngroups = gidsetsize; retval = groups16_from_user(group_info, grouplist);
return 0; if (retval) {
put_group_info(group_info);
return retval;
}
retval = set_current_groups(group_info);
put_group_info(group_info);
return retval;
} }
asmlinkage long sys32_getuid16(void) asmlinkage long sys32_getuid16(void)
......
...@@ -11,11 +11,26 @@ ...@@ -11,11 +11,26 @@
#include <linux/nfsd/nfsd.h> #include <linux/nfsd/nfsd.h>
#define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE)) #define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
void
nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
{ {
struct svc_cred *cred = &rqstp->rq_cred; struct svc_cred *cred = &rqstp->rq_cred;
int i; struct group_info *group_info;
int ngroups;
int i;
int ret;
ngroups = 0;
if (!(exp->ex_flags & NFSEXP_ALLSQUASH)) {
for (i = 0; i < SVC_CRED_NGROUPS; i++) {
if (cred->cr_groups[i] == (gid_t)NOGROUP)
break;
ngroups++;
}
}
group_info = groups_alloc(ngroups);
if (group_info == NULL)
return -ENOMEM;
if (exp->ex_flags & NFSEXP_ALLSQUASH) { if (exp->ex_flags & NFSEXP_ALLSQUASH) {
cred->cr_uid = exp->ex_anon_uid; cred->cr_uid = exp->ex_anon_uid;
...@@ -26,7 +41,7 @@ nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) ...@@ -26,7 +41,7 @@ nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
cred->cr_uid = exp->ex_anon_uid; cred->cr_uid = exp->ex_anon_uid;
if (!cred->cr_gid) if (!cred->cr_gid)
cred->cr_gid = exp->ex_anon_gid; cred->cr_gid = exp->ex_anon_gid;
for (i = 0; i < NGROUPS; i++) for (i = 0; i < SVC_CRED_NGROUPS; i++)
if (!cred->cr_groups[i]) if (!cred->cr_groups[i])
cred->cr_groups[i] = exp->ex_anon_gid; cred->cr_groups[i] = exp->ex_anon_gid;
} }
...@@ -39,19 +54,24 @@ nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) ...@@ -39,19 +54,24 @@ nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
current->fsgid = cred->cr_gid; current->fsgid = cred->cr_gid;
else else
current->fsgid = exp->ex_anon_gid; current->fsgid = exp->ex_anon_gid;
for (i = 0; i < NGROUPS; i++) {
for (i = 0; i < SVC_CRED_NGROUPS; i++) {
gid_t group = cred->cr_groups[i]; gid_t group = cred->cr_groups[i];
if (group == (gid_t) NOGROUP) if (group == (gid_t) NOGROUP)
break; break;
current->groups[i] = group; GROUP_AT(group_info, i) = group;
} }
current->ngroups = i;
if ((cred->cr_uid)) { ret = set_current_groups(group_info);
cap_t(current->cap_effective) &= ~CAP_NFSD_MASK; if (ret == 0) {
} else { if ((cred->cr_uid)) {
cap_t(current->cap_effective) |= (CAP_NFSD_MASK & cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
current->cap_permitted); } else {
cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
current->cap_permitted);
}
} }
put_group_info(group_info);
return ret;
} }
...@@ -244,7 +244,7 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) { ...@@ -244,7 +244,7 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) {
target->cr_uid = source->cr_uid; target->cr_uid = source->cr_uid;
target->cr_gid = source->cr_gid; target->cr_gid = source->cr_gid;
for(i = 0; i < NGROUPS; i++) for(i = 0; i < SVC_CRED_NGROUPS; i++)
target->cr_groups[i] = source->cr_groups[i]; target->cr_groups[i] = source->cr_groups[i];
} }
......
...@@ -176,8 +176,10 @@ static inline char * task_state(struct task_struct *p, char *buffer) ...@@ -176,8 +176,10 @@ static inline char * task_state(struct task_struct *p, char *buffer)
p->files ? p->files->max_fds : 0); p->files ? p->files->max_fds : 0);
task_unlock(p); task_unlock(p);
for (g = 0; g < p->ngroups; g++) get_group_info(p->group_info);
buffer += sprintf(buffer, "%d ", p->groups[g]); for (g = 0; g < min(p->group_info->ngroups,NGROUPS_SMALL); g++)
buffer += sprintf(buffer, "%d ", GROUP_AT(p->group_info,g));
put_group_info(p->group_info);
buffer += sprintf(buffer, "\n"); buffer += sprintf(buffer, "\n");
return buffer; return buffer;
......
...@@ -19,10 +19,6 @@ ...@@ -19,10 +19,6 @@
#define EXEC_PAGESIZE 8192 #define EXEC_PAGESIZE 8192
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -26,10 +26,6 @@ ...@@ -26,10 +26,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -22,10 +22,6 @@ ...@@ -22,10 +22,6 @@
# define HZ 100 # define HZ 100
#endif #endif
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
#define EXEC_PAGESIZE 8192 #define EXEC_PAGESIZE 8192
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -13,10 +13,6 @@ ...@@ -13,10 +13,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -12,10 +12,6 @@ ...@@ -12,10 +12,6 @@
#define EXEC_PAGESIZE 65536 #define EXEC_PAGESIZE 65536
#ifndef NGROUPS
# define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
# define NOGROUP (-1) # define NOGROUP (-1)
#endif #endif
......
...@@ -13,10 +13,6 @@ ...@@ -13,10 +13,6 @@
#define EXEC_PAGESIZE 8192 #define EXEC_PAGESIZE 8192
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -44,10 +44,6 @@ ...@@ -44,10 +44,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -33,10 +33,6 @@ ...@@ -33,10 +33,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -18,10 +18,6 @@ ...@@ -18,10 +18,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -13,10 +13,6 @@ ...@@ -13,10 +13,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -20,10 +20,6 @@ ...@@ -20,10 +20,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -21,10 +21,6 @@ ...@@ -21,10 +21,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -17,10 +17,6 @@ ...@@ -17,10 +17,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
#define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */ #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
#define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */ #define EXEC_PAGESIZE 8192 /* Thanks for sun4's we carry baggage... */
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -3,10 +3,6 @@ ...@@ -3,10 +3,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -18,10 +18,6 @@ ...@@ -18,10 +18,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -13,10 +13,6 @@ ...@@ -13,10 +13,6 @@
#define EXEC_PAGESIZE 4096 #define EXEC_PAGESIZE 4096
#ifndef NGROUPS
#define NGROUPS 32
#endif
#ifndef NOGROUP #ifndef NOGROUP
#define NOGROUP (-1) #define NOGROUP (-1)
#endif #endif
......
...@@ -57,6 +57,8 @@ ...@@ -57,6 +57,8 @@
.siglock = SPIN_LOCK_UNLOCKED, \ .siglock = SPIN_LOCK_UNLOCKED, \
} }
extern struct group_info init_groups;
/* /*
* INIT_TASK is used to set up the first task table, touch at * INIT_TASK is used to set up the first task table, touch at
* your own risk!. Base=0, limit=0x1fffff (=2MB) * your own risk!. Base=0, limit=0x1fffff (=2MB)
...@@ -88,6 +90,7 @@ ...@@ -88,6 +90,7 @@
.real_timer = { \ .real_timer = { \
.function = it_real_fn \ .function = it_real_fn \
}, \ }, \
.group_info = &init_groups, \
.cap_effective = CAP_INIT_EFF_SET, \ .cap_effective = CAP_INIT_EFF_SET, \
.cap_inheritable = CAP_INIT_INH_SET, \ .cap_inheritable = CAP_INIT_INH_SET, \
.cap_permitted = CAP_FULL_SET, \ .cap_permitted = CAP_FULL_SET, \
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#define NR_OPEN 1024 #define NR_OPEN 1024
#define NGROUPS_MAX 32 /* supplemental group IDs are available */ #define NGROUPS_MAX 65536 /* supplemental group IDs are available */
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ #define ARG_MAX 131072 /* # bytes of args + environ for exec() */
#define CHILD_MAX 999 /* no limit :-) */ #define CHILD_MAX 999 /* no limit :-) */
#define OPEN_MAX 256 /* # open files a process may have */ #define OPEN_MAX 256 /* # open files a process may have */
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
* Set the current process's fsuid/fsgid etc to those of the NFS * Set the current process's fsuid/fsgid etc to those of the NFS
* client user * client user
*/ */
void nfsd_setuser(struct svc_rqst *, struct svc_export *); int nfsd_setuser(struct svc_rqst *, struct svc_export *);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* LINUX_NFSD_AUTH_H */ #endif /* LINUX_NFSD_AUTH_H */
...@@ -330,6 +330,33 @@ struct k_itimer { ...@@ -330,6 +330,33 @@ struct k_itimer {
struct io_context; /* See blkdev.h */ struct io_context; /* See blkdev.h */
void exit_io_context(void); void exit_io_context(void);
#define NGROUPS_SMALL 32
#define NGROUPS_PER_BLOCK ((int)(EXEC_PAGESIZE / sizeof(gid_t)))
struct group_info {
int ngroups;
atomic_t usage;
gid_t small_block[NGROUPS_SMALL];
int nblocks;
gid_t *blocks[0];
};
#define get_group_info(group_info) do { \
atomic_inc(&(group_info)->usage); \
} while (0)
#define put_group_info(group_info) do { \
if (atomic_dec_and_test(&(group_info)->usage)) \
groups_free(group_info); \
} while (0)
struct group_info *groups_alloc(int gidsetsize);
void groups_free(struct group_info *group_info);
int set_current_groups(struct group_info *group_info);
/* access the groups "array" with this macro */
#define GROUP_AT(gi, i) \
((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK])
struct task_struct { struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
struct thread_info *thread_info; struct thread_info *thread_info;
...@@ -404,8 +431,7 @@ struct task_struct { ...@@ -404,8 +431,7 @@ struct task_struct {
/* process credentials */ /* process credentials */
uid_t uid,euid,suid,fsuid; uid_t uid,euid,suid,fsuid;
gid_t gid,egid,sgid,fsgid; gid_t gid,egid,sgid,fsgid;
int ngroups; struct group_info *group_info;
gid_t groups[NGROUPS];
kernel_cap_t cap_effective, cap_inheritable, cap_permitted; kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
int keep_capabilities:1; int keep_capabilities:1;
struct user_struct *user; struct user_struct *user;
......
...@@ -564,9 +564,8 @@ struct swap_info_struct; ...@@ -564,9 +564,8 @@ struct swap_info_struct;
* Return 0 if permission is granted. * Return 0 if permission is granted.
* @task_setgroups: * @task_setgroups:
* Check permission before setting the supplementary group set of the * Check permission before setting the supplementary group set of the
* current process to @grouplist. * current process.
* @gidsetsize contains the number of elements in @grouplist. * @group_info contains the new group information.
* @grouplist contains the array of gids.
* Return 0 if permission is granted. * Return 0 if permission is granted.
* @task_setnice: * @task_setnice:
* Check permission before setting the nice value of @p to @nice. * Check permission before setting the nice value of @p to @nice.
...@@ -1127,7 +1126,7 @@ struct security_operations { ...@@ -1127,7 +1126,7 @@ struct security_operations {
int (*task_setpgid) (struct task_struct * p, pid_t pgid); int (*task_setpgid) (struct task_struct * p, pid_t pgid);
int (*task_getpgid) (struct task_struct * p); int (*task_getpgid) (struct task_struct * p);
int (*task_getsid) (struct task_struct * p); int (*task_getsid) (struct task_struct * p);
int (*task_setgroups) (int gidsetsize, gid_t * grouplist); int (*task_setgroups) (struct group_info *group_info);
int (*task_setnice) (struct task_struct * p, int nice); int (*task_setnice) (struct task_struct * p, int nice);
int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim); int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim);
int (*task_setscheduler) (struct task_struct * p, int policy, int (*task_setscheduler) (struct task_struct * p, int policy,
...@@ -1686,9 +1685,9 @@ static inline int security_task_getsid (struct task_struct *p) ...@@ -1686,9 +1685,9 @@ static inline int security_task_getsid (struct task_struct *p)
return security_ops->task_getsid (p); return security_ops->task_getsid (p);
} }
static inline int security_task_setgroups (int gidsetsize, gid_t *grouplist) static inline int security_task_setgroups (struct group_info *group_info)
{ {
return security_ops->task_setgroups (gidsetsize, grouplist); return security_ops->task_setgroups (group_info);
} }
static inline int security_task_setnice (struct task_struct *p, int nice) static inline int security_task_setnice (struct task_struct *p, int nice)
...@@ -2320,7 +2319,7 @@ static inline int security_task_getsid (struct task_struct *p) ...@@ -2320,7 +2319,7 @@ static inline int security_task_getsid (struct task_struct *p)
return 0; return 0;
} }
static inline int security_task_setgroups (int gidsetsize, gid_t *grouplist) static inline int security_task_setgroups (struct group_info *group_info)
{ {
return 0; return 0;
} }
......
...@@ -28,8 +28,7 @@ ...@@ -28,8 +28,7 @@
struct auth_cred { struct auth_cred {
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
int ngroups; struct group_info *group_info;
gid_t *groups;
}; };
/* /*
......
...@@ -16,10 +16,11 @@ ...@@ -16,10 +16,11 @@
#include <linux/sunrpc/cache.h> #include <linux/sunrpc/cache.h>
#include <linux/hash.h> #include <linux/hash.h>
#define SVC_CRED_NGROUPS 32
struct svc_cred { struct svc_cred {
uid_t cr_uid; uid_t cr_uid;
gid_t cr_gid; gid_t cr_gid;
gid_t cr_groups[NGROUPS]; gid_t cr_groups[SVC_CRED_NGROUPS];
}; };
struct svc_rqst; /* forward decl */ struct svc_rqst; /* forward decl */
......
...@@ -86,6 +86,7 @@ void __put_task_struct(struct task_struct *tsk) ...@@ -86,6 +86,7 @@ void __put_task_struct(struct task_struct *tsk)
security_task_free(tsk); security_task_free(tsk);
free_uid(tsk->user); free_uid(tsk->user);
put_group_info(tsk->group_info);
free_task(tsk); free_task(tsk);
} }
...@@ -878,6 +879,7 @@ struct task_struct *copy_process(unsigned long clone_flags, ...@@ -878,6 +879,7 @@ struct task_struct *copy_process(unsigned long clone_flags,
atomic_inc(&p->user->__count); atomic_inc(&p->user->__count);
atomic_inc(&p->user->processes); atomic_inc(&p->user->processes);
get_group_info(p->group_info);
/* /*
* If multiple threads are within copy_process(), then this check * If multiple threads are within copy_process(), then this check
...@@ -1084,6 +1086,7 @@ struct task_struct *copy_process(unsigned long clone_flags, ...@@ -1084,6 +1086,7 @@ struct task_struct *copy_process(unsigned long clone_flags,
bad_fork_cleanup_put_domain: bad_fork_cleanup_put_domain:
module_put(p->thread_info->exec_domain->module); module_put(p->thread_info->exec_domain->module);
bad_fork_cleanup_count: bad_fork_cleanup_count:
put_group_info(p->group_info);
atomic_dec(&p->user->processes); atomic_dec(&p->user->processes);
free_uid(p->user); free_uid(p->user);
bad_fork_free: bad_fork_free:
......
...@@ -1089,10 +1089,178 @@ asmlinkage long sys_setsid(void) ...@@ -1089,10 +1089,178 @@ asmlinkage long sys_setsid(void)
/* /*
* Supplementary group IDs * Supplementary group IDs
*/ */
asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
/* init to 2 - one for init_task, one to ensure it is never freed */
struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
struct group_info *groups_alloc(int gidsetsize)
{ {
struct group_info *group_info;
int nblocks;
int i; int i;
nblocks = (gidsetsize/NGROUPS_PER_BLOCK) +
(gidsetsize%NGROUPS_PER_BLOCK?1:0);
group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *),
GFP_USER);
if (!group_info)
return NULL;
group_info->ngroups = gidsetsize;
group_info->nblocks = nblocks;
atomic_set(&group_info->usage, 1);
if (gidsetsize <= NGROUPS_SMALL) {
group_info->blocks[0] = group_info->small_block;
} else {
for (i = 0; i < nblocks; i++) {
gid_t *b;
b = (void *)__get_free_page(GFP_USER);
if (!b)
goto out_undo_partial_alloc;
group_info->blocks[i] = b;
}
}
return group_info;
out_undo_partial_alloc:
while (--i >= 0) {
free_page((unsigned long)group_info->blocks[i]);
}
kfree(group_info);
return NULL;
}
EXPORT_SYMBOL(groups_alloc);
void groups_free(struct group_info *group_info)
{
if (group_info->blocks[0] != group_info->small_block) {
int i;
for (i = 0; i < group_info->nblocks; i++)
free_page((unsigned long)group_info->blocks[i]);
}
kfree(group_info);
}
EXPORT_SYMBOL(groups_free);
/* export the group_info to a user-space array */
static int groups_to_user(gid_t __user *grouplist,
struct group_info *group_info)
{
int i;
int count = group_info->ngroups;
for (i = 0; i < group_info->nblocks; i++) {
int cp_count = min(NGROUPS_PER_BLOCK, count);
int off = i * NGROUPS_PER_BLOCK;
int len = cp_count * sizeof(*grouplist);
if (copy_to_user(grouplist+off, group_info->blocks[i], len))
return -EFAULT;
count -= cp_count;
}
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)
{
int i;
int count = group_info->ngroups;
for (i = 0; i < group_info->nblocks; i++) {
int cp_count = min(NGROUPS_PER_BLOCK, count);
int off = i * NGROUPS_PER_BLOCK;
int len = cp_count * sizeof(*grouplist);
if (copy_from_user(group_info->blocks[i], grouplist+off, len))
return -EFAULT;
count -= cp_count;
}
return 0;
}
/* a simple shell-metzner sort */
static void groups_sort(struct group_info *group_info)
{
int base, max, stride;
int gidsetsize = group_info->ngroups;
for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
; /* nothing */
stride /= 3;
while (stride) {
max = gidsetsize - stride;
for (base = 0; base < max; base++) {
int left = base;
int right = left + stride;
gid_t tmp = GROUP_AT(group_info, right);
while (left >= 0 && GROUP_AT(group_info, left) > tmp) {
GROUP_AT(group_info, right) =
GROUP_AT(group_info, left);
right = left;
left -= stride;
}
GROUP_AT(group_info, right) = tmp;
}
stride /= 3;
}
}
/* a simple bsearch */
static int groups_search(struct group_info *group_info, gid_t grp)
{
int left, right;
if (!group_info)
return 0;
left = 0;
right = group_info->ngroups;
while (left < right) {
int mid = (left+right)/2;
int cmp = grp - GROUP_AT(group_info, mid);
if (cmp > 0)
left = mid + 1;
else if (cmp < 0)
right = mid;
else
return 1;
}
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);
old_info = current->group_info;
current->group_info = group_info;
put_group_info(old_info);
return 0;
}
EXPORT_SYMBOL(set_current_groups);
asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
{
int i = 0;
/* /*
* SMP: Nobody else can change our grouplist. Thus we are * SMP: Nobody else can change our grouplist. Thus we are
* safe. * safe.
...@@ -1100,54 +1268,52 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist) ...@@ -1100,54 +1268,52 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
if (gidsetsize < 0) if (gidsetsize < 0)
return -EINVAL; return -EINVAL;
i = current->ngroups;
get_group_info(current->group_info);
i = current->group_info->ngroups;
if (gidsetsize) { if (gidsetsize) {
if (i > gidsetsize) if (i > gidsetsize) {
return -EINVAL; i = -EINVAL;
if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i)) goto out;
return -EFAULT; }
if (groups_to_user(grouplist, current->group_info)) {
i = -EFAULT;
goto out;
}
} }
out:
put_group_info(current->group_info);
return i; return i;
} }
/* /*
* SMP: Our groups are not shared. We can copy to/from them safely * SMP: Our groups are copy-on-write. We can set them safely
* without another task interfering. * without another task interfering.
*/ */
asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist) asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
{ {
gid_t groups[NGROUPS]; struct group_info *group_info;
int retval; int retval;
if (!capable(CAP_SETGID)) if (!capable(CAP_SETGID))
return -EPERM; return -EPERM;
if ((unsigned) gidsetsize > NGROUPS) if ((unsigned)gidsetsize > NGROUPS_MAX)
return -EINVAL; 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;
}
static int supplemental_group_member(gid_t grp) group_info = groups_alloc(gidsetsize);
{ if (!group_info)
int i = current->ngroups; return -ENOMEM;
retval = groups_from_user(group_info, grouplist);
if (i) { if (retval) {
gid_t *groups = current->groups; put_group_info(group_info);
do { return retval;
if (*groups == grp)
return 1;
groups++;
i--;
} while (i);
} }
return 0;
retval = set_current_groups(group_info);
put_group_info(group_info);
return retval;
} }
/* /*
...@@ -1156,8 +1322,11 @@ static int supplemental_group_member(gid_t grp) ...@@ -1156,8 +1322,11 @@ static int supplemental_group_member(gid_t grp)
int in_group_p(gid_t grp) int in_group_p(gid_t grp)
{ {
int retval = 1; int retval = 1;
if (grp != current->fsgid) if (grp != current->fsgid) {
retval = supplemental_group_member(grp); get_group_info(current->group_info);
retval = groups_search(current->group_info, grp);
put_group_info(current->group_info);
}
return retval; return retval;
} }
...@@ -1166,8 +1335,11 @@ EXPORT_SYMBOL(in_group_p); ...@@ -1166,8 +1335,11 @@ EXPORT_SYMBOL(in_group_p);
int in_egroup_p(gid_t grp) int in_egroup_p(gid_t grp)
{ {
int retval = 1; int retval = 1;
if (grp != current->egid) if (grp != current->egid) {
retval = supplemental_group_member(grp); get_group_info(current->group_info);
retval = groups_search(current->group_info, grp);
put_group_info(current->group_info);
}
return retval; return retval;
} }
......
...@@ -107,45 +107,83 @@ asmlinkage long sys_setfsgid16(old_gid_t gid) ...@@ -107,45 +107,83 @@ asmlinkage long sys_setfsgid16(old_gid_t gid)
return sys_setfsgid((gid_t)gid); return sys_setfsgid((gid_t)gid);
} }
static int groups16_to_user(old_gid_t __user *grouplist,
struct group_info *group_info)
{
int i;
old_gid_t group;
for (i = 0; i < group_info->ngroups; i++) {
group = (old_gid_t)GROUP_AT(group_info, i);
if (put_user(group, grouplist+i))
return -EFAULT;
}
return 0;
}
static int groups16_from_user(struct group_info *group_info,
old_gid_t __user *grouplist)
{
int i;
old_gid_t group;
for (i = 0; i < group_info->ngroups; i++) {
if (get_user(group, grouplist+i))
return -EFAULT;
GROUP_AT(group_info, i) = (gid_t)group;
}
return 0;
}
asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist) asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist)
{ {
old_gid_t groups[NGROUPS]; int i = 0;
int i,j;
if (gidsetsize < 0) if (gidsetsize < 0)
return -EINVAL; return -EINVAL;
i = current->ngroups;
get_group_info(current->group_info);
i = current->group_info->ngroups;
if (gidsetsize) { if (gidsetsize) {
if (i > gidsetsize) if (i > gidsetsize) {
return -EINVAL; i = -EINVAL;
for(j=0;j<i;j++) goto out;
groups[j] = current->groups[j]; }
if (copy_to_user(grouplist, groups, sizeof(old_gid_t)*i)) if (groups16_to_user(grouplist, current->group_info)) {
return -EFAULT; i = -EFAULT;
goto out;
}
} }
out:
put_group_info(current->group_info);
return i; return i;
} }
asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist) asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist)
{ {
old_gid_t groups[NGROUPS]; struct group_info *group_info;
gid_t new_groups[NGROUPS]; int retval;
int i;
if (!capable(CAP_SETGID)) if (!capable(CAP_SETGID))
return -EPERM; return -EPERM;
if ((unsigned) gidsetsize > NGROUPS) if ((unsigned)gidsetsize > NGROUPS_MAX)
return -EINVAL; return -EINVAL;
if (copy_from_user(groups, grouplist, gidsetsize * sizeof(old_gid_t)))
return -EFAULT; group_info = groups_alloc(gidsetsize);
for (i = 0 ; i < gidsetsize ; i++) if (!group_info)
new_groups[i] = (gid_t)groups[i]; return -ENOMEM;
i = security_task_setgroups(gidsetsize, new_groups); retval = groups16_from_user(group_info, grouplist);
if (i) if (retval) {
return i; put_group_info(group_info);
memcpy(current->groups, new_groups, gidsetsize * sizeof(gid_t)); return retval;
current->ngroups = gidsetsize; }
return 0;
retval = set_current_groups(group_info);
put_group_info(group_info);
return retval;
} }
asmlinkage long sys_getuid16(void) asmlinkage long sys_getuid16(void)
......
...@@ -255,34 +255,41 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, ...@@ -255,34 +255,41 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
struct rpc_cred * struct rpc_cred *
rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) rpcauth_lookupcred(struct rpc_auth *auth, int taskflags)
{ {
struct auth_cred acred = { struct auth_cred acred;
.uid = current->fsuid, struct rpc_cred *ret;
.gid = current->fsgid,
.ngroups = current->ngroups, get_group_info(current->group_info);
.groups = current->groups, acred.uid = current->fsuid;
}; acred.gid = current->fsgid;
acred.group_info = current->group_info;
dprintk("RPC: looking up %s cred\n", dprintk("RPC: looking up %s cred\n",
auth->au_ops->au_name); auth->au_ops->au_name);
return rpcauth_lookup_credcache(auth, &acred, taskflags); ret = rpcauth_lookup_credcache(auth, &acred, taskflags);
put_group_info(current->group_info);
return ret;
} }
struct rpc_cred * struct rpc_cred *
rpcauth_bindcred(struct rpc_task *task) rpcauth_bindcred(struct rpc_task *task)
{ {
struct rpc_auth *auth = task->tk_auth; struct rpc_auth *auth = task->tk_auth;
struct auth_cred acred = { struct auth_cred acred;
.uid = current->fsuid, struct rpc_cred *ret;
.gid = current->fsgid,
.ngroups = current->ngroups, get_group_info(current->group_info);
.groups = current->groups, acred.uid = current->fsuid;
}; acred.gid = current->fsgid;
acred.group_info = current->group_info;
dprintk("RPC: %4d looking up %s cred\n", dprintk("RPC: %4d looking up %s cred\n",
task->tk_pid, task->tk_auth->au_ops->au_name); task->tk_pid, task->tk_auth->au_ops->au_name);
task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, &acred, task->tk_flags); task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, &acred, task->tk_flags);
if (task->tk_msg.rpc_cred == 0) if (task->tk_msg.rpc_cred == 0)
task->tk_status = -ENOMEM; task->tk_status = -ENOMEM;
return task->tk_msg.rpc_cred; ret = task->tk_msg.rpc_cred;
put_group_info(current->group_info);
return ret;
} }
void void
......
...@@ -82,7 +82,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) ...@@ -82,7 +82,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
cred->uc_gid = cred->uc_pgid = 0; cred->uc_gid = cred->uc_pgid = 0;
cred->uc_gids[0] = NOGROUP; cred->uc_gids[0] = NOGROUP;
} else { } else {
int groups = acred->ngroups; int groups = acred->group_info->ngroups;
if (groups > NFS_NGROUPS) if (groups > NFS_NGROUPS)
groups = NFS_NGROUPS; groups = NFS_NGROUPS;
...@@ -91,7 +91,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) ...@@ -91,7 +91,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
cred->uc_puid = current->uid; cred->uc_puid = current->uid;
cred->uc_pgid = current->gid; cred->uc_pgid = current->gid;
for (i = 0; i < groups; i++) for (i = 0; i < groups; i++)
cred->uc_gids[i] = (gid_t) acred->groups[i]; cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
if (i < NFS_NGROUPS) if (i < NFS_NGROUPS)
cred->uc_gids[i] = NOGROUP; cred->uc_gids[i] = NOGROUP;
} }
...@@ -126,11 +126,11 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags) ...@@ -126,11 +126,11 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags)
|| cred->uc_pgid != current->gid) || cred->uc_pgid != current->gid)
return 0; return 0;
groups = acred->ngroups; groups = acred->group_info->ngroups;
if (groups > NFS_NGROUPS) if (groups > NFS_NGROUPS)
groups = NFS_NGROUPS; groups = NFS_NGROUPS;
for (i = 0; i < groups ; i++) for (i = 0; i < groups ; i++)
if (cred->uc_gids[i] != (gid_t) acred->groups[i]) if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
return 0; return 0;
return 1; return 1;
} }
......
...@@ -434,11 +434,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp) ...@@ -434,11 +434,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, u32 *authp)
if (slen > 16 || (len -= (slen + 2)*4) < 0) if (slen > 16 || (len -= (slen + 2)*4) < 0)
goto badcred; goto badcred;
for (i = 0; i < slen; i++) for (i = 0; i < slen; i++)
if (i < NGROUPS) if (i < SVC_CRED_NGROUPS)
cred->cr_groups[i] = ntohl(svc_getu32(argv)); cred->cr_groups[i] = ntohl(svc_getu32(argv));
else else
svc_getu32(argv); svc_getu32(argv);
if (i < NGROUPS) if (i < SVC_CRED_NGROUPS)
cred->cr_groups[i] = NOGROUP; cred->cr_groups[i] = NOGROUP;
if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) { if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
......
...@@ -544,7 +544,7 @@ static int dummy_task_getsid (struct task_struct *p) ...@@ -544,7 +544,7 @@ static int dummy_task_getsid (struct task_struct *p)
return 0; return 0;
} }
static int dummy_task_setgroups (int gidsetsize, gid_t * grouplist) static int dummy_task_setgroups (struct group_info *group_info)
{ {
return 0; return 0;
} }
......
...@@ -2539,7 +2539,7 @@ static int selinux_task_getsid(struct task_struct *p) ...@@ -2539,7 +2539,7 @@ static int selinux_task_getsid(struct task_struct *p)
return task_has_perm(current, p, PROCESS__GETSESSION); return task_has_perm(current, p, PROCESS__GETSESSION);
} }
static int selinux_task_setgroups(int gidsetsize, gid_t *grouplist) static int selinux_task_setgroups(struct group_info *group_info)
{ {
/* See the comment for setuid above. */ /* See the comment for setuid above. */
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment