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