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 "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 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
37 gid_t *gp = current->parent->groups;
39 gid_t *gp = current->p_pptr->groups;
45 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
46 ngroups = current->parent->ngroups;
48 ngroups = current->p_pptr->ngroups;
51 if ((ngroups < 2) || (afs_get_pag_from_groups(gp[0], gp[1]) == NOPAG)) {
52 /* We will have to shift grouplist to make room for pag */
53 if (ngroups + 2 > NGROUPS) {
56 for (i = ngroups-1; i >= 0; i--) {
63 if (ngroups < NGROUPS)
64 gp[ngroups] = NOGROUP;
66 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
67 current->parent->ngroups = ngroups;
69 current->p_pptr->ngroups = ngroups;
74 int setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag, int change_parent)
77 afs_int32 ngroups, code = 0;
82 gidset = (gid_t *) osi_Alloc(NGROUPS*sizeof(gidset[0]));
83 ngroups = afs_getgroups(*cr, gidset);
85 if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
86 /* We will have to shift grouplist to make room for pag */
87 if (ngroups + 2 > NGROUPS) {
88 osi_Free((char *)gidset, NGROUPS*sizeof(int));
91 for (j = ngroups - 1; j >= 0; j--) {
92 gidset[j+2] = gidset[j];
96 *newpag = (pagvalue == -1 ? genpag(): pagvalue);
97 afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
98 code = afs_setgroups(cr, ngroups, gidset, change_parent);
100 /* If change_parent is set, then we should set the pag in the parent as
103 if (change_parent && !code) {
104 code = set_pag_in_parent(*newpag, gidset[0], gidset[1]);
107 osi_Free((char *)gidset, NGROUPS*sizeof(int));
112 /* Intercept the standard system call. */
113 extern long (*sys_setgroupsp)(int gidsetsize, gid_t *grouplist);
114 asmlinkage long afs_xsetgroups(int gidsetsize, gid_t *grouplist)
117 cred_t *cr = crref();
122 old_pag = PagInCred(cr);
126 code = (*sys_setgroupsp)(gidsetsize, grouplist);
133 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
134 /* re-install old pag if there's room. */
135 code = setpag(&cr, old_pag, &junk, 0);
143 #if defined(AFS_LINUX24_ENV)
144 /* Intercept the standard uid32 system call. */
145 extern int (*sys_setgroups32p)(int gidsetsize, gid_t *grouplist);
146 asmlinkage int afs_xsetgroups32(int gidsetsize, gid_t *grouplist)
149 cred_t *cr = crref();
154 old_pag = PagInCred(cr);
158 code = (*sys_setgroups32p)(gidsetsize, grouplist);
165 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
166 /* re-install old pag if there's room. */
167 code = setpag(&cr, old_pag, &junk, 0);
176 #if defined(AFS_SPARC64_LINUX20_ENV)
177 /* Intercept the uid16 system call as used by 32bit programs. */
178 extern int (*sys32_setgroupsp)(int gidsetsize, __kernel_gid_t32 *grouplist);
179 asmlinkage int afs32_xsetgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
182 cred_t *cr = crref();
187 old_pag = PagInCred(cr);
191 code = (*sys32_setgroupsp)(gidsetsize, grouplist);
198 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
199 /* re-install old pag if there's room. */
200 code = setpag(&cr, old_pag, &junk, 0);
207 #ifdef AFS_LINUX24_ENV
208 /* Intercept the uid32 system call as used by 32bit programs. */
209 extern int (*sys32_setgroups32p)(int gidsetsize, __kernel_gid_t32 *grouplist);
210 asmlinkage int afs32_xsetgroups32(int gidsetsize, __kernel_gid_t32 *grouplist)
213 cred_t *cr = crref();
218 old_pag = PagInCred(cr);
222 code = (*sys32_setgroups32p)(gidsetsize, grouplist);
229 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
230 /* re-install old pag if there's room. */
231 code = setpag(&cr, old_pag, &junk, 0);
241 static int afs_setgroups(cred_t **cr, int ngroups, gid_t *gidset, int change_parent)
247 AFS_STATCNT(afs_setgroups);
249 if (ngroups > NGROUPS)
252 gp = (*cr)->cr_groups;
253 if (ngroups < NGROUPS)
254 gp[ngroups] = (gid_t)NOGROUP;
256 for (i = ngroups; i > 0; i--) {
260 (*cr)->cr_ngroups = ngroups;
265 /* Returns number of groups. And we trust groups to be large enough to
266 * hold all the groups.
268 static int afs_getgroups(cred_t *cr, gid_t *groups)
271 gid_t *gp = cr->cr_groups;
272 int n = cr->cr_ngroups;
273 AFS_STATCNT(afs_getgroups);
275 for (i = 0; (i < n) && (*gp != (gid_t)NOGROUP); i++) {