Skip to content

Commit

Permalink
AppArmor: Update dfa matching routines.
Browse files Browse the repository at this point in the history
Update aa_dfa_match so that it doesn't result in an input string being
walked twice (once to get its length and another time to match)

Add a single step functions
  aa_dfa_next

Signed-off-by: John Johansen <[email protected]>
Acked-by: Kees Cook <[email protected]>
  • Loading branch information
John Johansen committed Mar 14, 2012
1 parent 3372b68 commit 0fe1212
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 4 deletions.
2 changes: 1 addition & 1 deletion security/apparmor/include/apparmor.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
unsigned int start)
{
/* the null transition only needs the string's null terminator byte */
return aa_dfa_match_len(dfa, start, "", 1);
return aa_dfa_next(dfa, start, 0);
}

static inline bool mediated_filesystem(struct inode *inode)
Expand Down
3 changes: 3 additions & 0 deletions security/apparmor/include/match.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
const char *str, int len);
unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
const char *str);
unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
const char c);

void aa_dfa_free_kref(struct kref *kref);

/**
Expand Down
80 changes: 77 additions & 3 deletions security/apparmor/match.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,12 +335,12 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
}

/**
* aa_dfa_next_state - traverse @dfa to find state @str stops at
* aa_dfa_match - traverse @dfa to find state @str stops at
* @dfa: the dfa to match @str against (NOT NULL)
* @start: the state of the dfa to start matching in
* @str: the null terminated string of bytes to match against the dfa (NOT NULL)
*
* aa_dfa_next_state will match @str against the dfa and return the state it
* aa_dfa_match 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.
*
Expand All @@ -349,5 +349,79 @@ unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
const char *str)
{
return aa_dfa_match_len(dfa, start, str, strlen(str));
u16 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
u16 *next = NEXT_TABLE(dfa);
u16 *check = CHECK_TABLE(dfa);
unsigned int state = start, pos;

if (state == 0)
return 0;

/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC]) {
/* Equivalence class table defined */
u8 *equiv = EQUIV_TABLE(dfa);
/* default is direct to next state */
while (*str) {
pos = base[state] + equiv[(u8) *str++];
if (check[pos] == state)
state = next[pos];
else
state = def[state];
}
} else {
/* default is direct to next state */
while (*str) {
pos = base[state] + (u8) *str++;
if (check[pos] == state)
state = next[pos];
else
state = def[state];
}
}

return state;
}

/**
* aa_dfa_next - step one character to the next state in the dfa
* @dfa: the dfa to tranverse (NOT NULL)
* @state: the state to start in
* @c: the input character to transition on
*
* aa_dfa_match will step through the dfa by one input character @c
*
* Returns: state reach after input @c
*/
unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
const char c)
{
u16 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
u16 *next = NEXT_TABLE(dfa);
u16 *check = CHECK_TABLE(dfa);
unsigned int pos;

/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC]) {
/* Equivalence class table defined */
u8 *equiv = EQUIV_TABLE(dfa);
/* default is direct to next state */

pos = base[state] + equiv[(u8) c];
if (check[pos] == state)
state = next[pos];
else
state = def[state];
} else {
/* default is direct to next state */
pos = base[state] + (u8) c;
if (check[pos] == state)
state = next[pos];
else
state = def[state];
}

return state;
}

0 comments on commit 0fe1212

Please sign in to comment.