]>
Commit | Line | Data |
---|---|---|
716154c5 BB |
1 | /*****************************************************************************\ |
2 | * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. | |
3 | * Copyright (C) 2007 The Regents of the University of California. | |
4 | * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). | |
5 | * Written by Brian Behlendorf <behlendorf1@llnl.gov>. | |
ec7d53e9 BB |
6 | * UCRL-CODE-235197 |
7 | * | |
716154c5 | 8 | * This file is part of the SPL, Solaris Porting Layer. |
3d6af2dd | 9 | * For details, see <http://zfsonlinux.org/>. |
ec7d53e9 | 10 | * |
716154c5 BB |
11 | * The SPL is free software; you can redistribute it and/or modify it |
12 | * under the terms of the GNU General Public License as published by the | |
13 | * Free Software Foundation; either version 2 of the License, or (at your | |
14 | * option) any later version. | |
15 | * | |
16 | * The SPL is distributed in the hope that it will be useful, but WITHOUT | |
ec7d53e9 BB |
17 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
18 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
19 | * for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License along | |
716154c5 BB |
22 | * with the SPL. If not, see <http://www.gnu.org/licenses/>. |
23 | ***************************************************************************** | |
24 | * Solaris Porting Layer (SPL) Credential Implementation. | |
25 | \*****************************************************************************/ | |
ec7d53e9 BB |
26 | |
27 | #include <sys/cred.h> | |
28 | ||
29 | #ifdef DEBUG_SUBSYSTEM | |
30 | #undef DEBUG_SUBSYSTEM | |
31 | #endif | |
32 | ||
33 | #define DEBUG_SUBSYSTEM S_CRED | |
34 | ||
35 | #ifdef HAVE_GROUPS_SEARCH | |
36 | /* Symbol may be exported by custom kernel patch */ | |
37 | #define cr_groups_search(gi, grp) groups_search(gi, grp) | |
38 | #else | |
39 | /* Implementation from 2.6.30 kernel */ | |
40 | static int | |
80093b6f AX |
41 | #ifdef HAVE_KUIDGID_T |
42 | cr_groups_search(const struct group_info *group_info, kgid_t grp) | |
43 | #else | |
ec7d53e9 | 44 | cr_groups_search(const struct group_info *group_info, gid_t grp) |
80093b6f | 45 | #endif |
ec7d53e9 | 46 | { |
9e4fb5c2 LG |
47 | unsigned int left, right, mid; |
48 | int cmp; | |
ec7d53e9 BB |
49 | |
50 | if (!group_info) | |
51 | return 0; | |
52 | ||
53 | left = 0; | |
54 | right = group_info->ngroups; | |
55 | while (left < right) { | |
9e4fb5c2 LG |
56 | mid = (left + right) / 2; |
57 | cmp = KGID_TO_SGID(grp) - | |
58 | KGID_TO_SGID(GROUP_AT(group_info, mid)); | |
59 | ||
ec7d53e9 BB |
60 | if (cmp > 0) |
61 | left = mid + 1; | |
62 | else if (cmp < 0) | |
63 | right = mid; | |
64 | else | |
65 | return 1; | |
66 | } | |
67 | return 0; | |
68 | } | |
69 | #endif | |
70 | ||
71 | #ifdef HAVE_CRED_STRUCT | |
72 | ||
73 | /* | |
74 | * As of 2.6.29 a clean credential API appears in the linux kernel. | |
75 | * We attempt to layer the Solaris API on top of the linux API. | |
76 | */ | |
77 | ||
78 | /* Hold a reference on the credential and group info */ | |
79 | void | |
80 | crhold(cred_t *cr) | |
81 | { | |
82 | (void)get_cred((const cred_t *)cr); | |
83 | (void)get_group_info(cr->group_info); | |
84 | } | |
85 | ||
86 | /* Free a reference on the credential and group info */ | |
87 | void | |
88 | crfree(cred_t *cr) | |
89 | { | |
90 | put_group_info(cr->group_info); | |
91 | put_cred((const cred_t *)cr); | |
92 | } | |
93 | ||
ec7d53e9 BB |
94 | /* Return the number of supplemental groups */ |
95 | int | |
96 | crgetngroups(const cred_t *cr) | |
97 | { | |
98 | struct group_info *gi; | |
99 | int rc; | |
100 | ||
101 | gi = get_group_info(cr->group_info); | |
102 | rc = gi->ngroups; | |
103 | put_group_info(gi); | |
104 | ||
105 | return rc; | |
106 | } | |
107 | ||
108 | /* | |
109 | * Return an array of supplemental gids. The returned address is safe | |
110 | * to use as long as the caller has taken a reference with crhold(). | |
111 | * The caller is responsible for releasing the reference with crfree(). | |
112 | */ | |
113 | gid_t * | |
114 | crgetgroups(const cred_t *cr) | |
115 | { | |
116 | struct group_info *gi; | |
117 | gid_t *gids; | |
118 | ||
119 | gi = get_group_info(cr->group_info); | |
80093b6f | 120 | gids = KGIDP_TO_SGIDP(gi->blocks[0]); |
ec7d53e9 BB |
121 | put_group_info(gi); |
122 | ||
123 | return gids; | |
124 | } | |
125 | ||
9e4fb5c2 | 126 | /* Check if the passed gid is available in supplied credential. */ |
ec7d53e9 BB |
127 | int |
128 | groupmember(gid_t gid, const cred_t *cr) | |
129 | { | |
130 | struct group_info *gi; | |
131 | int rc; | |
132 | ||
133 | gi = get_group_info(cr->group_info); | |
9e4fb5c2 | 134 | rc = cr_groups_search(gi, SGID_TO_KGID(gid)); |
ec7d53e9 BB |
135 | put_group_info(gi); |
136 | ||
137 | return rc; | |
138 | } | |
139 | ||
140 | #else /* HAVE_CRED_STRUCT */ | |
141 | ||
142 | /* | |
143 | * Until very recently all credential information was embedded in | |
144 | * the linux task struct. For this reason to simulate a Solaris | |
145 | * cred_t we need to pass the entire task structure around. | |
146 | */ | |
147 | ||
148 | /* Hold a reference on the credential and group info */ | |
6b09f739 | 149 | void crhold(cred_t *cr) { } |
ec7d53e9 BB |
150 | |
151 | /* Free a reference on the credential and group info */ | |
6b09f739 | 152 | void crfree(cred_t *cr) { } |
ec7d53e9 | 153 | |
ec7d53e9 BB |
154 | /* Return the number of supplemental groups */ |
155 | int | |
156 | crgetngroups(const cred_t *cr) | |
157 | { | |
158 | int lock, rc; | |
159 | ||
160 | lock = (cr != current); | |
161 | if (lock) | |
162 | task_lock((struct task_struct *)cr); | |
163 | ||
164 | get_group_info(cr->group_info); | |
165 | rc = cr->group_info->ngroups; | |
166 | put_group_info(cr->group_info); | |
167 | ||
168 | if (lock) | |
169 | task_unlock((struct task_struct *)cr); | |
170 | ||
171 | return rc; | |
172 | } | |
173 | ||
174 | /* | |
175 | * Return an array of supplemental gids. The returned address is safe | |
176 | * to use as long as the caller has taken a reference with crhold(). | |
177 | * The caller is responsible for releasing the reference with crfree(). | |
178 | */ | |
179 | gid_t * | |
180 | crgetgroups(const cred_t *cr) | |
181 | { | |
182 | gid_t *gids; | |
183 | int lock; | |
184 | ||
185 | lock = (cr != current); | |
186 | if (lock) | |
187 | task_lock((struct task_struct *)cr); | |
188 | ||
189 | get_group_info(cr->group_info); | |
80093b6f | 190 | gids = KGID_TO_SGID(cr->group_info->blocks[0]); |
ec7d53e9 BB |
191 | put_group_info(cr->group_info); |
192 | ||
193 | if (lock) | |
194 | task_unlock((struct task_struct *)cr); | |
195 | ||
196 | return gids; | |
197 | } | |
198 | ||
199 | /* Check if the passed gid is available is in supplied credential. */ | |
200 | int | |
201 | groupmember(gid_t gid, const cred_t *cr) | |
202 | { | |
203 | int lock, rc; | |
204 | ||
205 | lock = (cr != current); | |
206 | if (lock) | |
207 | task_lock((struct task_struct *)cr); | |
208 | ||
209 | get_group_info(cr->group_info); | |
210 | rc = cr_groups_search(cr->group_info, gid); | |
211 | put_group_info(cr->group_info); | |
212 | ||
213 | if (lock) | |
214 | task_unlock((struct task_struct *)cr); | |
215 | ||
216 | return rc; | |
217 | } | |
218 | ||
219 | #endif /* HAVE_CRED_STRUCT */ | |
220 | ||
734fcac7 BB |
221 | /* Return the effective user id */ |
222 | uid_t | |
223 | crgetuid(const cred_t *cr) | |
224 | { | |
80093b6f | 225 | return KUID_TO_SUID(cr->euid); |
734fcac7 BB |
226 | } |
227 | ||
228 | /* Return the real user id */ | |
229 | uid_t | |
230 | crgetruid(const cred_t *cr) | |
231 | { | |
80093b6f | 232 | return KUID_TO_SUID(cr->uid); |
734fcac7 BB |
233 | } |
234 | ||
235 | /* Return the saved user id */ | |
236 | uid_t | |
237 | crgetsuid(const cred_t *cr) | |
238 | { | |
80093b6f | 239 | return KUID_TO_SUID(cr->suid); |
734fcac7 BB |
240 | } |
241 | ||
242 | /* Return the filesystem user id */ | |
243 | uid_t | |
244 | crgetfsuid(const cred_t *cr) | |
245 | { | |
80093b6f | 246 | return KUID_TO_SUID(cr->fsuid); |
734fcac7 BB |
247 | } |
248 | ||
249 | /* Return the effective group id */ | |
250 | gid_t | |
251 | crgetgid(const cred_t *cr) | |
252 | { | |
80093b6f | 253 | return KGID_TO_SGID(cr->egid); |
734fcac7 BB |
254 | } |
255 | ||
256 | /* Return the real group id */ | |
257 | gid_t | |
258 | crgetrgid(const cred_t *cr) | |
259 | { | |
80093b6f | 260 | return KGID_TO_SGID(cr->gid); |
734fcac7 BB |
261 | } |
262 | ||
263 | /* Return the saved group id */ | |
264 | gid_t | |
265 | crgetsgid(const cred_t *cr) | |
266 | { | |
80093b6f | 267 | return KGID_TO_SGID(cr->sgid); |
734fcac7 BB |
268 | } |
269 | ||
270 | /* Return the filesystem group id */ | |
271 | gid_t | |
272 | crgetfsgid(const cred_t *cr) | |
273 | { | |
80093b6f | 274 | return KGID_TO_SGID(cr->fsgid); |
734fcac7 BB |
275 | } |
276 | ||
ec7d53e9 BB |
277 | EXPORT_SYMBOL(crhold); |
278 | EXPORT_SYMBOL(crfree); | |
279 | EXPORT_SYMBOL(crgetuid); | |
280 | EXPORT_SYMBOL(crgetruid); | |
281 | EXPORT_SYMBOL(crgetsuid); | |
734fcac7 | 282 | EXPORT_SYMBOL(crgetfsuid); |
ec7d53e9 BB |
283 | EXPORT_SYMBOL(crgetgid); |
284 | EXPORT_SYMBOL(crgetrgid); | |
285 | EXPORT_SYMBOL(crgetsgid); | |
734fcac7 | 286 | EXPORT_SYMBOL(crgetfsgid); |
ec7d53e9 BB |
287 | EXPORT_SYMBOL(crgetngroups); |
288 | EXPORT_SYMBOL(crgetgroups); | |
289 | EXPORT_SYMBOL(groupmember); |