Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
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 | |
8 | */ | |
9 | ||
10 | /* | |
11 | * Implements: | |
12 | * setgroups (syscall) | |
13 | * setpag | |
14 | * | |
15 | */ | |
16 | #include <afsconfig.h> | |
17 | #include "afs/param.h" | |
18 | ||
19 | ||
20 | #include "afs/sysincludes.h" | |
21 | #include "afsincludes.h" | |
22 | #include "afs/afs_stats.h" /* statistics */ | |
23 | ||
24 | static int | |
25 | afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset); | |
26 | ||
27 | static int | |
28 | afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset, | |
29 | int change_parent); | |
30 | ||
31 | int | |
32 | Afs_xsetgroups() | |
33 | { | |
34 | int code = 0; | |
35 | struct vrequest treq; | |
36 | ||
37 | AFS_STATCNT(afs_xsetgroups); | |
38 | AFS_GLOCK(); | |
39 | code = afs_InitReq(&treq, p_cred(u.u_procp)); | |
40 | AFS_GUNLOCK(); | |
41 | if (code) | |
42 | return code; | |
43 | setgroups(); | |
44 | ||
45 | /* Note that if there is a pag already in the new groups we don't | |
46 | * overwrite it with the old pag. | |
47 | */ | |
48 | if (PagInCred(p_cred(u.u_procp)) == NOPAG) { | |
49 | if (((treq.uid >> 24) & 0xff) == 'A') { | |
50 | struct ucred *cred; | |
51 | AFS_GLOCK(); | |
52 | /* we've already done a setpag, so now we redo it */ | |
53 | cred = p_cred(u.u_procp); | |
54 | AddPag(treq.uid, &cred); | |
55 | AFS_GUNLOCK(); | |
56 | } | |
57 | } | |
58 | return code; | |
59 | } | |
60 | ||
61 | int | |
62 | setpag(cred, pagvalue, newpag, change_parent) | |
63 | struct ucred **cred; | |
64 | afs_uint32 pagvalue; | |
65 | afs_uint32 *newpag; | |
66 | afs_uint32 change_parent; | |
67 | { | |
68 | gid_t gidset[NGROUPS]; | |
69 | int ngroups, code; | |
70 | int j; | |
71 | ||
72 | AFS_STATCNT(setpag); | |
73 | ngroups = afs_getgroups(*cred, NGROUPS, gidset); | |
74 | if (afs_get_pag_from_groups(gidset[0], gidset[1]) == NOPAG) { | |
75 | /* We will have to shift grouplist to make room for pag */ | |
76 | if (ngroups + 2 > NGROUPS) { | |
77 | return (setuerror(E2BIG), E2BIG); | |
78 | } | |
79 | for (j = ngroups - 1; j >= 0; j--) { | |
80 | gidset[j + 2] = gidset[j]; | |
81 | } | |
82 | ngroups += 2; | |
83 | } | |
84 | *newpag = (pagvalue == -1 ? genpag() : pagvalue); | |
85 | afs_get_groups_from_pag(*newpag, &gidset[0], &gidset[1]); | |
86 | ||
87 | if (code = afs_setgroups(cred, ngroups, gidset, change_parent)) { | |
88 | return (setuerror(code), code); | |
89 | } | |
90 | return code; | |
91 | } | |
92 | ||
93 | ||
94 | static int | |
95 | afs_getgroups(struct ucred *cred, int ngroups, gid_t * gidset) | |
96 | { | |
97 | int ngrps, savengrps; | |
98 | int *gp; | |
99 | ||
100 | gidset[0] = gidset[1] = 0; | |
101 | AFS_STATCNT(afs_getgroups); | |
102 | ||
103 | for (gp = &cred->cr_groups[NGROUPS]; gp > cred->cr_groups; gp--) { | |
104 | if (gp[-1] != NOGROUP) | |
105 | break; | |
106 | } | |
107 | savengrps = ngrps = MIN(ngroups, gp - cred->cr_groups); | |
108 | for (gp = cred->cr_groups; ngrps--;) | |
109 | *gidset++ = *gp++; | |
110 | return savengrps; | |
111 | } | |
112 | ||
113 | ||
114 | ||
115 | static int | |
116 | afs_setgroups(struct ucred **cred, int ngroups, gid_t * gidset, | |
117 | int change_parent) | |
118 | { | |
119 | int ngrps; | |
120 | int i; | |
121 | int *gp; | |
122 | struct ucred *newcr; | |
123 | ulong_t s; | |
124 | #if defined(AFS_HPUX110_ENV) | |
125 | ulong_t context; | |
126 | #endif | |
127 | ||
128 | AFS_STATCNT(afs_setgroups); | |
129 | ||
130 | if (!change_parent) { | |
131 | newcr = (struct ucred *)crdup(*cred); | |
132 | /* nobody else has the pointer to newcr because we | |
133 | ** just allocated it, so no need for locking */ | |
134 | } else { | |
135 | /* somebody else might have a pointer to this structure. | |
136 | ** make sure we do not have a race condition */ | |
137 | newcr = *cred; | |
138 | #if defined(AFS_HPUX110_ENV) | |
139 | /* all of the uniprocessor spinlocks are not defined. */ | |
140 | /* I assume the UP and MP are now handled together */ | |
141 | MP_SPINLOCK_USAV(cred_lock, context); | |
142 | #else | |
143 | s = UP_SPL6(); | |
144 | SPINLOCK(cred_lock); | |
145 | #endif | |
146 | } | |
147 | ||
148 | ||
149 | /* copy the group info */ | |
150 | gp = newcr->cr_groups; | |
151 | while (ngroups--) | |
152 | *gp++ = *gidset++; | |
153 | for (; gp < &(newcr)->cr_groups[NGROUPS]; gp++) | |
154 | *gp = ((gid_t) - 1); | |
155 | ||
156 | if (!change_parent) { | |
157 | /* replace the new cred structure in the proc area */ | |
158 | struct ucred *tmp; | |
159 | tmp = *cred; | |
160 | set_p_cred(u.u_procp, newcr); | |
161 | crfree(tmp); | |
162 | } else { | |
163 | #if defined(AFS_HPUX110_ENV) | |
164 | MP_SPINUNLOCK_USAV(cred_lock, context); | |
165 | #else | |
166 | (void)UP_SPLX(s); | |
167 | SPINUNLOCK(cred_lock); | |
168 | #endif | |
169 | } | |
170 | ||
171 | return (setuerror(0), 0); | |
172 | } |