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 <afsconfig.h>
17 #include "afs/param.h"
22 #include "afs/sysincludes.h"
23 #include "afsincludes.h"
24 #include "afs/afs_stats.h" /* statistics */
25 #ifdef AFS_LINUX22_ENV
26 #include "h/smp_lock.h"
29 static int afs_getgroups(cred_t * cr, gid_t * groups);
30 static int afs_setgroups(cred_t ** cr, int ngroups, gid_t * gidset,
33 /* Only propogate the PAG to the parent process. Unix's propogate to
34 * all processes sharing the cred.
37 set_pag_in_parent(int pag, int g0, int g1)
39 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
40 gid_t *gp = current->parent->groups;
42 gid_t *gp = current->p_pptr->groups;
48 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
49 ngroups = current->parent->ngroups;
51 ngroups = current->p_pptr->ngroups;
54 if ((ngroups < 2) || (afs_get_pag_from_groups(gp[0], gp[1]) == NOPAG)) {
55 /* We will have to shift grouplist to make room for pag */
56 if (ngroups + 2 > NGROUPS) {
59 for (i = ngroups - 1; i >= 0; i--) {
66 if (ngroups < NGROUPS)
67 gp[ngroups] = NOGROUP;
69 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
70 current->parent->ngroups = ngroups;
72 current->p_pptr->ngroups = ngroups;
78 setpag(cred_t ** cr, afs_uint32 pagvalue, afs_uint32 * newpag,
82 afs_int32 ngroups, code = 0;
87 gidset = (gid_t *) osi_Alloc(NGROUPS * sizeof(gidset[0]));
88 ngroups = afs_getgroups(*cr, gidset);
90 if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
91 /* We will have to shift grouplist to make room for pag */
92 if (ngroups + 2 > NGROUPS) {
93 osi_Free((char *)gidset, NGROUPS * sizeof(int));
96 for (j = ngroups - 1; j >= 0; j--) {
97 gidset[j + 2] = gidset[j];
101 *newpag = (pagvalue == -1 ? genpag() : pagvalue);
102 afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
103 code = afs_setgroups(cr, ngroups, gidset, change_parent);
105 /* If change_parent is set, then we should set the pag in the parent as
108 if (change_parent && !code) {
109 code = set_pag_in_parent(*newpag, gidset[0], gidset[1]);
112 osi_Free((char *)gidset, NGROUPS * sizeof(int));
117 /* Intercept the standard system call. */
118 extern long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
120 afs_xsetgroups(int gidsetsize, gid_t * grouplist)
123 cred_t *cr = crref();
128 old_pag = PagInCred(cr);
132 code = (*sys_setgroupsp) (gidsetsize, grouplist);
139 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
140 /* re-install old pag if there's room. */
141 code = setpag(&cr, old_pag, &junk, 0);
146 /* Linux syscall ABI returns errno as negative */
150 #if defined(AFS_LINUX24_ENV)
151 /* Intercept the standard uid32 system call. */
152 extern long (*sys_setgroups32p) (int gidsetsize, gid_t * grouplist);
154 afs_xsetgroups32(int gidsetsize, gid_t * grouplist)
157 cred_t *cr = crref();
162 old_pag = PagInCred(cr);
166 code = (*sys_setgroups32p) (gidsetsize, grouplist);
174 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
175 /* re-install old pag if there's room. */
176 code = setpag(&cr, old_pag, &junk, 0);
181 /* Linux syscall ABI returns errno as negative */
186 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_AMD64_LINUX20_ENV)
187 /* Intercept the uid16 system call as used by 32bit programs. */
188 extern long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
190 afs32_xsetgroups(int gidsetsize, u16 * grouplist)
193 cred_t *cr = crref();
198 old_pag = PagInCred(cr);
202 code = (*sys32_setgroupsp) (gidsetsize, grouplist);
209 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
210 /* re-install old pag if there's room. */
211 code = setpag(&cr, old_pag, &junk, 0);
216 /* Linux syscall ABI returns errno as negative */
220 #ifdef AFS_LINUX24_ENV
221 /* Intercept the uid32 system call as used by 32bit programs. */
222 extern long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
224 afs32_xsetgroups32(int gidsetsize, gid_t * grouplist)
227 cred_t *cr = crref();
232 old_pag = PagInCred(cr);
236 code = (*sys32_setgroups32p) (gidsetsize, grouplist);
243 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
244 /* re-install old pag if there's room. */
245 code = setpag(&cr, old_pag, &junk, 0);
250 /* Linux syscall ABI returns errno as negative */
257 afs_setgroups(cred_t ** cr, int ngroups, gid_t * gidset, int change_parent)
263 AFS_STATCNT(afs_setgroups);
265 if (ngroups > NGROUPS)
268 gp = (*cr)->cr_groups;
269 if (ngroups < NGROUPS)
270 gp[ngroups] = (gid_t) NOGROUP;
272 for (i = ngroups; i > 0; i--) {
276 (*cr)->cr_ngroups = ngroups;
281 /* Returns number of groups. And we trust groups to be large enough to
282 * hold all the groups.
285 afs_getgroups(cred_t * cr, gid_t * groups)
288 gid_t *gp = cr->cr_groups;
289 int n = cr->cr_ngroups;
290 AFS_STATCNT(afs_getgroups);
292 for (i = 0; (i < n) && (*gp != (gid_t) NOGROUP); i++) {