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