]>
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/>. |
716154c5 BB |
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. | |
ec7d53e9 | 15 | * |
716154c5 | 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 Tests (SPLAT) Credential Tests. | |
25 | \*****************************************************************************/ | |
ec7d53e9 | 26 | |
df870a69 | 27 | #include <sys/cred.h> |
9e4fb5c2 | 28 | #include <sys/random.h> |
ec7d53e9 BB |
29 | #include "splat-internal.h" |
30 | ||
31 | #define SPLAT_CRED_NAME "cred" | |
32 | #define SPLAT_CRED_DESC "Kernel Cred Tests" | |
33 | ||
34 | #define SPLAT_CRED_TEST1_ID 0x0e01 | |
35 | #define SPLAT_CRED_TEST1_NAME "cred" | |
36 | #define SPLAT_CRED_TEST1_DESC "Task Credential Test" | |
37 | ||
38 | #define SPLAT_CRED_TEST2_ID 0x0e02 | |
39 | #define SPLAT_CRED_TEST2_NAME "kcred" | |
40 | #define SPLAT_CRED_TEST2_DESC "Kernel Credential Test" | |
41 | ||
42 | #define SPLAT_CRED_TEST3_ID 0x0e03 | |
43 | #define SPLAT_CRED_TEST3_NAME "groupmember" | |
44 | #define SPLAT_CRED_TEST3_DESC "Group Member Test" | |
45 | ||
46 | #define GROUP_STR_SIZE 128 | |
47 | #define GROUP_STR_REDZONE 16 | |
48 | ||
49 | static int | |
50 | splat_cred_test1(struct file *file, void *arg) | |
51 | { | |
52 | char str[GROUP_STR_SIZE]; | |
53 | uid_t uid, ruid, suid; | |
54 | gid_t gid, rgid, sgid, *groups; | |
55 | int ngroups, i, count = 0; | |
ac9cc135 | 56 | cred_t *cr = CRED(); |
ec7d53e9 | 57 | |
ac9cc135 AX |
58 | uid = crgetuid(cr); |
59 | ruid = crgetruid(cr); | |
60 | suid = crgetsuid(cr); | |
ec7d53e9 | 61 | |
ac9cc135 AX |
62 | gid = crgetgid(cr); |
63 | rgid = crgetrgid(cr); | |
64 | sgid = crgetsgid(cr); | |
ec7d53e9 | 65 | |
ac9cc135 AX |
66 | ngroups = crgetngroups(cr); |
67 | groups = crgetgroups(cr); | |
ec7d53e9 BB |
68 | |
69 | memset(str, 0, GROUP_STR_SIZE); | |
70 | for (i = 0; i < ngroups; i++) { | |
71 | count += sprintf(str + count, "%d ", groups[i]); | |
72 | ||
73 | if (count > (GROUP_STR_SIZE - GROUP_STR_REDZONE)) { | |
74 | splat_vprint(file, SPLAT_CRED_TEST1_NAME, | |
75 | "Failed too many group entries for temp " | |
76 | "buffer: %d, %s\n", ngroups, str); | |
77 | return -ENOSPC; | |
78 | } | |
79 | } | |
80 | ||
ec7d53e9 BB |
81 | splat_vprint(file, SPLAT_CRED_TEST1_NAME, |
82 | "uid: %d ruid: %d suid: %d " | |
83 | "gid: %d rgid: %d sgid: %d\n", | |
84 | uid, ruid, suid, gid, rgid, sgid); | |
85 | splat_vprint(file, SPLAT_CRED_TEST1_NAME, | |
86 | "ngroups: %d groups: %s\n", ngroups, str); | |
87 | ||
88 | if (uid || ruid || suid || gid || rgid || sgid) { | |
89 | splat_vprint(file, SPLAT_CRED_TEST1_NAME, | |
90 | "Failed expected all uids+gids to be %d\n", 0); | |
91 | return -EIDRM; | |
92 | } | |
93 | ||
94 | if (ngroups > NGROUPS_MAX) { | |
95 | splat_vprint(file, SPLAT_CRED_TEST1_NAME, | |
96 | "Failed ngroups must not exceed NGROUPS_MAX: " | |
97 | "%d > %d\n", ngroups, NGROUPS_MAX); | |
98 | return -EIDRM; | |
99 | } | |
100 | ||
101 | splat_vprint(file, SPLAT_CRED_TEST1_NAME, | |
102 | "Success sane CRED(): %d\n", 0); | |
103 | ||
104 | return 0; | |
105 | } /* splat_cred_test1() */ | |
106 | ||
107 | static int | |
108 | splat_cred_test2(struct file *file, void *arg) | |
109 | { | |
110 | char str[GROUP_STR_SIZE]; | |
111 | uid_t uid, ruid, suid; | |
112 | gid_t gid, rgid, sgid, *groups; | |
113 | int ngroups, i, count = 0; | |
114 | ||
ac9cc135 AX |
115 | crhold(kcred); |
116 | ||
ec7d53e9 BB |
117 | uid = crgetuid(kcred); |
118 | ruid = crgetruid(kcred); | |
119 | suid = crgetsuid(kcred); | |
120 | ||
121 | gid = crgetgid(kcred); | |
122 | rgid = crgetrgid(kcred); | |
123 | sgid = crgetsgid(kcred); | |
124 | ||
ec7d53e9 BB |
125 | ngroups = crgetngroups(kcred); |
126 | groups = crgetgroups(kcred); | |
127 | ||
128 | memset(str, 0, GROUP_STR_SIZE); | |
129 | for (i = 0; i < ngroups; i++) { | |
130 | count += sprintf(str + count, "%d ", groups[i]); | |
131 | ||
132 | if (count > (GROUP_STR_SIZE - GROUP_STR_REDZONE)) { | |
133 | splat_vprint(file, SPLAT_CRED_TEST2_NAME, | |
134 | "Failed too many group entries for temp " | |
135 | "buffer: %d, %s\n", ngroups, str); | |
ac9cc135 | 136 | crfree(kcred); |
ec7d53e9 BB |
137 | return -ENOSPC; |
138 | } | |
139 | } | |
140 | ||
141 | crfree(kcred); | |
142 | ||
143 | splat_vprint(file, SPLAT_CRED_TEST2_NAME, | |
144 | "uid: %d ruid: %d suid: %d " | |
145 | "gid: %d rgid: %d sgid: %d\n", | |
146 | uid, ruid, suid, gid, rgid, sgid); | |
147 | splat_vprint(file, SPLAT_CRED_TEST2_NAME, | |
148 | "ngroups: %d groups: %s\n", ngroups, str); | |
149 | ||
150 | if (uid || ruid || suid || gid || rgid || sgid) { | |
151 | splat_vprint(file, SPLAT_CRED_TEST2_NAME, | |
152 | "Failed expected all uids+gids to be %d\n", 0); | |
153 | return -EIDRM; | |
154 | } | |
155 | ||
156 | if (ngroups > NGROUPS_MAX) { | |
157 | splat_vprint(file, SPLAT_CRED_TEST2_NAME, | |
158 | "Failed ngroups must not exceed NGROUPS_MAX: " | |
159 | "%d > %d\n", ngroups, NGROUPS_MAX); | |
160 | return -EIDRM; | |
161 | } | |
162 | ||
163 | splat_vprint(file, SPLAT_CRED_TEST2_NAME, | |
164 | "Success sane kcred: %d\n", 0); | |
165 | ||
166 | return 0; | |
167 | } /* splat_cred_test2() */ | |
168 | ||
ac9cc135 | 169 | #define SPLAT_NGROUPS 32 |
ec7d53e9 | 170 | /* |
9e4fb5c2 LG |
171 | * Verify the groupmember() works correctly by constructing an interesting |
172 | * CRED() and checking that the expected gids are part of it. | |
ec7d53e9 BB |
173 | */ |
174 | static int | |
175 | splat_cred_test3(struct file *file, void *arg) | |
176 | { | |
9e4fb5c2 LG |
177 | gid_t known_gid, missing_gid, tmp_gid; |
178 | unsigned char rnd; | |
179 | struct group_info *gi; | |
180 | int i, rc; | |
181 | ||
182 | get_random_bytes((void *)&rnd, 1); | |
183 | known_gid = (rnd > 0) ? rnd : 1; | |
184 | missing_gid = 0; | |
185 | ||
186 | /* | |
187 | * Create an interesting known set of gids for test purposes. The | |
188 | * gids are pseudo randomly selected are will be in the range of | |
189 | * 1:(NGROUPS_MAX-1). Gid 0 is explicitly avoided so we can reliably | |
190 | * test for its absence in the test cases. | |
191 | */ | |
ac9cc135 | 192 | gi = groups_alloc(SPLAT_NGROUPS); |
9e4fb5c2 LG |
193 | if (gi == NULL) { |
194 | splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed create " | |
195 | "group_info for known gids: %d\n", -ENOMEM); | |
196 | rc = -ENOMEM; | |
197 | goto show_groups; | |
198 | } | |
199 | ||
ac9cc135 | 200 | for (i = 0, tmp_gid = known_gid; i < SPLAT_NGROUPS; i++) { |
9e4fb5c2 LG |
201 | splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Adding gid %d " |
202 | "to current CRED() (%d/%d)\n", tmp_gid, i, gi->ngroups); | |
203 | #ifdef HAVE_KUIDGID_T | |
204 | GROUP_AT(gi, i) = make_kgid(current_user_ns(), tmp_gid); | |
205 | #else | |
206 | GROUP_AT(gi, i) = tmp_gid; | |
207 | #endif /* HAVE_KUIDGID_T */ | |
208 | tmp_gid = ((tmp_gid * 17) % (NGROUPS_MAX - 1)) + 1; | |
209 | } | |
ec7d53e9 | 210 | |
9e4fb5c2 LG |
211 | /* Set the new groups in the CRED() and release our reference. */ |
212 | rc = set_current_groups(gi); | |
213 | put_group_info(gi); | |
ec7d53e9 | 214 | |
9e4fb5c2 LG |
215 | if (rc) { |
216 | splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed to add " | |
217 | "gid %d to current group: %d\n", known_gid, rc); | |
218 | goto show_groups; | |
219 | } | |
220 | ||
221 | /* Verify groupmember() finds the known_gid in the CRED() */ | |
222 | rc = groupmember(known_gid, CRED()); | |
ec7d53e9 | 223 | if (!rc) { |
9e4fb5c2 LG |
224 | splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed to find " |
225 | "known gid %d in CRED()'s groups.\n", known_gid); | |
226 | rc = -EIDRM; | |
227 | goto show_groups; | |
ec7d53e9 BB |
228 | } |
229 | ||
9e4fb5c2 LG |
230 | /* Verify groupmember() does NOT finds the missing gid in the CRED() */ |
231 | rc = groupmember(missing_gid, CRED()); | |
ec7d53e9 | 232 | if (rc) { |
9e4fb5c2 LG |
233 | splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed missing " |
234 | "gid %d was found in CRED()'s groups.\n", missing_gid); | |
235 | rc = -EIDRM; | |
236 | goto show_groups; | |
237 | } | |
238 | ||
239 | splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Success groupmember() " | |
240 | "correctly detects expected gids in CRED(): %d\n", rc); | |
241 | ||
242 | show_groups: | |
243 | if (rc) { | |
244 | int i, grps = crgetngroups(CRED()); | |
245 | ||
246 | splat_vprint(file, SPLAT_CRED_TEST3_NAME, "%d groups: ", grps); | |
247 | for (i = 0; i < grps; i++) | |
248 | splat_print(file, "%d ", crgetgroups(CRED())[i]); | |
249 | splat_print(file, "%s", "\n"); | |
ec7d53e9 BB |
250 | } |
251 | ||
ec7d53e9 | 252 | |
9e4fb5c2 | 253 | return (rc); |
ec7d53e9 BB |
254 | } /* splat_cred_test3() */ |
255 | ||
256 | splat_subsystem_t * | |
257 | splat_cred_init(void) | |
258 | { | |
259 | splat_subsystem_t *sub; | |
260 | ||
261 | sub = kmalloc(sizeof(*sub), GFP_KERNEL); | |
262 | if (sub == NULL) | |
263 | return NULL; | |
264 | ||
265 | memset(sub, 0, sizeof(*sub)); | |
266 | strncpy(sub->desc.name, SPLAT_CRED_NAME, SPLAT_NAME_SIZE); | |
267 | strncpy(sub->desc.desc, SPLAT_CRED_DESC, SPLAT_DESC_SIZE); | |
268 | INIT_LIST_HEAD(&sub->subsystem_list); | |
269 | INIT_LIST_HEAD(&sub->test_list); | |
270 | spin_lock_init(&sub->test_lock); | |
271 | sub->desc.id = SPLAT_SUBSYSTEM_CRED; | |
272 | ||
ec06701b | 273 | splat_test_init(sub, SPLAT_CRED_TEST1_NAME, SPLAT_CRED_TEST1_DESC, |
ec7d53e9 | 274 | SPLAT_CRED_TEST1_ID, splat_cred_test1); |
ec06701b | 275 | splat_test_init(sub, SPLAT_CRED_TEST2_NAME, SPLAT_CRED_TEST2_DESC, |
ec7d53e9 | 276 | SPLAT_CRED_TEST2_ID, splat_cred_test2); |
ec06701b | 277 | splat_test_init(sub, SPLAT_CRED_TEST3_NAME, SPLAT_CRED_TEST3_DESC, |
ec7d53e9 BB |
278 | SPLAT_CRED_TEST3_ID, splat_cred_test3); |
279 | ||
280 | return sub; | |
281 | } /* splat_cred_init() */ | |
282 | ||
283 | void | |
284 | splat_cred_fini(splat_subsystem_t *sub) | |
285 | { | |
286 | ASSERT(sub); | |
287 | ||
ec06701b AX |
288 | splat_test_fini(sub, SPLAT_CRED_TEST3_ID); |
289 | splat_test_fini(sub, SPLAT_CRED_TEST2_ID); | |
290 | splat_test_fini(sub, SPLAT_CRED_TEST1_ID); | |
ec7d53e9 BB |
291 | |
292 | kfree(sub); | |
293 | } /* splat_cred_fini() */ | |
294 | ||
295 | int | |
296 | splat_cred_id(void) | |
297 | { | |
298 | return SPLAT_SUBSYSTEM_CRED; | |
299 | } /* splat_cred_id() */ |