summaryrefslogtreecommitdiff
path: root/security/apparmor/match.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/match.c')
-rw-r--r--security/apparmor/match.c58
1 files changed, 42 insertions, 16 deletions
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 8fa0a1494acd..e9fac67e5178 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -160,9 +160,10 @@ static int verify_dfa(struct aa_dfa *dfa)
if (state_count == 0)
goto out;
for (i = 0; i < state_count; i++) {
- if (!(BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE) &&
- (DEFAULT_TABLE(dfa)[i] >= state_count))
+ if (DEFAULT_TABLE(dfa)[i] >= state_count) {
+ pr_err("AppArmor DFA default state out of bounds");
goto out;
+ }
if (BASE_TABLE(dfa)[i] & MATCH_FLAGS_INVALID) {
pr_err("AppArmor DFA state with invalid match flags");
goto out;
@@ -201,16 +202,31 @@ static int verify_dfa(struct aa_dfa *dfa)
size_t j, k;
for (j = i;
- (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) &&
- !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE);
+ ((BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) &&
+ !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE_VERIFIED));
j = k) {
+ if (BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE)
+ /* loop in current chain */
+ goto out;
k = DEFAULT_TABLE(dfa)[j];
if (j == k)
+ /* self loop */
goto out;
- if (k < j)
- break; /* already verified */
BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE;
}
+ /* move mark to verified */
+ for (j = i;
+ (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE);
+ j = k) {
+ k = DEFAULT_TABLE(dfa)[j];
+ if (j < i)
+ /* jumps to state/chain that has been
+ * verified
+ */
+ break;
+ BASE_TABLE(dfa)[j] &= ~MARK_DIFF_ENCODE;
+ BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE_VERIFIED;
+ }
}
error = 0;
@@ -463,13 +479,18 @@ aa_state_t aa_dfa_match_len(struct aa_dfa *dfa, aa_state_t start,
if (dfa->tables[YYTD_ID_EC]) {
/* Equivalence class table defined */
u8 *equiv = EQUIV_TABLE(dfa);
- for (; len; len--)
- match_char(state, def, base, next, check,
- equiv[(u8) *str++]);
+ for (; len; len--) {
+ u8 c = equiv[(u8) *str];
+
+ match_char(state, def, base, next, check, c);
+ str++;
+ }
} else {
/* default is direct to next state */
- for (; len; len--)
- match_char(state, def, base, next, check, (u8) *str++);
+ for (; len; len--) {
+ match_char(state, def, base, next, check, (u8) *str);
+ str++;
+ }
}
return state;
@@ -503,13 +524,18 @@ aa_state_t aa_dfa_match(struct aa_dfa *dfa, aa_state_t start, const char *str)
/* Equivalence class table defined */
u8 *equiv = EQUIV_TABLE(dfa);
/* default is direct to next state */
- while (*str)
- match_char(state, def, base, next, check,
- equiv[(u8) *str++]);
+ while (*str) {
+ u8 c = equiv[(u8) *str];
+
+ match_char(state, def, base, next, check, c);
+ str++;
+ }
} else {
/* default is direct to next state */
- while (*str)
- match_char(state, def, base, next, check, (u8) *str++);
+ while (*str) {
+ match_char(state, def, base, next, check, (u8) *str);
+ str++;
+ }
}
return state;