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_TABLE(dfa)[i] & MATCH_FLAGS_INVALID) { 206 pr_err("AppArmor DFA state with invalid match flags"); 207 goto out; 208 } 209 if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE)) { 210 if (!(dfa->flags & YYTH_FLAG_DIFF_ENCODE)) { 211 pr_err("AppArmor DFA diff encoded transition state without header flag"); 212 goto out; 213 } 214 } 215 if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) { 216 pr_err("AppArmor DFA next/check upper bounds error\n"); 217 goto out; 218 } 219 } 220 221 for (i = 0; i < trans_count; i++) { 222 if (NEXT_TABLE(dfa)[i] >= state_count) 223 goto out; 224 if (CHECK_TABLE(dfa)[i] >= state_count) 225 goto out; 226 } 227 228 /* Now that all the other tables are verified, verify diffencoding */ 229 for (i = 0; i < state_count; i++) { 230 size_t j, k; 231 232 for (j = i; 233 (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) && 234 !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE); 235 j = k) { 236 k = DEFAULT_TABLE(dfa)[j]; 237 if (j == k) 238 goto out; 239 if (k < j) 240 break; /* already verified */ 241 BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE; 242 } 243 } 244 error = 0; 245 246 out: 247 return error; 248 } 249 250 /** 251 * dfa_free - free a dfa allocated by aa_dfa_unpack 252 * @dfa: the dfa to free (MAYBE NULL) 253 * 254 * Requires: reference count to dfa == 0 255 */ 256 static void dfa_free(struct aa_dfa *dfa) 257 { 258 if (dfa) { 259 int i; 260 261 for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) { 262 kvfree(dfa->tables[i]); 263 dfa->tables[i] = NULL; 264 } 265 kfree(dfa); 266 } 267 } 268 269 /** 270 * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa) 271 * @kr: kref callback for freeing of a dfa (NOT NULL) 272 */ 273 void aa_dfa_free_kref(struct kref *kref) 274 { 275 struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count); 276 dfa_free(dfa); 277 } 278 279 /** 280 * aa_dfa_unpack - unpack the binary tables of a serialized dfa 281 * @blob: aligned serialized stream of data to unpack (NOT NULL) 282 * @size: size of data to unpack 283 * @flags: flags controlling what type of accept tables are acceptable 284 * 285 * Unpack a dfa that has been serialized. To find information on the dfa 286 * format look in Documentation/admin-guide/LSM/apparmor.rst 287 * Assumes the dfa @blob stream has been aligned on a 8 byte boundary 288 * 289 * Returns: an unpacked dfa ready for matching or ERR_PTR on failure 290 */ 291 struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags) 292 { 293 int hsize; 294 int error = -ENOMEM; 295 char *data = blob; 296 struct table_header *table = NULL; 297 struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL); 298 if (!dfa) 299 goto fail; 300 301 kref_init(&dfa->count); 302 303 error = -EPROTO; 304 305 /* get dfa table set header */ 306 if (size < sizeof(struct table_set_header)) 307 goto fail; 308 309 if (ntohl(*(__be32 *) data) != YYTH_MAGIC) 310 goto fail; 311 312 hsize = ntohl(*(__be32 *) (data + 4)); 313 if (size < hsize) 314 goto fail; 315 316 dfa->flags = ntohs(*(__be16 *) (data + 12)); 317 if (dfa->flags != 0 && dfa->flags != YYTH_FLAG_DIFF_ENCODE) 318 goto fail; 319 320 data += hsize; 321 size -= hsize; 322 323 while (size > 0) { 324 table = unpack_table(data, size); 325 if (!table) 326 goto fail; 327 328 switch (table->td_id) { 329 case YYTD_ID_ACCEPT: 330 if (!(table->td_flags & ACCEPT1_FLAGS(flags))) 331 goto fail; 332 break; 333 case YYTD_ID_ACCEPT2: 334 if (!(table->td_flags & ACCEPT2_FLAGS(flags))) 335 goto fail; 336 break; 337 case YYTD_ID_BASE: 338 if (table->td_flags != YYTD_DATA32) 339 goto fail; 340 break; 341 case YYTD_ID_DEF: 342 case YYTD_ID_NXT: 343 case YYTD_ID_CHK: 344 if (table->td_flags != YYTD_DATA16) 345 goto fail; 346 break; 347 case YYTD_ID_EC: 348 if (table->td_flags != YYTD_DATA8) 349 goto fail; 350 break; 351 default: 352 goto fail; 353 } 354 /* check for duplicate table entry */ 355 if (dfa->tables[table->td_id]) 356 goto fail; 357 dfa->tables[table->td_id] = table; 358 data += table_size(table->td_lolen, table->td_flags); 359 size -= table_size(table->td_lolen, table->td_flags); 360 table = NULL; 361 } 362 error = verify_table_headers(dfa->tables, flags); 363 if (error) 364 goto fail; 365 366 if (flags & DFA_FLAG_VERIFY_STATES) { 367 error = verify_dfa(dfa); 368 if (error) 369 goto fail; 370 } 371 372 return dfa; 373 374 fail: 375 kvfree(table); 376 dfa_free(dfa); 377 return ERR_PTR(error); 378 } 379 380 #define match_char(state, def, base, next, check, C) \ 381 do { \ 382 u32 b = (base)[(state)]; \ 383 unsigned int pos = base_idx(b) + (C); \ 384 if ((check)[pos] != (state)) { \ 385 (state) = (def)[(state)]; \ 386 if (b & MATCH_FLAG_DIFF_ENCODE) \ 387 continue; \ 388 break; \ 389 } \ 390 (state) = (next)[pos]; \ 391 break; \ 392 } while (1) 393 394 /** 395 * aa_dfa_match_len - traverse @dfa to find state @str stops at 396 * @dfa: the dfa to match @str against (NOT NULL) 397 * @start: the state of the dfa to start matching in 398 * @str: the string of bytes to match against the dfa (NOT NULL) 399 * @len: length of the string of bytes to match 400 * 401 * aa_dfa_match_len will match @str against the dfa and return the state it 402 * finished matching in. The final state can be used to look up the accepting 403 * label, or as the start state of a continuing match. 404 * 405 * This function will happily match again the 0 byte and only finishes 406 * when @len input is consumed. 407 * 408 * Returns: final state reached after input is consumed 409 */ 410 unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start, 411 const char *str, int len) 412 { 413 u16 *def = DEFAULT_TABLE(dfa); 414 u32 *base = BASE_TABLE(dfa); 415 u16 *next = NEXT_TABLE(dfa); 416 u16 *check = CHECK_TABLE(dfa); 417 unsigned int state = start; 418 419 if (state == 0) 420 return 0; 421 422 /* current state is <state>, matching character *str */ 423 if (dfa->tables[YYTD_ID_EC]) { 424 /* Equivalence class table defined */ 425 u8 *equiv = EQUIV_TABLE(dfa); 426 for (; len; len--) 427 match_char(state, def, base, next, check, 428 equiv[(u8) *str++]); 429 } else { 430 /* default is direct to next state */ 431 for (; len; len--) 432 match_char(state, def, base, next, check, (u8) *str++); 433 } 434 435 return state; 436 } 437 438 /** 439 * aa_dfa_match - traverse @dfa to find state @str stops at 440 * @dfa: the dfa to match @str against (NOT NULL) 441 * @start: the state of the dfa to start matching in 442 * @str: the null terminated string of bytes to match against the dfa (NOT NULL) 443 * 444 * aa_dfa_match will match @str against the dfa and return the state it 445 * finished matching in. The final state can be used to look up the accepting 446 * label, or as the start state of a continuing match. 447 * 448 * Returns: final state reached after input is consumed 449 */ 450 unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start, 451 const char *str) 452 { 453 u16 *def = DEFAULT_TABLE(dfa); 454 u32 *base = BASE_TABLE(dfa); 455 u16 *next = NEXT_TABLE(dfa); 456 u16 *check = CHECK_TABLE(dfa); 457 unsigned int state = start; 458 459 if (state == 0) 460 return 0; 461 462 /* current state is <state>, matching character *str */ 463 if (dfa->tables[YYTD_ID_EC]) { 464 /* Equivalence class table defined */ 465 u8 *equiv = EQUIV_TABLE(dfa); 466 /* default is direct to next state */ 467 while (*str) 468 match_char(state, def, base, next, check, 469 equiv[(u8) *str++]); 470 } else { 471 /* default is direct to next state */ 472 while (*str) 473 match_char(state, def, base, next, check, (u8) *str++); 474 } 475 476 return state; 477 } 478 479 /** 480 * aa_dfa_next - step one character to the next state in the dfa 481 * @dfa: the dfa to traverse (NOT NULL) 482 * @state: the state to start in 483 * @c: the input character to transition on 484 * 485 * aa_dfa_match will step through the dfa by one input character @c 486 * 487 * Returns: state reach after input @c 488 */ 489 unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state, 490 const char c) 491 { 492 u16 *def = DEFAULT_TABLE(dfa); 493 u32 *base = BASE_TABLE(dfa); 494 u16 *next = NEXT_TABLE(dfa); 495 u16 *check = CHECK_TABLE(dfa); 496 497 /* current state is <state>, matching character *str */ 498 if (dfa->tables[YYTD_ID_EC]) { 499 /* Equivalence class table defined */ 500 u8 *equiv = EQUIV_TABLE(dfa); 501 match_char(state, def, base, next, check, equiv[(u8) c]); 502 } else 503 match_char(state, def, base, next, check, (u8) c); 504 505 return state; 506 } 507 508 /** 509 * aa_dfa_match_until - traverse @dfa until accept state or end of input 510 * @dfa: the dfa to match @str against (NOT NULL) 511 * @start: the state of the dfa to start matching in 512 * @str: the null terminated string of bytes to match against the dfa (NOT NULL) 513 * @retpos: first character in str after match OR end of string 514 * 515 * aa_dfa_match will match @str against the dfa and return the state it 516 * finished matching in. The final state can be used to look up the accepting 517 * label, or as the start state of a continuing match. 518 * 519 * Returns: final state reached after input is consumed 520 */ 521 unsigned int aa_dfa_match_until(struct aa_dfa *dfa, unsigned int start, 522 const char *str, const char **retpos) 523 { 524 u16 *def = DEFAULT_TABLE(dfa); 525 u32 *base = BASE_TABLE(dfa); 526 u16 *next = NEXT_TABLE(dfa); 527 u16 *check = CHECK_TABLE(dfa); 528 u32 *accept = ACCEPT_TABLE(dfa); 529 unsigned int state = start, pos; 530 531 if (state == 0) 532 return 0; 533 534 /* current state is <state>, matching character *str */ 535 if (dfa->tables[YYTD_ID_EC]) { 536 /* Equivalence class table defined */ 537 u8 *equiv = EQUIV_TABLE(dfa); 538 /* default is direct to next state */ 539 while (*str) { 540 pos = base_idx(base[state]) + equiv[(u8) *str++]; 541 if (check[pos] == state) 542 state = next[pos]; 543 else 544 state = def[state]; 545 if (accept[state]) 546 break; 547 } 548 } else { 549 /* default is direct to next state */ 550 while (*str) { 551 pos = base_idx(base[state]) + (u8) *str++; 552 if (check[pos] == state) 553 state = next[pos]; 554 else 555 state = def[state]; 556 if (accept[state]) 557 break; 558 } 559 } 560 561 *retpos = str; 562 return state; 563 } 564 565 /** 566 * aa_dfa_matchn_until - traverse @dfa until accept or @n bytes consumed 567 * @dfa: the dfa to match @str against (NOT NULL) 568 * @start: the state of the dfa to start matching in 569 * @str: the string of bytes to match against the dfa (NOT NULL) 570 * @n: length of the string of bytes to match 571 * @retpos: first character in str after match OR str + n 572 * 573 * aa_dfa_match_len will match @str against the dfa and return the state it 574 * finished matching in. The final state can be used to look up the accepting 575 * label, or as the start state of a continuing match. 576 * 577 * This function will happily match again the 0 byte and only finishes 578 * when @n input is consumed. 579 * 580 * Returns: final state reached after input is consumed 581 */ 582 unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start, 583 const char *str, int n, const char **retpos) 584 { 585 u16 *def = DEFAULT_TABLE(dfa); 586 u32 *base = BASE_TABLE(dfa); 587 u16 *next = NEXT_TABLE(dfa); 588 u16 *check = CHECK_TABLE(dfa); 589 u32 *accept = ACCEPT_TABLE(dfa); 590 unsigned int state = start, pos; 591 592 *retpos = NULL; 593 if (state == 0) 594 return 0; 595 596 /* current state is <state>, matching character *str */ 597 if (dfa->tables[YYTD_ID_EC]) { 598 /* Equivalence class table defined */ 599 u8 *equiv = EQUIV_TABLE(dfa); 600 /* default is direct to next state */ 601 for (; n; n--) { 602 pos = base_idx(base[state]) + equiv[(u8) *str++]; 603 if (check[pos] == state) 604 state = next[pos]; 605 else 606 state = def[state]; 607 if (accept[state]) 608 break; 609 } 610 } else { 611 /* default is direct to next state */ 612 for (; n; n--) { 613 pos = base_idx(base[state]) + (u8) *str++; 614 if (check[pos] == state) 615 state = next[pos]; 616 else 617 state = def[state]; 618 if (accept[state]) 619 break; 620 } 621 } 622 623 *retpos = str; 624 return state; 625 } 626 627 #define inc_wb_pos(wb) \ 628 do { \ 629 wb->pos = (wb->pos + 1) & (WB_HISTORY_SIZE - 1); \ 630 wb->len = (wb->len + 1) & (WB_HISTORY_SIZE - 1); \ 631 } while (0) 632 633 /* For DFAs that don't support extended tagging of states */ 634 static bool is_loop(struct match_workbuf *wb, unsigned int state, 635 unsigned int *adjust) 636 { 637 unsigned int pos = wb->pos; 638 unsigned int i; 639 640 if (wb->history[pos] < state) 641 return false; 642 643 for (i = 0; i <= wb->len; i++) { 644 if (wb->history[pos] == state) { 645 *adjust = i; 646 return true; 647 } 648 if (pos == 0) 649 pos = WB_HISTORY_SIZE; 650 pos--; 651 } 652 653 *adjust = i; 654 return true; 655 } 656 657 static unsigned int leftmatch_fb(struct aa_dfa *dfa, unsigned int start, 658 const char *str, struct match_workbuf *wb, 659 unsigned int *count) 660 { 661 u16 *def = DEFAULT_TABLE(dfa); 662 u32 *base = BASE_TABLE(dfa); 663 u16 *next = NEXT_TABLE(dfa); 664 u16 *check = CHECK_TABLE(dfa); 665 unsigned int state = start, pos; 666 667 AA_BUG(!dfa); 668 AA_BUG(!str); 669 AA_BUG(!wb); 670 AA_BUG(!count); 671 672 *count = 0; 673 if (state == 0) 674 return 0; 675 676 /* current state is <state>, matching character *str */ 677 if (dfa->tables[YYTD_ID_EC]) { 678 /* Equivalence class table defined */ 679 u8 *equiv = EQUIV_TABLE(dfa); 680 /* default is direct to next state */ 681 while (*str) { 682 unsigned int adjust; 683 684 wb->history[wb->pos] = state; 685 pos = base_idx(base[state]) + equiv[(u8) *str++]; 686 if (check[pos] == state) 687 state = next[pos]; 688 else 689 state = def[state]; 690 if (is_loop(wb, state, &adjust)) { 691 state = aa_dfa_match(dfa, state, str); 692 *count -= adjust; 693 goto out; 694 } 695 inc_wb_pos(wb); 696 (*count)++; 697 } 698 } else { 699 /* default is direct to next state */ 700 while (*str) { 701 unsigned int adjust; 702 703 wb->history[wb->pos] = state; 704 pos = base_idx(base[state]) + (u8) *str++; 705 if (check[pos] == state) 706 state = next[pos]; 707 else 708 state = def[state]; 709 if (is_loop(wb, state, &adjust)) { 710 state = aa_dfa_match(dfa, state, str); 711 *count -= adjust; 712 goto out; 713 } 714 inc_wb_pos(wb); 715 (*count)++; 716 } 717 } 718 719 out: 720 if (!state) 721 *count = 0; 722 return state; 723 } 724 725 /** 726 * aa_dfa_leftmatch - traverse @dfa to find state @str stops at 727 * @dfa: the dfa to match @str against (NOT NULL) 728 * @start: the state of the dfa to start matching in 729 * @str: the null terminated string of bytes to match against the dfa (NOT NULL) 730 * @count: current count of longest left. 731 * 732 * aa_dfa_match will match @str against the dfa and return the state it 733 * finished matching in. The final state can be used to look up the accepting 734 * label, or as the start state of a continuing match. 735 * 736 * Returns: final state reached after input is consumed 737 */ 738 unsigned int aa_dfa_leftmatch(struct aa_dfa *dfa, unsigned int start, 739 const char *str, unsigned int *count) 740 { 741 DEFINE_MATCH_WB(wb); 742 743 /* TODO: match for extended state dfas */ 744 745 return leftmatch_fb(dfa, start, str, &wb, count); 746 } 747