浏览代码

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 <john.johansen@canonical.com>
John Johansen 8 年之前
父节点
当前提交
031dcc8f4e
共有 2 个文件被更改,包括 29 次插入1 次删除
  1. 4 0
      security/apparmor/include/match.h
  2. 25 1
      security/apparmor/match.c

+ 4 - 0
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 */

+ 25 - 1
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];				\