From 4be07c326575f2122781e60bf78c6419aeed7f02 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Fri, 23 Jul 2010 13:29:35 +0200 Subject: [PATCH] This adds a basic debug dump for the conversion of each rule in a profile to its expression tree. It is limited in that it doesn't currently handle the permissions of a rule. conversion output presents an aare -> prce conversion followed by 1 or more expression tree rules, governed by what the rule does. eg. aare: /** -> /[^/\x00][^\x00]* rule: /[^/\x00][^\x00]* -> /[^\0000/]([^\0000])* eg. echo "/foo { /** rwlkmix, } " | ./apparmor_parser -QT -D rule-exprs -D expr-tree aare: /foo -> /foo aare: /** -> /[^/\x00][^\x00]* rule: /[^/\x00][^\x00]* -> /[^\0000/]([^\0000])* rule: /[^/\x00][^\x00]*\x00/[^/].* -> /[^\0000/]([^\0000])*\0000/[^/](.)* DFA: Expression Tree (/[^\0000/]([^\0000])*(((((((((((((<513>|<2>)|<4>)|<8>)|<16>)|<32>)|<64>)|<8404992>)|<32768>)|<65536>)|<131072>)|<262144>)|<524288>)|<1048576>)|/[^\0000/]([^\0000])*\0000/[^/](.)*((<16>|<32>)|<262144>)) This simple example shows many things 1. The profile name under goes pcre conversion. But since no regular expressions where found it doesn't generate any expr rules 2. /** is converted into the pcre expression /[^\0000/]([^\0000])* 3. The pcre expression /[^\0000/]([^\0000])* is converted into two rules that are then converted into expression trees. The reason for this can not be seen by the output as this is actually triggered by permissions separation for the rule. In this case the link permission is separated into what is shown as the second rule: statement. 4. DFA: Expression Tree dump shows how these rules are combined together You will notice that the rule conversion statement is fairly redundant currently as it just show pcre to expression tree pcre. This will change when direct aare parsing occurs, but currently serves to verify the pcre conversion step. It is not the prettiest patch, as its touching some ugly code that is schedule to be cleaned up/replaced. eg. convert_aaregex_to_pcre is going to replaced with native parse conversion from an aare straight to the expression tree, and dfaflag passing will become part of the rule set. --- parser/libapparmor_re/apparmor_re.h | 5 +++-- parser/libapparmor_re/regexp.y | 19 ++++++++++++++++--- parser/parser_main.c | 3 +++ parser/parser_regex.c | 25 ++++++++++++++++--------- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/parser/libapparmor_re/apparmor_re.h b/parser/libapparmor_re/apparmor_re.h index 7af71d095..acf0e7896 100644 --- a/parser/libapparmor_re/apparmor_re.h +++ b/parser/libapparmor_re/apparmor_re.h @@ -35,6 +35,7 @@ typedef enum dfaflags { DFA_DUMP_EQUIV_STATS = 1 << 19, DFA_DUMP_MINIMIZE = 1 << 20, DFA_DUMP_UNREACHABLE = 1 << 22, + DFA_DUMP_RULE_EXPR = 1 << 23, } dfaflags_t; #ifdef __cplusplus @@ -48,9 +49,9 @@ typedef struct aare_ruleset aare_ruleset_t; aare_ruleset_t *aare_new_ruleset(int reverse); void aare_delete_ruleset(aare_ruleset_t *rules); int aare_add_rule(aare_ruleset_t *rules, char *rule, int deny, - uint32_t perms, uint32_t audit); + uint32_t perms, uint32_t audit, dfaflags_t flags); int aare_add_rule_vec(aare_ruleset_t *rules, int deny, uint32_t perms, - uint32_t audit, int count, char **rulev); + uint32_t audit, int count, char **rulev, dfaflags_t flags); void *aare_create_dfa(aare_ruleset_t *rules, size_t *size, dfaflags_t flags); void aare_reset_matchflags(void); diff --git a/parser/libapparmor_re/regexp.y b/parser/libapparmor_re/regexp.y index d7119269f..2e86543ec 100644 --- a/parser/libapparmor_re/regexp.y +++ b/parser/libapparmor_re/regexp.y @@ -2568,9 +2568,9 @@ uint32_t accept_perms(State *state, uint32_t *audit_ctl, int *error) } extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, int deny, - uint32_t perms, uint32_t audit) + uint32_t perms, uint32_t audit, dfaflags_t flags) { - return aare_add_rule_vec(rules, deny, perms, audit, 1, &rule); + return aare_add_rule_vec(rules, deny, perms, audit, 1, &rule, flags); } #define FLAGS_WIDTH 2 @@ -2601,7 +2601,8 @@ extern "C" void aare_reset_matchflags(void) extern "C" int aare_add_rule_vec(aare_ruleset_t *rules, int deny, uint32_t perms, uint32_t audit, - int count, char **rulev) + int count, char **rulev, + dfaflags_t flags) { Node *tree = NULL, *accept; int exact_match; @@ -2718,6 +2719,18 @@ extern "C" int aare_add_rule_vec(aare_ruleset_t *rules, int deny, } } + if (flags & DFA_DUMP_RULE_EXPR) { + cerr << "rule: "; + cerr << rulev[0]; + for (int i = 1; i < count; i++) { + cerr << "\\x00"; + cerr << rulev[i]; + } + cerr << " -> "; + tree->dump(cerr); + cerr << "\n\n"; + } + if (rules->root) rules->root = new AltNode(rules->root, new CatNode(tree, accept)); else diff --git a/parser/parser_main.c b/parser/parser_main.c index a69662c81..3b60fbe0f 100644 --- a/parser/parser_main.c +++ b/parser/parser_main.c @@ -184,6 +184,7 @@ static void display_dump(char *command) "no option specified Dump variables\n" "variables Dump variables\n" "expanded-variables Dump expanded variables\n" + "rule-exprs Dump rule to expr tree conversions\n" "expr-stats Dump stats on expr tree\n" "expr-tree Dump expression tree\n" "expr-simple Dump simplified expression tree\n" @@ -349,6 +350,8 @@ static int process_args(int argc, char *argv[]) dump_vars = 1; } else if (strcmp(optarg, "expanded-variables") == 0) { dump_expanded_vars = 1; + } else if (strcmp(optarg, "rule-exprs") == 0) { + dfaflags |= DFA_DUMP_RULE_EXPR; } else if (strcmp(optarg, "expr-tree") == 0) { dfaflags |= DFA_DUMP_TREE; } else if (strcmp(optarg, "expr-simple") == 0) { diff --git a/parser/parser_regex.c b/parser/parser_regex.c index d6e99303a..d190bac15 100644 --- a/parser/parser_regex.c +++ b/parser/parser_regex.c @@ -154,6 +154,9 @@ static pattern_t convert_aaregex_to_pcre(const char *aare, int anchor, sptr = aare; dptr = pcre; + if (dfaflags & DFA_DUMP_RULE_EXPR) + fprintf(stderr, "aare: %s -> ", aare); + if (anchor) /* anchor beginning of regular expression */ *dptr++ = '^'; @@ -406,6 +409,10 @@ static pattern_t convert_aaregex_to_pcre(const char *aare, int anchor, out: if (ret == FALSE) ptype = ePatternInvalid; + + if (dfaflags & DFA_DUMP_RULE_EXPR) + fprintf(stderr, "%s\n", pcre); + return ptype; } @@ -519,7 +526,7 @@ static int process_profile_name_xmatch(struct codomain *cod) aare_ruleset_t *rule = aare_new_ruleset(0); if (!rule) return FALSE; - if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0)) { + if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0, dfaflags)) { aare_delete_ruleset(rule); return FALSE; } @@ -529,7 +536,7 @@ static int process_profile_name_xmatch(struct codomain *cod) int len; convert_aaregex_to_pcre(alt->name, 0, tbuf, PATH_MAX + 3, &len); - if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0)) { + if (!aare_add_rule(rule, tbuf, 0, AA_MAY_EXEC, 0, dfaflags)) { aare_delete_ruleset(rule); return FALSE; } @@ -581,11 +588,11 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry) if (entry->deny && (entry->mode & AA_LINK_BITS)) { if (!aare_add_rule(dfarules, tbuf, entry->deny, entry->mode & ~AA_LINK_BITS, - entry->audit & ~AA_LINK_BITS)) + entry->audit & ~AA_LINK_BITS, dfaflags)) return FALSE; } else if (entry->mode & ~AA_CHANGE_PROFILE) { if (!aare_add_rule(dfarules, tbuf, entry->deny, entry->mode, - entry->audit)) + entry->audit, dfaflags)) return FALSE; } @@ -607,7 +614,7 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry) perms |= LINK_TO_LINK_SUBSET(perms); vec[1] = "/[^/].*"; } - if (!aare_add_rule_vec(dfarules, entry->deny, perms, entry->audit & AA_LINK_BITS, 2, vec)) + if (!aare_add_rule_vec(dfarules, entry->deny, perms, entry->audit & AA_LINK_BITS, 2, vec, dfaflags)) return FALSE; } if (entry->mode & AA_CHANGE_PROFILE) { @@ -618,10 +625,10 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry) ptype = convert_aaregex_to_pcre(entry->namespace, 0, lbuf, PATH_MAX + 8, &pos); vec[0] = lbuf; vec[1] = tbuf; - if (!aare_add_rule_vec(dfarules, 0, AA_CHANGE_PROFILE, 0, 2, vec)) + if (!aare_add_rule_vec(dfarules, 0, AA_CHANGE_PROFILE, 0, 2, vec, dfaflags)) return FALSE; } else { - if (!aare_add_rule(dfarules, tbuf, 0, AA_CHANGE_PROFILE, 0)) + if (!aare_add_rule(dfarules, tbuf, 0, AA_CHANGE_PROFILE, 0, dfaflags)) return FALSE; } } @@ -631,10 +638,10 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry) char *vec[2]; vec[0] = entry->namespace; vec[1] = entry->name; - if (!aare_add_rule_vec(dfarules, 0, mode, 0, 2, vec)) + if (!aare_add_rule_vec(dfarules, 0, mode, 0, 2, vec, dfaflags)) return FALSE; } else { - if (!aare_add_rule(dfarules, entry->name, 0, mode, 0)) + if (!aare_add_rule(dfarules, entry->name, 0, mode, 0, dfaflags)) return FALSE; } }