| | 474 | /** State tracking struct used in the functions check_disabled, remove_symbol, and prune_disabled_symbols to handle disabled symbols */ |
|---|
| | 475 | struct symbol_pruning_state |
|---|
| | 476 | { |
|---|
| | 477 | qpol_policy_t *p; /**< The policy */ |
|---|
| | 478 | int symbol_type; /**< The current symbol type being processed */ |
|---|
| | 479 | }; |
|---|
| | 480 | |
|---|
| | 481 | /** Apply callback for hashtab_map_remove_on_error. |
|---|
| | 482 | * This function tests whether a symbol referenced by the policy is declared or only ever required. |
|---|
| | 483 | * Symbols without a declaration are disabled and must be removed. |
|---|
| | 484 | * @param key Symbol key to check. |
|---|
| | 485 | * @param datum Symbol datum to check. |
|---|
| | 486 | * @param args State object (of type struct symbol_pruning_state) |
|---|
| | 487 | * @return 0 if symbol is enabled, 1 if not enabled. |
|---|
| | 488 | */ |
|---|
| | 489 | static int check_disabled(hashtab_key_t key, hashtab_datum_t datum, void *args) |
|---|
| | 490 | { |
|---|
| | 491 | struct symbol_pruning_state *s = args; |
|---|
| | 492 | if (!is_id_enabled((char *)key, &(s->p->p->p), s->symbol_type)) |
|---|
| | 493 | return 1; |
|---|
| | 494 | return 0; |
|---|
| | 495 | } |
|---|
| | 496 | |
|---|
| | 497 | /** Remove callback for hashtab_map_remove_on_error. |
|---|
| | 498 | * Frees all memory associated with a disabled symbol that has been removed from the symbol table. |
|---|
| | 499 | * @param key Symbol key to remove |
|---|
| | 500 | * @param datum Symbol datum to remove |
|---|
| | 501 | * @param args State object (of type struct symbol_pruning_state) |
|---|
| | 502 | * @post All memory associated with the symbol is freed. |
|---|
| | 503 | */ |
|---|
| | 504 | static void remove_symbol(hashtab_key_t key, hashtab_datum_t datum, void *args) |
|---|
| | 505 | { |
|---|
| | 506 | struct symbol_pruning_state *s = args; |
|---|
| | 507 | switch (s->symbol_type) { |
|---|
| | 508 | case SYM_ROLES: |
|---|
| | 509 | { |
|---|
| | 510 | role_datum_destroy((role_datum_t *) datum); |
|---|
| | 511 | break; |
|---|
| | 512 | } |
|---|
| | 513 | case SYM_TYPES: |
|---|
| | 514 | { |
|---|
| | 515 | type_datum_destroy((type_datum_t *) datum); |
|---|
| | 516 | break; |
|---|
| | 517 | } |
|---|
| | 518 | case SYM_USERS: |
|---|
| | 519 | { |
|---|
| | 520 | user_datum_destroy((user_datum_t *) datum); |
|---|
| | 521 | break; |
|---|
| | 522 | } |
|---|
| | 523 | case SYM_BOOLS: |
|---|
| | 524 | { |
|---|
| | 525 | /* no-op */ |
|---|
| | 526 | break; |
|---|
| | 527 | } |
|---|
| | 528 | case SYM_LEVELS: |
|---|
| | 529 | { |
|---|
| | 530 | level_datum_destroy((level_datum_t *) datum); |
|---|
| | 531 | break; |
|---|
| | 532 | } |
|---|
| | 533 | case SYM_CATS: |
|---|
| | 534 | { |
|---|
| | 535 | cat_datum_destroy((cat_datum_t *) datum); |
|---|
| | 536 | break; |
|---|
| | 537 | } |
|---|
| | 538 | default: |
|---|
| | 539 | return; /* invalid type of datum to free; do nothing */ |
|---|
| | 540 | } |
|---|
| | 541 | free(key); |
|---|
| | 542 | free(datum); |
|---|
| | 543 | } |
|---|
| | 544 | |
|---|
| | 545 | /** Remove symbols that are only required but never declared from the policy. |
|---|
| | 546 | * Removes each disabled symbol freeing all memory associated with it. |
|---|
| | 547 | * @param policy The policy from which disabled symbols should be removed. |
|---|
| | 548 | * @return always 0. |
|---|
| | 549 | * @note Since hashtab_map_remove_on_error does not return any error status, |
|---|
| | 550 | * it is impossible to tell if it has failed; if it fails, the policy will |
|---|
| | 551 | * be in an inconsistent state. |
|---|
| | 552 | */ |
|---|
| | 553 | static int prune_disabled_symbols(qpol_policy_t * policy) |
|---|
| | 554 | { |
|---|
| | 555 | if (policy->type == QPOL_POLICY_KERNEL_BINARY) |
|---|
| | 556 | return 0; /* checkpolicy already prunes disabled symbols */ |
|---|
| | 557 | struct symbol_pruning_state state; |
|---|
| | 558 | state.p = policy; |
|---|
| | 559 | for (state.symbol_type = SYM_ROLES; state.symbol_type < SYM_NUM; state.symbol_type++) { |
|---|
| | 560 | hashtab_map_remove_on_error(policy->p->p.symtab[state.symbol_type].table, check_disabled, remove_symbol, &state); |
|---|
| | 561 | } |
|---|
| | 562 | return 0; |
|---|
| | 563 | } |
|---|
| | 564 | |
|---|