From 031dcc8f4e84fea37dc6f78fdc7288aa7f8386c3 Mon Sep 17 00:00:00 2001 From: John Johansen Date: Tue, 8 Aug 2017 12:10:50 -0700 Subject: apparmor: dfa add support for state differential encoding State differential encoding can provide better compression for apparmor policy, without having significant impact on match time. Signed-off-by: John Johansen --- security/apparmor/include/match.h | 4 ++++ security/apparmor/match.c | 26 +++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'security/apparmor') diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h index cd8aeab6ac57..e0de00bd16a8 100644 --- a/security/apparmor/include/match.h +++ b/security/apparmor/include/match.h @@ -40,6 +40,7 @@ */ #define YYTH_MAGIC 0x1B5E783D +#define YYTH_FLAG_DIFF_ENCODE 1 struct table_set_header { u32 th_magic; /* YYTH_MAGIC */ @@ -164,4 +165,7 @@ static inline void aa_put_dfa(struct aa_dfa *dfa) kref_put(&dfa->count, aa_dfa_free_kref); } +#define MATCH_FLAG_DIFF_ENCODE 0x80000000 +#define MARK_DIFF_ENCODE 0x40000000 + #endif /* __AA_MATCH_H */ diff --git a/security/apparmor/match.c b/security/apparmor/match.c index aeac68c58689..70cdcb3c3b25 100644 --- a/security/apparmor/match.c +++ b/security/apparmor/match.c @@ -185,7 +185,8 @@ static int verify_dfa(struct aa_dfa *dfa, int flags) if (flags & DFA_FLAG_VERIFY_STATES) { for (i = 0; i < state_count; i++) { - if (DEFAULT_TABLE(dfa)[i] >= state_count) + if (!(BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE) && + (DEFAULT_TABLE(dfa)[i] >= state_count)) goto out; if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) { printk(KERN_ERR "AppArmor DFA next/check upper " @@ -202,6 +203,24 @@ static int verify_dfa(struct aa_dfa *dfa, int flags) } } + /* Now that all the other tables are verified, verify diffencoding */ + if (flags & DFA_FLAG_VERIFY_STATES) { + size_t j, k; + + for (i = 0; i < state_count; i++) { + for (j = i; + (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) && + !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE); + j = k) { + k = DEFAULT_TABLE(dfa)[j]; + if (j == k) + goto out; + if (k < j) + break; /* already verified */ + BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE; + } + } + } error = 0; out: return error; @@ -274,6 +293,9 @@ struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags) goto fail; dfa->flags = ntohs(*(__be16 *) (data + 12)); + if (dfa->flags != 0 && dfa->flags != YYTH_FLAG_DIFF_ENCODE) + goto fail; + data += hsize; size -= hsize; @@ -335,6 +357,8 @@ do { \ unsigned int pos = base_idx(b) + (C); \ if ((check)[pos] != (state)) { \ (state) = (def)[(state)]; \ + if (b & MATCH_FLAG_DIFF_ENCODE) \ + continue; \ break; \ } \ (state) = (next)[pos]; \ -- cgit v1.2.3