mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 10:07:12 +00:00
Add basic controls for dfa optimization
This commit is contained in:
parent
926b0c72e8
commit
dce395e7ad
@ -12,6 +12,11 @@
|
|||||||
#define APPARMOR_RE_H
|
#define APPARMOR_RE_H
|
||||||
|
|
||||||
typedef enum dfaflags {
|
typedef enum dfaflags {
|
||||||
|
DFA_CONTROL_EQUIV = 1 << 0,
|
||||||
|
DFA_CONTROL_NO_TREE_NORMAL = 1 << 1,
|
||||||
|
DFA_CONTROL_NO_TREE_SIMPLE = 1 << 2,
|
||||||
|
DFA_CONTROL_TREE_LEFT = 1 << 3,
|
||||||
|
|
||||||
DFA_DUMP_TREE_STATS = 1 << 8,
|
DFA_DUMP_TREE_STATS = 1 << 8,
|
||||||
DFA_DUMP_TREE = 1 << 9,
|
DFA_DUMP_TREE = 1 << 9,
|
||||||
DFA_DUMP_SIMPLE_TREE = 1 << 10,
|
DFA_DUMP_SIMPLE_TREE = 1 << 10,
|
||||||
@ -40,8 +45,7 @@ int aare_add_rule(aare_ruleset_t *rules, char *rule, int deny,
|
|||||||
uint32_t perms, uint32_t audit);
|
uint32_t perms, uint32_t audit);
|
||||||
int aare_add_rule_vec(aare_ruleset_t *rules, int deny, uint32_t perms,
|
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);
|
||||||
void *aare_create_dfa(aare_ruleset_t *rules, int equiv_classes, size_t *size,
|
void *aare_create_dfa(aare_ruleset_t *rules, size_t *size, dfaflags_t flags);
|
||||||
dfaflags_t flags);
|
|
||||||
void aare_reset_matchflags(void);
|
void aare_reset_matchflags(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -858,21 +858,29 @@ Node *simplify_tree(Node *t, dfaflags_t flags)
|
|||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
update = false;
|
update = false;
|
||||||
//do right normalize first as this reduces the number
|
//default to right normalize first as this reduces the number
|
||||||
//of trailing nodes which might follow an internal *
|
//of trailing nodes which might follow an internal *
|
||||||
//or **, which is where state explosion can happen
|
//or **, which is where state explosion can happen
|
||||||
//eg. in one test this makes the difference between
|
//eg. in one test this makes the difference between
|
||||||
// the dfa having about 7 thousands states,
|
// the dfa having about 7 thousands states,
|
||||||
// and it having about 1.25 million states
|
// and it having about 1.25 million states
|
||||||
for (int dir = 1; dir >= 0 ; dir--) {
|
int dir = 1;
|
||||||
|
if (flags & DFA_CONTROL_TREE_LEFT)
|
||||||
|
dir = 0;
|
||||||
|
for (int count = 0; count < 2; count++) {
|
||||||
bool modified;
|
bool modified;
|
||||||
do {
|
do {
|
||||||
modified = false;
|
modified = false;
|
||||||
normalize_tree(t, dir);
|
if (!(flags & DFA_CONTROL_NO_TREE_NORMAL))
|
||||||
|
normalize_tree(t, dir);
|
||||||
t = simplify_tree_base(t, dir, modified);
|
t = simplify_tree_base(t, dir, modified);
|
||||||
if (modified)
|
if (modified)
|
||||||
update = true;
|
update = true;
|
||||||
} while (modified);
|
} while (modified);
|
||||||
|
if (flags & DFA_CONTROL_TREE_LEFT)
|
||||||
|
dir++;
|
||||||
|
else
|
||||||
|
dir--;
|
||||||
}
|
}
|
||||||
} while(update);
|
} while(update);
|
||||||
if (flags & DFA_DUMP_TREE_STATS) {
|
if (flags & DFA_DUMP_TREE_STATS) {
|
||||||
@ -2308,8 +2316,7 @@ extern "C" int aare_add_rule_vec(aare_ruleset_t *rules, int deny,
|
|||||||
* returns: buffer contain dfa tables, @size set to the size of the tables
|
* returns: buffer contain dfa tables, @size set to the size of the tables
|
||||||
* else NULL on failure
|
* else NULL on failure
|
||||||
*/
|
*/
|
||||||
extern "C" void *aare_create_dfa(aare_ruleset_t *rules, int equiv_classes,
|
extern "C" void *aare_create_dfa(aare_ruleset_t *rules, size_t *size, dfaflags_t flags)
|
||||||
size_t *size, dfaflags_t flags)
|
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
|
|
||||||
@ -2320,12 +2327,14 @@ extern "C" void *aare_create_dfa(aare_ruleset_t *rules, int equiv_classes,
|
|||||||
cerr << "\n\n";
|
cerr << "\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
rules->root = simplify_tree(rules->root, flags);
|
if (!(flags & DFA_CONTROL_NO_TREE_SIMPLE)) {
|
||||||
|
rules->root = simplify_tree(rules->root, flags);
|
||||||
|
|
||||||
if (flags & DFA_DUMP_SIMPLE_TREE) {
|
if (flags & DFA_DUMP_SIMPLE_TREE) {
|
||||||
cerr << "\nDFA: Simplified Expression Tree\n";
|
cerr << "\nDFA: Simplified Expression Tree\n";
|
||||||
rules->root->dump(cerr);
|
rules->root->dump(cerr);
|
||||||
cerr << "\n\n";
|
cerr << "\n\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DFA dfa(rules->root, flags);
|
DFA dfa(rules->root, flags);
|
||||||
@ -2337,13 +2346,14 @@ extern "C" void *aare_create_dfa(aare_ruleset_t *rules, int equiv_classes,
|
|||||||
dfa.dump_dot_graph(cerr);
|
dfa.dump_dot_graph(cerr);
|
||||||
|
|
||||||
map<uchar, uchar> eq;
|
map<uchar, uchar> eq;
|
||||||
if (equiv_classes) {
|
if (flags & DFA_CONTROL_EQUIV) {
|
||||||
eq = dfa.equivalence_classes(flags);
|
eq = dfa.equivalence_classes(flags);
|
||||||
dfa.apply_equivalence_classes(eq);
|
dfa.apply_equivalence_classes(eq);
|
||||||
|
|
||||||
if (flags & DFA_DUMP_EQUIV)
|
if (flags & DFA_DUMP_EQUIV) {
|
||||||
cerr << "\nDFA equivalence class\n";
|
cerr << "\nDFA equivalence class\n";
|
||||||
dump_equivalence_classes(cerr, eq);
|
dump_equivalence_classes(cerr, eq);
|
||||||
|
}
|
||||||
} else if (flags & DFA_DUMP_EQUIV)
|
} else if (flags & DFA_DUMP_EQUIV)
|
||||||
cerr << "\nDFA did not generate an equivalence class\n";
|
cerr << "\nDFA did not generate an equivalence class\n";
|
||||||
|
|
||||||
|
@ -159,6 +159,7 @@ static void display_usage(char *command)
|
|||||||
"-V, --version Display version info and exit\n"
|
"-V, --version Display version info and exit\n"
|
||||||
"-d, --debug Debug apparmor definitions\n"
|
"-d, --debug Debug apparmor definitions\n"
|
||||||
"-D [n], --dump Dump internal info for debugging\n"
|
"-D [n], --dump Dump internal info for debugging\n"
|
||||||
|
"-O [n], --Optimize Control dfa optimizations\n"
|
||||||
"-h [command], --help Display this text or info about command\n"
|
"-h [command], --help Display this text or info about command\n"
|
||||||
,command);
|
,command);
|
||||||
}
|
}
|
||||||
@ -187,6 +188,24 @@ static void display_dump(char *command)
|
|||||||
,command);
|
,command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void display_optimize(char *command)
|
||||||
|
{
|
||||||
|
display_version();
|
||||||
|
printf("\n%s: -O [Option]\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
"--------\n"
|
||||||
|
"0 no optimizations\n"
|
||||||
|
"equiv use equivalent classes\n"
|
||||||
|
"no-equiv don't use equivalent classes\n"
|
||||||
|
"expr-normalize do expr normalization\n"
|
||||||
|
"expr-simplify do expr tree simplification\n"
|
||||||
|
"no-expr-normalize don't do expr normalization\n"
|
||||||
|
"no-expr-simplify don't do expr tree simplification\n"
|
||||||
|
"expr-left-simplify do left simplification first\n"
|
||||||
|
"expr-right-simplify do right simplification first\n"
|
||||||
|
,command);
|
||||||
|
}
|
||||||
|
|
||||||
void pwarn(char *fmt, ...)
|
void pwarn(char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list arg;
|
va_list arg;
|
||||||
@ -216,7 +235,7 @@ static int process_args(int argc, char *argv[])
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
option = OPTION_ADD;
|
option = OPTION_ADD;
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "adf:h::rRVvI:b:BCD:NSm:qQn:XKTWk", long_options, &o)) != -1)
|
while ((c = getopt_long(argc, argv, "adf:h::rRVvI:b:BCD:NSm:qQn:XKTWkO:", long_options, &o)) != -1)
|
||||||
{
|
{
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -319,6 +338,29 @@ static int process_args(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'O':
|
||||||
|
skip_cache = 1;
|
||||||
|
if (strcmp(optarg, "0") == 0) {
|
||||||
|
dfaflags |= DFA_CONTROL_NO_TREE_NORMAL |
|
||||||
|
DFA_CONTROL_NO_TREE_SIMPLE;
|
||||||
|
} else if (strcmp(optarg, "equiv") == 0) {
|
||||||
|
dfaflags |= DFA_CONTROL_EQUIV;
|
||||||
|
} else if (strcmp(optarg, "no-equiv") == 0) {
|
||||||
|
dfaflags &= ~DFA_CONTROL_EQUIV;
|
||||||
|
} else if (strcmp(optarg, "expr-normalize") == 0) {
|
||||||
|
dfaflags &= ~DFA_CONTROL_NO_TREE_NORMAL;
|
||||||
|
} else if (strcmp(optarg, "no-expr-normalize") == 0) {
|
||||||
|
dfaflags |= DFA_CONTROL_NO_TREE_NORMAL;
|
||||||
|
} else if (strcmp(optarg, "expr-simplify") == 0) {
|
||||||
|
dfaflags &= ~DFA_CONTROL_NO_TREE_SIMPLE;
|
||||||
|
} else if (strcmp(optarg, "no-expr-simplify") == 0) {
|
||||||
|
dfaflags |= DFA_CONTROL_NO_TREE_SIMPLE;
|
||||||
|
} else if (strcmp(optarg, "expr-left-simplify") == 0) {
|
||||||
|
dfaflags |= DFA_CONTROL_TREE_LEFT;
|
||||||
|
} else if (strcmp(optarg, "expr-right-simplify") == 0) {
|
||||||
|
dfaflags &= ~DFA_CONTROL_TREE_LEFT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
match_string = strdup(optarg);
|
match_string = strdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
@ -523,7 +523,7 @@ static int process_profile_name_xmatch(struct codomain *cod)
|
|||||||
aare_delete_ruleset(rule);
|
aare_delete_ruleset(rule);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
cod->xmatch = aare_create_dfa(rule, 0, &cod->xmatch_size,
|
cod->xmatch = aare_create_dfa(rule, &cod->xmatch_size,
|
||||||
dfaflags);
|
dfaflags);
|
||||||
aare_delete_ruleset(rule);
|
aare_delete_ruleset(rule);
|
||||||
if (!cod->xmatch)
|
if (!cod->xmatch)
|
||||||
@ -667,7 +667,7 @@ int process_regex(struct codomain *cod)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (regex_type == AARE_DFA && cod->dfarule_count > 0) {
|
if (regex_type == AARE_DFA && cod->dfarule_count > 0) {
|
||||||
cod->dfa = aare_create_dfa(cod->dfarules, 0, &cod->dfa_size,
|
cod->dfa = aare_create_dfa(cod->dfarules, &cod->dfa_size,
|
||||||
dfaflags);
|
dfaflags);
|
||||||
aare_delete_ruleset(cod->dfarules);
|
aare_delete_ruleset(cod->dfarules);
|
||||||
cod->dfarules = NULL;
|
cod->dfarules = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user