mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-06 09:21:00 +01:00
173 lines
5.2 KiB
Diff
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
|