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