1/* Authors: Karl MacMillan <kmacmillan@tresys.com> 2 * Frank Mayer <mayerf@tresys.com> 3 * 4 * Copyright (C) 2003 - 2004 Tresys Technology, LLC 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, version 2. 8 */ 9 10#include <linux/kernel.h> 11#include <linux/errno.h> 12#include <linux/string.h> 13#include <linux/spinlock.h> 14#include <linux/slab.h> 15 16#include "security.h" 17#include "conditional.h" 18#include "services.h" 19 20/* 21 * cond_evaluate_expr evaluates a conditional expr 22 * in reverse polish notation. It returns true (1), false (0), 23 * or undefined (-1). Undefined occurs when the expression 24 * exceeds the stack depth of COND_EXPR_MAXDEPTH. 25 */ 26static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr) 27{ 28 29 struct cond_expr *cur; 30 int s[COND_EXPR_MAXDEPTH]; 31 int sp = -1; 32 33 for (cur = expr; cur; cur = cur->next) { 34 switch (cur->expr_type) { 35 case COND_BOOL: 36 if (sp == (COND_EXPR_MAXDEPTH - 1)) 37 return -1; 38 sp++; 39 s[sp] = p->bool_val_to_struct[cur->bool - 1]->state; 40 break; 41 case COND_NOT: 42 if (sp < 0) 43 return -1; 44 s[sp] = !s[sp]; 45 break; 46 case COND_OR: 47 if (sp < 1) 48 return -1; 49 sp--; 50 s[sp] |= s[sp + 1]; 51 break; 52 case COND_AND: 53 if (sp < 1) 54 return -1; 55 sp--; 56 s[sp] &= s[sp + 1]; 57 break; 58 case COND_XOR: 59 if (sp < 1) 60 return -1; 61 sp--; 62 s[sp] ^= s[sp + 1]; 63 break; 64 case COND_EQ: 65 if (sp < 1) 66 return -1; 67 sp--; 68 s[sp] = (s[sp] == s[sp + 1]); 69 break; 70 case COND_NEQ: 71 if (sp < 1) 72 return -1; 73 sp--; 74 s[sp] = (s[sp] != s[sp + 1]); 75 break; 76 default: 77 return -1; 78 } 79 } 80 return s[0]; 81} 82 83/* 84 * evaluate_cond_node evaluates the conditional stored in 85 * a struct cond_node and if the result is different than the 86 * current state of the node it sets the rules in the true/false 87 * list appropriately. If the result of the expression is undefined 88 * all of the rules are disabled for safety. 89 */ 90int evaluate_cond_node(struct policydb *p, struct cond_node *node) 91{ 92 int new_state; 93 struct cond_av_list *cur; 94 95 new_state = cond_evaluate_expr(p, node->expr); 96 if (new_state != node->cur_state) { 97 node->cur_state = new_state; 98 if (new_state == -1) 99 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); 100 /* turn the rules on or off */ 101 for (cur = node->true_list; cur; cur = cur->next) { 102 if (new_state <= 0) 103 cur->node->key.specified &= ~AVTAB_ENABLED; 104 else 105 cur->node->key.specified |= AVTAB_ENABLED; 106 } 107 108 for (cur = node->false_list; cur; cur = cur->next) { 109 /* -1 or 1 */ 110 if (new_state) 111 cur->node->key.specified &= ~AVTAB_ENABLED; 112 else 113 cur->node->key.specified |= AVTAB_ENABLED; 114 } 115 } 116 return 0; 117} 118 119int cond_policydb_init(struct policydb *p) 120{ 121 int rc; 122 123 p->bool_val_to_struct = NULL; 124 p->cond_list = NULL; 125 126 rc = avtab_init(&p->te_cond_avtab); 127 if (rc) 128 return rc; 129 130 return 0; 131} 132 133static void cond_av_list_destroy(struct cond_av_list *list) 134{ 135 struct cond_av_list *cur, *next; 136 for (cur = list; cur; cur = next) { 137 next = cur->next; 138 /* the avtab_ptr_t node is destroy by the avtab */ 139 kfree(cur); 140 } 141} 142 143static void cond_node_destroy(struct cond_node *node) 144{ 145 struct cond_expr *cur_expr, *next_expr; 146 147 for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) { 148 next_expr = cur_expr->next; 149 kfree(cur_expr); 150 } 151 cond_av_list_destroy(node->true_list); 152 cond_av_list_destroy(node->false_list); 153 kfree(node); 154} 155 156static void cond_list_destroy(struct cond_node *list) 157{ 158 struct cond_node *next, *cur; 159 160 if (list == NULL) 161 return; 162 163 for (cur = list; cur; cur = next) { 164 next = cur->next; 165 cond_node_destroy(cur); 166 } 167} 168 169void cond_policydb_destroy(struct policydb *p) 170{ 171 kfree(p->bool_val_to_struct); 172 avtab_destroy(&p->te_cond_avtab); 173 cond_list_destroy(p->cond_list); 174} 175 176int cond_init_bool_indexes(struct policydb *p) 177{ 178 kfree(p->bool_val_to_struct); 179 p->bool_val_to_struct = 180 kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum *), GFP_KERNEL); 181 if (!p->bool_val_to_struct) 182 return -ENOMEM; 183 return 0; 184} 185 186int cond_destroy_bool(void *key, void *datum, void *p) 187{ 188 kfree(key); 189 kfree(datum); 190 return 0; 191} 192 193int cond_index_bool(void *key, void *datum, void *datap) 194{ 195 struct policydb *p; 196 struct cond_bool_datum *booldatum; 197 struct flex_array *fa; 198 199 booldatum = datum; 200 p = datap; 201 202 if (!booldatum->value || booldatum->value > p->p_bools.nprim) 203 return -EINVAL; 204 205 fa = p->sym_val_to_name[SYM_BOOLS]; 206 if (flex_array_put_ptr(fa, booldatum->value - 1, key, 207 GFP_KERNEL | __GFP_ZERO)) 208 BUG(); 209 p->bool_val_to_struct[booldatum->value - 1] = booldatum; 210 211 return 0; 212} 213 214static int bool_isvalid(struct cond_bool_datum *b) 215{ 216 if (!(b->state == 0 || b->state == 1)) 217 return 0; 218 return 1; 219} 220 221int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) 222{ 223 char *key = NULL; 224 struct cond_bool_datum *booldatum; 225 __le32 buf[3]; 226 u32 len; 227 int rc; 228 229 booldatum = kzalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); 230 if (!booldatum) 231 return -ENOMEM; 232 233 rc = next_entry(buf, fp, sizeof buf); 234 if (rc) 235 goto err; 236 237 booldatum->value = le32_to_cpu(buf[0]); 238 booldatum->state = le32_to_cpu(buf[1]); 239 240 rc = -EINVAL; 241 if (!bool_isvalid(booldatum)) 242 goto err; 243 244 len = le32_to_cpu(buf[2]); 245 246 rc = -ENOMEM; 247 key = kmalloc(len + 1, GFP_KERNEL); 248 if (!key) 249 goto err; 250 rc = next_entry(key, fp, len); 251 if (rc) 252 goto err; 253 key[len] = '\0'; 254 rc = hashtab_insert(h, key, booldatum); 255 if (rc) 256 goto err; 257 258 return 0; 259err: 260 cond_destroy_bool(key, booldatum, NULL); 261 return rc; 262} 263 264struct cond_insertf_data { 265 struct policydb *p; 266 struct cond_av_list *other; 267 struct cond_av_list *head; 268 struct cond_av_list *tail; 269}; 270 271static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr) 272{ 273 struct cond_insertf_data *data = ptr; 274 struct policydb *p = data->p; 275 struct cond_av_list *other = data->other, *list, *cur; 276 struct avtab_node *node_ptr; 277 u8 found; 278 int rc = -EINVAL; 279 280 /* 281 * For type rules we have to make certain there aren't any 282 * conflicting rules by searching the te_avtab and the 283 * cond_te_avtab. 284 */ 285 if (k->specified & AVTAB_TYPE) { 286 if (avtab_search(&p->te_avtab, k)) { 287 printk(KERN_ERR "SELinux: type rule already exists outside of a conditional.\n"); 288 goto err; 289 } 290 /* 291 * If we are reading the false list other will be a pointer to 292 * the true list. We can have duplicate entries if there is only 293 * 1 other entry and it is in our true list. 294 * 295 * If we are reading the true list (other == NULL) there shouldn't 296 * be any other entries. 297 */ 298 if (other) { 299 node_ptr = avtab_search_node(&p->te_cond_avtab, k); 300 if (node_ptr) { 301 if (avtab_search_node_next(node_ptr, k->specified)) { 302 printk(KERN_ERR "SELinux: too many conflicting type rules.\n"); 303 goto err; 304 } 305 found = 0; 306 for (cur = other; cur; cur = cur->next) { 307 if (cur->node == node_ptr) { 308 found = 1; 309 break; 310 } 311 } 312 if (!found) { 313 printk(KERN_ERR "SELinux: conflicting type rules.\n"); 314 goto err; 315 } 316 } 317 } else { 318 if (avtab_search(&p->te_cond_avtab, k)) { 319 printk(KERN_ERR "SELinux: conflicting type rules when adding type rule for true.\n"); 320 goto err; 321 } 322 } 323 } 324 325 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); 326 if (!node_ptr) { 327 printk(KERN_ERR "SELinux: could not insert rule.\n"); 328 rc = -ENOMEM; 329 goto err; 330 } 331 332 list = kzalloc(sizeof(struct cond_av_list), GFP_KERNEL); 333 if (!list) { 334 rc = -ENOMEM; 335 goto err; 336 } 337 338 list->node = node_ptr; 339 if (!data->head) 340 data->head = list; 341 else 342 data->tail->next = list; 343 data->tail = list; 344 return 0; 345 346err: 347 cond_av_list_destroy(data->head); 348 data->head = NULL; 349 return rc; 350} 351 352static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) 353{ 354 int i, rc; 355 __le32 buf[1]; 356 u32 len; 357 struct cond_insertf_data data; 358 359 *ret_list = NULL; 360 361 len = 0; 362 rc = next_entry(buf, fp, sizeof(u32)); 363 if (rc) 364 return rc; 365 366 len = le32_to_cpu(buf[0]); 367 if (len == 0) 368 return 0; 369 370 data.p = p; 371 data.other = other; 372 data.head = NULL; 373 data.tail = NULL; 374 for (i = 0; i < len; i++) { 375 rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf, 376 &data); 377 if (rc) 378 return rc; 379 } 380 381 *ret_list = data.head; 382 return 0; 383} 384 385static int expr_isvalid(struct policydb *p, struct cond_expr *expr) 386{ 387 if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { 388 printk(KERN_ERR "SELinux: conditional expressions uses unknown operator.\n"); 389 return 0; 390 } 391 392 if (expr->bool > p->p_bools.nprim) { 393 printk(KERN_ERR "SELinux: conditional expressions uses unknown bool.\n"); 394 return 0; 395 } 396 return 1; 397} 398 399static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) 400{ 401 __le32 buf[2]; 402 u32 len, i; 403 int rc; 404 struct cond_expr *expr = NULL, *last = NULL; 405 406 rc = next_entry(buf, fp, sizeof(u32) * 2); 407 if (rc) 408 goto err; 409 410 node->cur_state = le32_to_cpu(buf[0]); 411 412 /* expr */ 413 len = le32_to_cpu(buf[1]); 414 415 for (i = 0; i < len; i++) { 416 rc = next_entry(buf, fp, sizeof(u32) * 2); 417 if (rc) 418 goto err; 419 420 rc = -ENOMEM; 421 expr = kzalloc(sizeof(struct cond_expr), GFP_KERNEL); 422 if (!expr) 423 goto err; 424 425 expr->expr_type = le32_to_cpu(buf[0]); 426 expr->bool = le32_to_cpu(buf[1]); 427 428 if (!expr_isvalid(p, expr)) { 429 rc = -EINVAL; 430 kfree(expr); 431 goto err; 432 } 433 434 if (i == 0) 435 node->expr = expr; 436 else 437 last->next = expr; 438 last = expr; 439 } 440 441 rc = cond_read_av_list(p, fp, &node->true_list, NULL); 442 if (rc) 443 goto err; 444 rc = cond_read_av_list(p, fp, &node->false_list, node->true_list); 445 if (rc) 446 goto err; 447 return 0; 448err: 449 cond_node_destroy(node); 450 return rc; 451} 452 453int cond_read_list(struct policydb *p, void *fp) 454{ 455 struct cond_node *node, *last = NULL; 456 __le32 buf[1]; 457 u32 i, len; 458 int rc; 459 460 rc = next_entry(buf, fp, sizeof buf); 461 if (rc) 462 return rc; 463 464 len = le32_to_cpu(buf[0]); 465 466 rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel); 467 if (rc) 468 goto err; 469 470 for (i = 0; i < len; i++) { 471 rc = -ENOMEM; 472 node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); 473 if (!node) 474 goto err; 475 476 rc = cond_read_node(p, node, fp); 477 if (rc) 478 goto err; 479 480 if (i == 0) 481 p->cond_list = node; 482 else 483 last->next = node; 484 last = node; 485 } 486 return 0; 487err: 488 cond_list_destroy(p->cond_list); 489 p->cond_list = NULL; 490 return rc; 491} 492 493int cond_write_bool(void *vkey, void *datum, void *ptr) 494{ 495 char *key = vkey; 496 struct cond_bool_datum *booldatum = datum; 497 struct policy_data *pd = ptr; 498 void *fp = pd->fp; 499 __le32 buf[3]; 500 u32 len; 501 int rc; 502 503 len = strlen(key); 504 buf[0] = cpu_to_le32(booldatum->value); 505 buf[1] = cpu_to_le32(booldatum->state); 506 buf[2] = cpu_to_le32(len); 507 rc = put_entry(buf, sizeof(u32), 3, fp); 508 if (rc) 509 return rc; 510 rc = put_entry(key, 1, len, fp); 511 if (rc) 512 return rc; 513 return 0; 514} 515 516/* 517 * cond_write_cond_av_list doesn't write out the av_list nodes. 518 * Instead it writes out the key/value pairs from the avtab. This 519 * is necessary because there is no way to uniquely identifying rules 520 * in the avtab so it is not possible to associate individual rules 521 * in the avtab with a conditional without saving them as part of 522 * the conditional. This means that the avtab with the conditional 523 * rules will not be saved but will be rebuilt on policy load. 524 */ 525static int cond_write_av_list(struct policydb *p, 526 struct cond_av_list *list, struct policy_file *fp) 527{ 528 __le32 buf[1]; 529 struct cond_av_list *cur_list; 530 u32 len; 531 int rc; 532 533 len = 0; 534 for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) 535 len++; 536 537 buf[0] = cpu_to_le32(len); 538 rc = put_entry(buf, sizeof(u32), 1, fp); 539 if (rc) 540 return rc; 541 542 if (len == 0) 543 return 0; 544 545 for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) { 546 rc = avtab_write_item(p, cur_list->node, fp); 547 if (rc) 548 return rc; 549 } 550 551 return 0; 552} 553 554static int cond_write_node(struct policydb *p, struct cond_node *node, 555 struct policy_file *fp) 556{ 557 struct cond_expr *cur_expr; 558 __le32 buf[2]; 559 int rc; 560 u32 len = 0; 561 562 buf[0] = cpu_to_le32(node->cur_state); 563 rc = put_entry(buf, sizeof(u32), 1, fp); 564 if (rc) 565 return rc; 566 567 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) 568 len++; 569 570 buf[0] = cpu_to_le32(len); 571 rc = put_entry(buf, sizeof(u32), 1, fp); 572 if (rc) 573 return rc; 574 575 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) { 576 buf[0] = cpu_to_le32(cur_expr->expr_type); 577 buf[1] = cpu_to_le32(cur_expr->bool); 578 rc = put_entry(buf, sizeof(u32), 2, fp); 579 if (rc) 580 return rc; 581 } 582 583 rc = cond_write_av_list(p, node->true_list, fp); 584 if (rc) 585 return rc; 586 rc = cond_write_av_list(p, node->false_list, fp); 587 if (rc) 588 return rc; 589 590 return 0; 591} 592 593int cond_write_list(struct policydb *p, struct cond_node *list, void *fp) 594{ 595 struct cond_node *cur; 596 u32 len; 597 __le32 buf[1]; 598 int rc; 599 600 len = 0; 601 for (cur = list; cur != NULL; cur = cur->next) 602 len++; 603 buf[0] = cpu_to_le32(len); 604 rc = put_entry(buf, sizeof(u32), 1, fp); 605 if (rc) 606 return rc; 607 608 for (cur = list; cur != NULL; cur = cur->next) { 609 rc = cond_write_node(p, cur, fp); 610 if (rc) 611 return rc; 612 } 613 614 return 0; 615} 616 617void cond_compute_xperms(struct avtab *ctab, struct avtab_key *key, 618 struct extended_perms_decision *xpermd) 619{ 620 struct avtab_node *node; 621 622 if (!ctab || !key || !xpermd) 623 return; 624 625 for (node = avtab_search_node(ctab, key); node; 626 node = avtab_search_node_next(node, key->specified)) { 627 if (node->key.specified & AVTAB_ENABLED) 628 services_compute_xperms_decision(xpermd, node); 629 } 630 return; 631 632} 633/* Determine whether additional permissions are granted by the conditional 634 * av table, and if so, add them to the result 635 */ 636void cond_compute_av(struct avtab *ctab, struct avtab_key *key, 637 struct av_decision *avd, struct extended_perms *xperms) 638{ 639 struct avtab_node *node; 640 641 if (!ctab || !key || !avd) 642 return; 643 644 for (node = avtab_search_node(ctab, key); node; 645 node = avtab_search_node_next(node, key->specified)) { 646 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == 647 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) 648 avd->allowed |= node->datum.u.data; 649 if ((u16)(AVTAB_AUDITDENY|AVTAB_ENABLED) == 650 (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) 651 /* Since a '0' in an auditdeny mask represents a 652 * permission we do NOT want to audit (dontaudit), we use 653 * the '&' operand to ensure that all '0's in the mask 654 * are retained (much unlike the allow and auditallow cases). 655 */ 656 avd->auditdeny &= node->datum.u.data; 657 if ((u16)(AVTAB_AUDITALLOW|AVTAB_ENABLED) == 658 (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) 659 avd->auditallow |= node->datum.u.data; 660 if (xperms && (node->key.specified & AVTAB_ENABLED) && 661 (node->key.specified & AVTAB_XPERMS)) 662 services_compute_xperms_drivers(xperms, node); 663 } 664 return; 665} 666