diff --git a/tools/README b/tools/README new file mode 100644 index 000000000..9b329f6e8 --- /dev/null +++ b/tools/README @@ -0,0 +1,83 @@ +This directory contains a number of tools related to policy, some of +which are used in building and validating the policy and others are +available for help in auditing and analyzing policy. The tools are +described further below. + +checkfc + A utility for checking the validity of a file_contexts or a + property_contexts configuration file. Used as part of the policy + build to validate both files. Requires the sepolicy file as an + argument in order to check the validity of the security contexts + in the file_contexts or property_contexts file. + + Usage: + checkfc sepolicy file_contexts + checkfc -p sepolicy property_contexts + +checkseapp + A utility for merging together the main seapp_contexts + configuration and the device-specific one, and simultaneously + checking the validity of the configurations. Used as part of the + policy build process to merge and validate the configuration. + + Usage: + checkseapp -p sepolicy input_seapp_contexts0 [input_seapp_contexts1...] -o seapp_contexts + +insertkeys.py + A helper script for mapping tags in the signature stanzas of + mac_permissions.xml to public keys found in pem files. This + script is described further in the top-level sepolicy/README. + +sepolicy-check + A tool for auditing a sepolicy file for any allow rule that grants + a given permission. + + Usage: + sepolicy-check -s -t -c -p -P out/target/product//root/sepolicy + +sepolicy-analyze + A tool for performing various kinds of analysis on a sepolicy + file. The current kinds of analysis that are currently supported + include: + + TYPE EQUIVALENCE + sepolicy-analyze -e -P out/target/product//root/sepolicy + + Display all type pairs that are "equivalent", i.e. they are + identical with respect to allow rules, including indirect allow + rules via attributes and default-enabled conditional rules + (i.e. default boolean values yield a true conditional expression). + + Equivalent types are candidates for being coalesced into a single + type. However, there may be legitimate reasons for them to remain + separate, for example: - the types may differ in a respect not + included in the current analysis, such as default-disabled + conditional rules, audit-related rules (auditallow or dontaudit), + default type transitions, or constraints (e.g. mls), or - the + current policy may be overly permissive with respect to one or the + other of the types and thus the correct action may be to tighten + access to one or the other rather than coalescing them together, + or - the domains that would in fact have different accesses to the + types may not yet be defined or may be unconfined in the policy + you are analyzing. + + TYPE DIFFERENCE + sepolicy-analyze -d -P out/target/product//root/sepolicy + + Display type pairs that differ and the first difference found + between the two types. This may be used in looking for similar + types that are not equivalent but may be candidates for coalescing. + + DUPLICATE ALLOW RULES + sepolicy-analyze -D -P out/target/product//root/sepolicy + + Displays duplicate allow rules, i.e. pairs of allow rules that + grant the same permissions where one allow rule is written + directly in terms of individual types and the other is written in + terms of attributes associated with those same types. The rule + with individual types is a candidate for removal. The rule with + individual types may be directly represented in the source policy + or may be a result of expansion of a type negation (e.g. domain + -foo -bar is expanded to individual allow rules by the policy + compiler). Domains with unconfineddomain will typically have such + duplicate rules as a natural side effect and can be ignored. diff --git a/tools/sepolicy-analyze.c b/tools/sepolicy-analyze.c index 9b3d444c9..1901033a4 100644 --- a/tools/sepolicy-analyze.c +++ b/tools/sepolicy-analyze.c @@ -14,7 +14,7 @@ void usage(char *arg0) { - fprintf(stderr, "%s [-e|--equiv] [-d|--diff] -P \n", arg0); + fprintf(stderr, "%s [-e|--equiv] [-d|--diff] [-D|--dups] -P \n", arg0); exit(1); } @@ -173,18 +173,18 @@ static void free_type_rules(struct avtab_node *l) } } -static void display_allow(policydb_t *policydb, struct avtab_node *n, int idx, - uint32_t perms) +static void display_allow(policydb_t *policydb, avtab_key_t *key, int idx, + uint32_t perms) { printf(" allow %s %s:%s { %s };\n", - policydb->p_type_val_to_name[n->key.source_type - ? n->key.source_type - 1 : idx], - n->key.target_type == n->key.source_type ? "self" : - policydb->p_type_val_to_name[n->key.target_type - ? n->key.target_type - 1 : idx], - policydb->p_class_val_to_name[n->key.target_class - 1], + policydb->p_type_val_to_name[key->source_type + ? key->source_type - 1 : idx], + key->target_type == key->source_type ? "self" : + policydb->p_type_val_to_name[key->target_type + ? key->target_type - 1 : idx], + policydb->p_class_val_to_name[key->target_class - 1], sepol_av_to_string - (policydb, n->key.target_class, perms)); + (policydb, key->target_class, perms)); } static int find_match(policydb_t *policydb, struct avtab_node *l1, @@ -213,9 +213,9 @@ static int find_match(policydb_t *policydb, struct avtab_node *l1, perms2 = c->datum.data & ~l1->datum.data; if (perms1 || perms2) { if (perms1) - display_allow(policydb, l1, idx1, perms1); + display_allow(policydb, &l1->key, idx1, perms1); if (perms2) - display_allow(policydb, c, idx2, perms2); + display_allow(policydb, &c->key, idx2, perms2); printf("\n"); return 1; } @@ -311,9 +311,9 @@ static int analyze_types(policydb_t * policydb, char equiv, char diff) continue; } if (l1) - display_allow(policydb, l1, i, l1->datum.data); + display_allow(policydb, &l1->key, i, l1->datum.data); if (l2) - display_allow(policydb, l2, j, l2->datum.data); + display_allow(policydb, &l2->key, j, l2->datum.data); printf("\n"); } continue; @@ -334,22 +334,76 @@ static int analyze_types(policydb_t * policydb, char equiv, char diff) return 0; } +static int find_dups_helper(avtab_key_t * k, avtab_datum_t * d, + void *args) +{ + policydb_t *policydb = args; + ebitmap_t *sattr, *tattr; + ebitmap_node_t *snode, *tnode; + unsigned int i, j; + avtab_key_t avkey; + avtab_ptr_t node; + + if (!(k->specified & AVTAB_ALLOWED)) + return 0; + + avkey.target_class = k->target_class; + avkey.specified = k->specified; + + sattr = &policydb->type_attr_map[k->source_type - 1]; + tattr = &policydb->type_attr_map[k->target_type - 1]; + ebitmap_for_each_bit(sattr, snode, i) { + if (!ebitmap_node_get_bit(snode, i)) + continue; + ebitmap_for_each_bit(tattr, tnode, j) { + if (!ebitmap_node_get_bit(tnode, j)) + continue; + avkey.source_type = i + 1; + avkey.target_type = j + 1; + if (avkey.source_type == k->source_type && + avkey.target_type == k->target_type) + continue; + for (node = avtab_search_node(&policydb->te_avtab, &avkey); + node != NULL; + node = avtab_search_node_next(node, avkey.specified)) { + if (node->datum.data & d->data) { + uint32_t perms = node->datum.data & d->data; + printf("Duplicate allow rule found:\n"); + display_allow(policydb, k, i, perms); + display_allow(policydb, &node->key, i, perms); + printf("\n"); + } + } + } + } + + return 0; +} + +static int find_dups(policydb_t * policydb) +{ + if (avtab_map(&policydb->te_avtab, find_dups_helper, policydb)) + return -1; + return 0; +} + int main(int argc, char **argv) { char *policy = NULL; struct policy_file pf; policydb_t policydb; char ch; - char equiv = 0, diff = 0; + char equiv = 0, diff = 0, dups = 0; struct option long_options[] = { {"equiv", no_argument, NULL, 'e'}, {"diff", no_argument, NULL, 'd'}, + {"dups", no_argument, NULL, 'D'}, {"policy", required_argument, NULL, 'P'}, {NULL, 0, NULL, 0} }; - while ((ch = getopt_long(argc, argv, "edP:", long_options, NULL)) != -1) { + while ((ch = getopt_long(argc, argv, "edDP:", long_options, NULL)) != -1) { switch (ch) { case 'e': equiv = 1; @@ -357,6 +411,9 @@ int main(int argc, char **argv) case 'd': diff = 1; break; + case 'D': + dups = 1; + break; case 'P': policy = optarg; break; @@ -365,13 +422,17 @@ int main(int argc, char **argv) } } - if (!policy || (!equiv && !diff)) + if (!policy || (!equiv && !diff && !dups)) usage(argv[0]); if (load_policy(policy, &policydb, &pf)) exit(1); - analyze_types(&policydb, equiv, diff); + if (equiv || diff) + analyze_types(&policydb, equiv, diff); + + if (dups) + find_dups(&policydb); policydb_destroy(&policydb);