--- security/apparmor/match.c | 74 +++++++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 23 deletions(-) --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -213,17 +213,23 @@ void aa_match_free(struct aa_dfa *dfa) } /** - * aa_dfa_next_state - traverse @dfa to find state @str stops at + * aa_dfa_next_state_len - traverse @dfa to find state @str stops at * @dfa: the dfa to match @str against * @start: the state of the dfa to start matching in - * @str: the string to match against the dfa + * @str: the string of bytes to match against the dfa + * @len: length of the string of bytes to match * * aa_dfa_next_state will match @str against the dfa and return the state it * finished matching in. The final state can be used to look up the accepting * label, or as the start state of a continuing match. + * + * aa_dfa_next_state could be implement using this function by doing + * return aa_dfa_next_state_len(dfa, start, str, strlen(str)); + * but that would require traversing the string twice and be slightly + * slower. */ -unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start, - const char *str) +unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start, + const char *str, int len) { u16 *def = DEFAULT_TABLE(dfa); u32 *base = BASE_TABLE(dfa); @@ -237,7 +243,7 @@ unsigned int aa_dfa_next_state(struct aa /* current state is , matching character *str */ if (dfa->tables[YYTD_ID_EC - 1]) { u8 *equiv = EQUIV_TABLE(dfa); - while (*str) { + for (; len; len--) { pos = base[state] + equiv[(u8)*str++]; if (check[pos] == state) state = next[pos]; @@ -245,7 +251,7 @@ unsigned int aa_dfa_next_state(struct aa state = def[state]; } } else { - while (*str) { + for (; len; len--) { pos = base[state] + (u8)*str++; if (check[pos] == state) state = next[pos]; @@ -257,15 +263,17 @@ unsigned int aa_dfa_next_state(struct aa } /** - * aa_dfa_null_transition - step to next state after null character - * @dfa: the dfa to match against + * aa_dfa_next_state - traverse @dfa to find state @str stops at + * @dfa: the dfa to match @str against * @start: the state of the dfa to start matching in + * @str: the null terminated string of bytes to match against the dfa * - * aa_dfa_null_transition transitions to the next state after a null - * character which is not used in standard matching and is only - * used to seperate pairs. + * aa_dfa_next_state will match @str against the dfa and return the state it + * finished matching in. The final state can be used to look up the accepting + * label, or as the start state of a continuing match. */ -unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start) +unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start, + const char *str) { u16 *def = DEFAULT_TABLE(dfa); u32 *base = BASE_TABLE(dfa); @@ -273,26 +281,46 @@ unsigned int aa_dfa_null_transition(stru u16 *check = CHECK_TABLE(dfa); unsigned int state = start, pos; + if (state == 0) + return 0; + /* current state is , matching character *str */ if (dfa->tables[YYTD_ID_EC - 1]) { u8 *equiv = EQUIV_TABLE(dfa); - pos = base[state] + equiv[0]; - if (check[pos] == state) - state = next[pos]; - else - state = def[state]; + while (*str) { + pos = base[state] + equiv[(u8)*str++]; + if (check[pos] == state) + state = next[pos]; + else + state = def[state]; + } } else { - pos = base[state] + 0; - if (check[pos] == state) - state = next[pos]; - else - state = def[state]; + while (*str) { + pos = base[state] + (u8)*str++; + if (check[pos] == state) + state = next[pos]; + else + state = def[state]; + } } - return state; } /** + * aa_dfa_null_transition - step to next state after null character + * @dfa: the dfa to match against + * @start: the state of the dfa to start matching in + * + * aa_dfa_null_transition transitions to the next state after a null + * character which is not used in standard matching and is only + * used to seperate pairs. + */ +unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start) +{ + return aa_dfa_next_state_len(dfa, start, "", 1); +} + +/** * aa_dfa_match - find accept perm for @str in @dfa * @dfa: the dfa to match @str against * @str: the string to match against the dfa