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 <afsconfig.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 (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 int (*sys_setgroupsp)(int gidsetsize, gid_t *grouplist);
104 asmlinkage int 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);
165 #if defined(AFS_SPARC64_LINUX20_ENV)
166 asmlinkage int afs32_xsetgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
170 mm_segment_t old_fs = get_fs ();
172 if ((unsigned) gidsetsize > NGROUPS)
174 for (i = 0; i < gidsetsize; i++, grouplist++)
175 if (__get_user (gl[i], grouplist))
178 ret = afs_xsetgroups(gidsetsize, gl);
182 #ifdef AFS_LINUX24_ENV
183 asmlinkage int afs32_xsetgroups32(int gidsetsize, __kernel_gid_t32 *grouplist)
187 mm_segment_t old_fs = get_fs ();
189 if ((unsigned) gidsetsize > NGROUPS)
191 for (i = 0; i < gidsetsize; i++, grouplist++)
192 if (__get_user (gl[i], grouplist))
195 ret = afs_xsetgroups32(gidsetsize, gl);
202 static int afs_setgroups(cred_t **cr, int ngroups, gid_t *gidset, int change_parent)
208 AFS_STATCNT(afs_setgroups);
210 if (ngroups > NGROUPS)
213 gp = (*cr)->cr_groups;
214 if (ngroups < NGROUPS)
215 gp[ngroups] = (gid_t)NOGROUP;
217 for (i = ngroups; i > 0; i--) {
221 (*cr)->cr_ngroups = ngroups;
226 /* Returns number of groups. And we trust groups to be large enough to
227 * hold all the groups.
229 static int afs_getgroups(cred_t *cr, gid_t *groups)
232 gid_t *gp = cr->cr_groups;
233 int n = cr->cr_ngroups;
234 AFS_STATCNT(afs_getgroups);
236 for (i = 0; (i < n) && (*gp != (gid_t)NOGROUP); i++) {