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_positive_bit(sattr, snode, i) {
161 ebitmap_for_each_positive_bit(tattr, tnode, j) {
162 tmp_key.source_type = i + 1;
163 tmp_key.target_type = j + 1;
164 for (node = avtab_search_node(avtab, &tmp_key);
165 node;
166 node = avtab_search_node_next(node, tmp_key.specified)) {
167 xperms = node->datum.xperms;
168 if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
169 && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
170 continue;
171
172 rc = check_extended_permissions(avrule->xperms, xperms);
173 /* failure on the extended permission check_extended_permissions */
174 if (rc) {
175 extended_permissions_violated(&error, avrule->xperms, xperms);
176 ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
177 "allowxperm %s %s:%s %s;",
178 avrule->source_line, avrule->source_filename, avrule->line,
179 p->p_type_val_to_name[i],
180 p->p_type_val_to_name[j],
181 p->p_class_val_to_name[curperm->tclass - 1],
182 sepol_extended_perms_to_string(&error));
183
184 rc = 0;
185 ret++;
186 }
187 }
188 }
189 }
190
191 /* failure on the regular permissions */
192 if (rc) {
193 ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
194 "allow %s %s:%s {%s };",
195 avrule->source_line, avrule->source_filename, avrule->line,
196 p->p_type_val_to_name[stype],
197 p->p_type_val_to_name[ttype],
198 p->p_class_val_to_name[curperm->tclass - 1],
199 sepol_av_to_string(p, curperm->tclass, perms));
200 ret++;
201
202 }
203
204 return ret;
205 }
206
report_assertion_avtab_matches(avtab_key_t * k,avtab_datum_t * d,void * args)207 static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args)
208 {
209 int rc = 0;
210 struct avtab_match_args *a = (struct avtab_match_args *)args;
211 sepol_handle_t *handle = a->handle;
212 policydb_t *p = a->p;
213 avtab_t *avtab = a->avtab;
214 avrule_t *avrule = a->avrule;
215 class_perm_node_t *cp;
216 uint32_t perms;
217 ebitmap_t src_matches, tgt_matches, self_matches, matches;
218 ebitmap_node_t *snode, *tnode;
219 unsigned int i, j;
220
221 if ((k->specified & AVTAB_ALLOWED) == 0)
222 return 0;
223
224 if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
225 return 0;
226
227 ebitmap_init(&src_matches);
228 ebitmap_init(&tgt_matches);
229 ebitmap_init(&self_matches);
230 ebitmap_init(&matches);
231
232 rc = ebitmap_and(&src_matches, &avrule->stypes.types,
233 &p->attr_type_map[k->source_type - 1]);
234 if (rc)
235 goto oom;
236
237 if (ebitmap_length(&src_matches) == 0)
238 goto exit;
239
240 rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
241 if (rc)
242 goto oom;
243
244 if (avrule->flags == RULE_SELF) {
245 rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1]);
246 if (rc)
247 goto oom;
248 rc = ebitmap_and(&self_matches, &avrule->stypes.types, &matches);
249 if (rc)
250 goto oom;
251
252 if (ebitmap_length(&self_matches) > 0) {
253 rc = ebitmap_union(&tgt_matches, &self_matches);
254 if (rc)
255 goto oom;
256 }
257 }
258
259 if (ebitmap_length(&tgt_matches) == 0)
260 goto exit;
261
262 for (cp = avrule->perms; cp; cp = cp->next) {
263
264 perms = cp->data & d->data;
265 if ((cp->tclass != k->target_class) || !perms) {
266 continue;
267 }
268
269 ebitmap_for_each_positive_bit(&src_matches, snode, i) {
270 ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
271 if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
272 a->errors += report_assertion_extended_permissions(handle,p, avrule,
273 i, j, cp, perms, k, avtab);
274 } else {
275 a->errors++;
276 report_failure(handle, p, avrule, i, j, cp, perms);
277 }
278 }
279 }
280 }
281 goto exit;
282
283 oom:
284 ERR(NULL, "Out of memory - unable to check neverallows");
285
286 exit:
287 ebitmap_destroy(&src_matches);
288 ebitmap_destroy(&tgt_matches);
289 ebitmap_destroy(&self_matches);
290 ebitmap_destroy(&matches);
291 return rc;
292 }
293
report_assertion_failures(sepol_handle_t * handle,policydb_t * p,avrule_t * avrule)294 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 rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args);
305 if (rc)
306 goto oom;
307
308 rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args);
309 if (rc)
310 goto oom;
311
312 return args.errors;
313
314 oom:
315 return rc;
316 }
317
318 /*
319 * Look up the extended permissions in avtab and verify that neverallowed
320 * permissions are not granted.
321 */
check_assertion_extended_permissions_avtab(avrule_t * avrule,avtab_t * avtab,unsigned int stype,unsigned int ttype,avtab_key_t * k,policydb_t * p)322 static int check_assertion_extended_permissions_avtab(avrule_t *avrule, avtab_t *avtab,
323 unsigned int stype, unsigned int ttype,
324 avtab_key_t *k, policydb_t *p)
325 {
326 avtab_ptr_t node;
327 avtab_key_t tmp_key;
328 avtab_extended_perms_t *xperms;
329 av_extended_perms_t *neverallow_xperms = avrule->xperms;
330 ebitmap_t *sattr = &p->type_attr_map[stype];
331 ebitmap_t *tattr = &p->type_attr_map[ttype];
332 ebitmap_node_t *snode, *tnode;
333 unsigned int i, j;
334 int rc = 1;
335
336 memcpy(&tmp_key, k, sizeof(avtab_key_t));
337 tmp_key.specified = AVTAB_XPERMS_ALLOWED;
338
339 ebitmap_for_each_positive_bit(sattr, snode, i) {
340 ebitmap_for_each_positive_bit(tattr, tnode, j) {
341 tmp_key.source_type = i + 1;
342 tmp_key.target_type = j + 1;
343 for (node = avtab_search_node(avtab, &tmp_key);
344 node;
345 node = avtab_search_node_next(node, tmp_key.specified)) {
346 xperms = node->datum.xperms;
347
348 if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
349 && (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
350 continue;
351 rc = check_extended_permissions(neverallow_xperms, xperms);
352 if (rc)
353 break;
354 }
355 }
356 }
357
358 return rc;
359 }
360
361 /*
362 * When the ioctl permission is granted on an avtab entry that matches an
363 * avrule neverallowxperm entry, enumerate over the matching
364 * source/target/class sets to determine if the extended permissions exist
365 * and if the neverallowed ioctls are granted.
366 *
367 * Four scenarios of interest:
368 * 1. PASS - the ioctl permission is not granted for this source/target/class
369 * This case is handled in check_assertion_avtab_match
370 * 2. PASS - The ioctl permission is granted AND the extended permission
371 * is NOT granted
372 * 3. FAIL - The ioctl permission is granted AND no extended permissions
373 * exist
374 * 4. FAIL - The ioctl permission is granted AND the extended permission is
375 * granted
376 */
check_assertion_extended_permissions(avrule_t * avrule,avtab_t * avtab,avtab_key_t * k,policydb_t * p)377 static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab,
378 avtab_key_t *k, policydb_t *p)
379 {
380 ebitmap_t src_matches, tgt_matches, self_matches, matches;
381 unsigned int i, j;
382 ebitmap_node_t *snode, *tnode;
383 class_perm_node_t *cp;
384 int rc;
385 int ret = 1;
386
387 ebitmap_init(&src_matches);
388 ebitmap_init(&tgt_matches);
389 ebitmap_init(&self_matches);
390 ebitmap_init(&matches);
391
392 rc = ebitmap_and(&src_matches, &avrule->stypes.types,
393 &p->attr_type_map[k->source_type - 1]);
394 if (rc)
395 goto oom;
396
397 if (ebitmap_length(&src_matches) == 0)
398 goto exit;
399
400 rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types,
401 &p->attr_type_map[k->target_type -1]);
402 if (rc)
403 goto oom;
404
405 if (avrule->flags == RULE_SELF) {
406 rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1],
407 &p->attr_type_map[k->target_type - 1]);
408 if (rc)
409 goto oom;
410 rc = ebitmap_and(&self_matches, &avrule->stypes.types, &matches);
411 if (rc)
412 goto oom;
413
414 if (ebitmap_length(&self_matches) > 0) {
415 rc = ebitmap_union(&tgt_matches, &self_matches);
416 if (rc)
417 goto oom;
418 }
419 }
420
421 if (ebitmap_length(&tgt_matches) == 0)
422 goto exit;
423
424 for (cp = avrule->perms; cp; cp = cp->next) {
425 if (cp->tclass != k->target_class)
426 continue;
427 ebitmap_for_each_positive_bit(&src_matches, snode, i) {
428 ebitmap_for_each_positive_bit(&tgt_matches, tnode, j) {
429 ret = check_assertion_extended_permissions_avtab(
430 avrule, avtab, i, j, k, p);
431 if (ret)
432 goto exit;
433 }
434 }
435 }
436 goto exit;
437
438 oom:
439 ERR(NULL, "Out of memory - unable to check neverallows");
440
441 exit:
442 ebitmap_destroy(&src_matches);
443 ebitmap_destroy(&tgt_matches);
444 ebitmap_destroy(&matches);
445 return ret;
446 }
447
check_assertion_avtab_match(avtab_key_t * k,avtab_datum_t * d,void * args)448 static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args)
449 {
450 int rc, rc2 = 0;
451 struct avtab_match_args *a = (struct avtab_match_args *)args;
452 policydb_t *p = a->p;
453 avrule_t *avrule = a->avrule;
454 avtab_t *avtab = a->avtab;
455
456 if ((k->specified & AVTAB_ALLOWED) == 0)
457 goto exit;
458
459 if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
460 goto exit;
461
462 rc = ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1]);
463 if (rc == 0)
464 goto exit;
465
466 if (avrule->flags == RULE_SELF) {
467 /* If the neverallow uses SELF, then it is not enough that the
468 * neverallow's source matches the src and tgt of the rule being checked.
469 * It must match the same thing in the src and tgt, so AND the source
470 * and target together and check for a match on the result.
471 */
472 ebitmap_t match;
473 rc = ebitmap_and(&match, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1] );
474 if (rc) {
475 ebitmap_destroy(&match);
476 goto oom;
477 }
478 rc2 = ebitmap_match_any(&avrule->stypes.types, &match);
479 ebitmap_destroy(&match);
480 }
481
482 /* neverallow may have tgts even if it uses SELF */
483 rc = ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
484 if (rc == 0 && rc2 == 0)
485 goto exit;
486
487 if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
488 rc = check_assertion_extended_permissions(avrule, avtab, k, p);
489 if (rc == 0)
490 goto exit;
491 }
492 return 1;
493
494 exit:
495 return 0;
496
497 oom:
498 ERR(NULL, "Out of memory - unable to check neverallows");
499 return rc;
500 }
501
check_assertion(policydb_t * p,avrule_t * avrule)502 int check_assertion(policydb_t *p, avrule_t *avrule)
503 {
504 int rc;
505 struct avtab_match_args args;
506
507 args.handle = NULL;
508 args.p = p;
509 args.avrule = avrule;
510 args.errors = 0;
511 args.avtab = &p->te_avtab;
512
513 rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args);
514
515 if (rc == 0) {
516 args.avtab = &p->te_cond_avtab;
517 rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args);
518 }
519
520 return rc;
521 }
522
check_assertions(sepol_handle_t * handle,policydb_t * p,avrule_t * avrules)523 int check_assertions(sepol_handle_t * handle, policydb_t * p,
524 avrule_t * avrules)
525 {
526 int rc;
527 avrule_t *a;
528 unsigned long errors = 0;
529
530 if (!avrules) {
531 /* Since assertions are stored in avrules, if it is NULL
532 there won't be any to check. This also prevents an invalid
533 free if the avtabs are never initialized */
534 return 0;
535 }
536
537 for (a = avrules; a != NULL; a = a->next) {
538 if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)))
539 continue;
540 rc = check_assertion(p, a);
541 if (rc) {
542 rc = report_assertion_failures(handle, p, a);
543 if (rc < 0) {
544 ERR(handle, "Error occurred while checking neverallows");
545 return -1;
546 }
547 errors += rc;
548 }
549 }
550
551 if (errors)
552 ERR(handle, "%lu neverallow failures occurred", errors);
553
554 return errors ? -1 : 0;
555 }
556