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