summaryrefslogtreecommitdiff
path: root/security/apparmor/match.c
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2017-09-06 02:53:15 -0700
committerJohn Johansen <john.johansen@canonical.com>2018-02-09 11:30:01 -0800
commitcf65fabc2a2c8c12031678d86a2bd4a660865011 (patch)
tree7a5d579197b39c0701fe2d995c68cad8d460026b /security/apparmor/match.c
parenta6a52579e52b55448326db88bd9a5740e7c1a037 (diff)
apparmor: add first substr match to dfa
Signed-off-by: John Johansen <john.johansen@canonical.com> Acked-by: Seth Arnold <seth.arnold@canonical.com>
Diffstat (limited to 'security/apparmor/match.c')
-rw-r--r--security/apparmor/match.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 72c604350e80..6c6dc1a22f9a 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -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;
+}