diff options
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r-- | security/tomoyo/common.c | 383 |
1 files changed, 278 insertions, 105 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 507ebf01e43b..50481d2cf970 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -11,12 +11,6 @@ | |||
11 | #include <linux/security.h> | 11 | #include <linux/security.h> |
12 | #include "common.h" | 12 | #include "common.h" |
13 | 13 | ||
14 | /* Profile version. Currently only 20090903 is defined. */ | ||
15 | static unsigned int tomoyo_profile_version; | ||
16 | |||
17 | /* Profile table. Memory is allocated as needed. */ | ||
18 | static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; | ||
19 | |||
20 | /* String table for operation mode. */ | 14 | /* String table for operation mode. */ |
21 | const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = { | 15 | const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = { |
22 | [TOMOYO_CONFIG_DISABLED] = "disabled", | 16 | [TOMOYO_CONFIG_DISABLED] = "disabled", |
@@ -216,6 +210,50 @@ static void tomoyo_set_slash(struct tomoyo_io_buffer *head) | |||
216 | tomoyo_set_string(head, "/"); | 210 | tomoyo_set_string(head, "/"); |
217 | } | 211 | } |
218 | 212 | ||
213 | /* List of namespaces. */ | ||
214 | LIST_HEAD(tomoyo_namespace_list); | ||
215 | /* True if namespace other than tomoyo_kernel_namespace is defined. */ | ||
216 | static bool tomoyo_namespace_enabled; | ||
217 | |||
218 | /** | ||
219 | * tomoyo_init_policy_namespace - Initialize namespace. | ||
220 | * | ||
221 | * @ns: Pointer to "struct tomoyo_policy_namespace". | ||
222 | * | ||
223 | * Returns nothing. | ||
224 | */ | ||
225 | void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns) | ||
226 | { | ||
227 | unsigned int idx; | ||
228 | for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++) | ||
229 | INIT_LIST_HEAD(&ns->acl_group[idx]); | ||
230 | for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) | ||
231 | INIT_LIST_HEAD(&ns->group_list[idx]); | ||
232 | for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) | ||
233 | INIT_LIST_HEAD(&ns->policy_list[idx]); | ||
234 | ns->profile_version = 20100903; | ||
235 | tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list); | ||
236 | list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list); | ||
237 | } | ||
238 | |||
239 | /** | ||
240 | * tomoyo_print_namespace - Print namespace header. | ||
241 | * | ||
242 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
243 | * | ||
244 | * Returns nothing. | ||
245 | */ | ||
246 | static void tomoyo_print_namespace(struct tomoyo_io_buffer *head) | ||
247 | { | ||
248 | if (!tomoyo_namespace_enabled) | ||
249 | return; | ||
250 | tomoyo_set_string(head, | ||
251 | container_of(head->r.ns, | ||
252 | struct tomoyo_policy_namespace, | ||
253 | namespace_list)->name); | ||
254 | tomoyo_set_space(head); | ||
255 | } | ||
256 | |||
219 | /** | 257 | /** |
220 | * tomoyo_print_name_union - Print a tomoyo_name_union. | 258 | * tomoyo_print_name_union - Print a tomoyo_name_union. |
221 | * | 259 | * |
@@ -283,23 +321,25 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, | |||
283 | /** | 321 | /** |
284 | * tomoyo_assign_profile - Create a new profile. | 322 | * tomoyo_assign_profile - Create a new profile. |
285 | * | 323 | * |
324 | * @ns: Pointer to "struct tomoyo_policy_namespace". | ||
286 | * @profile: Profile number to create. | 325 | * @profile: Profile number to create. |
287 | * | 326 | * |
288 | * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. | 327 | * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. |
289 | */ | 328 | */ |
290 | static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile) | 329 | static struct tomoyo_profile *tomoyo_assign_profile |
330 | (struct tomoyo_policy_namespace *ns, const unsigned int profile) | ||
291 | { | 331 | { |
292 | struct tomoyo_profile *ptr; | 332 | struct tomoyo_profile *ptr; |
293 | struct tomoyo_profile *entry; | 333 | struct tomoyo_profile *entry; |
294 | if (profile >= TOMOYO_MAX_PROFILES) | 334 | if (profile >= TOMOYO_MAX_PROFILES) |
295 | return NULL; | 335 | return NULL; |
296 | ptr = tomoyo_profile_ptr[profile]; | 336 | ptr = ns->profile_ptr[profile]; |
297 | if (ptr) | 337 | if (ptr) |
298 | return ptr; | 338 | return ptr; |
299 | entry = kzalloc(sizeof(*entry), GFP_NOFS); | 339 | entry = kzalloc(sizeof(*entry), GFP_NOFS); |
300 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 340 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
301 | goto out; | 341 | goto out; |
302 | ptr = tomoyo_profile_ptr[profile]; | 342 | ptr = ns->profile_ptr[profile]; |
303 | if (!ptr && tomoyo_memory_ok(entry)) { | 343 | if (!ptr && tomoyo_memory_ok(entry)) { |
304 | ptr = entry; | 344 | ptr = entry; |
305 | ptr->default_config = TOMOYO_CONFIG_DISABLED | | 345 | ptr->default_config = TOMOYO_CONFIG_DISABLED | |
@@ -310,7 +350,7 @@ static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile) | |||
310 | ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] = 1024; | 350 | ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] = 1024; |
311 | ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048; | 351 | ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048; |
312 | mb(); /* Avoid out-of-order execution. */ | 352 | mb(); /* Avoid out-of-order execution. */ |
313 | tomoyo_profile_ptr[profile] = ptr; | 353 | ns->profile_ptr[profile] = ptr; |
314 | entry = NULL; | 354 | entry = NULL; |
315 | } | 355 | } |
316 | mutex_unlock(&tomoyo_policy_lock); | 356 | mutex_unlock(&tomoyo_policy_lock); |
@@ -322,14 +362,16 @@ static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile) | |||
322 | /** | 362 | /** |
323 | * tomoyo_profile - Find a profile. | 363 | * tomoyo_profile - Find a profile. |
324 | * | 364 | * |
365 | * @ns: Pointer to "struct tomoyo_policy_namespace". | ||
325 | * @profile: Profile number to find. | 366 | * @profile: Profile number to find. |
326 | * | 367 | * |
327 | * Returns pointer to "struct tomoyo_profile". | 368 | * Returns pointer to "struct tomoyo_profile". |
328 | */ | 369 | */ |
329 | struct tomoyo_profile *tomoyo_profile(const u8 profile) | 370 | struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, |
371 | const u8 profile) | ||
330 | { | 372 | { |
331 | static struct tomoyo_profile tomoyo_null_profile; | 373 | static struct tomoyo_profile tomoyo_null_profile; |
332 | struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile]; | 374 | struct tomoyo_profile *ptr = ns->profile_ptr[profile]; |
333 | if (!ptr) | 375 | if (!ptr) |
334 | ptr = &tomoyo_null_profile; | 376 | ptr = &tomoyo_null_profile; |
335 | return ptr; | 377 | return ptr; |
@@ -454,13 +496,14 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
454 | unsigned int i; | 496 | unsigned int i; |
455 | char *cp; | 497 | char *cp; |
456 | struct tomoyo_profile *profile; | 498 | struct tomoyo_profile *profile; |
457 | if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1) | 499 | if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version) |
500 | == 1) | ||
458 | return 0; | 501 | return 0; |
459 | i = simple_strtoul(data, &cp, 10); | 502 | i = simple_strtoul(data, &cp, 10); |
460 | if (*cp != '-') | 503 | if (*cp != '-') |
461 | return -EINVAL; | 504 | return -EINVAL; |
462 | data = cp + 1; | 505 | data = cp + 1; |
463 | profile = tomoyo_assign_profile(i); | 506 | profile = tomoyo_assign_profile(head->w.ns, i); |
464 | if (!profile) | 507 | if (!profile) |
465 | return -EINVAL; | 508 | return -EINVAL; |
466 | cp = strchr(data, '='); | 509 | cp = strchr(data, '='); |
@@ -518,19 +561,25 @@ static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config) | |||
518 | static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | 561 | static void tomoyo_read_profile(struct tomoyo_io_buffer *head) |
519 | { | 562 | { |
520 | u8 index; | 563 | u8 index; |
564 | struct tomoyo_policy_namespace *ns = | ||
565 | container_of(head->r.ns, typeof(*ns), namespace_list); | ||
521 | const struct tomoyo_profile *profile; | 566 | const struct tomoyo_profile *profile; |
567 | if (head->r.eof) | ||
568 | return; | ||
522 | next: | 569 | next: |
523 | index = head->r.index; | 570 | index = head->r.index; |
524 | profile = tomoyo_profile_ptr[index]; | 571 | profile = ns->profile_ptr[index]; |
525 | switch (head->r.step) { | 572 | switch (head->r.step) { |
526 | case 0: | 573 | case 0: |
527 | tomoyo_io_printf(head, "PROFILE_VERSION=%u\n", 20090903); | 574 | tomoyo_print_namespace(head); |
575 | tomoyo_io_printf(head, "PROFILE_VERSION=%u\n", | ||
576 | ns->profile_version); | ||
528 | head->r.step++; | 577 | head->r.step++; |
529 | break; | 578 | break; |
530 | case 1: | 579 | case 1: |
531 | for ( ; head->r.index < TOMOYO_MAX_PROFILES; | 580 | for ( ; head->r.index < TOMOYO_MAX_PROFILES; |
532 | head->r.index++) | 581 | head->r.index++) |
533 | if (tomoyo_profile_ptr[head->r.index]) | 582 | if (ns->profile_ptr[head->r.index]) |
534 | break; | 583 | break; |
535 | if (head->r.index == TOMOYO_MAX_PROFILES) | 584 | if (head->r.index == TOMOYO_MAX_PROFILES) |
536 | return; | 585 | return; |
@@ -541,6 +590,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
541 | u8 i; | 590 | u8 i; |
542 | const struct tomoyo_path_info *comment = | 591 | const struct tomoyo_path_info *comment = |
543 | profile->comment; | 592 | profile->comment; |
593 | tomoyo_print_namespace(head); | ||
544 | tomoyo_io_printf(head, "%u-COMMENT=", index); | 594 | tomoyo_io_printf(head, "%u-COMMENT=", index); |
545 | tomoyo_set_string(head, comment ? comment->name : ""); | 595 | tomoyo_set_string(head, comment ? comment->name : ""); |
546 | tomoyo_set_lf(head); | 596 | tomoyo_set_lf(head); |
@@ -555,6 +605,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
555 | break; | 605 | break; |
556 | case 3: | 606 | case 3: |
557 | { | 607 | { |
608 | tomoyo_print_namespace(head); | ||
558 | tomoyo_io_printf(head, "%u-%s", index, "CONFIG"); | 609 | tomoyo_io_printf(head, "%u-%s", index, "CONFIG"); |
559 | tomoyo_print_config(head, profile->default_config); | 610 | tomoyo_print_config(head, profile->default_config); |
560 | head->r.bit = 0; | 611 | head->r.bit = 0; |
@@ -568,6 +619,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
568 | const u8 config = profile->config[i]; | 619 | const u8 config = profile->config[i]; |
569 | if (config == TOMOYO_CONFIG_USE_DEFAULT) | 620 | if (config == TOMOYO_CONFIG_USE_DEFAULT) |
570 | continue; | 621 | continue; |
622 | tomoyo_print_namespace(head); | ||
571 | tomoyo_io_printf(head, "%u-%s%s", index, "CONFIG::", | 623 | tomoyo_io_printf(head, "%u-%s%s", index, "CONFIG::", |
572 | tomoyo_mac_keywords[i]); | 624 | tomoyo_mac_keywords[i]); |
573 | tomoyo_print_config(head, config); | 625 | tomoyo_print_config(head, config); |
@@ -607,8 +659,10 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
607 | { | 659 | { |
608 | struct tomoyo_manager e = { }; | 660 | struct tomoyo_manager e = { }; |
609 | struct tomoyo_acl_param param = { | 661 | struct tomoyo_acl_param param = { |
662 | /* .ns = &tomoyo_kernel_namespace, */ | ||
610 | .is_delete = is_delete, | 663 | .is_delete = is_delete, |
611 | .list = &tomoyo_policy_list[TOMOYO_ID_MANAGER], | 664 | .list = &tomoyo_kernel_namespace. |
665 | policy_list[TOMOYO_ID_MANAGER], | ||
612 | }; | 666 | }; |
613 | int error = is_delete ? -ENOENT : -ENOMEM; | 667 | int error = is_delete ? -ENOENT : -ENOMEM; |
614 | if (tomoyo_domain_def(manager)) { | 668 | if (tomoyo_domain_def(manager)) { |
@@ -640,13 +694,12 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
640 | static int tomoyo_write_manager(struct tomoyo_io_buffer *head) | 694 | static int tomoyo_write_manager(struct tomoyo_io_buffer *head) |
641 | { | 695 | { |
642 | char *data = head->write_buf; | 696 | char *data = head->write_buf; |
643 | bool is_delete = tomoyo_str_starts(&data, "delete "); | ||
644 | 697 | ||
645 | if (!strcmp(data, "manage_by_non_root")) { | 698 | if (!strcmp(data, "manage_by_non_root")) { |
646 | tomoyo_manage_by_non_root = !is_delete; | 699 | tomoyo_manage_by_non_root = !head->w.is_delete; |
647 | return 0; | 700 | return 0; |
648 | } | 701 | } |
649 | return tomoyo_update_manager_entry(data, is_delete); | 702 | return tomoyo_update_manager_entry(data, head->w.is_delete); |
650 | } | 703 | } |
651 | 704 | ||
652 | /** | 705 | /** |
@@ -660,8 +713,8 @@ static void tomoyo_read_manager(struct tomoyo_io_buffer *head) | |||
660 | { | 713 | { |
661 | if (head->r.eof) | 714 | if (head->r.eof) |
662 | return; | 715 | return; |
663 | list_for_each_cookie(head->r.acl, | 716 | list_for_each_cookie(head->r.acl, &tomoyo_kernel_namespace. |
664 | &tomoyo_policy_list[TOMOYO_ID_MANAGER]) { | 717 | policy_list[TOMOYO_ID_MANAGER]) { |
665 | struct tomoyo_manager *ptr = | 718 | struct tomoyo_manager *ptr = |
666 | list_entry(head->r.acl, typeof(*ptr), head.list); | 719 | list_entry(head->r.acl, typeof(*ptr), head.list); |
667 | if (ptr->head.is_deleted) | 720 | if (ptr->head.is_deleted) |
@@ -694,8 +747,8 @@ static bool tomoyo_manager(void) | |||
694 | return true; | 747 | return true; |
695 | if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) | 748 | if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) |
696 | return false; | 749 | return false; |
697 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER], | 750 | list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace. |
698 | head.list) { | 751 | policy_list[TOMOYO_ID_MANAGER], head.list) { |
699 | if (!ptr->head.is_deleted && ptr->is_domain | 752 | if (!ptr->head.is_deleted && ptr->is_domain |
700 | && !tomoyo_pathcmp(domainname, ptr->manager)) { | 753 | && !tomoyo_pathcmp(domainname, ptr->manager)) { |
701 | found = true; | 754 | found = true; |
@@ -707,8 +760,8 @@ static bool tomoyo_manager(void) | |||
707 | exe = tomoyo_get_exe(); | 760 | exe = tomoyo_get_exe(); |
708 | if (!exe) | 761 | if (!exe) |
709 | return false; | 762 | return false; |
710 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER], | 763 | list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace. |
711 | head.list) { | 764 | policy_list[TOMOYO_ID_MANAGER], head.list) { |
712 | if (!ptr->head.is_deleted && !ptr->is_domain | 765 | if (!ptr->head.is_deleted && !ptr->is_domain |
713 | && !strcmp(exe, ptr->manager->name)) { | 766 | && !strcmp(exe, ptr->manager->name)) { |
714 | found = true; | 767 | found = true; |
@@ -729,7 +782,7 @@ static bool tomoyo_manager(void) | |||
729 | } | 782 | } |
730 | 783 | ||
731 | /** | 784 | /** |
732 | * tomoyo_select_one - Parse select command. | 785 | * tomoyo_select_domain - Parse select command. |
733 | * | 786 | * |
734 | * @head: Pointer to "struct tomoyo_io_buffer". | 787 | * @head: Pointer to "struct tomoyo_io_buffer". |
735 | * @data: String to parse. | 788 | * @data: String to parse. |
@@ -738,16 +791,15 @@ static bool tomoyo_manager(void) | |||
738 | * | 791 | * |
739 | * Caller holds tomoyo_read_lock(). | 792 | * Caller holds tomoyo_read_lock(). |
740 | */ | 793 | */ |
741 | static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data) | 794 | static bool tomoyo_select_domain(struct tomoyo_io_buffer *head, |
795 | const char *data) | ||
742 | { | 796 | { |
743 | unsigned int pid; | 797 | unsigned int pid; |
744 | struct tomoyo_domain_info *domain = NULL; | 798 | struct tomoyo_domain_info *domain = NULL; |
745 | bool global_pid = false; | 799 | bool global_pid = false; |
746 | 800 | if (strncmp(data, "select ", 7)) | |
747 | if (!strcmp(data, "allow_execute")) { | 801 | return false; |
748 | head->r.print_execute_only = true; | 802 | data += 7; |
749 | return true; | ||
750 | } | ||
751 | if (sscanf(data, "pid=%u", &pid) == 1 || | 803 | if (sscanf(data, "pid=%u", &pid) == 1 || |
752 | (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { | 804 | (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { |
753 | struct task_struct *p; | 805 | struct task_struct *p; |
@@ -818,6 +870,7 @@ static int tomoyo_delete_domain(char *domainname) | |||
818 | /** | 870 | /** |
819 | * tomoyo_write_domain2 - Write domain policy. | 871 | * tomoyo_write_domain2 - Write domain policy. |
820 | * | 872 | * |
873 | * @ns: Pointer to "struct tomoyo_policy_namespace". | ||
821 | * @list: Pointer to "struct list_head". | 874 | * @list: Pointer to "struct list_head". |
822 | * @data: Policy to be interpreted. | 875 | * @data: Policy to be interpreted. |
823 | * @is_delete: True if it is a delete request. | 876 | * @is_delete: True if it is a delete request. |
@@ -826,10 +879,12 @@ static int tomoyo_delete_domain(char *domainname) | |||
826 | * | 879 | * |
827 | * Caller holds tomoyo_read_lock(). | 880 | * Caller holds tomoyo_read_lock(). |
828 | */ | 881 | */ |
829 | static int tomoyo_write_domain2(struct list_head *list, char *data, | 882 | static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns, |
883 | struct list_head *list, char *data, | ||
830 | const bool is_delete) | 884 | const bool is_delete) |
831 | { | 885 | { |
832 | struct tomoyo_acl_param param = { | 886 | struct tomoyo_acl_param param = { |
887 | .ns = ns, | ||
833 | .list = list, | 888 | .list = list, |
834 | .data = data, | 889 | .data = data, |
835 | .is_delete = is_delete, | 890 | .is_delete = is_delete, |
@@ -862,37 +917,28 @@ static int tomoyo_write_domain2(struct list_head *list, char *data, | |||
862 | static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | 917 | static int tomoyo_write_domain(struct tomoyo_io_buffer *head) |
863 | { | 918 | { |
864 | char *data = head->write_buf; | 919 | char *data = head->write_buf; |
920 | struct tomoyo_policy_namespace *ns; | ||
865 | struct tomoyo_domain_info *domain = head->w.domain; | 921 | struct tomoyo_domain_info *domain = head->w.domain; |
866 | bool is_delete = false; | 922 | const bool is_delete = head->w.is_delete; |
867 | bool is_select = false; | 923 | bool is_select = !is_delete && tomoyo_str_starts(&data, "select "); |
868 | unsigned int profile; | 924 | unsigned int profile; |
869 | 925 | if (*data == '<') { | |
870 | if (tomoyo_str_starts(&data, "delete ")) | ||
871 | is_delete = true; | ||
872 | else if (tomoyo_str_starts(&data, "select ")) | ||
873 | is_select = true; | ||
874 | if (is_select && tomoyo_select_one(head, data)) | ||
875 | return 0; | ||
876 | /* Don't allow updating policies by non manager programs. */ | ||
877 | if (!tomoyo_manager()) | ||
878 | return -EPERM; | ||
879 | if (tomoyo_domain_def(data)) { | ||
880 | domain = NULL; | 926 | domain = NULL; |
881 | if (is_delete) | 927 | if (is_delete) |
882 | tomoyo_delete_domain(data); | 928 | tomoyo_delete_domain(data); |
883 | else if (is_select) | 929 | else if (is_select) |
884 | domain = tomoyo_find_domain(data); | 930 | domain = tomoyo_find_domain(data); |
885 | else | 931 | else |
886 | domain = tomoyo_assign_domain(data, 0); | 932 | domain = tomoyo_assign_domain(data, false); |
887 | head->w.domain = domain; | 933 | head->w.domain = domain; |
888 | return 0; | 934 | return 0; |
889 | } | 935 | } |
890 | if (!domain) | 936 | if (!domain) |
891 | return -EINVAL; | 937 | return -EINVAL; |
892 | 938 | ns = domain->ns; | |
893 | if (sscanf(data, "use_profile %u", &profile) == 1 | 939 | if (sscanf(data, "use_profile %u", &profile) == 1 |
894 | && profile < TOMOYO_MAX_PROFILES) { | 940 | && profile < TOMOYO_MAX_PROFILES) { |
895 | if (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded) | 941 | if (!tomoyo_policy_loaded || ns->profile_ptr[profile]) |
896 | domain->profile = (u8) profile; | 942 | domain->profile = (u8) profile; |
897 | return 0; | 943 | return 0; |
898 | } | 944 | } |
@@ -910,7 +956,8 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
910 | domain->transition_failed = !is_delete; | 956 | domain->transition_failed = !is_delete; |
911 | return 0; | 957 | return 0; |
912 | } | 958 | } |
913 | return tomoyo_write_domain2(&domain->acl_info_list, data, is_delete); | 959 | return tomoyo_write_domain2(ns, &domain->acl_info_list, data, |
960 | is_delete); | ||
914 | } | 961 | } |
915 | 962 | ||
916 | /** | 963 | /** |
@@ -924,9 +971,11 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
924 | static void tomoyo_set_group(struct tomoyo_io_buffer *head, | 971 | static void tomoyo_set_group(struct tomoyo_io_buffer *head, |
925 | const char *category) | 972 | const char *category) |
926 | { | 973 | { |
927 | if (head->type == TOMOYO_EXCEPTIONPOLICY) | 974 | if (head->type == TOMOYO_EXCEPTIONPOLICY) { |
975 | tomoyo_print_namespace(head); | ||
928 | tomoyo_io_printf(head, "acl_group %u ", | 976 | tomoyo_io_printf(head, "acl_group %u ", |
929 | head->r.acl_group_index); | 977 | head->r.acl_group_index); |
978 | } | ||
930 | tomoyo_set_string(head, category); | 979 | tomoyo_set_string(head, category); |
931 | } | 980 | } |
932 | 981 | ||
@@ -956,7 +1005,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
956 | for (bit = 0; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { | 1005 | for (bit = 0; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { |
957 | if (!(perm & (1 << bit))) | 1006 | if (!(perm & (1 << bit))) |
958 | continue; | 1007 | continue; |
959 | if (head->r.print_execute_only && | 1008 | if (head->r.print_transition_related_only && |
960 | bit != TOMOYO_TYPE_EXECUTE) | 1009 | bit != TOMOYO_TYPE_EXECUTE) |
961 | continue; | 1010 | continue; |
962 | if (first) { | 1011 | if (first) { |
@@ -970,7 +1019,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
970 | if (first) | 1019 | if (first) |
971 | return true; | 1020 | return true; |
972 | tomoyo_print_name_union(head, &ptr->name); | 1021 | tomoyo_print_name_union(head, &ptr->name); |
973 | } else if (head->r.print_execute_only) { | 1022 | } else if (head->r.print_transition_related_only) { |
974 | return true; | 1023 | return true; |
975 | } else if (acl_type == TOMOYO_TYPE_PATH2_ACL) { | 1024 | } else if (acl_type == TOMOYO_TYPE_PATH2_ACL) { |
976 | struct tomoyo_path2_acl *ptr = | 1025 | struct tomoyo_path2_acl *ptr = |
@@ -1147,8 +1196,8 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) | |||
1147 | domain = tomoyo_find_domain(cp + 1); | 1196 | domain = tomoyo_find_domain(cp + 1); |
1148 | if (strict_strtoul(data, 10, &profile)) | 1197 | if (strict_strtoul(data, 10, &profile)) |
1149 | return -EINVAL; | 1198 | return -EINVAL; |
1150 | if (domain && profile < TOMOYO_MAX_PROFILES | 1199 | if (domain && (!tomoyo_policy_loaded || |
1151 | && (tomoyo_profile_ptr[profile] || !tomoyo_policy_loaded)) | 1200 | head->w.ns->profile_ptr[(u8) profile])) |
1152 | domain->profile = (u8) profile; | 1201 | domain->profile = (u8) profile; |
1153 | return 0; | 1202 | return 0; |
1154 | } | 1203 | } |
@@ -1246,10 +1295,12 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head) | |||
1246 | } | 1295 | } |
1247 | 1296 | ||
1248 | static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = { | 1297 | static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = { |
1249 | [TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain", | 1298 | [TOMOYO_TRANSITION_CONTROL_NO_RESET] = "no_reset_domain ", |
1250 | [TOMOYO_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain", | 1299 | [TOMOYO_TRANSITION_CONTROL_RESET] = "reset_domain ", |
1251 | [TOMOYO_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain", | 1300 | [TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ", |
1252 | [TOMOYO_TRANSITION_CONTROL_KEEP] = "keep_domain", | 1301 | [TOMOYO_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain ", |
1302 | [TOMOYO_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain ", | ||
1303 | [TOMOYO_TRANSITION_CONTROL_KEEP] = "keep_domain ", | ||
1253 | }; | 1304 | }; |
1254 | 1305 | ||
1255 | static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { | 1306 | static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { |
@@ -1268,19 +1319,13 @@ static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { | |||
1268 | */ | 1319 | */ |
1269 | static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | 1320 | static int tomoyo_write_exception(struct tomoyo_io_buffer *head) |
1270 | { | 1321 | { |
1322 | const bool is_delete = head->w.is_delete; | ||
1271 | struct tomoyo_acl_param param = { | 1323 | struct tomoyo_acl_param param = { |
1324 | .ns = head->w.ns, | ||
1325 | .is_delete = is_delete, | ||
1272 | .data = head->write_buf, | 1326 | .data = head->write_buf, |
1273 | }; | 1327 | }; |
1274 | u8 i; | 1328 | u8 i; |
1275 | param.is_delete = tomoyo_str_starts(¶m.data, "delete "); | ||
1276 | if (!param.is_delete && tomoyo_str_starts(¶m.data, "select ") && | ||
1277 | !strcmp(param.data, "execute_only")) { | ||
1278 | head->r.print_execute_only = true; | ||
1279 | return 0; | ||
1280 | } | ||
1281 | /* Don't allow updating policies by non manager programs. */ | ||
1282 | if (!tomoyo_manager()) | ||
1283 | return -EPERM; | ||
1284 | if (tomoyo_str_starts(¶m.data, "aggregator ")) | 1329 | if (tomoyo_str_starts(¶m.data, "aggregator ")) |
1285 | return tomoyo_write_aggregator(¶m); | 1330 | return tomoyo_write_aggregator(¶m); |
1286 | for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) | 1331 | for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) |
@@ -1294,8 +1339,9 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | |||
1294 | char *data; | 1339 | char *data; |
1295 | group = simple_strtoul(param.data, &data, 10); | 1340 | group = simple_strtoul(param.data, &data, 10); |
1296 | if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ') | 1341 | if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ') |
1297 | return tomoyo_write_domain2(&tomoyo_acl_group[group], | 1342 | return tomoyo_write_domain2 |
1298 | data, param.is_delete); | 1343 | (head->w.ns, &head->w.ns->acl_group[group], |
1344 | data, is_delete); | ||
1299 | } | 1345 | } |
1300 | return -EINVAL; | 1346 | return -EINVAL; |
1301 | } | 1347 | } |
@@ -1312,7 +1358,10 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | |||
1312 | */ | 1358 | */ |
1313 | static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) | 1359 | static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) |
1314 | { | 1360 | { |
1315 | list_for_each_cookie(head->r.group, &tomoyo_group_list[idx]) { | 1361 | struct tomoyo_policy_namespace *ns = |
1362 | container_of(head->r.ns, typeof(*ns), namespace_list); | ||
1363 | struct list_head *list = &ns->group_list[idx]; | ||
1364 | list_for_each_cookie(head->r.group, list) { | ||
1316 | struct tomoyo_group *group = | 1365 | struct tomoyo_group *group = |
1317 | list_entry(head->r.group, typeof(*group), head.list); | 1366 | list_entry(head->r.group, typeof(*group), head.list); |
1318 | list_for_each_cookie(head->r.acl, &group->member_list) { | 1367 | list_for_each_cookie(head->r.acl, &group->member_list) { |
@@ -1322,6 +1371,7 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) | |||
1322 | continue; | 1371 | continue; |
1323 | if (!tomoyo_flush(head)) | 1372 | if (!tomoyo_flush(head)) |
1324 | return false; | 1373 | return false; |
1374 | tomoyo_print_namespace(head); | ||
1325 | tomoyo_set_string(head, tomoyo_group_name[idx]); | 1375 | tomoyo_set_string(head, tomoyo_group_name[idx]); |
1326 | tomoyo_set_string(head, group->group_name->name); | 1376 | tomoyo_set_string(head, group->group_name->name); |
1327 | if (idx == TOMOYO_PATH_GROUP) { | 1377 | if (idx == TOMOYO_PATH_GROUP) { |
@@ -1355,7 +1405,10 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) | |||
1355 | */ | 1405 | */ |
1356 | static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | 1406 | static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) |
1357 | { | 1407 | { |
1358 | list_for_each_cookie(head->r.acl, &tomoyo_policy_list[idx]) { | 1408 | struct tomoyo_policy_namespace *ns = |
1409 | container_of(head->r.ns, typeof(*ns), namespace_list); | ||
1410 | struct list_head *list = &ns->policy_list[idx]; | ||
1411 | list_for_each_cookie(head->r.acl, list) { | ||
1359 | struct tomoyo_acl_head *acl = | 1412 | struct tomoyo_acl_head *acl = |
1360 | container_of(head->r.acl, typeof(*acl), list); | 1413 | container_of(head->r.acl, typeof(*acl), list); |
1361 | if (acl->is_deleted) | 1414 | if (acl->is_deleted) |
@@ -1367,6 +1420,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | |||
1367 | { | 1420 | { |
1368 | struct tomoyo_transition_control *ptr = | 1421 | struct tomoyo_transition_control *ptr = |
1369 | container_of(acl, typeof(*ptr), head); | 1422 | container_of(acl, typeof(*ptr), head); |
1423 | tomoyo_print_namespace(head); | ||
1370 | tomoyo_set_string(head, tomoyo_transition_type | 1424 | tomoyo_set_string(head, tomoyo_transition_type |
1371 | [ptr->type]); | 1425 | [ptr->type]); |
1372 | tomoyo_set_string(head, ptr->program ? | 1426 | tomoyo_set_string(head, ptr->program ? |
@@ -1381,6 +1435,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | |||
1381 | { | 1435 | { |
1382 | struct tomoyo_aggregator *ptr = | 1436 | struct tomoyo_aggregator *ptr = |
1383 | container_of(acl, typeof(*ptr), head); | 1437 | container_of(acl, typeof(*ptr), head); |
1438 | tomoyo_print_namespace(head); | ||
1384 | tomoyo_set_string(head, "aggregator "); | 1439 | tomoyo_set_string(head, "aggregator "); |
1385 | tomoyo_set_string(head, | 1440 | tomoyo_set_string(head, |
1386 | ptr->original_name->name); | 1441 | ptr->original_name->name); |
@@ -1407,6 +1462,8 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | |||
1407 | */ | 1462 | */ |
1408 | static void tomoyo_read_exception(struct tomoyo_io_buffer *head) | 1463 | static void tomoyo_read_exception(struct tomoyo_io_buffer *head) |
1409 | { | 1464 | { |
1465 | struct tomoyo_policy_namespace *ns = | ||
1466 | container_of(head->r.ns, typeof(*ns), namespace_list); | ||
1410 | if (head->r.eof) | 1467 | if (head->r.eof) |
1411 | return; | 1468 | return; |
1412 | while (head->r.step < TOMOYO_MAX_POLICY && | 1469 | while (head->r.step < TOMOYO_MAX_POLICY && |
@@ -1423,7 +1480,7 @@ static void tomoyo_read_exception(struct tomoyo_io_buffer *head) | |||
1423 | + TOMOYO_MAX_ACL_GROUPS) { | 1480 | + TOMOYO_MAX_ACL_GROUPS) { |
1424 | head->r.acl_group_index = head->r.step - TOMOYO_MAX_POLICY | 1481 | head->r.acl_group_index = head->r.step - TOMOYO_MAX_POLICY |
1425 | - TOMOYO_MAX_GROUP; | 1482 | - TOMOYO_MAX_GROUP; |
1426 | if (!tomoyo_read_domain2(head, &tomoyo_acl_group | 1483 | if (!tomoyo_read_domain2(head, &ns->acl_group |
1427 | [head->r.acl_group_index])) | 1484 | [head->r.acl_group_index])) |
1428 | return; | 1485 | return; |
1429 | head->r.step++; | 1486 | head->r.step++; |
@@ -1484,7 +1541,8 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) | |||
1484 | return; | 1541 | return; |
1485 | snprintf(buffer, len - 1, "%s", cp); | 1542 | snprintf(buffer, len - 1, "%s", cp); |
1486 | tomoyo_normalize_line(buffer); | 1543 | tomoyo_normalize_line(buffer); |
1487 | tomoyo_write_domain2(&domain->acl_info_list, buffer, false); | 1544 | tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer, |
1545 | false); | ||
1488 | kfree(buffer); | 1546 | kfree(buffer); |
1489 | } | 1547 | } |
1490 | 1548 | ||
@@ -1896,6 +1954,45 @@ int tomoyo_poll_control(struct file *file, poll_table *wait) | |||
1896 | } | 1954 | } |
1897 | 1955 | ||
1898 | /** | 1956 | /** |
1957 | * tomoyo_set_namespace_cursor - Set namespace to read. | ||
1958 | * | ||
1959 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
1960 | * | ||
1961 | * Returns nothing. | ||
1962 | */ | ||
1963 | static inline void tomoyo_set_namespace_cursor(struct tomoyo_io_buffer *head) | ||
1964 | { | ||
1965 | struct list_head *ns; | ||
1966 | if (head->type != TOMOYO_EXCEPTIONPOLICY && | ||
1967 | head->type != TOMOYO_PROFILE) | ||
1968 | return; | ||
1969 | /* | ||
1970 | * If this is the first read, or reading previous namespace finished | ||
1971 | * and has more namespaces to read, update the namespace cursor. | ||
1972 | */ | ||
1973 | ns = head->r.ns; | ||
1974 | if (!ns || (head->r.eof && ns->next != &tomoyo_namespace_list)) { | ||
1975 | /* Clearing is OK because tomoyo_flush() returned true. */ | ||
1976 | memset(&head->r, 0, sizeof(head->r)); | ||
1977 | head->r.ns = ns ? ns->next : tomoyo_namespace_list.next; | ||
1978 | } | ||
1979 | } | ||
1980 | |||
1981 | /** | ||
1982 | * tomoyo_has_more_namespace - Check for unread namespaces. | ||
1983 | * | ||
1984 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
1985 | * | ||
1986 | * Returns true if we have more entries to print, false otherwise. | ||
1987 | */ | ||
1988 | static inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head) | ||
1989 | { | ||
1990 | return (head->type == TOMOYO_EXCEPTIONPOLICY || | ||
1991 | head->type == TOMOYO_PROFILE) && head->r.eof && | ||
1992 | head->r.ns->next != &tomoyo_namespace_list; | ||
1993 | } | ||
1994 | |||
1995 | /** | ||
1899 | * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. | 1996 | * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. |
1900 | * | 1997 | * |
1901 | * @head: Pointer to "struct tomoyo_io_buffer". | 1998 | * @head: Pointer to "struct tomoyo_io_buffer". |
@@ -1919,14 +2016,54 @@ int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | |||
1919 | head->read_user_buf_avail = buffer_len; | 2016 | head->read_user_buf_avail = buffer_len; |
1920 | if (tomoyo_flush(head)) | 2017 | if (tomoyo_flush(head)) |
1921 | /* Call the policy handler. */ | 2018 | /* Call the policy handler. */ |
1922 | head->read(head); | 2019 | do { |
1923 | tomoyo_flush(head); | 2020 | tomoyo_set_namespace_cursor(head); |
2021 | head->read(head); | ||
2022 | } while (tomoyo_flush(head) && | ||
2023 | tomoyo_has_more_namespace(head)); | ||
1924 | len = head->read_user_buf - buffer; | 2024 | len = head->read_user_buf - buffer; |
1925 | mutex_unlock(&head->io_sem); | 2025 | mutex_unlock(&head->io_sem); |
1926 | return len; | 2026 | return len; |
1927 | } | 2027 | } |
1928 | 2028 | ||
1929 | /** | 2029 | /** |
2030 | * tomoyo_parse_policy - Parse a policy line. | ||
2031 | * | ||
2032 | * @head: Poiter to "struct tomoyo_io_buffer". | ||
2033 | * @line: Line to parse. | ||
2034 | * | ||
2035 | * Returns 0 on success, negative value otherwise. | ||
2036 | * | ||
2037 | * Caller holds tomoyo_read_lock(). | ||
2038 | */ | ||
2039 | static int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line) | ||
2040 | { | ||
2041 | /* Delete request? */ | ||
2042 | head->w.is_delete = !strncmp(line, "delete ", 7); | ||
2043 | if (head->w.is_delete) | ||
2044 | memmove(line, line + 7, strlen(line + 7) + 1); | ||
2045 | /* Selecting namespace to update. */ | ||
2046 | if (head->type == TOMOYO_EXCEPTIONPOLICY || | ||
2047 | head->type == TOMOYO_PROFILE) { | ||
2048 | if (*line == '<') { | ||
2049 | char *cp = strchr(line, ' '); | ||
2050 | if (cp) { | ||
2051 | *cp++ = '\0'; | ||
2052 | head->w.ns = tomoyo_assign_namespace(line); | ||
2053 | memmove(line, cp, strlen(cp) + 1); | ||
2054 | } else | ||
2055 | head->w.ns = NULL; | ||
2056 | } else | ||
2057 | head->w.ns = &tomoyo_kernel_namespace; | ||
2058 | /* Don't allow updating if namespace is invalid. */ | ||
2059 | if (!head->w.ns) | ||
2060 | return -ENOENT; | ||
2061 | } | ||
2062 | /* Do the update. */ | ||
2063 | return head->write(head); | ||
2064 | } | ||
2065 | |||
2066 | /** | ||
1930 | * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface. | 2067 | * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface. |
1931 | * | 2068 | * |
1932 | * @head: Pointer to "struct tomoyo_io_buffer". | 2069 | * @head: Pointer to "struct tomoyo_io_buffer". |
@@ -1941,27 +2078,31 @@ int tomoyo_write_control(struct tomoyo_io_buffer *head, | |||
1941 | const char __user *buffer, const int buffer_len) | 2078 | const char __user *buffer, const int buffer_len) |
1942 | { | 2079 | { |
1943 | int error = buffer_len; | 2080 | int error = buffer_len; |
1944 | int avail_len = buffer_len; | 2081 | size_t avail_len = buffer_len; |
1945 | char *cp0 = head->write_buf; | 2082 | char *cp0 = head->write_buf; |
1946 | |||
1947 | if (!head->write) | 2083 | if (!head->write) |
1948 | return -ENOSYS; | 2084 | return -ENOSYS; |
1949 | if (!access_ok(VERIFY_READ, buffer, buffer_len)) | 2085 | if (!access_ok(VERIFY_READ, buffer, buffer_len)) |
1950 | return -EFAULT; | 2086 | return -EFAULT; |
1951 | /* Don't allow updating policies by non manager programs. */ | ||
1952 | if (head->write != tomoyo_write_pid && | ||
1953 | head->write != tomoyo_write_domain && | ||
1954 | head->write != tomoyo_write_exception && !tomoyo_manager()) | ||
1955 | return -EPERM; | ||
1956 | if (mutex_lock_interruptible(&head->io_sem)) | 2087 | if (mutex_lock_interruptible(&head->io_sem)) |
1957 | return -EINTR; | 2088 | return -EINTR; |
1958 | /* Read a line and dispatch it to the policy handler. */ | 2089 | /* Read a line and dispatch it to the policy handler. */ |
1959 | while (avail_len > 0) { | 2090 | while (avail_len > 0) { |
1960 | char c; | 2091 | char c; |
1961 | if (head->w.avail >= head->writebuf_size - 1) { | 2092 | if (head->w.avail >= head->writebuf_size - 1) { |
1962 | error = -ENOMEM; | 2093 | const int len = head->writebuf_size * 2; |
1963 | break; | 2094 | char *cp = kzalloc(len, GFP_NOFS); |
1964 | } else if (get_user(c, buffer)) { | 2095 | if (!cp) { |
2096 | error = -ENOMEM; | ||
2097 | break; | ||
2098 | } | ||
2099 | memmove(cp, cp0, head->w.avail); | ||
2100 | kfree(cp0); | ||
2101 | head->write_buf = cp; | ||
2102 | cp0 = cp; | ||
2103 | head->writebuf_size = len; | ||
2104 | } | ||
2105 | if (get_user(c, buffer)) { | ||
1965 | error = -EFAULT; | 2106 | error = -EFAULT; |
1966 | break; | 2107 | break; |
1967 | } | 2108 | } |
@@ -1973,8 +2114,40 @@ int tomoyo_write_control(struct tomoyo_io_buffer *head, | |||
1973 | cp0[head->w.avail - 1] = '\0'; | 2114 | cp0[head->w.avail - 1] = '\0'; |
1974 | head->w.avail = 0; | 2115 | head->w.avail = 0; |
1975 | tomoyo_normalize_line(cp0); | 2116 | tomoyo_normalize_line(cp0); |
1976 | head->write(head); | 2117 | if (!strcmp(cp0, "reset")) { |
2118 | head->w.ns = &tomoyo_kernel_namespace; | ||
2119 | head->w.domain = NULL; | ||
2120 | memset(&head->r, 0, sizeof(head->r)); | ||
2121 | continue; | ||
2122 | } | ||
2123 | /* Don't allow updating policies by non manager programs. */ | ||
2124 | switch (head->type) { | ||
2125 | case TOMOYO_PROCESS_STATUS: | ||
2126 | /* This does not write anything. */ | ||
2127 | break; | ||
2128 | case TOMOYO_DOMAINPOLICY: | ||
2129 | if (tomoyo_select_domain(head, cp0)) | ||
2130 | continue; | ||
2131 | /* fall through */ | ||
2132 | case TOMOYO_EXCEPTIONPOLICY: | ||
2133 | if (!strcmp(cp0, "select transition_only")) { | ||
2134 | head->r.print_transition_related_only = true; | ||
2135 | continue; | ||
2136 | } | ||
2137 | /* fall through */ | ||
2138 | default: | ||
2139 | if (!tomoyo_manager()) { | ||
2140 | error = -EPERM; | ||
2141 | goto out; | ||
2142 | } | ||
2143 | } | ||
2144 | switch (tomoyo_parse_policy(head, cp0)) { | ||
2145 | case -EPERM: | ||
2146 | error = -EPERM; | ||
2147 | goto out; | ||
2148 | } | ||
1977 | } | 2149 | } |
2150 | out: | ||
1978 | mutex_unlock(&head->io_sem); | 2151 | mutex_unlock(&head->io_sem); |
1979 | return error; | 2152 | return error; |
1980 | } | 2153 | } |
@@ -2019,27 +2192,27 @@ void tomoyo_check_profile(void) | |||
2019 | struct tomoyo_domain_info *domain; | 2192 | struct tomoyo_domain_info *domain; |
2020 | const int idx = tomoyo_read_lock(); | 2193 | const int idx = tomoyo_read_lock(); |
2021 | tomoyo_policy_loaded = true; | 2194 | tomoyo_policy_loaded = true; |
2022 | /* Check all profiles currently assigned to domains are defined. */ | 2195 | printk(KERN_INFO "TOMOYO: 2.4.0\n"); |
2023 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | 2196 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
2024 | const u8 profile = domain->profile; | 2197 | const u8 profile = domain->profile; |
2025 | if (tomoyo_profile_ptr[profile]) | 2198 | const struct tomoyo_policy_namespace *ns = domain->ns; |
2199 | if (ns->profile_version != 20100903) | ||
2200 | printk(KERN_ERR | ||
2201 | "Profile version %u is not supported.\n", | ||
2202 | ns->profile_version); | ||
2203 | else if (!ns->profile_ptr[profile]) | ||
2204 | printk(KERN_ERR | ||
2205 | "Profile %u (used by '%s') is not defined.\n", | ||
2206 | profile, domain->domainname->name); | ||
2207 | else | ||
2026 | continue; | 2208 | continue; |
2027 | printk(KERN_ERR "You need to define profile %u before using it.\n", | 2209 | printk(KERN_ERR |
2028 | profile); | 2210 | "Userland tools for TOMOYO 2.4 must be installed and " |
2029 | printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.3/ " | 2211 | "policy must be initialized.\n"); |
2212 | printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.4/ " | ||
2030 | "for more information.\n"); | 2213 | "for more information.\n"); |
2031 | panic("Profile %u (used by '%s') not defined.\n", | 2214 | panic("STOP!"); |
2032 | profile, domain->domainname->name); | ||
2033 | } | 2215 | } |
2034 | tomoyo_read_unlock(idx); | 2216 | tomoyo_read_unlock(idx); |
2035 | if (tomoyo_profile_version != 20090903) { | ||
2036 | printk(KERN_ERR "You need to install userland programs for " | ||
2037 | "TOMOYO 2.3 and initialize policy configuration.\n"); | ||
2038 | printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.3/ " | ||
2039 | "for more information.\n"); | ||
2040 | panic("Profile version %u is not supported.\n", | ||
2041 | tomoyo_profile_version); | ||
2042 | } | ||
2043 | printk(KERN_INFO "TOMOYO: 2.3.0\n"); | ||
2044 | printk(KERN_INFO "Mandatory Access Control activated.\n"); | 2217 | printk(KERN_INFO "Mandatory Access Control activated.\n"); |
2045 | } | 2218 | } |