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"
21 #include "../afs/sysincludes.h"
22 #include "../afs/afsincludes.h"
23 #include "../afs/afs_stats.h" /* statistics */
24 #ifdef AFS_LINUX22_ENV
25 #include "../h/smp_lock.h"
28 static int afs_getgroups(cred_t *cr, gid_t *groups);
29 static int afs_setgroups(cred_t **cr, int ngroups, gid_t *gidset, int change_parent);
31 /* Only propogate the PAG to the parent process. Unix's propogate to
32 * all processes sharing the cred.
34 int set_pag_in_parent(int pag, int g0, int g1)
36 gid_t *gp = current->p_pptr->groups;
41 ngroups = current->p_pptr->ngroups;
42 gp = current->p_pptr->groups;
45 if ((ngroups < 2) || (afs_get_pag_from_groups(gp[0], gp[1]) == NOPAG)) {
46 /* We will have to shift grouplist to make room for pag */
47 if (ngroups + 2 > NGROUPS) {
50 for (i = ngroups-1; i >= 0; i--) {
57 if (ngroups < NGROUPS)
58 gp[ngroups] = NOGROUP;
60 current->p_pptr->ngroups = ngroups;
64 int setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag, int change_parent)
67 afs_int32 ngroups, code = 0;
72 gidset = (gid_t *) osi_Alloc(NGROUPS*sizeof(gidset[0]));
73 ngroups = afs_getgroups(*cr, gidset);
75 if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
76 /* We will have to shift grouplist to make room for pag */
77 if (ngroups + 2 > NGROUPS) {
78 osi_Free((char *)gidset, NGROUPS*sizeof(int));
81 for (j = ngroups - 1; j >= 0; j--) {
82 gidset[j+2] = gidset[j];
86 *newpag = (pagvalue == -1 ? genpag(): pagvalue);
87 afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
88 code = afs_setgroups(cr, ngroups, gidset, change_parent);
90 /* If change_parent is set, then we should set the pag in the parent as
93 if (change_parent && !code) {
94 code = set_pag_in_parent(*newpag, gidset[0], gidset[1]);
97 osi_Free((char *)gidset, NGROUPS*sizeof(int));
102 /* Intercept the standard system call. */
103 extern long (*sys_setgroupsp)(int gidsetsize, gid_t *grouplist);
104 asmlinkage long afs_xsetgroups(int gidsetsize, gid_t *grouplist)
107 cred_t *cr = crref();
112 old_pag = PagInCred(cr);
116 code = (*sys_setgroupsp)(gidsetsize, grouplist);
123 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
124 /* re-install old pag if there's room. */
125 code = setpag(&cr, old_pag, &junk, 0);
133 #if defined(AFS_LINUX24_ENV)
134 /* Intercept the standard uid32 system call. */
135 extern int (*sys_setgroups32p)(int gidsetsize, gid_t *grouplist);
136 asmlinkage int afs_xsetgroups32(int gidsetsize, gid_t *grouplist)
139 cred_t *cr = crref();
144 old_pag = PagInCred(cr);
148 code = (*sys_setgroups32p)(gidsetsize, grouplist);
155 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
156 /* re-install old pag if there's room. */
157 code = setpag(&cr, old_pag, &junk, 0);
166 #if defined(AFS_SPARC64_LINUX20_ENV)
167 /* Intercept the uid16 system call as used by 32bit programs. */
168 extern int (*sys32_setgroupsp)(int gidsetsize, __kernel_gid_t32 *grouplist);
169 asmlinkage int afs32_xsetgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
172 cred_t *cr = crref();
177 old_pag = PagInCred(cr);
181 code = (*sys32_setgroupsp)(gidsetsize, grouplist);
188 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
189 /* re-install old pag if there's room. */
190 code = setpag(&cr, old_pag, &junk, 0);
197 #ifdef AFS_LINUX24_ENV
198 /* Intercept the uid32 system call as used by 32bit programs. */
199 extern int (*sys32_setgroups32p)(int gidsetsize, __kernel_gid_t32 *grouplist);
200 asmlinkage int afs32_xsetgroups32(int gidsetsize, __kernel_gid_t32 *grouplist)
203 cred_t *cr = crref();
208 old_pag = PagInCred(cr);
212 code = (*sys32_setgroups32p)(gidsetsize, grouplist);
219 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
220 /* re-install old pag if there's room. */
221 code = setpag(&cr, old_pag, &junk, 0);
231 static int afs_setgroups(cred_t **cr, int ngroups, gid_t *gidset, int change_parent)
237 AFS_STATCNT(afs_setgroups);
239 if (ngroups > NGROUPS)
242 gp = (*cr)->cr_groups;
243 if (ngroups < NGROUPS)
244 gp[ngroups] = (gid_t)NOGROUP;
246 for (i = ngroups; i > 0; i--) {
250 (*cr)->cr_ngroups = ngroups;
255 /* Returns number of groups. And we trust groups to be large enough to
256 * hold all the groups.
258 static int afs_getgroups(cred_t *cr, gid_t *groups)
261 gid_t *gp = cr->cr_groups;
262 int n = cr->cr_ngroups;
263 AFS_STATCNT(afs_getgroups);
265 for (i = 0; (i < n) && (*gp != (gid_t)NOGROUP); i++) {