]> git.proxmox.com Git - mirror_spl-debian.git/blob - module/spl/spl-cred.c
0ed65725eb53a9dcab10e77dc47b0bf49c6051a0
[mirror_spl-debian.git] / module / spl / spl-cred.c
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>.
6 * UCRL-CODE-235197
7 *
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://zfsonlinux.org/>.
10 *
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
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
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting Layer (SPL) Credential Implementation.
25 \*****************************************************************************/
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
41 #ifdef HAVE_KUIDGID_T
42 cr_groups_search(const struct group_info *group_info, kgid_t grp)
43 #else
44 cr_groups_search(const struct group_info *group_info, gid_t grp)
45 #endif
46 {
47 unsigned int left, right;
48
49 if (!group_info)
50 return 0;
51
52 left = 0;
53 right = group_info->ngroups;
54 while (left < right) {
55 unsigned int mid = (left+right)/2;
56 int cmp = KGID_TO_SGID(grp) - KGID_TO_SGID(GROUP_AT(group_info, mid));
57 if (cmp > 0)
58 left = mid + 1;
59 else if (cmp < 0)
60 right = mid;
61 else
62 return 1;
63 }
64 return 0;
65 }
66 #endif
67
68 #ifdef HAVE_CRED_STRUCT
69
70 /*
71 * As of 2.6.29 a clean credential API appears in the linux kernel.
72 * We attempt to layer the Solaris API on top of the linux API.
73 */
74
75 /* Hold a reference on the credential and group info */
76 void
77 crhold(cred_t *cr)
78 {
79 (void)get_cred((const cred_t *)cr);
80 (void)get_group_info(cr->group_info);
81 }
82
83 /* Free a reference on the credential and group info */
84 void
85 crfree(cred_t *cr)
86 {
87 put_group_info(cr->group_info);
88 put_cred((const cred_t *)cr);
89 }
90
91 /* Return the number of supplemental groups */
92 int
93 crgetngroups(const cred_t *cr)
94 {
95 struct group_info *gi;
96 int rc;
97
98 gi = get_group_info(cr->group_info);
99 rc = gi->ngroups;
100 put_group_info(gi);
101
102 return rc;
103 }
104
105 /*
106 * Return an array of supplemental gids. The returned address is safe
107 * to use as long as the caller has taken a reference with crhold().
108 * The caller is responsible for releasing the reference with crfree().
109 */
110 gid_t *
111 crgetgroups(const cred_t *cr)
112 {
113 struct group_info *gi;
114 gid_t *gids;
115
116 gi = get_group_info(cr->group_info);
117 gids = KGIDP_TO_SGIDP(gi->blocks[0]);
118 put_group_info(gi);
119
120 return gids;
121 }
122
123 /* Check if the passed gid is available is in supplied credential. */
124 int
125 groupmember(gid_t gid, const cred_t *cr)
126 {
127 struct group_info *gi;
128 int rc;
129
130 gi = get_group_info(cr->group_info);
131 rc = cr_groups_search(cr->group_info, SGID_TO_KGID(gid));
132 put_group_info(gi);
133
134 return rc;
135 }
136
137 #else /* HAVE_CRED_STRUCT */
138
139 /*
140 * Until very recently all credential information was embedded in
141 * the linux task struct. For this reason to simulate a Solaris
142 * cred_t we need to pass the entire task structure around.
143 */
144
145 /* Hold a reference on the credential and group info */
146 void crhold(cred_t *cr) { }
147
148 /* Free a reference on the credential and group info */
149 void crfree(cred_t *cr) { }
150
151 /* Return the number of supplemental groups */
152 int
153 crgetngroups(const cred_t *cr)
154 {
155 int lock, rc;
156
157 lock = (cr != current);
158 if (lock)
159 task_lock((struct task_struct *)cr);
160
161 get_group_info(cr->group_info);
162 rc = cr->group_info->ngroups;
163 put_group_info(cr->group_info);
164
165 if (lock)
166 task_unlock((struct task_struct *)cr);
167
168 return rc;
169 }
170
171 /*
172 * Return an array of supplemental gids. The returned address is safe
173 * to use as long as the caller has taken a reference with crhold().
174 * The caller is responsible for releasing the reference with crfree().
175 */
176 gid_t *
177 crgetgroups(const cred_t *cr)
178 {
179 gid_t *gids;
180 int lock;
181
182 lock = (cr != current);
183 if (lock)
184 task_lock((struct task_struct *)cr);
185
186 get_group_info(cr->group_info);
187 gids = KGID_TO_SGID(cr->group_info->blocks[0]);
188 put_group_info(cr->group_info);
189
190 if (lock)
191 task_unlock((struct task_struct *)cr);
192
193 return gids;
194 }
195
196 /* Check if the passed gid is available is in supplied credential. */
197 int
198 groupmember(gid_t gid, const cred_t *cr)
199 {
200 int lock, rc;
201
202 lock = (cr != current);
203 if (lock)
204 task_lock((struct task_struct *)cr);
205
206 get_group_info(cr->group_info);
207 rc = cr_groups_search(cr->group_info, gid);
208 put_group_info(cr->group_info);
209
210 if (lock)
211 task_unlock((struct task_struct *)cr);
212
213 return rc;
214 }
215
216 #endif /* HAVE_CRED_STRUCT */
217
218 /* Return the effective user id */
219 uid_t
220 crgetuid(const cred_t *cr)
221 {
222 return KUID_TO_SUID(cr->euid);
223 }
224
225 /* Return the real user id */
226 uid_t
227 crgetruid(const cred_t *cr)
228 {
229 return KUID_TO_SUID(cr->uid);
230 }
231
232 /* Return the saved user id */
233 uid_t
234 crgetsuid(const cred_t *cr)
235 {
236 return KUID_TO_SUID(cr->suid);
237 }
238
239 /* Return the filesystem user id */
240 uid_t
241 crgetfsuid(const cred_t *cr)
242 {
243 return KUID_TO_SUID(cr->fsuid);
244 }
245
246 /* Return the effective group id */
247 gid_t
248 crgetgid(const cred_t *cr)
249 {
250 return KGID_TO_SGID(cr->egid);
251 }
252
253 /* Return the real group id */
254 gid_t
255 crgetrgid(const cred_t *cr)
256 {
257 return KGID_TO_SGID(cr->gid);
258 }
259
260 /* Return the saved group id */
261 gid_t
262 crgetsgid(const cred_t *cr)
263 {
264 return KGID_TO_SGID(cr->sgid);
265 }
266
267 /* Return the filesystem group id */
268 gid_t
269 crgetfsgid(const cred_t *cr)
270 {
271 return KGID_TO_SGID(cr->fsgid);
272 }
273
274 EXPORT_SYMBOL(crhold);
275 EXPORT_SYMBOL(crfree);
276 EXPORT_SYMBOL(crgetuid);
277 EXPORT_SYMBOL(crgetruid);
278 EXPORT_SYMBOL(crgetsuid);
279 EXPORT_SYMBOL(crgetfsuid);
280 EXPORT_SYMBOL(crgetgid);
281 EXPORT_SYMBOL(crgetrgid);
282 EXPORT_SYMBOL(crgetsgid);
283 EXPORT_SYMBOL(crgetfsgid);
284 EXPORT_SYMBOL(crgetngroups);
285 EXPORT_SYMBOL(crgetgroups);
286 EXPORT_SYMBOL(groupmember);