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"
18 #ifdef LINUX_KEYRING_SUPPORT
19 #include <linux/seq_file.h>
23 #include "afs/sysincludes.h"
24 #include "afsincludes.h"
25 #include "afs/afs_stats.h" /* statistics */
26 #include "afs/nfsclient.h"
27 #ifdef AFS_LINUX22_ENV
28 #include "h/smp_lock.h"
31 #define NUMPAGGROUPS 2
34 afs_setgroups(cred_t **cr, int ngroups, gid_t * gidset, int change_parent)
40 AFS_STATCNT(afs_setgroups);
42 if (ngroups > NGROUPS)
45 gp = (*cr)->cr_groups;
46 if (ngroups < NGROUPS)
47 gp[ngroups] = (gid_t) NOGROUP;
49 for (i = ngroups; i > 0; i--) {
53 (*cr)->cr_ngroups = ngroups;
58 /* Returns number of groups. And we trust groups to be large enough to
59 * hold all the groups.
62 afs_getgroups(cred_t *cr, gid_t *groups)
68 AFS_STATCNT(afs_getgroups);
73 for (i = 0; (i < n) && (*gp != (gid_t) NOGROUP); i++)
78 /* Only propogate the PAG to the parent process. Unix's propogate to
79 * all processes sharing the cred.
82 set_pag_in_parent(int pag, int g0, int g1)
85 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
86 gid_t *gp = current->parent->groups;
87 int ngroups = current->parent->ngroups;
89 gid_t *gp = current->p_pptr->groups;
90 int ngroups = current->p_pptr->ngroups;
93 if ((ngroups < 2) || (afs_get_pag_from_groups(gp[0], gp[1]) == NOPAG)) {
94 /* We will have to shift grouplist to make room for pag */
95 if (ngroups + 2 > NGROUPS) {
98 for (i = ngroups - 1; i >= 0; i--) {
105 if (ngroups < NGROUPS)
106 gp[ngroups] = NOGROUP;
108 #ifdef STRUCT_TASK_STRUCT_HAS_PARENT
109 current->parent->ngroups = ngroups;
111 current->p_pptr->ngroups = ngroups;
117 __setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
121 afs_int32 ngroups, code = 0;
124 gidset = (gid_t *) osi_Alloc(NGROUPS * sizeof(gidset[0]));
125 ngroups = afs_getgroups(*cr, gidset);
127 if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) {
128 /* We will have to shift grouplist to make room for pag */
129 if (ngroups + 2 > NGROUPS) {
130 osi_Free((char *)gidset, NGROUPS * sizeof(int));
133 for (j = ngroups - 1; j >= 0; j--) {
134 gidset[j + 2] = gidset[j];
138 *newpag = (pagvalue == -1 ? genpag() : pagvalue);
139 afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]);
140 code = afs_setgroups(cr, ngroups, gidset, change_parent);
142 /* If change_parent is set, then we should set the pag in the parent as
145 if (change_parent && !code) {
146 code = set_pag_in_parent(*newpag, gidset[0], gidset[1]);
149 osi_Free((char *)gidset, NGROUPS * sizeof(int));
154 setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
161 code = __setpag(cr, pagvalue, newpag, change_parent);
167 /* Intercept the standard system call. */
168 extern asmlinkage long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist);
170 afs_xsetgroups(int gidsetsize, gid_t * grouplist)
173 cred_t *cr = crref();
178 old_pag = PagInCred(cr);
182 code = (*sys_setgroupsp) (gidsetsize, grouplist);
189 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
190 /* re-install old pag if there's room. */
191 code = __setpag(&cr, old_pag, &junk, 0);
196 /* Linux syscall ABI returns errno as negative */
200 #if defined(AFS_LINUX24_ENV)
201 /* Intercept the standard uid32 system call. */
202 extern asmlinkage long (*sys_setgroups32p) (int gidsetsize, gid_t * grouplist);
204 afs_xsetgroups32(int gidsetsize, gid_t * grouplist)
207 cred_t *cr = crref();
212 old_pag = PagInCred(cr);
216 code = (*sys_setgroups32p) (gidsetsize, grouplist);
224 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
225 /* re-install old pag if there's room. */
226 code = __setpag(&cr, old_pag, &junk, 0);
231 /* Linux syscall ABI returns errno as negative */
236 #if defined(AFS_PPC64_LINUX20_ENV)
237 /* Intercept the uid16 system call as used by 32bit programs. */
238 extern long (*sys32_setgroupsp)(int gidsetsize, gid_t *grouplist);
239 asmlinkage long afs32_xsetgroups(int gidsetsize, gid_t *grouplist)
242 cred_t *cr = crref();
247 old_pag = PagInCred(cr);
251 code = (*sys32_setgroupsp)(gidsetsize, grouplist);
258 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
259 /* re-install old pag if there's room. */
260 code = __setpag(&cr, old_pag, &junk, 0);
265 /* Linux syscall ABI returns errno as negative */
270 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_AMD64_LINUX20_ENV)
271 /* Intercept the uid16 system call as used by 32bit programs. */
272 extern long (*sys32_setgroupsp) (int gidsetsize, u16 * grouplist);
274 afs32_xsetgroups(int gidsetsize, u16 * grouplist)
277 cred_t *cr = crref();
282 old_pag = PagInCred(cr);
286 code = (*sys32_setgroupsp) (gidsetsize, grouplist);
293 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
294 /* re-install old pag if there's room. */
295 code = __setpag(&cr, old_pag, &junk, 0);
300 /* Linux syscall ABI returns errno as negative */
304 #ifdef AFS_LINUX24_ENV
305 /* Intercept the uid32 system call as used by 32bit programs. */
306 extern long (*sys32_setgroups32p) (int gidsetsize, gid_t * grouplist);
308 afs32_xsetgroups32(int gidsetsize, gid_t * grouplist)
311 cred_t *cr = crref();
316 old_pag = PagInCred(cr);
320 code = (*sys32_setgroups32p) (gidsetsize, grouplist);
327 if (old_pag != NOPAG && PagInCred(cr) == NOPAG) {
328 /* re-install old pag if there's room. */
329 code = __setpag(&cr, old_pag, &junk, 0);
334 /* Linux syscall ABI returns errno as negative */