apparmor/kernel-patches/for-mainline/expand-dfa.diff
2007-11-19 23:18:48 +00:00

173 lines
5.2 KiB
Diff

Allow the dfa to return its state, which will allow for pair matches.
---
security/apparmor/apparmor.h | 7 ++-
security/apparmor/inline.h | 2
security/apparmor/match.c | 99 ++++++++++++++++++++++++++++++++++++++-----
security/apparmor/match.h | 2
4 files changed, 99 insertions(+), 11 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -45,7 +45,6 @@
#define AA_SECURE_EXEC_NEEDED 1
-
/* Control parameters (0 or 1), settable thru module/boot flags or
* via /sys/kernel/security/apparmor/control */
extern int apparmor_complain;
@@ -260,5 +259,11 @@ extern void aa_match_free(struct aa_dfa
extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
extern int verify_dfa(struct aa_dfa *dfa);
extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str);
+extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
+ const char *str);
+extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
+ const char *str, unsigned int *final);
+extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
+ unsigned int start);
#endif /* __APPARMOR_H */
--- a/security/apparmor/inline.h
+++ b/security/apparmor/inline.h
@@ -12,6 +12,8 @@
#include <linux/sched.h>
+#include "match.h"
+
static inline int mediated_filesystem(struct inode *inode)
{
return !(inode->i_sb->s_flags & MS_NOUSER);
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -208,22 +208,26 @@ void aa_match_free(struct aa_dfa *dfa)
}
/**
- * aa_dfa_match - match @path against @dfa starting in @state
- * @dfa: the dfa to match @path against
- * @state: the state to start matching in
- * @path: the path to match against the dfa
+ * 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 string to match against the dfa
*
- * aa_dfa_match will match the full path length and return the state it
- * finished matching in. The final state is used to look up the accepting
- * label.
+ * 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_match(struct aa_dfa *dfa, const char *str)
+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);
u16 *next = NEXT_TABLE(dfa);
u16 *check = CHECK_TABLE(dfa);
- unsigned int state = 1, pos;
+ unsigned int state = start, pos;
+
+ if (state == 0)
+ return 0;
/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC - 1]) {
@@ -244,5 +248,80 @@ unsigned int aa_dfa_match(struct aa_dfa
state = def[state];
}
}
- return ACCEPT_TABLE(dfa)[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)
+{
+ 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;
+
+ /* current state is <state>, 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];
+ } else {
+ pos = base[state] + 0;
+ if (check[pos] == state)
+ state = next[pos];
+ else
+ state = def[state];
+ }
+
+ return state;
+}
+
+/**
+ * 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
+ *
+ * aa_dfa_match will match @str and return the accept perms for the
+ * final state.
+ */
+unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str)
+{
+ return ACCEPT_TABLE(dfa)[aa_dfa_next_state(dfa, DFA_START, str)];
}
+
+/**
+ * aa_match_state - find accept perm and state for @str in @dfa
+ * @dfa: the dfa to match @str against
+ * @start: the state to start the match from
+ * @str: the string to match against the dfa
+ * @final: the state that the match finished in
+ *
+ * aa_match_state will match @str and return the accept perms, and @final
+ * state, the match occured in.
+ */
+unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
+ const char *str, unsigned int *final)
+{
+ unsigned int state;
+ if (dfa) {
+ state = aa_dfa_next_state(dfa, start, str);
+ if (final)
+ *final = state;
+ return ACCEPT_TABLE(dfa)[state];
+ }
+ if (final)
+ *final = 0;
+ return 0;
+}
+
--- a/security/apparmor/match.h
+++ b/security/apparmor/match.h
@@ -12,6 +12,8 @@
#ifndef __MATCH_H
#define __MATCH_H
+#define DFA_START 1
+
/**
* The format used for transition tables is based on the GNU flex table
* file format (--tables-file option; see Table File Format in the flex