0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/errno.h>
0012 #include <linux/kernel.h>
0013 #include <linux/mm.h>
0014 #include <linux/slab.h>
0015 #include <linux/vmalloc.h>
0016 #include <linux/err.h>
0017 #include <linux/kref.h>
0018
0019 #include "include/lib.h"
0020 #include "include/match.h"
0021
0022 #define base_idx(X) ((X) & 0xffffff)
0023
0024 static char nulldfa_src[] = {
0025 #include "nulldfa.in"
0026 };
0027 struct aa_dfa *nulldfa;
0028
0029 static char stacksplitdfa_src[] = {
0030 #include "stacksplitdfa.in"
0031 };
0032 struct aa_dfa *stacksplitdfa;
0033
0034 int aa_setup_dfa_engine(void)
0035 {
0036 int error;
0037
0038 nulldfa = aa_dfa_unpack(nulldfa_src, sizeof(nulldfa_src),
0039 TO_ACCEPT1_FLAG(YYTD_DATA32) |
0040 TO_ACCEPT2_FLAG(YYTD_DATA32));
0041 if (IS_ERR(nulldfa)) {
0042 error = PTR_ERR(nulldfa);
0043 nulldfa = NULL;
0044 return error;
0045 }
0046
0047 stacksplitdfa = aa_dfa_unpack(stacksplitdfa_src,
0048 sizeof(stacksplitdfa_src),
0049 TO_ACCEPT1_FLAG(YYTD_DATA32) |
0050 TO_ACCEPT2_FLAG(YYTD_DATA32));
0051 if (IS_ERR(stacksplitdfa)) {
0052 aa_put_dfa(nulldfa);
0053 nulldfa = NULL;
0054 error = PTR_ERR(stacksplitdfa);
0055 stacksplitdfa = NULL;
0056 return error;
0057 }
0058
0059 return 0;
0060 }
0061
0062 void aa_teardown_dfa_engine(void)
0063 {
0064 aa_put_dfa(stacksplitdfa);
0065 aa_put_dfa(nulldfa);
0066 }
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 static struct table_header *unpack_table(char *blob, size_t bsize)
0078 {
0079 struct table_header *table = NULL;
0080 struct table_header th;
0081 size_t tsize;
0082
0083 if (bsize < sizeof(struct table_header))
0084 goto out;
0085
0086
0087
0088
0089 th.td_id = be16_to_cpu(*(__be16 *) (blob)) - 1;
0090 if (th.td_id > YYTD_ID_MAX)
0091 goto out;
0092 th.td_flags = be16_to_cpu(*(__be16 *) (blob + 2));
0093 th.td_lolen = be32_to_cpu(*(__be32 *) (blob + 8));
0094 blob += sizeof(struct table_header);
0095
0096 if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
0097 th.td_flags == YYTD_DATA8))
0098 goto out;
0099
0100
0101 if (th.td_lolen == 0)
0102 goto out;
0103 tsize = table_size(th.td_lolen, th.td_flags);
0104 if (bsize < tsize)
0105 goto out;
0106
0107 table = kvzalloc(tsize, GFP_KERNEL);
0108 if (table) {
0109 table->td_id = th.td_id;
0110 table->td_flags = th.td_flags;
0111 table->td_lolen = th.td_lolen;
0112 if (th.td_flags == YYTD_DATA8)
0113 UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
0114 u8, u8, byte_to_byte);
0115 else if (th.td_flags == YYTD_DATA16)
0116 UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
0117 u16, __be16, be16_to_cpu);
0118 else if (th.td_flags == YYTD_DATA32)
0119 UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
0120 u32, __be32, be32_to_cpu);
0121 else
0122 goto fail;
0123
0124
0125
0126 if (is_vmalloc_addr(table))
0127 vm_unmap_aliases();
0128 }
0129
0130 out:
0131 return table;
0132 fail:
0133 kvfree(table);
0134 return NULL;
0135 }
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 static int verify_table_headers(struct table_header **tables, int flags)
0148 {
0149 size_t state_count, trans_count;
0150 int error = -EPROTO;
0151
0152
0153 if (!(tables[YYTD_ID_DEF] && tables[YYTD_ID_BASE] &&
0154 tables[YYTD_ID_NXT] && tables[YYTD_ID_CHK]))
0155 goto out;
0156
0157
0158 state_count = tables[YYTD_ID_BASE]->td_lolen;
0159 if (ACCEPT1_FLAGS(flags)) {
0160 if (!tables[YYTD_ID_ACCEPT])
0161 goto out;
0162 if (state_count != tables[YYTD_ID_ACCEPT]->td_lolen)
0163 goto out;
0164 }
0165 if (ACCEPT2_FLAGS(flags)) {
0166 if (!tables[YYTD_ID_ACCEPT2])
0167 goto out;
0168 if (state_count != tables[YYTD_ID_ACCEPT2]->td_lolen)
0169 goto out;
0170 }
0171 if (state_count != tables[YYTD_ID_DEF]->td_lolen)
0172 goto out;
0173
0174
0175 trans_count = tables[YYTD_ID_NXT]->td_lolen;
0176 if (trans_count != tables[YYTD_ID_CHK]->td_lolen)
0177 goto out;
0178
0179
0180 if (tables[YYTD_ID_EC] && tables[YYTD_ID_EC]->td_lolen != 256)
0181 goto out;
0182
0183 error = 0;
0184 out:
0185 return error;
0186 }
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197 static int verify_dfa(struct aa_dfa *dfa)
0198 {
0199 size_t i, state_count, trans_count;
0200 int error = -EPROTO;
0201
0202 state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
0203 trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen;
0204 if (state_count == 0)
0205 goto out;
0206 for (i = 0; i < state_count; i++) {
0207 if (!(BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE) &&
0208 (DEFAULT_TABLE(dfa)[i] >= state_count))
0209 goto out;
0210 if (BASE_TABLE(dfa)[i] & MATCH_FLAGS_INVALID) {
0211 pr_err("AppArmor DFA state with invalid match flags");
0212 goto out;
0213 }
0214 if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_DIFF_ENCODE)) {
0215 if (!(dfa->flags & YYTH_FLAG_DIFF_ENCODE)) {
0216 pr_err("AppArmor DFA diff encoded transition state without header flag");
0217 goto out;
0218 }
0219 }
0220 if ((BASE_TABLE(dfa)[i] & MATCH_FLAG_OOB_TRANSITION)) {
0221 if (base_idx(BASE_TABLE(dfa)[i]) < dfa->max_oob) {
0222 pr_err("AppArmor DFA out of bad transition out of range");
0223 goto out;
0224 }
0225 if (!(dfa->flags & YYTH_FLAG_OOB_TRANS)) {
0226 pr_err("AppArmor DFA out of bad transition state without header flag");
0227 goto out;
0228 }
0229 }
0230 if (base_idx(BASE_TABLE(dfa)[i]) + 255 >= trans_count) {
0231 pr_err("AppArmor DFA next/check upper bounds error\n");
0232 goto out;
0233 }
0234 }
0235
0236 for (i = 0; i < trans_count; i++) {
0237 if (NEXT_TABLE(dfa)[i] >= state_count)
0238 goto out;
0239 if (CHECK_TABLE(dfa)[i] >= state_count)
0240 goto out;
0241 }
0242
0243
0244 for (i = 0; i < state_count; i++) {
0245 size_t j, k;
0246
0247 for (j = i;
0248 (BASE_TABLE(dfa)[j] & MATCH_FLAG_DIFF_ENCODE) &&
0249 !(BASE_TABLE(dfa)[j] & MARK_DIFF_ENCODE);
0250 j = k) {
0251 k = DEFAULT_TABLE(dfa)[j];
0252 if (j == k)
0253 goto out;
0254 if (k < j)
0255 break;
0256 BASE_TABLE(dfa)[j] |= MARK_DIFF_ENCODE;
0257 }
0258 }
0259 error = 0;
0260
0261 out:
0262 return error;
0263 }
0264
0265
0266
0267
0268
0269
0270
0271 static void dfa_free(struct aa_dfa *dfa)
0272 {
0273 if (dfa) {
0274 int i;
0275
0276 for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
0277 kvfree(dfa->tables[i]);
0278 dfa->tables[i] = NULL;
0279 }
0280 kfree(dfa);
0281 }
0282 }
0283
0284
0285
0286
0287
0288 void aa_dfa_free_kref(struct kref *kref)
0289 {
0290 struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count);
0291 dfa_free(dfa);
0292 }
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306 struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
0307 {
0308 int hsize;
0309 int error = -ENOMEM;
0310 char *data = blob;
0311 struct table_header *table = NULL;
0312 struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
0313 if (!dfa)
0314 goto fail;
0315
0316 kref_init(&dfa->count);
0317
0318 error = -EPROTO;
0319
0320
0321 if (size < sizeof(struct table_set_header))
0322 goto fail;
0323
0324 if (ntohl(*(__be32 *) data) != YYTH_MAGIC)
0325 goto fail;
0326
0327 hsize = ntohl(*(__be32 *) (data + 4));
0328 if (size < hsize)
0329 goto fail;
0330
0331 dfa->flags = ntohs(*(__be16 *) (data + 12));
0332 if (dfa->flags & ~(YYTH_FLAGS))
0333 goto fail;
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347 dfa->max_oob = 1;
0348
0349 data += hsize;
0350 size -= hsize;
0351
0352 while (size > 0) {
0353 table = unpack_table(data, size);
0354 if (!table)
0355 goto fail;
0356
0357 switch (table->td_id) {
0358 case YYTD_ID_ACCEPT:
0359 if (!(table->td_flags & ACCEPT1_FLAGS(flags)))
0360 goto fail;
0361 break;
0362 case YYTD_ID_ACCEPT2:
0363 if (!(table->td_flags & ACCEPT2_FLAGS(flags)))
0364 goto fail;
0365 break;
0366 case YYTD_ID_BASE:
0367 if (table->td_flags != YYTD_DATA32)
0368 goto fail;
0369 break;
0370 case YYTD_ID_DEF:
0371 case YYTD_ID_NXT:
0372 case YYTD_ID_CHK:
0373 if (table->td_flags != YYTD_DATA16)
0374 goto fail;
0375 break;
0376 case YYTD_ID_EC:
0377 if (table->td_flags != YYTD_DATA8)
0378 goto fail;
0379 break;
0380 default:
0381 goto fail;
0382 }
0383
0384 if (dfa->tables[table->td_id])
0385 goto fail;
0386 dfa->tables[table->td_id] = table;
0387 data += table_size(table->td_lolen, table->td_flags);
0388 size -= table_size(table->td_lolen, table->td_flags);
0389 table = NULL;
0390 }
0391 error = verify_table_headers(dfa->tables, flags);
0392 if (error)
0393 goto fail;
0394
0395 if (flags & DFA_FLAG_VERIFY_STATES) {
0396 error = verify_dfa(dfa);
0397 if (error)
0398 goto fail;
0399 }
0400
0401 return dfa;
0402
0403 fail:
0404 kvfree(table);
0405 dfa_free(dfa);
0406 return ERR_PTR(error);
0407 }
0408
0409 #define match_char(state, def, base, next, check, C) \
0410 do { \
0411 u32 b = (base)[(state)]; \
0412 unsigned int pos = base_idx(b) + (C); \
0413 if ((check)[pos] != (state)) { \
0414 (state) = (def)[(state)]; \
0415 if (b & MATCH_FLAG_DIFF_ENCODE) \
0416 continue; \
0417 break; \
0418 } \
0419 (state) = (next)[pos]; \
0420 break; \
0421 } while (1)
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
0440 const char *str, int len)
0441 {
0442 u16 *def = DEFAULT_TABLE(dfa);
0443 u32 *base = BASE_TABLE(dfa);
0444 u16 *next = NEXT_TABLE(dfa);
0445 u16 *check = CHECK_TABLE(dfa);
0446 unsigned int state = start;
0447
0448 if (state == 0)
0449 return 0;
0450
0451
0452 if (dfa->tables[YYTD_ID_EC]) {
0453
0454 u8 *equiv = EQUIV_TABLE(dfa);
0455 for (; len; len--)
0456 match_char(state, def, base, next, check,
0457 equiv[(u8) *str++]);
0458 } else {
0459
0460 for (; len; len--)
0461 match_char(state, def, base, next, check, (u8) *str++);
0462 }
0463
0464 return state;
0465 }
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479 unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
0480 const char *str)
0481 {
0482 u16 *def = DEFAULT_TABLE(dfa);
0483 u32 *base = BASE_TABLE(dfa);
0484 u16 *next = NEXT_TABLE(dfa);
0485 u16 *check = CHECK_TABLE(dfa);
0486 unsigned int state = start;
0487
0488 if (state == 0)
0489 return 0;
0490
0491
0492 if (dfa->tables[YYTD_ID_EC]) {
0493
0494 u8 *equiv = EQUIV_TABLE(dfa);
0495
0496 while (*str)
0497 match_char(state, def, base, next, check,
0498 equiv[(u8) *str++]);
0499 } else {
0500
0501 while (*str)
0502 match_char(state, def, base, next, check, (u8) *str++);
0503 }
0504
0505 return state;
0506 }
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518 unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
0519 const char c)
0520 {
0521 u16 *def = DEFAULT_TABLE(dfa);
0522 u32 *base = BASE_TABLE(dfa);
0523 u16 *next = NEXT_TABLE(dfa);
0524 u16 *check = CHECK_TABLE(dfa);
0525
0526
0527 if (dfa->tables[YYTD_ID_EC]) {
0528
0529 u8 *equiv = EQUIV_TABLE(dfa);
0530 match_char(state, def, base, next, check, equiv[(u8) c]);
0531 } else
0532 match_char(state, def, base, next, check, (u8) c);
0533
0534 return state;
0535 }
0536
0537 unsigned int aa_dfa_outofband_transition(struct aa_dfa *dfa, unsigned int state)
0538 {
0539 u16 *def = DEFAULT_TABLE(dfa);
0540 u32 *base = BASE_TABLE(dfa);
0541 u16 *next = NEXT_TABLE(dfa);
0542 u16 *check = CHECK_TABLE(dfa);
0543 u32 b = (base)[(state)];
0544
0545 if (!(b & MATCH_FLAG_OOB_TRANSITION))
0546 return DFA_NOMATCH;
0547
0548
0549 match_char(state, def, base, next, check, -1);
0550
0551 return state;
0552 }
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567 unsigned int aa_dfa_match_until(struct aa_dfa *dfa, unsigned int start,
0568 const char *str, const char **retpos)
0569 {
0570 u16 *def = DEFAULT_TABLE(dfa);
0571 u32 *base = BASE_TABLE(dfa);
0572 u16 *next = NEXT_TABLE(dfa);
0573 u16 *check = CHECK_TABLE(dfa);
0574 u32 *accept = ACCEPT_TABLE(dfa);
0575 unsigned int state = start, pos;
0576
0577 if (state == 0)
0578 return 0;
0579
0580
0581 if (dfa->tables[YYTD_ID_EC]) {
0582
0583 u8 *equiv = EQUIV_TABLE(dfa);
0584
0585 while (*str) {
0586 pos = base_idx(base[state]) + equiv[(u8) *str++];
0587 if (check[pos] == state)
0588 state = next[pos];
0589 else
0590 state = def[state];
0591 if (accept[state])
0592 break;
0593 }
0594 } else {
0595
0596 while (*str) {
0597 pos = base_idx(base[state]) + (u8) *str++;
0598 if (check[pos] == state)
0599 state = next[pos];
0600 else
0601 state = def[state];
0602 if (accept[state])
0603 break;
0604 }
0605 }
0606
0607 *retpos = str;
0608 return state;
0609 }
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628 unsigned int aa_dfa_matchn_until(struct aa_dfa *dfa, unsigned int start,
0629 const char *str, int n, const char **retpos)
0630 {
0631 u16 *def = DEFAULT_TABLE(dfa);
0632 u32 *base = BASE_TABLE(dfa);
0633 u16 *next = NEXT_TABLE(dfa);
0634 u16 *check = CHECK_TABLE(dfa);
0635 u32 *accept = ACCEPT_TABLE(dfa);
0636 unsigned int state = start, pos;
0637
0638 *retpos = NULL;
0639 if (state == 0)
0640 return 0;
0641
0642
0643 if (dfa->tables[YYTD_ID_EC]) {
0644
0645 u8 *equiv = EQUIV_TABLE(dfa);
0646
0647 for (; n; n--) {
0648 pos = base_idx(base[state]) + equiv[(u8) *str++];
0649 if (check[pos] == state)
0650 state = next[pos];
0651 else
0652 state = def[state];
0653 if (accept[state])
0654 break;
0655 }
0656 } else {
0657
0658 for (; n; n--) {
0659 pos = base_idx(base[state]) + (u8) *str++;
0660 if (check[pos] == state)
0661 state = next[pos];
0662 else
0663 state = def[state];
0664 if (accept[state])
0665 break;
0666 }
0667 }
0668
0669 *retpos = str;
0670 return state;
0671 }
0672
0673 #define inc_wb_pos(wb) \
0674 do { \
0675 wb->pos = (wb->pos + 1) & (WB_HISTORY_SIZE - 1); \
0676 wb->len = (wb->len + 1) & (WB_HISTORY_SIZE - 1); \
0677 } while (0)
0678
0679
0680 static bool is_loop(struct match_workbuf *wb, unsigned int state,
0681 unsigned int *adjust)
0682 {
0683 unsigned int pos = wb->pos;
0684 unsigned int i;
0685
0686 if (wb->history[pos] < state)
0687 return false;
0688
0689 for (i = 0; i <= wb->len; i++) {
0690 if (wb->history[pos] == state) {
0691 *adjust = i;
0692 return true;
0693 }
0694 if (pos == 0)
0695 pos = WB_HISTORY_SIZE;
0696 pos--;
0697 }
0698
0699 *adjust = i;
0700 return true;
0701 }
0702
0703 static unsigned int leftmatch_fb(struct aa_dfa *dfa, unsigned int start,
0704 const char *str, struct match_workbuf *wb,
0705 unsigned int *count)
0706 {
0707 u16 *def = DEFAULT_TABLE(dfa);
0708 u32 *base = BASE_TABLE(dfa);
0709 u16 *next = NEXT_TABLE(dfa);
0710 u16 *check = CHECK_TABLE(dfa);
0711 unsigned int state = start, pos;
0712
0713 AA_BUG(!dfa);
0714 AA_BUG(!str);
0715 AA_BUG(!wb);
0716 AA_BUG(!count);
0717
0718 *count = 0;
0719 if (state == 0)
0720 return 0;
0721
0722
0723 if (dfa->tables[YYTD_ID_EC]) {
0724
0725 u8 *equiv = EQUIV_TABLE(dfa);
0726
0727 while (*str) {
0728 unsigned int adjust;
0729
0730 wb->history[wb->pos] = state;
0731 pos = base_idx(base[state]) + equiv[(u8) *str++];
0732 if (check[pos] == state)
0733 state = next[pos];
0734 else
0735 state = def[state];
0736 if (is_loop(wb, state, &adjust)) {
0737 state = aa_dfa_match(dfa, state, str);
0738 *count -= adjust;
0739 goto out;
0740 }
0741 inc_wb_pos(wb);
0742 (*count)++;
0743 }
0744 } else {
0745
0746 while (*str) {
0747 unsigned int adjust;
0748
0749 wb->history[wb->pos] = state;
0750 pos = base_idx(base[state]) + (u8) *str++;
0751 if (check[pos] == state)
0752 state = next[pos];
0753 else
0754 state = def[state];
0755 if (is_loop(wb, state, &adjust)) {
0756 state = aa_dfa_match(dfa, state, str);
0757 *count -= adjust;
0758 goto out;
0759 }
0760 inc_wb_pos(wb);
0761 (*count)++;
0762 }
0763 }
0764
0765 out:
0766 if (!state)
0767 *count = 0;
0768 return state;
0769 }
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784 unsigned int aa_dfa_leftmatch(struct aa_dfa *dfa, unsigned int start,
0785 const char *str, unsigned int *count)
0786 {
0787 DEFINE_MATCH_WB(wb);
0788
0789
0790
0791 return leftmatch_fb(dfa, start, str, &wb, count);
0792 }