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
12 * afsDFS_SetPagInCred (shared with SGI)
13 * osi_DFSGetPagFromCred (shared with SGI)
14 * Afs_xsetgroups (syscall)
18 #include <afsconfig.h>
19 #include "afs/param.h"
22 #include "afs/sysincludes.h"
23 #include "afsincludes.h"
24 #include "afs/afs_stats.h" /* statistics */
28 afs_getgroups(struct ucred
*cred
, int ngroups
, gid_t
* gidset
);
31 afs_setgroups(struct ucred
**cred
, int ngroups
, gid_t
* gidset
,
35 /* This is common code between SGI's DFS and our AFS. Do *not* alter it's
36 * interface or semantics without notifying SGI.
39 /* fixup_pags returns error code if relevant or 0 on no error.
40 * Sets up the cred for the call to estgroups. This is pretty convoluted
41 * in order to avoid including the private proc.h header file.
44 fixup_pags(int **credpp
, int ngroups
, gid_t
* gidset
, int old_afs_pag
,
52 gid_t groups
[NGROUPS_UMAX
];
55 if (ngroups
< 0 || ngroups
> ngroups_max
)
59 AFS_COPYIN(gidset
, groups
, ngroups
* sizeof(gid_t
), code
);
64 if (ngroups
>= 2) { /* possibly an AFS PAG */
66 (afs_get_pag_from_groups(groups
[0], groups
[1]) != NOPAG
);
68 if (ngroups
>= 1) { /* possibly a DFS PAG */
69 new_dfs_pag
= (int)groups
[ngroups
- 1];
70 if (((new_dfs_pag
>> 24) & 0xff) == 'A')
71 new_dfs_pag
= (int)groups
[ngroups
- 1];
76 /* Now compute the number of groups we will need. */
78 if (old_afs_pag
&& !new_afs_pag
) /* prepend old AFS pag */
80 if (old_dfs_pag
&& !new_dfs_pag
) /* append old DFS pag */
83 if (new > ngroups_max
)
84 return EINVAL
; /* sorry */
86 cr
= crdup(OSI_GET_CURRENT_CRED()); /* we will replace all the groups. */
87 memset(&cr
->cr_groups
, 0, ngroups_max
* sizeof(gid_t
));
89 /* Now cobble the new groups list together. */
92 if (old_afs_pag
&& !new_afs_pag
) { /* prepend old AFS pag */
95 afs_get_groups_from_pag(old_afs_pag
, &g0
, &g1
);
96 cr
->cr_groups
[new++] = g0
;
97 cr
->cr_groups
[new++] = g1
;
100 for (old
= 0; old
< ngroups
; old
++)
101 cr
->cr_groups
[new++] = groups
[old
];
103 if (old_dfs_pag
&& !new_dfs_pag
) { /* append old DFS pag */
105 cr
->cr_groups
[new++] = old_dfs_pag
;
108 /* Now, did we do anything? */
110 cr
->cr_ngroups
= new;
120 * Generic routine to set the PAG in the cred for AFS and DFS.
121 * If flag = 0 this is a DFS pag held in one group.
122 * If flag = 1 this is a AFS pag held in two group entries
125 afsDFS_SetPagInCred(struct ucred
*credp
, int pag
, int flag
)
131 struct ucred
*newcredp
;
132 int groups_taken
= (flag
? 2 : 1);
134 ngrps
= credp
->cr_ngroups
+ groups_taken
;
135 if (ngrps
>= ngroups_max
)
140 /* Break out the AFS pag into two groups */
141 afs_get_groups_from_pag(pag
, &g0
, &g1
);
144 newcredp
= crdup(credp
);
145 newcredp
->cr_ngroups
= ngrps
;
149 newcredp
->cr_groups
[0] = g0
;
150 newcredp
->cr_groups
[1] = g1
;
153 if (PagInCred(newcredp
) != NOPAG
) {
154 /* found an AFS PAG is set in this cred */
157 newcredp
->cr_groups
[n
] = pag
;
159 for (i
= n
; i
< credp
->cr_ngroups
; i
++)
160 newcredp
->cr_groups
[i
+ groups_taken
] = credp
->cr_groups
[i
];
162 /* estgroups sets current threads cred from newcredp and crfree's credp */
163 estgroups(credp
, newcredp
);
167 #endif /* AFS_SGI65_ENV */
169 /* SGI's osi_GetPagFromCred - They return a long. */
171 osi_DFSGetPagFromCred(struct ucred
*credp
)
177 * For IRIX, the PAG is stored in the first entry
178 * of the gruop list in the cred structure. gid_t's
179 * are 32 bits on 64 bit and 32 bit hardware types.
180 * As of Irix 6.5, the DFS pag is the last group in the list.
182 ngroups
= credp
->cr_ngroups
;
186 * Keep in mind that we might be living with AFS here.
187 * This means we don't really know if our DFS PAG is in
188 * the first or third group entry.
191 pag
= credp
->cr_groups
[ngroups
- 1];
193 pag
= credp
->cr_groups
[0];
194 if (PagInCred(credp
) != NOPAG
) {
195 /* AFS has a PAG value in the first two group entries */
198 pag
= credp
->cr_groups
[2];
201 if (((pag
>> 24) & 0xff) == 'A')
208 Afs_xsetgroups(int ngroups
, gid_t
* gidset
)
210 int old_afs_pag
= NOPAG
;
211 int old_dfs_pag
= NOPAG
;
213 struct ucred
*credp
= OSI_GET_CURRENT_CRED();
214 struct ucred
*modcredp
;
217 credp
= OSI_GET_CURRENT_CRED();
218 /* First get any old PAG's */
219 old_afs_pag
= PagInCred(credp
);
220 old_dfs_pag
= osi_DFSGetPagFromCred(credp
);
222 /* Set the passed in group list. */
223 if (code
= setgroups(ngroups
, gidset
))
227 if (old_afs_pag
== NOPAG
&& old_dfs_pag
== NOPAG
)
230 /* Well, we could get the cred, except it's in the proc struct which
231 * is not a publicly available header. And the cred won't be valid on
232 * the uthread until we return to user space. So, we examine the passed
233 * in groups in fixup_pags.
236 fixup_pags(&modcredp
, ngroups
, gidset
,
237 (old_afs_pag
== NOPAG
) ? 0 : old_afs_pag
,
238 (old_dfs_pag
== NOPAG
) ? 0 : old_dfs_pag
);
239 if (!code
&& modcredp
)
240 estgroups(OSI_GET_CURRENT_PROCP(), modcredp
);
244 * The setgroups gave our curent thread a new cred pointer
245 * Get the value again
247 credp
= OSI_GET_CURRENT_CRED();
248 if ((PagInCred(credp
) == NOPAG
) && (old_afs_pag
!= NOPAG
)) {
249 /* reset the AFS PAG */
250 code
= afsDFS_SetPagInCred(credp
, old_afs_pag
, 1);
253 * Once again get the credp because the afsDFS_SetPagInCred might have
254 * assigned a new one.
256 credp
= OSI_GET_CURRENT_CRED();
257 if ((osi_DFSGetPagFromCred(credp
) == NOPAG
)
258 && (old_dfs_pag
!= NOPAG
)) {
259 code
= afsDFS_SetPagInCred(credp
, old_dfs_pag
, 0);
261 #endif /* AFS_SGI65_ENV */
267 setpag(cred
, pagvalue
, newpag
, change_parent
)
271 afs_uint32 change_parent
;
273 gid_t gidset
[NGROUPS
];
279 ngroups
= afs_getgroups(*cred
, NGROUPS
, gidset
);
280 if (afs_get_pag_from_groups(gidset
[0], gidset
[1]) == NOPAG
) {
281 /* We will have to shift grouplist to make room for pag */
282 if (ngroups
+ 2 > NGROUPS
) {
283 #if defined(KERNEL_HAVE_UERROR)
284 return (setuerror(E2BIG
), E2BIG
);
289 for (j
= ngroups
- 1; j
>= 0; j
--) {
290 gidset
[j
+ 2] = gidset
[j
];
294 *newpag
= (pagvalue
== -1 ? genpag() : pagvalue
);
295 afs_get_groups_from_pag(*newpag
, &gidset
[0], &gidset
[1]);
296 if (code
= afs_setgroups(cred
, ngroups
, gidset
, change_parent
)) {
297 #if defined(KERNEL_HAVE_UERROR)
298 return (setuerror(code
), code
);
308 afs_getgroups(struct ucred
*cred
, int ngroups
, gid_t
* gidset
)
310 int ngrps
, savengrps
;
313 gidset
[0] = gidset
[1] = 0;
314 AFS_STATCNT(afs_getgroups
);
315 savengrps
= ngrps
= MIN(ngroups
, cred
->cr_ngroups
);
316 gp
= cred
->cr_groups
;
325 afs_setgroups(struct ucred
**cred
, int ngroups
, gid_t
* gidset
,
331 AFS_STATCNT(afs_setgroups
);
333 if (ngroups
> ngroups_max
)
340 newcr
->cr_ngroups
= ngroups
;
341 gp
= newcr
->cr_groups
;
344 if (!change_parent
) {
346 estgroups(OSI_GET_CURRENT_PROCP(), newcr
);
348 estgroups(cr
, newcr
);