diff options
Diffstat (limited to 'security/tomoyo/condition.c')
-rw-r--r-- | security/tomoyo/condition.c | 71 |
1 files changed, 65 insertions, 6 deletions
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c index 8a05f71eaf67..986330b8c73e 100644 --- a/security/tomoyo/condition.c +++ b/security/tomoyo/condition.c | |||
@@ -348,6 +348,7 @@ static inline bool tomoyo_same_condition(const struct tomoyo_condition *a, | |||
348 | a->numbers_count == b->numbers_count && | 348 | a->numbers_count == b->numbers_count && |
349 | a->names_count == b->names_count && | 349 | a->names_count == b->names_count && |
350 | a->argc == b->argc && a->envc == b->envc && | 350 | a->argc == b->argc && a->envc == b->envc && |
351 | a->grant_log == b->grant_log && a->transit == b->transit && | ||
351 | !memcmp(a + 1, b + 1, a->size - sizeof(*a)); | 352 | !memcmp(a + 1, b + 1, a->size - sizeof(*a)); |
352 | } | 353 | } |
353 | 354 | ||
@@ -399,8 +400,9 @@ static struct tomoyo_condition *tomoyo_commit_condition | |||
399 | found = true; | 400 | found = true; |
400 | goto out; | 401 | goto out; |
401 | } | 402 | } |
402 | list_for_each_entry_rcu(ptr, &tomoyo_condition_list, head.list) { | 403 | list_for_each_entry(ptr, &tomoyo_condition_list, head.list) { |
403 | if (!tomoyo_same_condition(ptr, entry)) | 404 | if (!tomoyo_same_condition(ptr, entry) || |
405 | atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS) | ||
404 | continue; | 406 | continue; |
405 | /* Same entry found. Share this entry. */ | 407 | /* Same entry found. Share this entry. */ |
406 | atomic_inc(&ptr->head.users); | 408 | atomic_inc(&ptr->head.users); |
@@ -410,8 +412,7 @@ static struct tomoyo_condition *tomoyo_commit_condition | |||
410 | if (!found) { | 412 | if (!found) { |
411 | if (tomoyo_memory_ok(entry)) { | 413 | if (tomoyo_memory_ok(entry)) { |
412 | atomic_set(&entry->head.users, 1); | 414 | atomic_set(&entry->head.users, 1); |
413 | list_add_rcu(&entry->head.list, | 415 | list_add(&entry->head.list, &tomoyo_condition_list); |
414 | &tomoyo_condition_list); | ||
415 | } else { | 416 | } else { |
416 | found = true; | 417 | found = true; |
417 | ptr = NULL; | 418 | ptr = NULL; |
@@ -428,6 +429,46 @@ out: | |||
428 | } | 429 | } |
429 | 430 | ||
430 | /** | 431 | /** |
432 | * tomoyo_get_transit_preference - Parse domain transition preference for execve(). | ||
433 | * | ||
434 | * @param: Pointer to "struct tomoyo_acl_param". | ||
435 | * @e: Pointer to "struct tomoyo_condition". | ||
436 | * | ||
437 | * Returns the condition string part. | ||
438 | */ | ||
439 | static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param, | ||
440 | struct tomoyo_condition *e) | ||
441 | { | ||
442 | char * const pos = param->data; | ||
443 | bool flag; | ||
444 | if (*pos == '<') { | ||
445 | e->transit = tomoyo_get_domainname(param); | ||
446 | goto done; | ||
447 | } | ||
448 | { | ||
449 | char *cp = strchr(pos, ' '); | ||
450 | if (cp) | ||
451 | *cp = '\0'; | ||
452 | flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") || | ||
453 | !strcmp(pos, "initialize") || !strcmp(pos, "reset") || | ||
454 | !strcmp(pos, "child") || !strcmp(pos, "parent"); | ||
455 | if (cp) | ||
456 | *cp = ' '; | ||
457 | } | ||
458 | if (!flag) | ||
459 | return pos; | ||
460 | e->transit = tomoyo_get_name(tomoyo_read_token(param)); | ||
461 | done: | ||
462 | if (e->transit) | ||
463 | return param->data; | ||
464 | /* | ||
465 | * Return a bad read-only condition string that will let | ||
466 | * tomoyo_get_condition() return NULL. | ||
467 | */ | ||
468 | return "/"; | ||
469 | } | ||
470 | |||
471 | /** | ||
431 | * tomoyo_get_condition - Parse condition part. | 472 | * tomoyo_get_condition - Parse condition part. |
432 | * | 473 | * |
433 | * @param: Pointer to "struct tomoyo_acl_param". | 474 | * @param: Pointer to "struct tomoyo_acl_param". |
@@ -443,7 +484,8 @@ struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param) | |||
443 | struct tomoyo_argv *argv = NULL; | 484 | struct tomoyo_argv *argv = NULL; |
444 | struct tomoyo_envp *envp = NULL; | 485 | struct tomoyo_envp *envp = NULL; |
445 | struct tomoyo_condition e = { }; | 486 | struct tomoyo_condition e = { }; |
446 | char * const start_of_string = param->data; | 487 | char * const start_of_string = |
488 | tomoyo_get_transit_preference(param, &e); | ||
447 | char * const end_of_string = start_of_string + strlen(start_of_string); | 489 | char * const end_of_string = start_of_string + strlen(start_of_string); |
448 | char *pos; | 490 | char *pos; |
449 | rerun: | 491 | rerun: |
@@ -486,6 +528,20 @@ rerun: | |||
486 | goto out; | 528 | goto out; |
487 | dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word, | 529 | dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word, |
488 | is_not ? "!" : "", right_word); | 530 | is_not ? "!" : "", right_word); |
531 | if (!strcmp(left_word, "grant_log")) { | ||
532 | if (entry) { | ||
533 | if (is_not || | ||
534 | entry->grant_log != TOMOYO_GRANTLOG_AUTO) | ||
535 | goto out; | ||
536 | else if (!strcmp(right_word, "yes")) | ||
537 | entry->grant_log = TOMOYO_GRANTLOG_YES; | ||
538 | else if (!strcmp(right_word, "no")) | ||
539 | entry->grant_log = TOMOYO_GRANTLOG_NO; | ||
540 | else | ||
541 | goto out; | ||
542 | } | ||
543 | continue; | ||
544 | } | ||
489 | if (!strncmp(left_word, "exec.argv[", 10)) { | 545 | if (!strncmp(left_word, "exec.argv[", 10)) { |
490 | if (!argv) { | 546 | if (!argv) { |
491 | e.argc++; | 547 | e.argc++; |
@@ -593,8 +649,9 @@ store_value: | |||
593 | + e.envc * sizeof(struct tomoyo_envp); | 649 | + e.envc * sizeof(struct tomoyo_envp); |
594 | entry = kzalloc(e.size, GFP_NOFS); | 650 | entry = kzalloc(e.size, GFP_NOFS); |
595 | if (!entry) | 651 | if (!entry) |
596 | return NULL; | 652 | goto out2; |
597 | *entry = e; | 653 | *entry = e; |
654 | e.transit = NULL; | ||
598 | condp = (struct tomoyo_condition_element *) (entry + 1); | 655 | condp = (struct tomoyo_condition_element *) (entry + 1); |
599 | numbers_p = (struct tomoyo_number_union *) (condp + e.condc); | 656 | numbers_p = (struct tomoyo_number_union *) (condp + e.condc); |
600 | names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count); | 657 | names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count); |
@@ -621,6 +678,8 @@ out: | |||
621 | tomoyo_del_condition(&entry->head.list); | 678 | tomoyo_del_condition(&entry->head.list); |
622 | kfree(entry); | 679 | kfree(entry); |
623 | } | 680 | } |
681 | out2: | ||
682 | tomoyo_put_name(e.transit); | ||
624 | return NULL; | 683 | return NULL; |
625 | } | 684 | } |
626 | 685 | ||