1 #include <cil/android.h> 2 #include <sepol/policydb/hashtab.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include "cil_build_ast.h" 7 #include "cil_internal.h" 8 #include "cil_strpool.h" 9 #include "cil_symtab.h" 10 #include "cil_tree.h" 11 12 #define VER_MAP_SZ (1 << 12) 13 14 /* added to hashmap - currently unused as hashmap is used as a set */ 15 struct version_datum { 16 struct cil_db *db; 17 struct cil_tree_node *ast_node; 18 char *orig_name; 19 }; 20 21 struct version_args { 22 struct cil_db *db; 23 hashtab_t vers_map; 24 const char *num; 25 }; 26 27 enum plat_flavor { 28 PLAT_NONE = 0, 29 PLAT_TYPE, 30 PLAT_ATTRIB 31 }; 32 33 static unsigned int ver_map_hash_val(hashtab_t h, const_hashtab_key_t key) 34 { 35 /* from cil_stpool.c */ 36 char *p, *keyp; 37 size_t size; 38 unsigned int val; 39 40 val = 0; 41 keyp = (char*)key; 42 size = strlen(keyp); 43 for (p = keyp; ((size_t) (p - keyp)) < size; p++) 44 val = 45 (val << 4 | (val >> (8 * sizeof(unsigned int) - 4))) ^ (*p); 46 return val & (h->size - 1); 47 } 48 49 50 static int ver_map_key_cmp(hashtab_t h __attribute__ ((unused)), 51 const_hashtab_key_t key1, const_hashtab_key_t key2) 52 { 53 /* hashtab_key_t is just a const char* underneath */ 54 return strcmp(key1, key2); 55 } 56 57 /* 58 * version_datum pointers all refer to memory owned elsewhere, so just free the 59 * datum itself. 60 */ 61 static int ver_map_entry_destroy(__attribute__ ((unused))hashtab_key_t k, 62 hashtab_datum_t d, __attribute__ ((unused))void *args) 63 { 64 free(d); 65 return 0; 66 } 67 68 static void ver_map_destroy(hashtab_t h) 69 { 70 hashtab_map(h, ver_map_entry_destroy, NULL); 71 hashtab_destroy(h); 72 } 73 74 static int __extract_attributees_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) 75 { 76 int rc = SEPOL_ERR; 77 struct version_args *args = (struct version_args *) extra_args; 78 char *key; 79 struct version_datum *datum; 80 81 if (node == NULL || finished == NULL || extra_args == NULL) { 82 goto exit; 83 } 84 85 switch (node->flavor) { 86 case CIL_ROLE: 87 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n", 88 CIL_KEY_ROLE, node->line); 89 rc = SEPOL_ERR; 90 break; 91 case CIL_TYPE: 92 case CIL_TYPEATTRIBUTE: 93 datum = cil_malloc(sizeof(*datum)); 94 datum->db = args->db; 95 datum->ast_node = node; 96 datum->orig_name = DATUM(node->data)->name; 97 key = datum->orig_name; 98 if (!strncmp(key, "base_typeattr_", 14)) { 99 /* checkpolicy creates base attributes which are just typeattributesets, 100 of the existing types and attributes. These may be differnt in 101 every checkpolicy output, ignore them here, they'll be dealt with 102 as a special case when attributizing. */ 103 } else { 104 rc = hashtab_insert(args->vers_map, (hashtab_key_t) key, (hashtab_datum_t) datum); 105 if (rc != SEPOL_OK) { 106 goto exit; 107 } 108 } 109 break; 110 case CIL_TYPEALIAS: 111 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n", 112 CIL_KEY_TYPEALIAS, node->line); 113 goto exit; 114 break; 115 case CIL_TYPEPERMISSIVE: 116 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n", 117 CIL_KEY_TYPEPERMISSIVE, node->line); 118 goto exit; 119 break; 120 case CIL_NAMETYPETRANSITION: 121 case CIL_TYPE_RULE: 122 cil_log(CIL_ERR, "%s unsupported statement in attributee policy (line %d)\n", 123 CIL_KEY_TYPETRANSITION, node->line); 124 goto exit; 125 break; 126 default: 127 break; 128 } 129 return SEPOL_OK; 130 exit: 131 return rc; 132 } 133 134 /* 135 * For the given db, with an already-built AST, fill the vers_map hash table 136 * with every encountered type and attribute. This could eventually be expanded 137 * to include other language constructs, such as users and roles, in which case 138 * multiple hash tables would be needed. These tables can then be used by 139 * attributize() to change all references to these types. 140 */ 141 int cil_extract_attributees(struct cil_db *db, hashtab_t vers_map) 142 { 143 /* walk ast. */ 144 int rc = SEPOL_ERR; 145 struct version_args extra_args; 146 extra_args.db = db; 147 extra_args.vers_map = vers_map; 148 extra_args.num = NULL; 149 rc = cil_tree_walk(db->ast->root, __extract_attributees_helper, NULL, NULL, &extra_args); 150 if (rc != SEPOL_OK) { 151 goto exit; 152 } 153 154 return SEPOL_OK; 155 exit: 156 return rc; 157 } 158 159 static enum plat_flavor __cil_get_plat_flavor(hashtab_t vers_map, hashtab_key_t key) 160 { 161 enum plat_flavor rc; 162 struct version_datum *vers_datum; 163 164 vers_datum = (struct version_datum *)hashtab_search(vers_map, key); 165 if (vers_datum == NULL) { 166 return PLAT_NONE; 167 } 168 switch (vers_datum->ast_node->flavor) { 169 case CIL_TYPE: 170 rc = PLAT_TYPE; 171 break; 172 case CIL_TYPEATTRIBUTE: 173 rc = PLAT_ATTRIB; 174 break; 175 default: 176 rc = PLAT_NONE; 177 break; 178 } 179 return rc; 180 } 181 182 /* 183 * Takes the old name and version string and creates a new strpool entry by 184 * combining them. 185 */ 186 static char *__cil_attrib_get_versname(char *old, const char *vers) 187 { 188 size_t len = 0; 189 char *tmp_new = NULL; 190 char *final; 191 192 len += strlen(old) + strlen(vers) + 2; 193 tmp_new = cil_malloc(len); 194 snprintf(tmp_new, len, "%s_%s", old, vers); 195 final = cil_strpool_add(tmp_new); 196 free(tmp_new); 197 return final; 198 } 199 200 /* 201 * Change type to attribute - create new versioned name based on old, create 202 * typeattribute node and replace existing type node. 203 */ 204 static int __cil_attrib_convert_type(struct cil_tree_node *node, struct version_args *args) 205 { 206 int rc = SEPOL_ERR; 207 struct cil_type *type = (struct cil_type *)node->data; 208 struct cil_typeattribute *typeattr = NULL; 209 char *new_key; 210 211 cil_typeattribute_init(&typeattr); 212 213 new_key = __cil_attrib_get_versname(type->datum.name, args->num); 214 215 cil_symtab_datum_remove_node(&type->datum, node); 216 cil_destroy_type(type); 217 218 rc = cil_gen_node(args->db, node, (struct cil_symtab_datum *) typeattr, 219 new_key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE); 220 if (rc != SEPOL_OK) { 221 goto exit; 222 } 223 224 return SEPOL_OK; 225 exit: 226 return rc; 227 } 228 229 /* 230 * Update datum - create new key, remove entry under old key, 231 * update entry, and insert under new key 232 */ 233 static int __cil_attrib_swap_symtab_key(struct cil_tree_node *node, char *old_key, 234 const char *num) 235 { 236 int rc = SEPOL_ERR; 237 char *new_key; 238 symtab_t *symtab; 239 struct cil_symtab_datum *datum = (struct cil_symtab_datum *) node->data; 240 241 new_key = __cil_attrib_get_versname(old_key, num); 242 243 symtab = datum->symtab; 244 245 /* TODO: remove, but what happens to other nodes on this datum ?*/ 246 cil_list_remove(datum->nodes, CIL_NODE, node, 0); 247 cil_symtab_remove_datum(datum); 248 249 rc = cil_symtab_insert(symtab, new_key, datum, node); 250 251 if (rc != SEPOL_OK) { 252 goto exit; 253 } 254 255 return SEPOL_OK; 256 exit: 257 return rc; 258 } 259 260 /* 261 * expressions may contains strings which are not in the type-attribute 262 * namespace, so this is not a general cil_expr attributizer. 263 * TODO: add support for other types of expressions which may contain types. 264 */ 265 static int cil_attrib_type_expr(struct cil_list *expr_str, struct version_args *args) 266 { 267 int rc = SEPOL_ERR; 268 struct cil_list_item *curr = NULL; 269 char *new; 270 hashtab_key_t key; 271 272 /* iterate through cil_list, replacing types */ 273 cil_list_for_each(curr, expr_str) { 274 switch(curr->flavor) { 275 case CIL_LIST: 276 rc = cil_attrib_type_expr((struct cil_list *)curr->data, args); 277 if (rc != SEPOL_OK) 278 goto exit; 279 break; 280 case CIL_STRING: 281 key = (hashtab_key_t) curr->data; 282 enum plat_flavor pf = __cil_get_plat_flavor(args->vers_map, key); 283 if (!strncmp(curr->data, "base_typeattr_", 14) || pf == PLAT_TYPE) { 284 new = __cil_attrib_get_versname((char *) curr->data, args->num); 285 curr->data = (void *) new; 286 } 287 break; 288 case CIL_DATUM: 289 cil_log(CIL_ERR, "AST already resolved. Not yet supported.\n"); 290 rc = SEPOL_ERR; 291 goto exit; 292 break; 293 default: 294 break; 295 } 296 } 297 298 return SEPOL_OK; 299 exit: 300 return rc; 301 } 302 303 static int cil_attrib_check_context(struct cil_context *ctxt, struct version_args *args) 304 { 305 int rc = SEPOL_ERR; 306 hashtab_key_t key; 307 308 if (ctxt->type != NULL) { 309 cil_log(CIL_ERR, "AST already resolved. Not yet supported.\n"); 310 goto exit; 311 } 312 313 key = (hashtab_key_t) ctxt->type_str; 314 if (__cil_get_plat_flavor(args->vers_map, key) != PLAT_NONE) { 315 /* TODO: reinstate check, but leave out for now 316 cil_log(CIL_ERR, "AST contains context with platform public type: %s\n", 317 ctxt->type_str); 318 rc = SEPOL_ERR; 319 goto exit; */ 320 } 321 322 return SEPOL_OK; 323 exit: 324 return rc; 325 } 326 327 static int cil_attrib_sidcontext(struct cil_tree_node *node, struct version_args *args) 328 { 329 int rc = SEPOL_ERR; 330 struct cil_sidcontext *sidcon = (struct cil_sidcontext *)node->data; 331 332 if (sidcon->context_str == NULL) { 333 /* sidcon contains an anon context, which needs to have type checked */ 334 rc = cil_attrib_check_context(sidcon->context, args); 335 if (rc != SEPOL_OK) { 336 goto exit; 337 } 338 } 339 340 return SEPOL_OK; 341 exit: 342 return rc; 343 } 344 345 static int cil_attrib_context(struct cil_tree_node *node, struct version_args *args) 346 { 347 struct cil_context *ctxt = (struct cil_context *)node->data; 348 349 return cil_attrib_check_context(ctxt, args); 350 } 351 352 static int cil_attrib_roletype(struct cil_tree_node *node, 353 __attribute__((unused)) struct version_args *args) 354 { 355 int rc = SEPOL_ERR; 356 char *key; 357 struct cil_roletype *roletype = (struct cil_roletype *)node->data; 358 359 if (roletype->role) { 360 cil_log(CIL_ERR, "AST already resolved. !!! Not yet supported.\n"); 361 goto exit; 362 } 363 key = roletype->type_str; 364 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { 365 roletype->type_str = __cil_attrib_get_versname(key, args->num); 366 } 367 368 return SEPOL_OK; 369 exit: 370 return rc; 371 } 372 373 static int cil_attrib_type(struct cil_tree_node *node, struct version_args *args) 374 { 375 int rc = SEPOL_ERR; 376 struct cil_type *type = (struct cil_type *)node->data; 377 char *key = type->datum.name; 378 379 if (type->value) { 380 cil_log(CIL_ERR, "AST already resolved. !!! Not yet supported.\n"); 381 goto exit; 382 } 383 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { 384 rc = __cil_attrib_convert_type(node, args); 385 if (rc != SEPOL_OK) { 386 goto exit; 387 } 388 } 389 390 return SEPOL_OK; 391 exit: 392 return rc; 393 } 394 395 static int cil_attrib_typepermissive(struct cil_tree_node *node, 396 struct version_args *args __attribute__ ((unused))) 397 { 398 struct cil_typepermissive *typeperm = (struct cil_typepermissive *)node->data; 399 400 if (typeperm->type != NULL) { 401 cil_log(CIL_ERR, "AST already resolved. ### Not yet supported.\n"); 402 return SEPOL_ERR; 403 } 404 405 return SEPOL_OK; 406 } 407 408 static int cil_attrib_typeattribute(struct cil_tree_node *node, struct version_args *args) 409 { 410 int rc = SEPOL_ERR; 411 struct cil_typeattribute *typeattr = (struct cil_typeattribute *)node->data; 412 char *key = typeattr->datum.name; 413 414 if (typeattr->types) { 415 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", 416 node->line); 417 goto exit; 418 } 419 if (!strncmp(key, "base_typeattr_", 14)) { 420 rc = __cil_attrib_swap_symtab_key(node, key, args->num); 421 if (rc != SEPOL_OK) { 422 goto exit; 423 } 424 } else if (__cil_get_plat_flavor(args->vers_map, key) == PLAT_ATTRIB) { 425 // platform attribute declaration to be provided by platform policy 426 cil_symtab_datum_remove_node(&typeattr->datum, node); 427 cil_destroy_typeattribute(typeattr); 428 node->flavor = CIL_NONE; // traversal relies on this node sticking around, empty it. 429 } 430 431 return SEPOL_OK; 432 exit: 433 return rc; 434 } 435 436 static int cil_attrib_typeattributeset(struct cil_tree_node *node, struct version_args *args) 437 { 438 int rc = SEPOL_ERR; 439 char *key; 440 struct cil_typeattributeset *typeattrset = (struct cil_typeattributeset *) node->data; 441 442 if (typeattrset->datum_expr != NULL) { 443 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", 444 node->line); 445 goto exit; 446 } 447 448 key = typeattrset->attr_str; 449 /* first check to see if the attribute to which this set belongs is versioned */ 450 if (!strncmp(key, "base_typeattr_", 14)) { 451 typeattrset->attr_str = __cil_attrib_get_versname(key, args->num); 452 } 453 454 rc = cil_attrib_type_expr(typeattrset->str_expr, args); 455 if (rc != SEPOL_OK) { 456 goto exit; 457 } 458 459 return SEPOL_OK; 460 exit: 461 return rc; 462 } 463 464 static int cil_attrib_typealiasactual(struct cil_tree_node *node, struct version_args *args) 465 { 466 int rc = SEPOL_ERR; 467 char *key; 468 struct cil_aliasactual *aliasact = (struct cil_aliasactual *)node->data; 469 470 key = aliasact->actual_str; 471 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) != PLAT_NONE) { 472 cil_log(CIL_ERR, "%s with platform public type not allowed (line %d)\n", 473 CIL_KEY_TYPEALIASACTUAL, node->line); 474 goto exit; 475 } 476 477 return SEPOL_OK; 478 exit: 479 return rc; 480 } 481 482 static int cil_attrib_nametypetransition(struct cil_tree_node *node, struct version_args *args) 483 { 484 int rc = SEPOL_ERR; 485 char *key; 486 struct cil_nametypetransition *namettrans = (struct cil_nametypetransition *)node->data; 487 488 if (namettrans->src != NULL) { 489 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", 490 node->line); 491 goto exit; 492 } 493 key = namettrans->src_str; 494 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { 495 namettrans->src_str = __cil_attrib_get_versname(key, args->num); 496 } 497 498 key = namettrans->tgt_str; 499 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { 500 namettrans->tgt_str = __cil_attrib_get_versname(key, args->num); 501 } 502 503 return SEPOL_OK; 504 exit: 505 return rc; 506 } 507 508 /* 509 * This is exactly the same as cil_attrib_nametypetransition, but the struct 510 * layouts differ, so we can't reuse it. 511 */ 512 static int cil_attrib_type_rule(struct cil_tree_node *node, struct version_args *args) 513 { 514 int rc = SEPOL_ERR; 515 char *key; 516 struct cil_type_rule *type_rule = (struct cil_type_rule *)node->data; 517 518 if (type_rule->src != NULL) { 519 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", 520 node->line); 521 goto exit; 522 } 523 key = type_rule->src_str; 524 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { 525 type_rule->src_str = __cil_attrib_get_versname(key, args->num); 526 } 527 528 key = type_rule->tgt_str; 529 if (__cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { 530 type_rule->tgt_str = __cil_attrib_get_versname(key, args->num); 531 } 532 533 return SEPOL_OK; 534 exit: 535 return rc; 536 } 537 538 static int cil_attrib_avrule(struct cil_tree_node *node, struct version_args *args) 539 { 540 int rc = SEPOL_ERR; 541 char *key; 542 struct cil_avrule *avrule = (struct cil_avrule *)node->data; 543 544 if (avrule->src != NULL) { 545 cil_log(CIL_ERR, "AST already resolved. Not yet supported (line %d).\n", 546 node->line); 547 goto exit; 548 } 549 550 key = avrule->src_str; 551 if (!strncmp(key, "base_typeattr_", 14) || 552 __cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { 553 avrule->src_str = __cil_attrib_get_versname(key, args->num); 554 } 555 556 key = avrule->tgt_str; 557 if (!strncmp(key, "base_typeattr_", 14) || 558 __cil_get_plat_flavor(args->vers_map, (hashtab_key_t) key) == PLAT_TYPE) { 559 avrule->tgt_str = __cil_attrib_get_versname(key, args->num); 560 } 561 562 return SEPOL_OK; 563 exit: 564 return rc; 565 } 566 567 static int cil_attrib_genfscon(struct cil_tree_node *node, struct version_args *args) 568 { 569 int rc = SEPOL_ERR; 570 571 struct cil_genfscon *genfscon = (struct cil_genfscon *)node->data; 572 573 if (genfscon->context_str == NULL) { 574 /* genfscon contains an anon context, which needs to have type checked */ 575 rc = cil_attrib_check_context(genfscon->context, args); 576 if (rc != SEPOL_OK) { 577 goto exit; 578 } 579 } 580 581 return SEPOL_OK; 582 exit: 583 return rc; 584 } 585 586 static int cil_attrib_fsuse(struct cil_tree_node *node, struct version_args *args) 587 { 588 int rc = SEPOL_ERR; 589 struct cil_fsuse *fsuse = (struct cil_fsuse *)node->data; 590 591 if (fsuse->context_str == NULL) { 592 /* fsuse contains an anon context, which needs to have type checked */ 593 rc = cil_attrib_check_context(fsuse->context, args); 594 if (rc != SEPOL_OK) { 595 goto exit; 596 } 597 } 598 599 return SEPOL_OK; 600 exit: 601 return rc; 602 } 603 604 static int __attributize_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args) 605 { 606 int rc = SEPOL_ERR; 607 struct version_args *args = (struct version_args *) extra_args; 608 609 if (node == NULL || finished == NULL || extra_args == NULL) { 610 goto exit; 611 } 612 613 switch (node->flavor) { 614 case CIL_SIDCONTEXT: 615 /* contains type, but shouldn't involve an attributized type, maybe add 616 a check on type and error if it conflicts */ 617 rc = cil_attrib_sidcontext(node, args); 618 if (rc != SEPOL_OK) { 619 goto exit; 620 } 621 break; 622 case CIL_ROLE: 623 cil_log(CIL_ERR, "%s declaration illegal non-platform policy (line %d)\n", 624 CIL_KEY_ROLE, node->line); 625 rc = SEPOL_ERR; 626 break; 627 case CIL_ROLETYPE: 628 /* Yes, this is needed if we support roletype in non-platform policy. 629 type_id can be type, typealias or typeattr */ 630 rc = cil_attrib_roletype(node, args); 631 if (rc != SEPOL_OK) { 632 goto exit; 633 } 634 break; 635 case CIL_ROLEATTRIBUTE: 636 /* don't think this is needed, only used for cil_gen_req, and we aren't 637 yet supporting roles in non-platform policy. */ 638 break; 639 case CIL_TYPE: 640 /* conver to attribute if in policy */ 641 rc = cil_attrib_type(node, args); 642 if (rc != SEPOL_OK) { 643 goto exit; 644 } 645 break; 646 case CIL_TYPEPERMISSIVE: 647 rc = cil_attrib_typepermissive(node, args); 648 if (rc != SEPOL_OK) { 649 goto exit; 650 } 651 break; 652 case CIL_TYPEATTRIBUTE: 653 rc = cil_attrib_typeattribute(node, args); 654 if (rc != SEPOL_OK) { 655 goto exit; 656 } 657 break; 658 case CIL_TYPEATTRIBUTESET: 659 rc = cil_attrib_typeattributeset(node, args); 660 if (rc != SEPOL_OK) { 661 goto exit; 662 } 663 break; 664 case CIL_TYPEALIASACTUAL: 665 /* this will break on an attributized type - identify it and throw error */ 666 rc = cil_attrib_typealiasactual(node, args); 667 if (rc != SEPOL_OK) { 668 goto exit; 669 } 670 break; 671 case CIL_NAMETYPETRANSITION: 672 /* not allowed in plat-policy. Types present, throw error if attributee */ 673 rc = cil_attrib_nametypetransition(node, args); 674 if (rc != SEPOL_OK) { 675 goto exit; 676 } 677 break; 678 case CIL_TYPE_RULE: 679 /* not allowed in plat-policy. Types present, throw error if attributee */ 680 rc = cil_attrib_type_rule(node, args); 681 if (rc != SEPOL_OK) { 682 goto exit; 683 } 684 break; 685 case CIL_AVRULE: 686 case CIL_AVRULEX: 687 rc = cil_attrib_avrule(node, args); 688 if (rc != SEPOL_OK) { 689 goto exit; 690 } 691 break; 692 case CIL_CONTEXT: 693 /* not currently found in AOSP policy, but if found would need to be 694 checked to not be attributee */ 695 rc = cil_attrib_context(node, args); 696 if (rc != SEPOL_OK) { 697 goto exit; 698 } 699 break; 700 case CIL_GENFSCON: 701 /* not allowed in plat-policy, but types present, throw error if attributee */ 702 rc = cil_attrib_genfscon(node, args); 703 if (rc != SEPOL_OK) { 704 goto exit; 705 } 706 break; 707 case CIL_FILECON: 708 case CIL_NODECON: 709 case CIL_PORTCON: 710 case CIL_PIRQCON: 711 case CIL_IOMEMCON: 712 case CIL_IOPORTCON: 713 case CIL_PCIDEVICECON: 714 case CIL_DEVICETREECON: 715 case CIL_VALIDATETRANS: 716 case CIL_MLSVALIDATETRANS: 717 case CIL_CALL: 718 case CIL_MACRO: 719 case CIL_OPTIONAL: 720 /* Not currently found in AOSP and not yet properly handled. Return err until support added. */ 721 cil_log(CIL_ERR, "unsupported policy statement (line %d)\n", node->line); 722 rc = SEPOL_ERR; 723 goto exit; 724 case CIL_FSUSE: 725 /* not allowed in plat-policy, but types present, throw error if attributee */ 726 cil_attrib_fsuse(node, args); 727 if (rc != SEPOL_OK) { 728 goto exit; 729 } 730 break; 731 case CIL_CONSTRAIN: 732 case CIL_MLSCONSTRAIN: 733 /* there is type info here, but not sure if we'll allow non-platform code 734 to have this, or whether or not it's in platform policy. Currently 735 assuming that mlsconstrain is private-platform only, and that normal 736 constrain is verboten. */ 737 cil_log(CIL_ERR, "unsupported policy statement (line %d)\n", node->line); 738 rc = SEPOL_ERR; 739 goto exit; 740 default: 741 break; 742 } 743 744 return SEPOL_OK; 745 exit: 746 return rc; 747 } 748 749 /* 750 * walk ast, replacing previously identified types and attributes with the 751 * attributized version. Also replace previous references to the attributees 752 * with the versioned type. 753 */ 754 static int cil_attributize(struct cil_db *db, hashtab_t vers_map, const char *num) 755 { 756 int rc = SEPOL_ERR; 757 struct version_args extra_args; 758 extra_args.db = db; 759 extra_args.vers_map = vers_map; 760 extra_args.num = num; 761 762 rc = cil_tree_walk(db->ast->root, __attributize_helper, NULL, NULL, &extra_args); 763 if (rc != SEPOL_OK) { 764 goto exit; 765 } 766 767 return SEPOL_OK; 768 exit: 769 return rc; 770 } 771 772 /* 773 * Create typeattributeset mappings from the attributes generated from the 774 * original types/attributes to the original values. This mapping will provide 775 * the basis for the platform policy's mapping to this public version. 776 * 777 * Add these new typeattributeset nodes to the given cil_db. 778 */ 779 static int cil_build_mappings_tree(hashtab_key_t k, hashtab_datum_t d, void *args) 780 { 781 struct cil_typeattributeset *attrset = NULL; 782 struct cil_tree_node *ast_node = NULL; 783 struct version_args *verargs = (struct version_args *)args; 784 struct cil_tree_node *ast_parent = verargs->db->ast->root; 785 char *orig_type = (char *) k; 786 struct version_datum *vers_datum = (struct version_datum *) d; 787 788 if (vers_datum->ast_node->flavor == CIL_TYPEATTRIBUTE) { 789 // platform attributes are not versioned 790 return SEPOL_OK; 791 } 792 /* create typeattributeset datum */ 793 cil_typeattributeset_init(&attrset); 794 cil_list_init(&attrset->str_expr, CIL_TYPE); 795 attrset->attr_str = __cil_attrib_get_versname(orig_type, verargs->num); 796 cil_list_append(attrset->str_expr, CIL_STRING, orig_type); 797 798 /* create containing tree node */ 799 cil_tree_node_init(&ast_node); 800 ast_node->data = attrset; 801 ast_node->flavor = CIL_TYPEATTRIBUTESET; 802 803 /* add to tree */ 804 ast_node->parent = ast_parent; 805 if (ast_parent->cl_head == NULL) 806 ast_parent->cl_head = ast_node; 807 else 808 ast_parent->cl_tail->next = ast_node; 809 ast_parent->cl_tail = ast_node; 810 return SEPOL_OK; 811 } 812 813 /* 814 * Initializes the given db and uses the version mapping generated by 815 * cil_extract_attributees() to fill it with the glue policy required to 816 * connect the attributized policy created by cil_attributize() to the policy 817 * declaring the concrete types. 818 */ 819 static int cil_attrib_mapping(struct cil_db **db, hashtab_t vers_map, const char *num) 820 { 821 int rc = SEPOL_ERR; 822 struct version_args extra_args; 823 824 cil_db_init(db); 825 826 /* foreach entry in vers_map, create typeattributeset node and attach to tree */ 827 extra_args.db = *db; 828 extra_args.vers_map = NULL; 829 extra_args.num = num; 830 rc = hashtab_map(vers_map, cil_build_mappings_tree, &extra_args); 831 if (rc != SEPOL_OK) { 832 goto exit; 833 } 834 835 return SEPOL_OK; 836 exit: 837 return rc; 838 } 839 840 int cil_android_attrib_mapping(struct cil_db **mdb, struct cil_db *srcdb, const char *num) 841 { 842 int rc = SEPOL_ERR; 843 hashtab_t ver_map_tab = NULL; 844 845 ver_map_tab = hashtab_create(ver_map_hash_val, ver_map_key_cmp, VER_MAP_SZ); 846 if (!ver_map_tab) { 847 cil_log(CIL_ERR, "Unable to create version mapping table.\n"); 848 goto exit; 849 } 850 rc = cil_build_ast(srcdb, srcdb->parse->root, srcdb->ast->root); 851 if (rc != SEPOL_OK) { 852 cil_log(CIL_ERR, "Unable to build source db AST.\n"); 853 goto exit; 854 } 855 rc = cil_extract_attributees(srcdb, ver_map_tab); 856 if (rc != SEPOL_OK) { 857 cil_log(CIL_ERR, "Unable to extract attributizable elements from source db.\n"); 858 goto exit; 859 } 860 rc = cil_attrib_mapping(mdb, ver_map_tab, num); 861 if (rc != SEPOL_OK) { 862 cil_log(CIL_ERR, "Unable to create mapping db from source db.\n"); 863 goto exit; 864 } 865 exit: 866 ver_map_destroy(ver_map_tab); 867 return rc; 868 } 869 870 int cil_android_attributize(struct cil_db *tgtdb, struct cil_db *srcdb, const char *num) 871 { 872 int rc = SEPOL_ERR; 873 hashtab_t ver_map_tab = NULL; 874 875 ver_map_tab = hashtab_create(ver_map_hash_val, ver_map_key_cmp, VER_MAP_SZ); 876 if (!ver_map_tab) { 877 cil_log(CIL_ERR, "Unable to create version mapping table.\n"); 878 goto exit; 879 } 880 rc = cil_build_ast(srcdb, srcdb->parse->root, srcdb->ast->root); 881 if (rc != SEPOL_OK) { 882 cil_log(CIL_ERR, "Unable to build source db AST.\n"); 883 goto exit; 884 } 885 rc = cil_extract_attributees(srcdb, ver_map_tab); 886 if (rc != SEPOL_OK) { 887 cil_log(CIL_ERR, "Unable to extract attributizable elements from source db.\n"); 888 goto exit; 889 } 890 rc = cil_build_ast(tgtdb, tgtdb->parse->root, tgtdb->ast->root); 891 if (rc != SEPOL_OK) { 892 cil_log(CIL_ERR, "Unable to build target db AST.\n"); 893 goto exit; 894 } 895 rc = cil_attributize(tgtdb, ver_map_tab, num); 896 if (rc != SEPOL_OK) { 897 cil_log(CIL_ERR, "Unable to attributize target db.\n"); 898 goto exit; 899 } 900 exit: 901 ver_map_destroy(ver_map_tab); 902 return rc; 903 } 904