Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

apparmor: make str table more generic and be able to have multiple entries

The strtable is currently limited to a single entry string on unpack
even though domain has the concept of multiple entries within it. Make
this a reality as it will be used for tags and more advanced domain
transitions.

Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>

+91 -47
+1 -1
security/apparmor/domain.c
··· 529 529 /* TODO: move lookup parsing to unpack time so this is a straight 530 530 * index into the resultant label 531 531 */ 532 - for (next = rules->file->trans.table[index]; next; 532 + for (next = rules->file->trans.table[index].strs; next; 533 533 next = next_name(xtype, next)) { 534 534 const char *lookup = (*next == '&') ? next + 1 : next; 535 535 *name = next;
+10 -3
security/apparmor/include/lib.h
··· 30 30 #define DEBUG_DOMAIN 4 31 31 #define DEBUG_POLICY 8 32 32 #define DEBUG_INTERFACE 0x10 33 + #define DEBUG_UNPACK 0x40 33 34 34 35 #define DEBUG_ALL 0x1f /* update if new DEBUG_X added */ 35 36 #define DEBUG_PARSE_ERROR (-1) ··· 120 119 return !(dentry->d_sb->s_flags & SB_NOUSER); 121 120 } 122 121 123 - struct aa_str_table { 122 + struct aa_str_table_ent { 123 + int count; 124 124 int size; 125 - char **table; 125 + char *strs; 126 126 }; 127 127 128 - void aa_free_str_table(struct aa_str_table *table); 128 + struct aa_str_table { 129 + int size; 130 + struct aa_str_table_ent *table; 131 + }; 132 + 129 133 bool aa_resize_str_table(struct aa_str_table *t, int newsize, gfp_t gfp); 134 + void aa_destroy_str_table(struct aa_str_table *table); 130 135 131 136 struct counted_str { 132 137 struct kref count;
+6 -5
security/apparmor/lib.c
··· 44 44 { "domain", DEBUG_DOMAIN }, 45 45 { "policy", DEBUG_POLICY }, 46 46 { "interface", DEBUG_INTERFACE }, 47 + { "unpack", DEBUG_UNPACK }, 47 48 { NULL, 0 } 48 49 }; 49 50 ··· 119 118 120 119 bool aa_resize_str_table(struct aa_str_table *t, int newsize, gfp_t gfp) 121 120 { 122 - char **n; 121 + struct aa_str_table_ent *n; 123 122 int i; 124 123 125 124 if (t->size == newsize) ··· 130 129 for (i = 0; i < min(t->size, newsize); i++) 131 130 n[i] = t->table[i]; 132 131 for (; i < t->size; i++) 133 - kfree_sensitive(t->table[i]); 132 + kfree_sensitive(t->table[i].strs); 134 133 if (newsize > t->size) 135 134 memset(&n[t->size], 0, (newsize-t->size)*sizeof(*n)); 136 135 kfree_sensitive(t->table); ··· 141 140 } 142 141 143 142 /** 144 - * aa_free_str_table - free entries str table 143 + * aa_destroy_str_table - free entries str table 145 144 * @t: the string table to free (MAYBE NULL) 146 145 */ 147 - void aa_free_str_table(struct aa_str_table *t) 146 + void aa_destroy_str_table(struct aa_str_table *t) 148 147 { 149 148 int i; 150 149 ··· 153 152 return; 154 153 155 154 for (i = 0; i < t->size; i++) 156 - kfree_sensitive(t->table[i]); 155 + kfree_sensitive(t->table[i].strs); 157 156 kfree_sensitive(t->table); 158 157 t->table = NULL; 159 158 t->size = 0;
+1 -1
security/apparmor/policy.c
··· 104 104 if (pdb) { 105 105 aa_put_dfa(pdb->dfa); 106 106 kvfree(pdb->perms); 107 - aa_free_str_table(&pdb->trans); 107 + aa_destroy_str_table(&pdb->trans); 108 108 kfree(pdb); 109 109 } 110 110 }
+73 -37
security/apparmor/policy_unpack.c
··· 450 450 return dfa; 451 451 } 452 452 453 + static int process_strs_entry(char *str, int size, bool multi) 454 + { 455 + int c = 1; 456 + 457 + if (size <= 0) 458 + return -1; 459 + if (multi) { 460 + if (size < 2) 461 + return -2; 462 + /* multi ends with double \0 */ 463 + if (str[size - 2]) 464 + return -3; 465 + } 466 + 467 + char *save = str; 468 + char *pos = str; 469 + char *end = multi ? str + size - 2 : str + size - 1; 470 + /* count # of internal \0 */ 471 + while (str < end) { 472 + if (str == pos) { 473 + /* starts with ... */ 474 + if (!*str) { 475 + AA_DEBUG(DEBUG_UNPACK, 476 + "starting with null save=%lu size %d c=%d", 477 + str - save, size, c); 478 + return -4; 479 + } 480 + if (isspace(*str)) 481 + return -5; 482 + if (*str == ':') { 483 + /* :ns_str\0str\0 484 + * first character after : must be valid 485 + */ 486 + if (!str[1]) 487 + return -6; 488 + } 489 + } else if (!*str) { 490 + if (*pos == ':') 491 + *str = ':'; 492 + else 493 + c++; 494 + pos = str + 1; 495 + } 496 + str++; 497 + } /* while */ 498 + 499 + return c; 500 + } 501 + 453 502 /** 454 - * unpack_trans_table - unpack a profile transition table 503 + * unpack_strs_table - unpack a profile transition table 455 504 * @e: serialized data extent information (NOT NULL) 505 + * @name: name of table (MAY BE NULL) 506 + * @multi: allow multiple strings on a single entry 456 507 * @strs: str table to unpack to (NOT NULL) 457 508 * 458 509 * Returns: true if table successfully unpacked or not present 459 510 */ 460 - static bool unpack_trans_table(struct aa_ext *e, struct aa_str_table *strs) 511 + static bool unpack_strs_table(struct aa_ext *e, const char *name, bool multi, 512 + struct aa_str_table *strs) 461 513 { 462 514 void *saved_pos = e->pos; 463 - char **table = NULL; 515 + struct aa_str_table_ent *table = NULL; 464 516 465 517 /* exec table is optional */ 466 - if (aa_unpack_nameX(e, AA_STRUCT, "xtable")) { 518 + if (aa_unpack_nameX(e, AA_STRUCT, name)) { 467 519 u16 size; 468 520 int i; 469 521 ··· 527 475 * for size check here 528 476 */ 529 477 goto fail; 530 - table = kcalloc(size, sizeof(char *), GFP_KERNEL); 478 + table = kcalloc(size, sizeof(struct aa_str_table_ent), 479 + GFP_KERNEL); 531 480 if (!table) 532 481 goto fail; 533 482 ··· 536 483 strs->size = size; 537 484 for (i = 0; i < size; i++) { 538 485 char *str; 539 - int c, j, pos, size2 = aa_unpack_strdup(e, &str, NULL); 486 + int c, size2 = aa_unpack_strdup(e, &str, NULL); 540 487 /* aa_unpack_strdup verifies that the last character is 541 488 * null termination byte. 542 489 */ 543 - if (!size2) 490 + c = process_strs_entry(str, size2, multi); 491 + if (c <= 0) { 492 + AA_DEBUG(DEBUG_UNPACK, "process_strs %d", c); 544 493 goto fail; 545 - table[i] = str; 546 - /* verify that name doesn't start with space */ 547 - if (isspace(*str)) 548 - goto fail; 549 - 550 - /* count internal # of internal \0 */ 551 - for (c = j = 0; j < size2 - 1; j++) { 552 - if (!str[j]) { 553 - pos = j; 554 - c++; 555 - } 556 494 } 557 - if (*str == ':') { 558 - /* first character after : must be valid */ 559 - if (!str[1]) 560 - goto fail; 561 - /* beginning with : requires an embedded \0, 562 - * verify that exactly 1 internal \0 exists 563 - * trailing \0 already verified by aa_unpack_strdup 564 - * 565 - * convert \0 back to : for label_parse 566 - */ 567 - if (c == 1) 568 - str[pos] = ':'; 569 - else if (c > 1) 570 - goto fail; 571 - } else if (c) 495 + if (!multi && c > 1) { 496 + AA_DEBUG(DEBUG_UNPACK, "!multi && c > 1"); 572 497 /* fail - all other cases with embedded \0 */ 573 498 goto fail; 499 + } 500 + table[i].strs = str; 501 + table[i].count = c; 502 + table[i].size = size2; 574 503 } 575 504 if (!aa_unpack_nameX(e, AA_ARRAYEND, NULL)) 576 505 goto fail; ··· 562 527 return true; 563 528 564 529 fail: 565 - aa_free_str_table(strs); 530 + aa_destroy_str_table(strs); 566 531 e->pos = saved_pos; 567 532 return false; 568 533 } ··· 830 795 * transition table may be present even when the dfa is 831 796 * not. For compatibility reasons unpack and discard. 832 797 */ 833 - if (!unpack_trans_table(e, &pdb->trans) && required_trans) { 798 + if (!unpack_strs_table(e, "xtable", false, &pdb->trans) && 799 + required_trans) { 834 800 *info = "failed to unpack profile transition table"; 835 801 goto fail; 836 802 } 837 803 838 804 if (!pdb->dfa && pdb->trans.table) 839 - aa_free_str_table(&pdb->trans); 805 + aa_destroy_str_table(&pdb->trans); 840 806 841 807 /* TODO: 842 808 * - move compat mapping here, requires dfa merging first ··· 1304 1268 } 1305 1269 /* deal with incorrectly constructed string tables */ 1306 1270 if (xmax == -1) { 1307 - aa_free_str_table(&pdb->trans); 1271 + aa_destroy_str_table(&pdb->trans); 1308 1272 } else if (pdb->trans.size > xmax + 1) { 1309 1273 if (!aa_resize_str_table(&pdb->trans, xmax + 1, GFP_KERNEL)) 1310 1274 return false;