apparmor: add first substr match to dfa
authorJohn Johansen <john.johansen@canonical.com>
Wed, 6 Sep 2017 09:53:15 +0000 (02:53 -0700)
committerJohn Johansen <john.johansen@canonical.com>
Fri, 9 Feb 2018 19:30:01 +0000 (11:30 -0800)
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
security/apparmor/include/match.h
security/apparmor/match.c

index add4c672655844a33d9cadc18893f67d605d751f..72b9b89670e6a81cb17d6dbba0f61ec92203a968 100644 (file)
@@ -129,6 +129,10 @@ unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
                          const char *str);
 unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
                         const char c);
+unsigned int aa_dfa_match_until(struct aa_dfa *dfa, unsigned int start,
+                               const char *str, const char **retpos);
+unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start,
+                                const char *str, int n, const char **retpos);
 
 void aa_dfa_free_kref(struct kref *kref);
 
index 72c604350e805d87b16d7f6595c94fc6028648e6..6c6dc1a22f9a1a6f49e40b1396a3b16628bb3be9 100644 (file)
@@ -457,3 +457,123 @@ unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
 
        return state;
 }
+
+/**
+ * aa_dfa_match_until - traverse @dfa until accept state or end of input
+ * @dfa: the dfa to match @str against  (NOT NULL)
+ * @start: the state of the dfa to start matching in
+ * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
+ * @retpos: first character in str after match OR end of string
+ *
+ * aa_dfa_match 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.
+ *
+ * Returns: final state reached after input is consumed
+ */
+unsigned int aa_dfa_match_until(struct aa_dfa *dfa, unsigned int start,
+                               const char *str, const char **retpos)
+{
+       u16 *def = DEFAULT_TABLE(dfa);
+       u32 *base = BASE_TABLE(dfa);
+       u16 *next = NEXT_TABLE(dfa);
+       u16 *check = CHECK_TABLE(dfa);
+       u32 *accept = ACCEPT_TABLE(dfa);
+       unsigned int state = start, pos;
+
+       if (state == 0)
+               return 0;
+
+       /* current state is <state>, matching character *str */
+       if (dfa->tables[YYTD_ID_EC]) {
+               /* Equivalence class table defined */
+               u8 *equiv = EQUIV_TABLE(dfa);
+               /* default is direct to next state */
+               while (*str) {
+                       pos = base_idx(base[state]) + equiv[(u8) *str++];
+                       if (check[pos] == state)
+                               state = next[pos];
+                       else
+                               state = def[state];
+                       if (accept[state])
+                               break;
+               }
+       } else {
+               /* default is direct to next state */
+               while (*str) {
+                       pos = base_idx(base[state]) + (u8) *str++;
+                       if (check[pos] == state)
+                               state = next[pos];
+                       else
+                               state = def[state];
+                       if (accept[state])
+                               break;
+               }
+       }
+
+       *retpos = str;
+       return state;
+}
+
+
+/**
+ * aa_dfa_matchn_until - traverse @dfa until accept or @n bytes consumed
+ * @dfa: the dfa to match @str against  (NOT NULL)
+ * @start: the state of the dfa to start matching in
+ * @str: the string of bytes to match against the dfa  (NOT NULL)
+ * @n: length of the string of bytes to match
+ * @retpos: first character in str after match OR str + n
+ *
+ * aa_dfa_match_len 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.
+ *
+ * This function will happily match again the 0 byte and only finishes
+ * when @n input is consumed.
+ *
+ * Returns: final state reached after input is consumed
+ */
+unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start,
+                                const char *str, int n, const char **retpos)
+{
+       u16 *def = DEFAULT_TABLE(dfa);
+       u32 *base = BASE_TABLE(dfa);
+       u16 *next = NEXT_TABLE(dfa);
+       u16 *check = CHECK_TABLE(dfa);
+       u32 *accept = ACCEPT_TABLE(dfa);
+       unsigned int state = start, pos;
+
+       *retpos = NULL;
+       if (state == 0)
+               return 0;
+
+       /* current state is <state>, matching character *str */
+       if (dfa->tables[YYTD_ID_EC]) {
+               /* Equivalence class table defined */
+               u8 *equiv = EQUIV_TABLE(dfa);
+               /* default is direct to next state */
+               for (; n; n--) {
+                       pos = base_idx(base[state]) + equiv[(u8) *str++];
+                       if (check[pos] == state)
+                               state = next[pos];
+                       else
+                               state = def[state];
+                       if (accept[state])
+                               break;
+               }
+       } else {
+               /* default is direct to next state */
+               for (; n; n--) {
+                       pos = base_idx(base[state]) + (u8) *str++;
+                       if (check[pos] == state)
+                               state = next[pos];
+                       else
+                               state = def[state];
+                       if (accept[state])
+                               break;
+               }
+       }
+
+       *retpos = str;
+       return state;
+}