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