diff options
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r-- | security/tomoyo/common.c | 119 |
1 files changed, 82 insertions, 37 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ddfb9cccf468..fdd1f4b8c448 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -28,7 +28,13 @@ static const char *tomoyo_mode_2[4] = { | |||
28 | "disabled", "enabled", "enabled", "enabled" | 28 | "disabled", "enabled", "enabled", "enabled" |
29 | }; | 29 | }; |
30 | 30 | ||
31 | /* Table for profile. */ | 31 | /* |
32 | * tomoyo_control_array is a static data which contains | ||
33 | * | ||
34 | * (1) functionality name used by /sys/kernel/security/tomoyo/profile . | ||
35 | * (2) initial values for "struct tomoyo_profile". | ||
36 | * (3) max values for "struct tomoyo_profile". | ||
37 | */ | ||
32 | static struct { | 38 | static struct { |
33 | const char *keyword; | 39 | const char *keyword; |
34 | unsigned int current_value; | 40 | unsigned int current_value; |
@@ -39,7 +45,13 @@ static struct { | |||
39 | [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 }, | 45 | [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 }, |
40 | }; | 46 | }; |
41 | 47 | ||
42 | /* Profile table. Memory is allocated as needed. */ | 48 | /* |
49 | * tomoyo_profile is a structure which is used for holding the mode of access | ||
50 | * controls. TOMOYO has 4 modes: disabled, learning, permissive, enforcing. | ||
51 | * An administrator can define up to 256 profiles. | ||
52 | * The ->profile of "struct tomoyo_domain_info" is used for remembering | ||
53 | * the profile's number (0 - 255) assigned to that domain. | ||
54 | */ | ||
43 | static struct tomoyo_profile { | 55 | static struct tomoyo_profile { |
44 | unsigned int value[TOMOYO_MAX_CONTROL_INDEX]; | 56 | unsigned int value[TOMOYO_MAX_CONTROL_INDEX]; |
45 | const struct tomoyo_path_info *comment; | 57 | const struct tomoyo_path_info *comment; |
@@ -428,7 +440,6 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr) | |||
428 | const char *name = ptr->name; | 440 | const char *name = ptr->name; |
429 | const int len = strlen(name); | 441 | const int len = strlen(name); |
430 | 442 | ||
431 | ptr->total_len = len; | ||
432 | ptr->const_len = tomoyo_const_part_length(name); | 443 | ptr->const_len = tomoyo_const_part_length(name); |
433 | ptr->is_dir = len && (name[len - 1] == '/'); | 444 | ptr->is_dir = len && (name[len - 1] == '/'); |
434 | ptr->is_patterned = (ptr->const_len < len); | 445 | ptr->is_patterned = (ptr->const_len < len); |
@@ -866,7 +877,6 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned | |||
866 | 877 | ||
867 | if (profile >= TOMOYO_MAX_PROFILES) | 878 | if (profile >= TOMOYO_MAX_PROFILES) |
868 | return NULL; | 879 | return NULL; |
869 | /***** EXCLUSIVE SECTION START *****/ | ||
870 | mutex_lock(&lock); | 880 | mutex_lock(&lock); |
871 | ptr = tomoyo_profile_ptr[profile]; | 881 | ptr = tomoyo_profile_ptr[profile]; |
872 | if (ptr) | 882 | if (ptr) |
@@ -880,7 +890,6 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned | |||
880 | tomoyo_profile_ptr[profile] = ptr; | 890 | tomoyo_profile_ptr[profile] = ptr; |
881 | ok: | 891 | ok: |
882 | mutex_unlock(&lock); | 892 | mutex_unlock(&lock); |
883 | /***** EXCLUSIVE SECTION END *****/ | ||
884 | return ptr; | 893 | return ptr; |
885 | } | 894 | } |
886 | 895 | ||
@@ -1009,7 +1018,19 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
1009 | return 0; | 1018 | return 0; |
1010 | } | 1019 | } |
1011 | 1020 | ||
1012 | /* Structure for policy manager. */ | 1021 | /* |
1022 | * tomoyo_policy_manager_entry is a structure which is used for holding list of | ||
1023 | * domainnames or programs which are permitted to modify configuration via | ||
1024 | * /sys/kernel/security/tomoyo/ interface. | ||
1025 | * It has following fields. | ||
1026 | * | ||
1027 | * (1) "list" which is linked to tomoyo_policy_manager_list . | ||
1028 | * (2) "manager" is a domainname or a program's pathname. | ||
1029 | * (3) "is_domain" is a bool which is true if "manager" is a domainname, false | ||
1030 | * otherwise. | ||
1031 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
1032 | * otherwise. | ||
1033 | */ | ||
1013 | struct tomoyo_policy_manager_entry { | 1034 | struct tomoyo_policy_manager_entry { |
1014 | struct list_head list; | 1035 | struct list_head list; |
1015 | /* A path to program or a domainname. */ | 1036 | /* A path to program or a domainname. */ |
@@ -1018,7 +1039,36 @@ struct tomoyo_policy_manager_entry { | |||
1018 | bool is_deleted; /* True if this entry is deleted. */ | 1039 | bool is_deleted; /* True if this entry is deleted. */ |
1019 | }; | 1040 | }; |
1020 | 1041 | ||
1021 | /* The list for "struct tomoyo_policy_manager_entry". */ | 1042 | /* |
1043 | * tomoyo_policy_manager_list is used for holding list of domainnames or | ||
1044 | * programs which are permitted to modify configuration via | ||
1045 | * /sys/kernel/security/tomoyo/ interface. | ||
1046 | * | ||
1047 | * An entry is added by | ||
1048 | * | ||
1049 | * # echo '<kernel> /sbin/mingetty /bin/login /bin/bash' > \ | ||
1050 | * /sys/kernel/security/tomoyo/manager | ||
1051 | * (if you want to specify by a domainname) | ||
1052 | * | ||
1053 | * or | ||
1054 | * | ||
1055 | * # echo '/usr/lib/ccs/editpolicy' > /sys/kernel/security/tomoyo/manager | ||
1056 | * (if you want to specify by a program's location) | ||
1057 | * | ||
1058 | * and is deleted by | ||
1059 | * | ||
1060 | * # echo 'delete <kernel> /sbin/mingetty /bin/login /bin/bash' > \ | ||
1061 | * /sys/kernel/security/tomoyo/manager | ||
1062 | * | ||
1063 | * or | ||
1064 | * | ||
1065 | * # echo 'delete /usr/lib/ccs/editpolicy' > \ | ||
1066 | * /sys/kernel/security/tomoyo/manager | ||
1067 | * | ||
1068 | * and all entries are retrieved by | ||
1069 | * | ||
1070 | * # cat /sys/kernel/security/tomoyo/manager | ||
1071 | */ | ||
1022 | static LIST_HEAD(tomoyo_policy_manager_list); | 1072 | static LIST_HEAD(tomoyo_policy_manager_list); |
1023 | static DECLARE_RWSEM(tomoyo_policy_manager_list_lock); | 1073 | static DECLARE_RWSEM(tomoyo_policy_manager_list_lock); |
1024 | 1074 | ||
@@ -1050,7 +1100,6 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1050 | saved_manager = tomoyo_save_name(manager); | 1100 | saved_manager = tomoyo_save_name(manager); |
1051 | if (!saved_manager) | 1101 | if (!saved_manager) |
1052 | return -ENOMEM; | 1102 | return -ENOMEM; |
1053 | /***** EXCLUSIVE SECTION START *****/ | ||
1054 | down_write(&tomoyo_policy_manager_list_lock); | 1103 | down_write(&tomoyo_policy_manager_list_lock); |
1055 | list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { | 1104 | list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { |
1056 | if (ptr->manager != saved_manager) | 1105 | if (ptr->manager != saved_manager) |
@@ -1072,7 +1121,6 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1072 | error = 0; | 1121 | error = 0; |
1073 | out: | 1122 | out: |
1074 | up_write(&tomoyo_policy_manager_list_lock); | 1123 | up_write(&tomoyo_policy_manager_list_lock); |
1075 | /***** EXCLUSIVE SECTION END *****/ | ||
1076 | return error; | 1124 | return error; |
1077 | } | 1125 | } |
1078 | 1126 | ||
@@ -1117,10 +1165,9 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | |||
1117 | list); | 1165 | list); |
1118 | if (ptr->is_deleted) | 1166 | if (ptr->is_deleted) |
1119 | continue; | 1167 | continue; |
1120 | if (!tomoyo_io_printf(head, "%s\n", ptr->manager->name)) { | 1168 | done = tomoyo_io_printf(head, "%s\n", ptr->manager->name); |
1121 | done = false; | 1169 | if (!done) |
1122 | break; | 1170 | break; |
1123 | } | ||
1124 | } | 1171 | } |
1125 | up_read(&tomoyo_policy_manager_list_lock); | 1172 | up_read(&tomoyo_policy_manager_list_lock); |
1126 | head->read_eof = done; | 1173 | head->read_eof = done; |
@@ -1197,13 +1244,11 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1197 | 1244 | ||
1198 | if (sscanf(data, "pid=%u", &pid) == 1) { | 1245 | if (sscanf(data, "pid=%u", &pid) == 1) { |
1199 | struct task_struct *p; | 1246 | struct task_struct *p; |
1200 | /***** CRITICAL SECTION START *****/ | ||
1201 | read_lock(&tasklist_lock); | 1247 | read_lock(&tasklist_lock); |
1202 | p = find_task_by_vpid(pid); | 1248 | p = find_task_by_vpid(pid); |
1203 | if (p) | 1249 | if (p) |
1204 | domain = tomoyo_real_domain(p); | 1250 | domain = tomoyo_real_domain(p); |
1205 | read_unlock(&tasklist_lock); | 1251 | read_unlock(&tasklist_lock); |
1206 | /***** CRITICAL SECTION END *****/ | ||
1207 | } else if (!strncmp(data, "domain=", 7)) { | 1252 | } else if (!strncmp(data, "domain=", 7)) { |
1208 | if (tomoyo_is_domain_def(data + 7)) { | 1253 | if (tomoyo_is_domain_def(data + 7)) { |
1209 | down_read(&tomoyo_domain_list_lock); | 1254 | down_read(&tomoyo_domain_list_lock); |
@@ -1447,15 +1492,14 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) | |||
1447 | TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) | 1492 | TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) |
1448 | ignore_global_allow_read | 1493 | ignore_global_allow_read |
1449 | = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; | 1494 | = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; |
1450 | if (!tomoyo_io_printf(head, | 1495 | done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE |
1451 | "%s\n" TOMOYO_KEYWORD_USE_PROFILE "%u\n" | 1496 | "%u\n%s%s%s\n", |
1452 | "%s%s%s\n", domain->domainname->name, | 1497 | domain->domainname->name, |
1453 | domain->profile, quota_exceeded, | 1498 | domain->profile, quota_exceeded, |
1454 | transition_failed, | 1499 | transition_failed, |
1455 | ignore_global_allow_read)) { | 1500 | ignore_global_allow_read); |
1456 | done = false; | 1501 | if (!done) |
1457 | break; | 1502 | break; |
1458 | } | ||
1459 | head->read_step = 2; | 1503 | head->read_step = 2; |
1460 | acl_loop: | 1504 | acl_loop: |
1461 | if (head->read_step == 3) | 1505 | if (head->read_step == 3) |
@@ -1463,24 +1507,22 @@ acl_loop: | |||
1463 | /* Print ACL entries in the domain. */ | 1507 | /* Print ACL entries in the domain. */ |
1464 | down_read(&tomoyo_domain_acl_info_list_lock); | 1508 | down_read(&tomoyo_domain_acl_info_list_lock); |
1465 | list_for_each_cookie(apos, head->read_var2, | 1509 | list_for_each_cookie(apos, head->read_var2, |
1466 | &domain->acl_info_list) { | 1510 | &domain->acl_info_list) { |
1467 | struct tomoyo_acl_info *ptr | 1511 | struct tomoyo_acl_info *ptr |
1468 | = list_entry(apos, struct tomoyo_acl_info, | 1512 | = list_entry(apos, struct tomoyo_acl_info, |
1469 | list); | 1513 | list); |
1470 | if (!tomoyo_print_entry(head, ptr)) { | 1514 | done = tomoyo_print_entry(head, ptr); |
1471 | done = false; | 1515 | if (!done) |
1472 | break; | 1516 | break; |
1473 | } | ||
1474 | } | 1517 | } |
1475 | up_read(&tomoyo_domain_acl_info_list_lock); | 1518 | up_read(&tomoyo_domain_acl_info_list_lock); |
1476 | if (!done) | 1519 | if (!done) |
1477 | break; | 1520 | break; |
1478 | head->read_step = 3; | 1521 | head->read_step = 3; |
1479 | tail_mark: | 1522 | tail_mark: |
1480 | if (!tomoyo_io_printf(head, "\n")) { | 1523 | done = tomoyo_io_printf(head, "\n"); |
1481 | done = false; | 1524 | if (!done) |
1482 | break; | 1525 | break; |
1483 | } | ||
1484 | head->read_step = 1; | 1526 | head->read_step = 1; |
1485 | if (head->read_single_domain) | 1527 | if (head->read_single_domain) |
1486 | break; | 1528 | break; |
@@ -1550,11 +1592,10 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) | |||
1550 | domain = list_entry(pos, struct tomoyo_domain_info, list); | 1592 | domain = list_entry(pos, struct tomoyo_domain_info, list); |
1551 | if (domain->is_deleted) | 1593 | if (domain->is_deleted) |
1552 | continue; | 1594 | continue; |
1553 | if (!tomoyo_io_printf(head, "%u %s\n", domain->profile, | 1595 | done = tomoyo_io_printf(head, "%u %s\n", domain->profile, |
1554 | domain->domainname->name)) { | 1596 | domain->domainname->name); |
1555 | done = false; | 1597 | if (!done) |
1556 | break; | 1598 | break; |
1557 | } | ||
1558 | } | 1599 | } |
1559 | up_read(&tomoyo_domain_list_lock); | 1600 | up_read(&tomoyo_domain_list_lock); |
1560 | head->read_eof = done; | 1601 | head->read_eof = done; |
@@ -1594,13 +1635,11 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head) | |||
1594 | const int pid = head->read_step; | 1635 | const int pid = head->read_step; |
1595 | struct task_struct *p; | 1636 | struct task_struct *p; |
1596 | struct tomoyo_domain_info *domain = NULL; | 1637 | struct tomoyo_domain_info *domain = NULL; |
1597 | /***** CRITICAL SECTION START *****/ | ||
1598 | read_lock(&tasklist_lock); | 1638 | read_lock(&tasklist_lock); |
1599 | p = find_task_by_vpid(pid); | 1639 | p = find_task_by_vpid(pid); |
1600 | if (p) | 1640 | if (p) |
1601 | domain = tomoyo_real_domain(p); | 1641 | domain = tomoyo_real_domain(p); |
1602 | read_unlock(&tasklist_lock); | 1642 | read_unlock(&tasklist_lock); |
1603 | /***** CRITICAL SECTION END *****/ | ||
1604 | if (domain) | 1643 | if (domain) |
1605 | tomoyo_io_printf(head, "%d %u %s", pid, domain->profile, | 1644 | tomoyo_io_printf(head, "%d %u %s", pid, domain->profile, |
1606 | domain->domainname->name); | 1645 | domain->domainname->name); |
@@ -2138,7 +2177,13 @@ static ssize_t tomoyo_write(struct file *file, const char __user *buf, | |||
2138 | return tomoyo_write_control(file, buf, count); | 2177 | return tomoyo_write_control(file, buf, count); |
2139 | } | 2178 | } |
2140 | 2179 | ||
2141 | /* Operations for /sys/kernel/security/tomoyo/ interface. */ | 2180 | /* |
2181 | * tomoyo_operations is a "struct file_operations" which is used for handling | ||
2182 | * /sys/kernel/security/tomoyo/ interface. | ||
2183 | * | ||
2184 | * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR). | ||
2185 | * See tomoyo_io_buffer for internals. | ||
2186 | */ | ||
2142 | static const struct file_operations tomoyo_operations = { | 2187 | static const struct file_operations tomoyo_operations = { |
2143 | .open = tomoyo_open, | 2188 | .open = tomoyo_open, |
2144 | .release = tomoyo_release, | 2189 | .release = tomoyo_release, |