.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * AppArmor security module |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * |
---|
6 | 7 | * Copyright (C) 1998-2008 Novell/SUSE |
---|
7 | 8 | * Copyright 2009-2012 Canonical Ltd. |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or |
---|
10 | | - * modify it under the terms of the GNU General Public License as |
---|
11 | | - * published by the Free Software Foundation, version 2 of the |
---|
12 | | - * License. |
---|
13 | 9 | */ |
---|
14 | 10 | |
---|
15 | 11 | #include <linux/errno.h> |
---|
.. | .. |
---|
211 | 207 | if (!(BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE) && |
---|
212 | 208 | (DEFAULT_TABLE(dfa)[i] >= state_count)) |
---|
213 | 209 | goto out; |
---|
| 210 | + if (BASE_TABLE(dfa)[i] & MATCH_FLAGS_INVALID) { |
---|
| 211 | + pr_err("AppArmor DFA state with invalid match flags"); |
---|
| 212 | + goto out; |
---|
| 213 | + } |
---|
| 214 | + if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE)) { |
---|
| 215 | + if (!(dfa->flags & YYTH_FLAG_DIFF_ENCODE)) { |
---|
| 216 | + pr_err("AppArmor DFA diff encoded transition state without header flag"); |
---|
| 217 | + goto out; |
---|
| 218 | + } |
---|
| 219 | + } |
---|
| 220 | + if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_OOB_TRANSITION)) { |
---|
| 221 | + if (base_idx(BASE_TABLE(dfa)[i]) < dfa->max_oob) { |
---|
| 222 | + pr_err("AppArmor DFA out of bad transition out of range"); |
---|
| 223 | + goto out; |
---|
| 224 | + } |
---|
| 225 | + if (!(dfa->flags & YYTH_FLAG_OOB_TRANS)) { |
---|
| 226 | + pr_err("AppArmor DFA out of bad transition state without header flag"); |
---|
| 227 | + goto out; |
---|
| 228 | + } |
---|
| 229 | + } |
---|
214 | 230 | if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) { |
---|
215 | 231 | pr_err("AppArmor DFA next/check upper bounds error\n"); |
---|
216 | 232 | goto out; |
---|
.. | .. |
---|
313 | 329 | goto fail; |
---|
314 | 330 | |
---|
315 | 331 | dfa->flags = ntohs(*(__be16 *) (data + 12)); |
---|
316 | | - if (dfa->flags != 0 && dfa->flags != YYTH_FLAG_DIFF_ENCODE) |
---|
| 332 | + if (dfa->flags & ~(YYTH_FLAGS)) |
---|
317 | 333 | goto fail; |
---|
| 334 | + |
---|
| 335 | + /* |
---|
| 336 | + * TODO: needed for dfa to support more than 1 oob |
---|
| 337 | + * if (dfa->flags & YYTH_FLAGS_OOB_TRANS) { |
---|
| 338 | + * if (hsize < 16 + 4) |
---|
| 339 | + * goto fail; |
---|
| 340 | + * dfa->max_oob = ntol(*(__be32 *) (data + 16)); |
---|
| 341 | + * if (dfa->max <= MAX_OOB_SUPPORTED) { |
---|
| 342 | + * pr_err("AppArmor DFA OOB greater than supported\n"); |
---|
| 343 | + * goto fail; |
---|
| 344 | + * } |
---|
| 345 | + * } |
---|
| 346 | + */ |
---|
| 347 | + dfa->max_oob = 1; |
---|
318 | 348 | |
---|
319 | 349 | data += hsize; |
---|
320 | 350 | size -= hsize; |
---|
.. | .. |
---|
504 | 534 | return state; |
---|
505 | 535 | } |
---|
506 | 536 | |
---|
| 537 | +unsigned int aa_dfa_outofband_transition(struct aa_dfa *dfa, unsigned int state) |
---|
| 538 | +{ |
---|
| 539 | + u16 *def = DEFAULT_TABLE(dfa); |
---|
| 540 | + u32 *base = BASE_TABLE(dfa); |
---|
| 541 | + u16 *next = NEXT_TABLE(dfa); |
---|
| 542 | + u16 *check = CHECK_TABLE(dfa); |
---|
| 543 | + u32 b = (base)[(state)]; |
---|
| 544 | + |
---|
| 545 | + if (!(b & MATCH_FLAG_OOB_TRANSITION)) |
---|
| 546 | + return DFA_NOMATCH; |
---|
| 547 | + |
---|
| 548 | + /* No Equivalence class remapping for outofband transitions */ |
---|
| 549 | + match_char(state, def, base, next, check, -1); |
---|
| 550 | + |
---|
| 551 | + return state; |
---|
| 552 | +} |
---|
| 553 | + |
---|
507 | 554 | /** |
---|
508 | 555 | * aa_dfa_match_until - traverse @dfa until accept state or end of input |
---|
509 | 556 | * @dfa: the dfa to match @str against (NOT NULL) |
---|
.. | .. |
---|
625 | 672 | |
---|
626 | 673 | #define inc_wb_pos(wb) \ |
---|
627 | 674 | do { \ |
---|
628 | | - wb->pos = (wb->pos + 1) & (wb->size - 1); \ |
---|
629 | | - wb->len = (wb->len + 1) & (wb->size - 1); \ |
---|
| 675 | + wb->pos = (wb->pos + 1) & (WB_HISTORY_SIZE - 1); \ |
---|
| 676 | + wb->len = (wb->len + 1) & (WB_HISTORY_SIZE - 1); \ |
---|
630 | 677 | } while (0) |
---|
631 | 678 | |
---|
632 | 679 | /* For DFAs that don't support extended tagging of states */ |
---|
.. | .. |
---|
645 | 692 | return true; |
---|
646 | 693 | } |
---|
647 | 694 | if (pos == 0) |
---|
648 | | - pos = wb->size; |
---|
| 695 | + pos = WB_HISTORY_SIZE; |
---|
649 | 696 | pos--; |
---|
650 | 697 | } |
---|
651 | 698 | |
---|