Merge branch 'for-arm-soc' of git://git.armlinux.org.uk/~rmk/linux-arm into arm/soc
[sfrench/cifs-2.6.git] / security / apparmor / match.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * AppArmor security module
4  *
5  * This file contains AppArmor dfa based regular expression matching engine
6  *
7  * Copyright (C) 1998-2008 Novell/SUSE
8  * Copyright 2009-2012 Canonical Ltd.
9  */
10
11 #include <linux/errno.h>
12 #include <linux/kernel.h>
13 #include <linux/mm.h>
14 #include <linux/slab.h>
15 #include <linux/vmalloc.h>
16 #include <linux/err.h>
17 #include <linux/kref.h>
18
19 #include "include/lib.h"
20 #include "include/match.h"
21
22 #define base_idx(X) ((X) & 0xffffff)
23
24 static char nulldfa_src[] = {
25         #include "nulldfa.in"
26 };
27 struct aa_dfa *nulldfa;
28
29 static char stacksplitdfa_src[] = {
30         #include "stacksplitdfa.in"
31 };
32 struct aa_dfa *stacksplitdfa;
33
34 int aa_setup_dfa_engine(void)
35 {
36         int error;
37
38         nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src),
39                                 TO_ACCEPT1_FLAG(YYTD_DATA32) |
40                                 TO_ACCEPT2_FLAG(YYTD_DATA32));
41         if (IS_ERR(nulldfa)) {
42                 error = PTR_ERR(nulldfa);
43                 nulldfa = NULL;
44                 return error;
45         }
46
47         stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src,
48                                       sizeof(stacksplitdfa_src),
49                                       TO_ACCEPT1_FLAG(YYTD_DATA32) |
50                                       TO_ACCEPT2_FLAG(YYTD_DATA32));
51         if (IS_ERR(stacksplitdfa)) {
52                 aa_put_dfa(nulldfa);
53                 nulldfa = NULL;
54                 error = PTR_ERR(stacksplitdfa);
55                 stacksplitdfa = NULL;
56                 return error;
57         }
58
59         return 0;
60 }
61
62 void aa_teardown_dfa_engine(void)
63 {
64         aa_put_dfa(stacksplitdfa);
65         aa_put_dfa(nulldfa);
66 }
67
68 /**
69  * unpack_table - unpack a dfa table (one of accept, default, base, next check)
70  * @blob: data to unpack (NOT NULL)
71  * @bsize: size of blob
72  *
73  * Returns: pointer to table else NULL on failure
74  *
75  * NOTE: must be freed by kvfree (not kfree)
76  */
77 static struct table_header *unpack_table(char *blob, size_t bsize)
78 {
79         struct table_header *table = NULL;
80         struct table_header th;
81         size_t tsize;
82
83         if (bsize < sizeof(struct table_header))
84                 goto out;
85
86         /* loaded td_id's start at 1, subtract 1 now to avoid doing
87          * it every time we use td_id as an index
88          */
89         th.td_id = be16_to_cpu(*(__be16 *) (blob)) - 1;
90         if (th.td_id > YYTD_ID_MAX)
91                 goto out;
92         th.td_flags = be16_to_cpu(*(__be16 *) (blob + 2));
93         th.td_lolen = be32_to_cpu(*(__be32 *) (blob + 8));
94         blob += sizeof(struct table_header);
95
96         if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
97               th.td_flags == YYTD_DATA8))
98                 goto out;
99
100         tsize = table_size(th.td_lolen, th.td_flags);
101         if (bsize < tsize)
102                 goto out;
103
104         table = kvzalloc(tsize, GFP_KERNEL);
105         if (table) {
106                 table->td_id = th.td_id;
107                 table->td_flags = th.td_flags;
108                 table->td_lolen = th.td_lolen;
109                 if (th.td_flags == YYTD_DATA8)
110                         UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
111                                      u8, u8, byte_to_byte);
112                 else if (th.td_flags == YYTD_DATA16)
113                         UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
114                                      u16, __be16, be16_to_cpu);
115                 else if (th.td_flags == YYTD_DATA32)
116                         UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
117                                      u32, __be32, be32_to_cpu);
118                 else
119                         goto fail;
120                 /* if table was vmalloced make sure the page tables are synced
121                  * before it is used, as it goes live to all cpus.
122                  */
123                 if (is_vmalloc_addr(table))
124                         vm_unmap_aliases();
125         }
126
127 out:
128         return table;
129 fail:
130         kvfree(table);
131         return NULL;
132 }
133
134 /**
135  * verify_table_headers - verify that the tables headers are as expected
136  * @tables - array of dfa tables to check (NOT NULL)
137  * @flags: flags controlling what type of accept table are acceptable
138  *
139  * Assumes dfa has gone through the first pass verification done by unpacking
140  * NOTE: this does not valid accept table values
141  *
142  * Returns: %0 else error code on failure to verify
143  */
144 static int verify_table_headers(struct table_header **tables, int flags)
145 {
146         size_t state_count, trans_count;
147         int error = -EPROTO;
148
149         /* check that required tables exist */
150         if (!(tables[YYTD_ID_DEF] && tables[YYTD_ID_BASE] &&
151               tables[YYTD_ID_NXT] && tables[YYTD_ID_CHK]))
152                 goto out;
153
154         /* accept.size == default.size == base.size */
155         state_count = tables[YYTD_ID_BASE]->td_lolen;
156         if (ACCEPT1_FLAGS(flags)) {
157                 if (!tables[YYTD_ID_ACCEPT])
158                         goto out;
159                 if (state_count != tables[YYTD_ID_ACCEPT]->td_lolen)
160                         goto out;
161         }
162         if (ACCEPT2_FLAGS(flags)) {
163                 if (!tables[YYTD_ID_ACCEPT2])
164                         goto out;
165                 if (state_count != tables[YYTD_ID_ACCEPT2]->td_lolen)
166                         goto out;
167         }
168         if (state_count != tables[YYTD_ID_DEF]->td_lolen)
169                 goto out;
170
171         /* next.size == chk.size */
172         trans_count = tables[YYTD_ID_NXT]->td_lolen;
173         if (trans_count != tables[YYTD_ID_CHK]->td_lolen)
174                 goto out;
175
176         /* if equivalence classes then its table size must be 256 */
177         if (tables[YYTD_ID_EC] && tables[YYTD_ID_EC]->td_lolen != 256)
178                 goto out;
179
180         error = 0;
181 out:
182         return error;
183 }
184
185 /**
186  * verify_dfa - verify that transitions and states in the tables are in bounds.
187  * @dfa: dfa to test  (NOT NULL)
188  *
189  * Assumes dfa has gone through the first pass verification done by unpacking
190  * NOTE: this does not valid accept table values
191  *
192  * Returns: %0 else error code on failure to verify
193  */
194 static int verify_dfa(struct aa_dfa *dfa)
195 {
196         size_t i, state_count, trans_count;
197         int error = -EPROTO;
198
199         state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
200         trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen;
201         for (i = 0; i < state_count; i++) {
202                 if (!(BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE) &&
203                     (DEFAULT_TABLE(dfa)[i] >= state_count))
204                         goto out;
205                 if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) {
206                         pr_err("AppArmor DFA next/check upper bounds error\n");
207                         goto out;
208                 }
209         }
210
211         for (i = 0; i < trans_count; i++) {
212                 if (NEXT_TABLE(dfa)[i] >= state_count)
213                         goto out;
214                 if (CHECK_TABLE(dfa)[i] >= state_count)
215                         goto out;
216         }
217
218         /* Now that all the other tables are verified, verify diffencoding */
219         for (i = 0; i < state_count; i++) {
220                 size_t j, k;
221
222                 for (j = i;
223                      (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) &&
224                      !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE);
225                      j = k) {
226                         k = DEFAULT_TABLE(dfa)[j];
227                         if (j == k)
228                                 goto out;
229                         if (k < j)
230                                 break;          /* already verified */
231                         BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE;
232                 }
233         }
234         error = 0;
235
236 out:
237         return error;
238 }
239
240 /**
241  * dfa_free - free a dfa allocated by aa_dfa_unpack
242  * @dfa: the dfa to free  (MAYBE NULL)
243  *
244  * Requires: reference count to dfa == 0
245  */
246 static void dfa_free(struct aa_dfa *dfa)
247 {
248         if (dfa) {
249                 int i;
250
251                 for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
252                         kvfree(dfa->tables[i]);
253                         dfa->tables[i] = NULL;
254                 }
255                 kfree(dfa);
256         }
257 }
258
259 /**
260  * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa)
261  * @kr: kref callback for freeing of a dfa  (NOT NULL)
262  */
263 void aa_dfa_free_kref(struct kref *kref)
264 {
265         struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count);
266         dfa_free(dfa);
267 }
268
269 /**
270  * aa_dfa_unpack - unpack the binary tables of a serialized dfa
271  * @blob: aligned serialized stream of data to unpack  (NOT NULL)
272  * @size: size of data to unpack
273  * @flags: flags controlling what type of accept tables are acceptable
274  *
275  * Unpack a dfa that has been serialized.  To find information on the dfa
276  * format look in Documentation/admin-guide/LSM/apparmor.rst
277  * Assumes the dfa @blob stream has been aligned on a 8 byte boundary
278  *
279  * Returns: an unpacked dfa ready for matching or ERR_PTR on failure
280  */
281 struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
282 {
283         int hsize;
284         int error = -ENOMEM;
285         char *data = blob;
286         struct table_header *table = NULL;
287         struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
288         if (!dfa)
289                 goto fail;
290
291         kref_init(&dfa->count);
292
293         error = -EPROTO;
294
295         /* get dfa table set header */
296         if (size < sizeof(struct table_set_header))
297                 goto fail;
298
299         if (ntohl(*(__be32 *) data) != YYTH_MAGIC)
300                 goto fail;
301
302         hsize = ntohl(*(__be32 *) (data + 4));
303         if (size < hsize)
304                 goto fail;
305
306         dfa->flags = ntohs(*(__be16 *) (data + 12));
307         if (dfa->flags != 0 && dfa->flags != YYTH_FLAG_DIFF_ENCODE)
308                 goto fail;
309
310         data += hsize;
311         size -= hsize;
312
313         while (size > 0) {
314                 table = unpack_table(data, size);
315                 if (!table)
316                         goto fail;
317
318                 switch (table->td_id) {
319                 case YYTD_ID_ACCEPT:
320                         if (!(table->td_flags & ACCEPT1_FLAGS(flags)))
321                                 goto fail;
322                         break;
323                 case YYTD_ID_ACCEPT2:
324                         if (!(table->td_flags & ACCEPT2_FLAGS(flags)))
325                                 goto fail;
326                         break;
327                 case YYTD_ID_BASE:
328                         if (table->td_flags != YYTD_DATA32)
329                                 goto fail;
330                         break;
331                 case YYTD_ID_DEF:
332                 case YYTD_ID_NXT:
333                 case YYTD_ID_CHK:
334                         if (table->td_flags != YYTD_DATA16)
335                                 goto fail;
336                         break;
337                 case YYTD_ID_EC:
338                         if (table->td_flags != YYTD_DATA8)
339                                 goto fail;
340                         break;
341                 default:
342                         goto fail;
343                 }
344                 /* check for duplicate table entry */
345                 if (dfa->tables[table->td_id])
346                         goto fail;
347                 dfa->tables[table->td_id] = table;
348                 data += table_size(table->td_lolen, table->td_flags);
349                 size -= table_size(table->td_lolen, table->td_flags);
350                 table = NULL;
351         }
352         error = verify_table_headers(dfa->tables, flags);
353         if (error)
354                 goto fail;
355
356         if (flags & DFA_FLAG_VERIFY_STATES) {
357                 error = verify_dfa(dfa);
358                 if (error)
359                         goto fail;
360         }
361
362         return dfa;
363
364 fail:
365         kvfree(table);
366         dfa_free(dfa);
367         return ERR_PTR(error);
368 }
369
370 #define match_char(state, def, base, next, check, C)    \
371 do {                                                    \
372         u32 b = (base)[(state)];                        \
373         unsigned int pos = base_idx(b) + (C);           \
374         if ((check)[pos] != (state)) {                  \
375                 (state) = (def)[(state)];               \
376                 if (b & MATCH_FLAG_DIFF_ENCODE)         \
377                         continue;                       \
378                 break;                                  \
379         }                                               \
380         (state) = (next)[pos];                          \
381         break;                                          \
382 } while (1)
383
384 /**
385  * aa_dfa_match_len - traverse @dfa to find state @str stops at
386  * @dfa: the dfa to match @str against  (NOT NULL)
387  * @start: the state of the dfa to start matching in
388  * @str: the string of bytes to match against the dfa  (NOT NULL)
389  * @len: length of the string of bytes to match
390  *
391  * aa_dfa_match_len will match @str against the dfa and return the state it
392  * finished matching in. The final state can be used to look up the accepting
393  * label, or as the start state of a continuing match.
394  *
395  * This function will happily match again the 0 byte and only finishes
396  * when @len input is consumed.
397  *
398  * Returns: final state reached after input is consumed
399  */
400 unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
401                               const char *str, int len)
402 {
403         u16 *def = DEFAULT_TABLE(dfa);
404         u32 *base = BASE_TABLE(dfa);
405         u16 *next = NEXT_TABLE(dfa);
406         u16 *check = CHECK_TABLE(dfa);
407         unsigned int state = start;
408
409         if (state == 0)
410                 return 0;
411
412         /* current state is <state>, matching character *str */
413         if (dfa->tables[YYTD_ID_EC]) {
414                 /* Equivalence class table defined */
415                 u8 *equiv = EQUIV_TABLE(dfa);
416                 for (; len; len--)
417                         match_char(state, def, base, next, check,
418                                    equiv[(u8) *str++]);
419         } else {
420                 /* default is direct to next state */
421                 for (; len; len--)
422                         match_char(state, def, base, next, check, (u8) *str++);
423         }
424
425         return state;
426 }
427
428 /**
429  * aa_dfa_match - traverse @dfa to find state @str stops at
430  * @dfa: the dfa to match @str against  (NOT NULL)
431  * @start: the state of the dfa to start matching in
432  * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
433  *
434  * aa_dfa_match will match @str against the dfa and return the state it
435  * finished matching in. The final state can be used to look up the accepting
436  * label, or as the start state of a continuing match.
437  *
438  * Returns: final state reached after input is consumed
439  */
440 unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
441                           const char *str)
442 {
443         u16 *def = DEFAULT_TABLE(dfa);
444         u32 *base = BASE_TABLE(dfa);
445         u16 *next = NEXT_TABLE(dfa);
446         u16 *check = CHECK_TABLE(dfa);
447         unsigned int state = start;
448
449         if (state == 0)
450                 return 0;
451
452         /* current state is <state>, matching character *str */
453         if (dfa->tables[YYTD_ID_EC]) {
454                 /* Equivalence class table defined */
455                 u8 *equiv = EQUIV_TABLE(dfa);
456                 /* default is direct to next state */
457                 while (*str)
458                         match_char(state, def, base, next, check,
459                                    equiv[(u8) *str++]);
460         } else {
461                 /* default is direct to next state */
462                 while (*str)
463                         match_char(state, def, base, next, check, (u8) *str++);
464         }
465
466         return state;
467 }
468
469 /**
470  * aa_dfa_next - step one character to the next state in the dfa
471  * @dfa: the dfa to traverse (NOT NULL)
472  * @state: the state to start in
473  * @c: the input character to transition on
474  *
475  * aa_dfa_match will step through the dfa by one input character @c
476  *
477  * Returns: state reach after input @c
478  */
479 unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
480                           const char c)
481 {
482         u16 *def = DEFAULT_TABLE(dfa);
483         u32 *base = BASE_TABLE(dfa);
484         u16 *next = NEXT_TABLE(dfa);
485         u16 *check = CHECK_TABLE(dfa);
486
487         /* current state is <state>, matching character *str */
488         if (dfa->tables[YYTD_ID_EC]) {
489                 /* Equivalence class table defined */
490                 u8 *equiv = EQUIV_TABLE(dfa);
491                 match_char(state, def, base, next, check, equiv[(u8) c]);
492         } else
493                 match_char(state, def, base, next, check, (u8) c);
494
495         return state;
496 }
497
498 /**
499  * aa_dfa_match_until - traverse @dfa until accept state or end of input
500  * @dfa: the dfa to match @str against  (NOT NULL)
501  * @start: the state of the dfa to start matching in
502  * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
503  * @retpos: first character in str after match OR end of string
504  *
505  * aa_dfa_match will match @str against the dfa and return the state it
506  * finished matching in. The final state can be used to look up the accepting
507  * label, or as the start state of a continuing match.
508  *
509  * Returns: final state reached after input is consumed
510  */
511 unsigned int aa_dfa_match_until(struct aa_dfa *dfa, unsigned int start,
512                                 const char *str, const char **retpos)
513 {
514         u16 *def = DEFAULT_TABLE(dfa);
515         u32 *base = BASE_TABLE(dfa);
516         u16 *next = NEXT_TABLE(dfa);
517         u16 *check = CHECK_TABLE(dfa);
518         u32 *accept = ACCEPT_TABLE(dfa);
519         unsigned int state = start, pos;
520
521         if (state == 0)
522                 return 0;
523
524         /* current state is <state>, matching character *str */
525         if (dfa->tables[YYTD_ID_EC]) {
526                 /* Equivalence class table defined */
527                 u8 *equiv = EQUIV_TABLE(dfa);
528                 /* default is direct to next state */
529                 while (*str) {
530                         pos = base_idx(base[state]) + equiv[(u8) *str++];
531                         if (check[pos] == state)
532                                 state = next[pos];
533                         else
534                                 state = def[state];
535                         if (accept[state])
536                                 break;
537                 }
538         } else {
539                 /* default is direct to next state */
540                 while (*str) {
541                         pos = base_idx(base[state]) + (u8) *str++;
542                         if (check[pos] == state)
543                                 state = next[pos];
544                         else
545                                 state = def[state];
546                         if (accept[state])
547                                 break;
548                 }
549         }
550
551         *retpos = str;
552         return state;
553 }
554
555 /**
556  * aa_dfa_matchn_until - traverse @dfa until accept or @n bytes consumed
557  * @dfa: the dfa to match @str against  (NOT NULL)
558  * @start: the state of the dfa to start matching in
559  * @str: the string of bytes to match against the dfa  (NOT NULL)
560  * @n: length of the string of bytes to match
561  * @retpos: first character in str after match OR str + n
562  *
563  * aa_dfa_match_len will match @str against the dfa and return the state it
564  * finished matching in. The final state can be used to look up the accepting
565  * label, or as the start state of a continuing match.
566  *
567  * This function will happily match again the 0 byte and only finishes
568  * when @n input is consumed.
569  *
570  * Returns: final state reached after input is consumed
571  */
572 unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start,
573                                  const char *str, int n, const char **retpos)
574 {
575         u16 *def = DEFAULT_TABLE(dfa);
576         u32 *base = BASE_TABLE(dfa);
577         u16 *next = NEXT_TABLE(dfa);
578         u16 *check = CHECK_TABLE(dfa);
579         u32 *accept = ACCEPT_TABLE(dfa);
580         unsigned int state = start, pos;
581
582         *retpos = NULL;
583         if (state == 0)
584                 return 0;
585
586         /* current state is <state>, matching character *str */
587         if (dfa->tables[YYTD_ID_EC]) {
588                 /* Equivalence class table defined */
589                 u8 *equiv = EQUIV_TABLE(dfa);
590                 /* default is direct to next state */
591                 for (; n; n--) {
592                         pos = base_idx(base[state]) + equiv[(u8) *str++];
593                         if (check[pos] == state)
594                                 state = next[pos];
595                         else
596                                 state = def[state];
597                         if (accept[state])
598                                 break;
599                 }
600         } else {
601                 /* default is direct to next state */
602                 for (; n; n--) {
603                         pos = base_idx(base[state]) + (u8) *str++;
604                         if (check[pos] == state)
605                                 state = next[pos];
606                         else
607                                 state = def[state];
608                         if (accept[state])
609                                 break;
610                 }
611         }
612
613         *retpos = str;
614         return state;
615 }
616
617 #define inc_wb_pos(wb)                                          \
618 do {                                                            \
619         wb->pos = (wb->pos + 1) & (wb->size - 1);               \
620         wb->len = (wb->len + 1) & (wb->size - 1);               \
621 } while (0)
622
623 /* For DFAs that don't support extended tagging of states */
624 static bool is_loop(struct match_workbuf *wb, unsigned int state,
625                     unsigned int *adjust)
626 {
627         unsigned int pos = wb->pos;
628         unsigned int i;
629
630         if (wb->history[pos] < state)
631                 return false;
632
633         for (i = 0; i <= wb->len; i++) {
634                 if (wb->history[pos] == state) {
635                         *adjust = i;
636                         return true;
637                 }
638                 if (pos == 0)
639                         pos = wb->size;
640                 pos--;
641         }
642
643         *adjust = i;
644         return true;
645 }
646
647 static unsigned int leftmatch_fb(struct aa_dfa *dfa, unsigned int start,
648                                  const char *str, struct match_workbuf *wb,
649                                  unsigned int *count)
650 {
651         u16 *def = DEFAULT_TABLE(dfa);
652         u32 *base = BASE_TABLE(dfa);
653         u16 *next = NEXT_TABLE(dfa);
654         u16 *check = CHECK_TABLE(dfa);
655         unsigned int state = start, pos;
656
657         AA_BUG(!dfa);
658         AA_BUG(!str);
659         AA_BUG(!wb);
660         AA_BUG(!count);
661
662         *count = 0;
663         if (state == 0)
664                 return 0;
665
666         /* current state is <state>, matching character *str */
667         if (dfa->tables[YYTD_ID_EC]) {
668                 /* Equivalence class table defined */
669                 u8 *equiv = EQUIV_TABLE(dfa);
670                 /* default is direct to next state */
671                 while (*str) {
672                         unsigned int adjust;
673
674                         wb->history[wb->pos] = state;
675                         pos = base_idx(base[state]) + equiv[(u8) *str++];
676                         if (check[pos] == state)
677                                 state = next[pos];
678                         else
679                                 state = def[state];
680                         if (is_loop(wb, state, &adjust)) {
681                                 state = aa_dfa_match(dfa, state, str);
682                                 *count -= adjust;
683                                 goto out;
684                         }
685                         inc_wb_pos(wb);
686                         (*count)++;
687                 }
688         } else {
689                 /* default is direct to next state */
690                 while (*str) {
691                         unsigned int adjust;
692
693                         wb->history[wb->pos] = state;
694                         pos = base_idx(base[state]) + (u8) *str++;
695                         if (check[pos] == state)
696                                 state = next[pos];
697                         else
698                                 state = def[state];
699                         if (is_loop(wb, state, &adjust)) {
700                                 state = aa_dfa_match(dfa, state, str);
701                                 *count -= adjust;
702                                 goto out;
703                         }
704                         inc_wb_pos(wb);
705                         (*count)++;
706                 }
707         }
708
709 out:
710         if (!state)
711                 *count = 0;
712         return state;
713 }
714
715 /**
716  * aa_dfa_leftmatch - traverse @dfa to find state @str stops at
717  * @dfa: the dfa to match @str against  (NOT NULL)
718  * @start: the state of the dfa to start matching in
719  * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
720  * @count: current count of longest left.
721  *
722  * aa_dfa_match will match @str against the dfa and return the state it
723  * finished matching in. The final state can be used to look up the accepting
724  * label, or as the start state of a continuing match.
725  *
726  * Returns: final state reached after input is consumed
727  */
728 unsigned int aa_dfa_leftmatch(struct aa_dfa *dfa, unsigned int start,
729                               const char *str, unsigned int *count)
730 {
731         DEFINE_MATCH_WB(wb);
732
733         /* TODO: match for extended state dfas */
734
735         return leftmatch_fb(dfa, start, str, &wb, count);
736 }