2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
16 #include "../afs/param.h"
17 #include "../afs/sysincludes.h"
18 #include "../afs/afsincludes.h"
19 #include "../afs/afs_stats.h" /* statistics */
20 #ifdef AFS_LINUX22_ENV
21 #include "../h/smp_lock.h"
24 static int afs_getgroups(cred_t *cr, gid_t *groups);
25 static int afs_setgroups(cred_t **cr, int ngroups, gid_t *gidset, int change_parent);
27 /* Only propogate the PAG to the parent process. Unix's propogate to
28 * all processes sharing the cred.
30 int set_pag_in_parent(int pag, int g0, int g1)
32 gid_t *gp = current->p_pptr->groups;
37 ngroups = current->p_pptr->ngroups;
38 gp = current->p_pptr->groups;
41 if (afs_get_pag_from_groups(gp[0], gp[1]) == NOPAG) {
42 /* We will have to shift grouplist to make room for pag */
43 if (ngroups + 2 > NGROUPS) {
46 for (i = ngroups-1; i >= 0; i--) {
53 if (ngroups < NGROUPS)
54 gp[ngroups] = NOGROUP;
56 current->p_pptr->ngroups = ngroups;
60 int setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag, int change_parent)
63 afs_int32 ngroups, code = 0;
68 gidset = (gid_t *) osi_Alloc(NGROUPS*sizeof(gidset[0]));
69 ngroups = afs_getgroups(*cr, gidset);
71 if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
72 /* We will have to shift grouplist to make room for pag */
73 if (ngroups + 2 > NGROUPS) {
74 osi_Free((char *)gidset, NGROUPS*sizeof(int));
77 for (j = ngroups - 1; j >= 0; j--) {
78 gidset[j+2] = gidset[j];
82 *newpag = (pagvalue == -1 ? genpag(): pagvalue);
83 afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
84 code = afs_setgroups(cr, ngroups, gidset, change_parent);
86 /* If change_parent is set, then we should set the pag in the parent as
89 if (change_parent && !code) {
90 code = set_pag_in_parent(*newpag, gidset[0], gidset[1]);
93 osi_Free((char *)gidset, NGROUPS*sizeof(int));
98 /* Intercept the standard system call. */
99 extern int (*sys_setgroupsp)(int gidsetsize, gid_t *grouplist);
100 asmlinkage int afs_xsetgroups(int gidsetsize, gid_t *grouplist)
103 cred_t *cr = crref();
108 old_pag = PagInCred(cr);
112 code = (*sys_setgroupsp)(gidsetsize, grouplist);
119 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
120 /* re-install old pag if there's room. */
121 code = setpag(&cr, old_pag, &junk, 0);
129 static int afs_setgroups(cred_t **cr, int ngroups, gid_t *gidset, int change_parent)
135 AFS_STATCNT(afs_setgroups);
137 if (ngroups > NGROUPS)
140 gp = (*cr)->cr_groups;
141 if (ngroups < NGROUPS)
142 gp[ngroups] = (gid_t)NOGROUP;
144 for (i = ngroups; i > 0; i--) {
148 (*cr)->cr_ngroups = ngroups;
153 /* Returns number of groups. And we trust groups to be large enough to
154 * hold all the groups.
156 static int afs_getgroups(cred_t *cr, gid_t *groups)
159 gid_t *gp = cr->cr_groups;
160 int n = cr->cr_ngroups;
161 AFS_STATCNT(afs_getgroups);
163 for (i = 0; (i < n) && (*gp != (gid_t)NOGROUP); i++) {