Merge "Add support for duplicate allow rule detection (-D / --dups)."
diff --git a/tools/README b/tools/README
new file mode 100644
index 0000000..9b329f6
--- /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 <domain> -t <type> -c <class> -p <permission> -P out/target/product/<board>/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/<board>/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/<board>/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/<board>/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 9b3d444..1901033 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 <policy file>\n", arg0);
+ fprintf(stderr, "%s [-e|--equiv] [-d|--diff] [-D|--dups] -P <policy file>\n", arg0);
exit(1);
}
@@ -173,18 +173,18 @@
}
}
-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 @@
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 @@
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 @@
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 @@
case 'd':
diff = 1;
break;
+ case 'D':
+ dups = 1;
+ break;
case 'P':
policy = optarg;
break;
@@ -365,13 +422,17 @@
}
}
- 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);