1 /* Authors: Joshua Brindle <jbrindle@tresys.com>
2 *
3 * Assertion checker for avtab entries, taken from
4 * checkpolicy.c by Stephen Smalley <sds@tycho.nsa.gov>
5 *
6 * Copyright (C) 2005 Tresys Technology, LLC
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <sepol/policydb/avtab.h>
24 #include <sepol/policydb/policydb.h>
25 #include <sepol/policydb/expand.h>
26 #include <sepol/policydb/util.h>
27
28 #include "private.h"
29 #include "debug.h"
30
31 struct avtab_match_args {
32 sepol_handle_t *handle;
33 policydb_t *p;
34 avrule_t *avrule;
35 avtab_t *avtab;
36 unsigned long errors;
37 };
38
report_failure(sepol_handle_t * handle,policydb_t * p,const avrule_t * avrule,unsigned int stype,unsigned int ttype,const class_perm_node_t * curperm,uint32_t perms)39 static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule,
40 unsigned int stype, unsigned int ttype,
41 const class_perm_node_t *curperm, uint32_t perms)
42 {
43 if (avrule->source_filename) {
44 ERR(handle, "neverallow on line %lu of %s (or line %lu of policy.conf) violated by allow %s %s:%s {%s };",
45 avrule->source_line, avrule->source_filename, avrule->line,
46 p->p_type_val_to_name[stype],
47 p->p_type_val_to_name[ttype],
48 p->p_class_val_to_name[curperm->tclass - 1],
49 sepol_av_to_string(p, curperm->tclass, perms));
50 } else if (avrule->line) {
51 ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };",
52 avrule->line, p->p_type_val_to_name[stype],
53 p->p_type_val_to_name[ttype],
54 p->p_class_val_to_name[curperm->tclass - 1],
55 sepol_av_to_string(p, curperm->tclass, perms));
56 } else {
57 ERR(handle, "neverallow violated by allow %s %s:%s {%s };",
58 p->p_type_val_to_name[stype],
59 p->p_type_val_to_name[ttype],
60 p->p_class_val_to_name[curperm->tclass - 1],
61 sepol_av_to_string(p, curperm->tclass, perms));
62 }
63 }
64
match_any_class_permissions(class_perm_node_t * cp,uint32_t class,uint32_t data)65 static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data)
66 {
67 for (; cp; cp = cp->next) {
68 if ((cp->tclass == class) && (cp->data & data)) {
69 break;
70 }
71 }
72 if (!cp)
73 return 0;
74
75 return 1;
76 }
77
extended_permissions_and(uint32_t * perms1,uint32_t * perms2)78 static int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) {
79 size_t i;
80 for (i = 0; i < EXTENDED_PERMS_LEN; i++) {
81 if (perms1[i] & perms2[i])
82 return 1;
83 }
84
85 return 0;
86 }
87
check_extended_permissions(av_extended_perms_t * neverallow,avtab_extended_perms_t * allow)88 static int check_extended_permissions(av_extended_perms_t *neverallow, avtab_extended_perms_t *allow)
89 {
90 int rc = 0;
91 if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
92 && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
93 if (neverallow->driver == allow->driver)
94 rc = extended_permissions_and(neverallow->perms, allow->perms);
95 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
96 && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
97 rc = xperm_test(neverallow->driver, allow->perms);
98 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
99 && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
100 rc = xperm_test(allow->driver, neverallow->perms);
101 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
102 && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
103 rc = extended_permissions_and(neverallow->perms, allow->perms);
104 }
105
106 return rc;
107 }
108
109 /* Compute which allowed extended permissions violate the neverallow rule */
extended_permissions_violated(avtab_extended_perms_t * result,av_extended_perms_t * neverallow,avtab_extended_perms_t * allow)110 static void extended_permissions_violated(avtab_extended_perms_t *result,
111 av_extended_perms_t *neverallow,
112 avtab_extended_perms_t *allow)
113 {
114 size_t i;
115 if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
116 && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
117 result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
118 result->driver = allow->driver;
119 for (i = 0; i < EXTENDED_PERMS_LEN; i++)
120 result->perms[i] = neverallow->perms[i] & allow->perms[i];
121 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
122 && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
123 result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
124 result->driver = neverallow->driver;
125 memcpy(result->perms, neverallow->perms, sizeof(result->perms));
126 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
127 && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
128 result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
129 result->driver = allow->driver;
130 memcpy(result->perms, allow->perms, sizeof(result->perms));
131 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
132 && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
133 result->specified = AVTAB_XPERMS_IOCTLDRIVER;
134 for (i = 0; i < EXTENDED_PERMS_LEN; i++)
135 result->perms[i] = neverallow->perms[i] & allow->perms[i];
136 }
137 }
138
139 /* Same scenarios of interest as check_assertion_extended_permissions */
report_assertion_extended_permissions(sepol_handle_t * handle,policydb_t * p,const avrule_t * avrule,unsigned int stype,unsigned int ttype,const class_perm_node_t * curperm,uint32_t perms,avtab_key_t * k,avtab_t * avtab)140 static int report_assertion_extended_permissions(sepol_handle_t *handle,
141 policydb_t *p, const avrule_t *avrule,
142 unsigned int stype, unsigned int ttype,
143 const class_perm_node_t *curperm, uint32_t perms,
144 avtab_key_t *k, avtab_t *avtab)
145 {
146 avtab_ptr_t node;
147 avtab_key_t tmp_key;
148 avtab_extended_perms_t *xperms;
149 avtab_extended_perms_t error;
150 ebitmap_t *sattr = &p->type_attr_map[stype];
151 ebitmap_t *tattr = &p->type_attr_map[ttype];
152 ebitmap_node_t *snode, *tnode;
153 unsigned int i, j;
154 int rc = 1;
155 int ret = 0;
156
157 memcpy(&tmp_key, k, sizeof(avtab_key_t));
158 tmp_key.specified = AVTAB_XPERMS_ALLOWED;
159
160 ebitmap_for_each_bit(sattr, snode, i) {
161 if (!ebitmap_node_get_bit(snode, i))
162 continue;
163 ebitmap_for_each_bit(tattr, tnode, j) {
164 if (!ebitmap_node_get_bit(tnode, j))
165 continue;
166 tmp_key.source_type = i + 1;
167 tmp_key.target_type = j + 1;
168 for (node = avtab_search_node(avtab, &tmp_key);
169 node;
170 node = avtab_search_node_next(node, tmp_key.specified)) {
171 xperms = node->datum.xperms;
172 if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
173 && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
174 continue;
175
176 rc = check_extended_permissions(avrule->xperms, xperms);
177 /* failure on the extended permission check_extended_permissions */
178 if (rc) {
179 extended_permissions_violated(&error, avrule->xperms, xperms);
180 ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
181 "allowxperm %s %s:%s %s;",
182 avrule->source_line, avrule->source_filename, avrule->line,
183 p->p_type_val_to_name[i],
184 p->p_type_val_to_name[j],
185 p->p_class_val_to_name[curperm->tclass - 1],
186 sepol_extended_perms_to_string(&error));
187
188 rc = 0;
189 ret++;
190 }
191 }
192 }
193 }
194
195 /* failure on the regular permissions */
196 if (rc) {
197 ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
198 "allow %s %s:%s {%s };",
199 avrule->source_line, avrule->source_filename, avrule->line,
200 p->p_type_val_to_name[stype],
201 p->p_type_val_to_name[ttype],
202 p->p_class_val_to_name[curperm->tclass - 1],
203 sepol_av_to_string(p, curperm->tclass, perms));
204 ret++;
205
206 }
207
208 return ret;
209 }
210
report_assertion_avtab_matches(avtab_key_t * k,avtab_datum_t * d,void * args)211 static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args)
212 {
213 int rc = 0;
214 struct avtab_match_args *a = (struct avtab_match_args *)args;
215 sepol_handle_t *handle = a->handle;
216 policydb_t *p = a->p;
217 avtab_t *avtab = a->avtab;
218 avrule_t *avrule = a->avrule;
219 class_perm_node_t *cp;
220 uint32_t perms;
221 ebitmap_t src_matches, tgt_matches, matches;
222 ebitmap_node_t *snode, *tnode;
223 unsigned int i, j;
224
225 if (k->specified != AVTAB_ALLOWED)
226 return 0;
227
228 if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
229 return 0;
230
231 ebitmap_init(&src_matches);
232 ebitmap_init(&tgt_matches);
233 ebitmap_init(&matches);
234
235 rc = ebitmap_and(&src_matches, &avrule->stypes.types,
236 &p->attr_type_map[k->source_type - 1]);
237 if (rc)
238 goto oom;
239
240 if (ebitmap_length(&src_matches) == 0)
241 goto exit;
242
243 if (avrule->flags == RULE_SELF) {
244 rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1]);
245 if (rc)
246 goto oom;
247 rc = ebitmap_and(&tgt_matches, &avrule->stypes.types, &matches);
248 if (rc)
249 goto oom;
250 } else {
251 rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
252 if (rc)
253 goto oom;
254 }
255
256 if (ebitmap_length(&tgt_matches) == 0)
257 goto exit;
258
259 for (cp = avrule->perms; cp; cp = cp->next) {
260
261 perms = cp->data & d->data;
262 if ((cp->tclass != k->target_class) || !perms) {
263 continue;
264 }
265
266 ebitmap_for_each_bit(&src_matches, snode, i) {
267 if (!ebitmap_node_get_bit(snode, i))
268 continue;
269 ebitmap_for_each_bit(&tgt_matches, tnode, j) {
270 if (!ebitmap_node_get_bit(tnode, j))
271 continue;
272
273 if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
274 a->errors += report_assertion_extended_permissions(handle,p, avrule,
275 i, j, cp, perms, k, avtab);
276 } else {
277 a->errors++;
278 report_failure(handle, p, avrule, i, j, cp, perms);
279 }
280 }
281 }
282 }
283 goto exit;
284
285 oom:
286 ERR(NULL, "Out of memory - unable to check neverallows");
287
288 exit:
289 ebitmap_destroy(&src_matches);
290 ebitmap_destroy(&tgt_matches);
291 ebitmap_destroy(&matches);
292 return rc;
293 }
294
report_assertion_failures(sepol_handle_t * handle,policydb_t * p,avrule_t * avrule)295 int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
296 {
297 int rc;
298 struct avtab_match_args args;
299
300 args.handle = handle;
301 args.p = p;
302 args.avrule = avrule;
303 args.errors = 0;
304
305 rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args);
306 if (rc)
307 goto oom;
308
309 rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args);
310 if (rc)
311 goto oom;
312
313 return args.errors;
314
315 oom:
316 return rc;
317 }
318
319 /*
320 * Look up the extended permissions in avtab and verify that neverallowed
321 * permissions are not granted.
322 */
check_assertion_extended_permissions_avtab(avrule_t * avrule,avtab_t * avtab,unsigned int stype,unsigned int ttype,avtab_key_t * k,policydb_t * p)323 static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab,
324 unsigned int stype, unsigned int ttype,
325 avtab_key_t *k, policydb_t *p)
326 {
327 avtab_ptr_t node;
328 avtab_key_t tmp_key;
329 avtab_extended_perms_t *xperms;
330 av_extended_perms_t *neverallow_xperms = avrule->xperms;
331 ebitmap_t *sattr = &p->type_attr_map[stype];
332 ebitmap_t *tattr = &p->type_attr_map[ttype];
333 ebitmap_node_t *snode, *tnode;
334 unsigned int i, j;
335 int rc = 1;
336
337 memcpy(&tmp_key, k, sizeof(avtab_key_t));
338 tmp_key.specified = AVTAB_XPERMS_ALLOWED;
339
340 ebitmap_for_each_bit(sattr, snode, i) {
341 if (!ebitmap_node_get_bit(snode, i))
342 continue;
343 ebitmap_for_each_bit(tattr, tnode, j) {
344 if (!ebitmap_node_get_bit(tnode, j))
345 continue;
346 tmp_key.source_type = i + 1;
347 tmp_key.target_type = j + 1;
348 for (node = avtab_search_node(avtab, &tmp_key);
349 node;
350 node = avtab_search_node_next(node, tmp_key.specified)) {
351 xperms = node->datum.xperms;
352
353 if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
354 && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
355 continue;
356 rc = check_extended_permissions(neverallow_xperms, xperms);
357 if (rc)
358 break;
359 }
360 }
361 }
362
363 return rc;
364 }
365
366 /*
367 * When the ioctl permission is granted on an avtab entry that matches an
368 * avrule neverallowxperm entry, enumerate over the matching
369 * source/target/class sets to determine if the extended permissions exist
370 * and if the neverallowed ioctls are granted.
371 *
372 * Four scenarios of interest:
373 * 1. PASS - the ioctl permission is not granted for this source/target/class
374 * This case is handled in check_assertion_avtab_match
375 * 2. PASS - The ioctl permission is granted AND the extended permission
376 * is NOT granted
377 * 3. FAIL - The ioctl permission is granted AND no extended permissions
378 * exist
379 * 4. FAIL - The ioctl permission is granted AND the extended permission is
380 * granted
381 */
check_assertion_extended_permissions(avrule_t * avrule,avtab_t * avtab,avtab_key_t * k,policydb_t * p)382 static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab,
383 avtab_key_t *k, policydb_t *p)
384 {
385 ebitmap_t src_matches, tgt_matches, matches;
386 unsigned int i, j;
387 ebitmap_node_t *snode, *tnode;
388 class_perm_node_t *cp;
389 int rc;
390 int ret = 1;
391
392 ebitmap_init(&src_matches);
393 ebitmap_init(&tgt_matches);
394 ebitmap_init(&matches);
395 rc = ebitmap_and(&src_matches, &avrule->stypes.types,
396 &p->attr_type_map[k->source_type - 1]);
397 if (rc)
398 goto oom;
399
400 if (ebitmap_length(&src_matches) == 0)
401 goto exit;
402
403 if (avrule->flags == RULE_SELF) {
404 rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1],
405 &p->attr_type_map[k->target_type - 1]);
406 if (rc)
407 goto oom;
408 rc = ebitmap_and(&tgt_matches, &avrule->stypes.types, &matches);
409 if (rc)
410 goto oom;
411 } else {
412 rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types,
413 &p->attr_type_map[k->target_type -1]);
414 if (rc)
415 goto oom;
416 }
417
418 if (ebitmap_length(&tgt_matches) == 0)
419 goto exit;
420
421 for (cp = avrule->perms; cp; cp = cp->next) {
422 if (cp->tclass != k->target_class)
423 continue;
424 ebitmap_for_each_bit(&src_matches, snode, i) {
425 if (!ebitmap_node_get_bit(snode, i))
426 continue;
427 ebitmap_for_each_bit(&tgt_matches, tnode, j) {
428 if (!ebitmap_node_get_bit(tnode, j))
429 continue;
430
431 ret = check_assertion_extended_permissions_avtab(
432 avrule, avtab, i, j, k, p);
433 if (ret)
434 goto exit;
435 }
436 }
437 }
438 goto exit;
439
440 oom:
441 ERR(NULL, "Out of memory - unable to check neverallows");
442
443 exit:
444 ebitmap_destroy(&src_matches);
445 ebitmap_destroy(&tgt_matches);
446 ebitmap_destroy(&matches);
447 return ret;
448 }
449
check_assertion_avtab_match(avtab_key_t * k,avtab_datum_t * d,void * args)450 static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args)
451 {
452 int rc;
453 struct avtab_match_args *a = (struct avtab_match_args *)args;
454 policydb_t *p = a->p;
455 avrule_t *avrule = a->avrule;
456 avtab_t *avtab = a->avtab;
457
458 if (k->specified != AVTAB_ALLOWED)
459 goto exit;
460
461 if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
462 goto exit;
463
464 rc = ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1]);
465 if (rc == 0)
466 goto exit;
467
468 if (avrule->flags == RULE_SELF) {
469 /* If the neverallow uses SELF, then it is not enough that the
470 * neverallow's source matches the src and tgt of the rule being checked.
471 * It must match the same thing in the src and tgt, so AND the source
472 * and target together and check for a match on the result.
473 */
474 ebitmap_t match;
475 rc = ebitmap_and(&match, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1] );
476 if (rc) {
477 ebitmap_destroy(&match);
478 goto oom;
479 }
480 rc = ebitmap_match_any(&avrule->stypes.types, &match);
481 ebitmap_destroy(&match);
482 } else {
483 rc = ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
484 }
485 if (rc == 0)
486 goto exit;
487
488 if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
489 rc = check_assertion_extended_permissions(avrule, avtab, k, p);
490 if (rc == 0)
491 goto exit;
492 }
493 return 1;
494
495 exit:
496 return 0;
497
498 oom:
499 ERR(NULL, "Out of memory - unable to check neverallows");
500 return rc;
501 }
502
check_assertion(policydb_t * p,avrule_t * avrule)503 int check_assertion(policydb_t *p, avrule_t *avrule)
504 {
505 int rc;
506 struct avtab_match_args args;
507
508 args.handle = NULL;
509 args.p = p;
510 args.avrule = avrule;
511 args.errors = 0;
512 args.avtab = &p->te_avtab;
513
514 rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args);
515
516 if (rc == 0) {
517 args.avtab = &p->te_cond_avtab;
518 rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args);
519 }
520
521 return rc;
522 }
523
check_assertions(sepol_handle_t * handle,policydb_t * p,avrule_t * avrules)524 int check_assertions(sepol_handle_t * handle, policydb_t * p,
525 avrule_t * avrules)
526 {
527 int rc;
528 avrule_t *a;
529 unsigned long errors = 0;
530
531 if (!avrules) {
532 /* Since assertions are stored in avrules, if it is NULL
533 there won't be any to check. This also prevents an invalid
534 free if the avtabs are never initialized */
535 return 0;
536 }
537
538 for (a = avrules; a != NULL; a = a->next) {
539 if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)))
540 continue;
541 rc = check_assertion(p, a);
542 if (rc) {
543 rc = report_assertion_failures(handle, p, a);
544 if (rc < 0) {
545 ERR(handle, "Error occurred while checking neverallows");
546 return -1;
547 }
548 errors += rc;
549 }
550 }
551
552 if (errors)
553 ERR(handle, "%lu neverallow failures occurred", errors);
554
555 return errors ? -1 : 0;
556 }
557