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
policy_name(policydb_t * p)39 static const char* policy_name(policydb_t *p) {
40 const char *policy_file = "policy.conf";
41 if (p->name) {
42 policy_file = p->name;
43 }
44 return policy_file;
45 }
46
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)47 static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule,
48 unsigned int stype, unsigned int ttype,
49 const class_perm_node_t *curperm, uint32_t perms)
50 {
51 if (avrule->source_filename) {
52 ERR(handle, "neverallow on line %lu of %s (or line %lu of %s) violated by allow %s %s:%s {%s };",
53 avrule->source_line, avrule->source_filename, avrule->line, policy_name(p),
54 p->p_type_val_to_name[stype],
55 p->p_type_val_to_name[ttype],
56 p->p_class_val_to_name[curperm->tclass - 1],
57 sepol_av_to_string(p, curperm->tclass, perms));
58 } else if (avrule->line) {
59 ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };",
60 avrule->line, p->p_type_val_to_name[stype],
61 p->p_type_val_to_name[ttype],
62 p->p_class_val_to_name[curperm->tclass - 1],
63 sepol_av_to_string(p, curperm->tclass, perms));
64 } else {
65 ERR(handle, "neverallow violated by allow %s %s:%s {%s };",
66 p->p_type_val_to_name[stype],
67 p->p_type_val_to_name[ttype],
68 p->p_class_val_to_name[curperm->tclass - 1],
69 sepol_av_to_string(p, curperm->tclass, perms));
70 }
71 }
72
match_any_class_permissions(class_perm_node_t * cp,uint32_t class,uint32_t data)73 static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data)
74 {
75 for (; cp; cp = cp->next) {
76 if ((cp->tclass == class) && (cp->data & data))
77 return 1;
78 }
79
80 return 0;
81 }
82
extended_permissions_and(uint32_t * perms1,uint32_t * perms2)83 static int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) {
84 size_t i;
85 for (i = 0; i < EXTENDED_PERMS_LEN; i++) {
86 if (perms1[i] & perms2[i])
87 return 1;
88 }
89
90 return 0;
91 }
92
check_extended_permissions(av_extended_perms_t * neverallow,avtab_extended_perms_t * allow)93 static int check_extended_permissions(av_extended_perms_t *neverallow, avtab_extended_perms_t *allow)
94 {
95 int rc = 0;
96 if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
97 && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
98 if (neverallow->driver == allow->driver)
99 rc = extended_permissions_and(neverallow->perms, allow->perms);
100 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
101 && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
102 rc = xperm_test(neverallow->driver, allow->perms);
103 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
104 && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
105 rc = xperm_test(allow->driver, neverallow->perms);
106 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
107 && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
108 rc = extended_permissions_and(neverallow->perms, allow->perms);
109 }
110
111 return rc;
112 }
113
114 /* 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)115 static void extended_permissions_violated(avtab_extended_perms_t *result,
116 av_extended_perms_t *neverallow,
117 avtab_extended_perms_t *allow)
118 {
119 size_t i;
120 if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
121 && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
122 result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
123 result->driver = allow->driver;
124 for (i = 0; i < EXTENDED_PERMS_LEN; i++)
125 result->perms[i] = neverallow->perms[i] & allow->perms[i];
126 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
127 && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
128 result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
129 result->driver = neverallow->driver;
130 memcpy(result->perms, neverallow->perms, sizeof(result->perms));
131 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
132 && (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
133 result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
134 result->driver = allow->driver;
135 memcpy(result->perms, allow->perms, sizeof(result->perms));
136 } else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
137 && (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
138 result->specified = AVTAB_XPERMS_IOCTLDRIVER;
139 for (i = 0; i < EXTENDED_PERMS_LEN; i++)
140 result->perms[i] = neverallow->perms[i] & allow->perms[i];
141 }
142 }
143
144 /* 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)145 static int report_assertion_extended_permissions(sepol_handle_t *handle,
146 policydb_t *p, const avrule_t *avrule,
147 unsigned int stype, unsigned int ttype,
148 const class_perm_node_t *curperm, uint32_t perms,
149 avtab_key_t *k, avtab_t *avtab)
150 {
151 avtab_ptr_t node;
152 avtab_key_t tmp_key;
153 avtab_extended_perms_t *xperms;
154 avtab_extended_perms_t error;
155 ebitmap_t *sattr = &p->type_attr_map[stype];
156 ebitmap_t *tattr = &p->type_attr_map[ttype];
157 ebitmap_node_t *snode, *tnode;
158 unsigned int i, j;
159 int rc;
160 int found_xperm = 0;
161 int errors = 0;
162
163 memcpy(&tmp_key, k, sizeof(avtab_key_t));
164 tmp_key.specified = AVTAB_XPERMS_ALLOWED;
165
166 ebitmap_for_each_positive_bit(sattr, snode, i) {
167 tmp_key.source_type = i + 1;
168 ebitmap_for_each_positive_bit(tattr, tnode, j) {
169 tmp_key.target_type = j + 1;
170 for (node = avtab_search_node(avtab, &tmp_key);
171 node;
172 node = avtab_search_node_next(node, tmp_key.specified)) {
173 xperms = node->datum.xperms;
174 if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
175 && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
176 continue;
177 found_xperm = 1;
178 rc = check_extended_permissions(avrule->xperms, xperms);
179 /* failure on the extended permission check_extended_permissions */
180 if (rc) {
181 extended_permissions_violated(&error, avrule->xperms, xperms);
182 ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
183 "allowxperm %s %s:%s %s;",
184 avrule->source_line, avrule->source_filename, avrule->line, policy_name(p),
185 p->p_type_val_to_name[i],
186 p->p_type_val_to_name[j],
187 p->p_class_val_to_name[curperm->tclass - 1],
188 sepol_extended_perms_to_string(&error));
189
190 errors++;
191 }
192 }
193 }
194 }
195
196 /* failure on the regular permissions */
197 if (!found_xperm) {
198 ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of %s) violated by\n"
199 "allow %s %s:%s {%s };",
200 avrule->source_line, avrule->source_filename, avrule->line, policy_name(p),
201 p->p_type_val_to_name[stype],
202 p->p_type_val_to_name[ttype],
203 p->p_class_val_to_name[curperm->tclass - 1],
204 sepol_av_to_string(p, curperm->tclass, perms));
205 errors++;
206
207 }
208
209 return errors;
210 }
211
report_assertion_avtab_matches(avtab_key_t * k,avtab_datum_t * d,void * args)212 static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args)
213 {
214 int rc = 0;
215 struct avtab_match_args *a = (struct avtab_match_args *)args;
216 sepol_handle_t *handle = a->handle;
217 policydb_t *p = a->p;
218 avtab_t *avtab = a->avtab;
219 avrule_t *avrule = a->avrule;
220 class_perm_node_t *cp;
221 uint32_t perms;
222 ebitmap_t src_matches, tgt_matches, self_matches;
223 ebitmap_node_t *snode, *tnode;
224 unsigned int i, j;
225 const int is_avrule_self = (avrule->flags & RULE_SELF) != 0;
226
227 if ((k->specified & AVTAB_ALLOWED) == 0)
228 return 0;
229
230 if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
231 return 0;
232
233 ebitmap_init(&src_matches);
234 ebitmap_init(&tgt_matches);
235 ebitmap_init(&self_matches);
236
237 rc = ebitmap_and(&src_matches, &avrule->stypes.types,
238 &p->attr_type_map[k->source_type - 1]);
239 if (rc < 0)
240 goto oom;
241
242 if (ebitmap_is_empty(&src_matches))
243 goto exit;
244
245 rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
246 if (rc < 0)
247 goto oom;
248
249 if (is_avrule_self) {
250 rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]);
251 if (rc < 0)
252 goto oom;
253
254 if (!ebitmap_is_empty(&self_matches)) {
255 rc = ebitmap_union(&tgt_matches, &self_matches);
256 if (rc < 0)
257 goto oom;
258 }
259 }
260
261 if (ebitmap_is_empty(&tgt_matches))
262 goto exit;
263
264 for (cp = avrule->perms; cp; cp = cp->next) {
265
266 perms = cp->data & d->data;
267 if ((cp->tclass != k->target_class) || !perms) {
268 continue;
269 }
270
271 ebitmap_for_each_positive_bit(&src_matches, snode, i) {
272 ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
273 if (is_avrule_self && i != j)
274 continue;
275 if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
276 a->errors += report_assertion_extended_permissions(handle,p, avrule,
277 i, j, cp, perms, k, avtab);
278 } else {
279 a->errors++;
280 report_failure(handle, p, avrule, i, j, cp, perms);
281 }
282 }
283 }
284 }
285
286 oom:
287 exit:
288 ebitmap_destroy(&src_matches);
289 ebitmap_destroy(&tgt_matches);
290 ebitmap_destroy(&self_matches);
291 return rc;
292 }
293
report_assertion_failures(sepol_handle_t * handle,policydb_t * p,avrule_t * avrule)294 static int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
295 {
296 int rc;
297 struct avtab_match_args args;
298
299 args.handle = handle;
300 args.p = p;
301 args.avrule = avrule;
302 args.errors = 0;
303
304 args.avtab = &p->te_avtab;
305 rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args);
306 if (rc < 0)
307 goto oom;
308
309 args.avtab = &p->te_cond_avtab;
310 rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args);
311 if (rc < 0)
312 goto oom;
313
314 return args.errors;
315
316 oom:
317 return rc;
318 }
319
320 /*
321 * Look up the extended permissions in avtab and verify that neverallowed
322 * permissions are not granted.
323 */
check_assertion_extended_permissions_avtab(avrule_t * avrule,avtab_t * avtab,unsigned int stype,unsigned int ttype,avtab_key_t * k,policydb_t * p)324 static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab,
325 unsigned int stype, unsigned int ttype,
326 avtab_key_t *k, policydb_t *p)
327 {
328 avtab_ptr_t node;
329 avtab_key_t tmp_key;
330 avtab_extended_perms_t *xperms;
331 av_extended_perms_t *neverallow_xperms = avrule->xperms;
332 ebitmap_t *sattr = &p->type_attr_map[stype];
333 ebitmap_t *tattr = &p->type_attr_map[ttype];
334 ebitmap_node_t *snode, *tnode;
335 unsigned int i, j;
336 int rc = 1;
337
338 memcpy(&tmp_key, k, sizeof(avtab_key_t));
339 tmp_key.specified = AVTAB_XPERMS_ALLOWED;
340
341 ebitmap_for_each_positive_bit(sattr, snode, i) {
342 tmp_key.source_type = i + 1;
343 ebitmap_for_each_positive_bit(tattr, tnode, j) {
344 tmp_key.target_type = j + 1;
345 for (node = avtab_search_node(avtab, &tmp_key);
346 node;
347 node = avtab_search_node_next(node, tmp_key.specified)) {
348 xperms = node->datum.xperms;
349
350 if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
351 && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
352 continue;
353 rc = check_extended_permissions(neverallow_xperms, xperms);
354 if (rc)
355 return rc;
356 }
357 }
358 }
359
360 return rc;
361 }
362
363 /*
364 * When the ioctl permission is granted on an avtab entry that matches an
365 * avrule neverallowxperm entry, enumerate over the matching
366 * source/target/class sets to determine if the extended permissions exist
367 * and if the neverallowed ioctls are granted.
368 *
369 * Four scenarios of interest:
370 * 1. PASS - the ioctl permission is not granted for this source/target/class
371 * This case is handled in check_assertion_avtab_match
372 * 2. PASS - The ioctl permission is granted AND the extended permission
373 * is NOT granted
374 * 3. FAIL - The ioctl permission is granted AND no extended permissions
375 * exist
376 * 4. FAIL - The ioctl permission is granted AND the extended permission is
377 * granted
378 */
check_assertion_extended_permissions(avrule_t * avrule,avtab_t * avtab,avtab_key_t * k,policydb_t * p)379 static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab,
380 avtab_key_t *k, policydb_t *p)
381 {
382 ebitmap_t src_matches, tgt_matches, self_matches;
383 unsigned int i, j;
384 ebitmap_node_t *snode, *tnode;
385 const int is_avrule_self = (avrule->flags & RULE_SELF) != 0;
386 int rc;
387
388 ebitmap_init(&src_matches);
389 ebitmap_init(&tgt_matches);
390 ebitmap_init(&self_matches);
391
392 rc = ebitmap_and(&src_matches, &avrule->stypes.types,
393 &p->attr_type_map[k->source_type - 1]);
394 if (rc < 0)
395 goto oom;
396
397 if (ebitmap_is_empty(&src_matches)) {
398 rc = 0;
399 goto exit;
400 }
401
402 rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types,
403 &p->attr_type_map[k->target_type -1]);
404 if (rc < 0)
405 goto oom;
406
407 if (is_avrule_self) {
408 rc = ebitmap_and(&self_matches, &src_matches, &p->attr_type_map[k->target_type - 1]);
409 if (rc < 0)
410 goto oom;
411
412 if (!ebitmap_is_empty(&self_matches)) {
413 rc = ebitmap_union(&tgt_matches, &self_matches);
414 if (rc < 0)
415 goto oom;
416 }
417 }
418
419 if (ebitmap_is_empty(&tgt_matches)) {
420 rc = 0;
421 goto exit;
422 }
423
424 ebitmap_for_each_positive_bit(&src_matches, snode, i) {
425 ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
426 if (is_avrule_self && i != j)
427 continue;
428 if (check_assertion_extended_permissions_avtab(avrule, avtab, i, j, k, p)) {
429 rc = 1;
430 goto exit;
431 }
432 }
433 }
434
435 rc = 0;
436
437 oom:
438 exit:
439 ebitmap_destroy(&src_matches);
440 ebitmap_destroy(&tgt_matches);
441 ebitmap_destroy(&self_matches);
442 return rc;
443 }
444
check_assertion_self_match(avtab_key_t * k,avrule_t * avrule,policydb_t * p)445 static int check_assertion_self_match(avtab_key_t *k, avrule_t *avrule, policydb_t *p)
446 {
447 ebitmap_t src_matches;
448 int rc;
449
450 /* The key's target must match something in the matches of the avrule's source
451 * and the key's source.
452 */
453
454 rc = ebitmap_and(&src_matches, &avrule->stypes.types, &p->attr_type_map[k->source_type - 1]);
455 if (rc < 0)
456 goto oom;
457
458 if (!ebitmap_match_any(&src_matches, &p->attr_type_map[k->target_type - 1])) {
459 rc = 0;
460 goto nomatch;
461 }
462
463 rc = 1;
464
465 oom:
466 nomatch:
467 ebitmap_destroy(&src_matches);
468 return rc;
469 }
470
check_assertion_avtab_match(avtab_key_t * k,avtab_datum_t * d,void * args)471 static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args)
472 {
473 int rc;
474 struct avtab_match_args *a = (struct avtab_match_args *)args;
475 policydb_t *p = a->p;
476 avrule_t *avrule = a->avrule;
477 avtab_t *avtab = a->avtab;
478
479 if ((k->specified & AVTAB_ALLOWED) == 0)
480 goto nomatch;
481
482 if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
483 goto nomatch;
484
485 if (!ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1]))
486 goto nomatch;
487
488 /* neverallow may have tgts even if it uses SELF */
489 if (!ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1])) {
490 if (avrule->flags == RULE_SELF) {
491 rc = check_assertion_self_match(k, avrule, p);
492 if (rc < 0)
493 goto oom;
494 if (rc == 0)
495 goto nomatch;
496 } else {
497 goto nomatch;
498 }
499 }
500
501 if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
502 rc = check_assertion_extended_permissions(avrule, avtab, k, p);
503 if (rc < 0)
504 goto oom;
505 if (rc == 0)
506 goto nomatch;
507 }
508 return 1;
509
510 nomatch:
511 return 0;
512
513 oom:
514 return rc;
515 }
516
check_assertion(policydb_t * p,avrule_t * avrule)517 int check_assertion(policydb_t *p, avrule_t *avrule)
518 {
519 int rc;
520 struct avtab_match_args args;
521
522 args.handle = NULL;
523 args.p = p;
524 args.avrule = avrule;
525 args.errors = 0;
526 args.avtab = &p->te_avtab;
527
528 rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args);
529
530 if (rc == 0) {
531 args.avtab = &p->te_cond_avtab;
532 rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args);
533 }
534
535 return rc;
536 }
537
check_assertions(sepol_handle_t * handle,policydb_t * p,avrule_t * avrules)538 int check_assertions(sepol_handle_t * handle, policydb_t * p,
539 avrule_t * avrules)
540 {
541 int rc;
542 avrule_t *a;
543 unsigned long errors = 0;
544
545 if (!avrules) {
546 /* Since assertions are stored in avrules, if it is NULL
547 there won't be any to check. This also prevents an invalid
548 free if the avtabs are never initialized */
549 return 0;
550 }
551
552 for (a = avrules; a != NULL; a = a->next) {
553 if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)))
554 continue;
555 rc = check_assertion(p, a);
556 if (rc < 0) {
557 ERR(handle, "Error occurred while checking neverallows");
558 return -1;
559 }
560 if (rc) {
561 rc = report_assertion_failures(handle, p, a);
562 if (rc < 0) {
563 ERR(handle, "Error occurred while checking neverallows");
564 return -1;
565 }
566 errors += rc;
567 }
568 }
569
570 if (errors)
571 ERR(handle, "%lu neverallow failures occurred", errors);
572
573 return errors ? -1 : 0;
574 }
575