aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 03:45:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 03:45:31 -0400
commit36b8d186e6cc8e32cb5227f5645a58e1bc0af190 (patch)
tree1000ad26e189e6ff2c53fb7eeff605f59c7ad94e /security/tomoyo
parentcd85b557414fe4cd44ea6608825e96612a5fe2b2 (diff)
parentc45ed235abf1b0b6666417e3c394f18717976acd (diff)
Merge branch 'next' of git://selinuxproject.org/~jmorris/linux-security
* 'next' of git://selinuxproject.org/~jmorris/linux-security: (95 commits) TOMOYO: Fix incomplete read after seek. Smack: allow to access /smack/access as normal user TOMOYO: Fix unused kernel config option. Smack: fix: invalid length set for the result of /smack/access Smack: compilation fix Smack: fix for /smack/access output, use string instead of byte Smack: domain transition protections (v3) Smack: Provide information for UDS getsockopt(SO_PEERCRED) Smack: Clean up comments Smack: Repair processing of fcntl Smack: Rule list lookup performance Smack: check permissions from user space (v2) TOMOYO: Fix quota and garbage collector. TOMOYO: Remove redundant tasklist_lock. TOMOYO: Fix domain transition failure warning. TOMOYO: Remove tomoyo_policy_memory_lock spinlock. TOMOYO: Simplify garbage collector. TOMOYO: Fix make namespacecheck warnings. target: check hex2bin result encrypted-keys: check hex2bin result ...
Diffstat (limited to 'security/tomoyo')
-rw-r--r--security/tomoyo/Kconfig2
-rw-r--r--security/tomoyo/Makefile4
-rw-r--r--security/tomoyo/audit.c7
-rw-r--r--security/tomoyo/common.c228
-rw-r--r--security/tomoyo/common.h189
-rw-r--r--security/tomoyo/condition.c71
-rw-r--r--security/tomoyo/domain.c209
-rw-r--r--security/tomoyo/environ.c122
-rw-r--r--security/tomoyo/file.c42
-rw-r--r--security/tomoyo/gc.c540
-rw-r--r--security/tomoyo/group.c61
-rw-r--r--security/tomoyo/memory.c39
-rw-r--r--security/tomoyo/network.c771
-rw-r--r--security/tomoyo/realpath.c32
-rw-r--r--security/tomoyo/securityfs_if.c123
-rw-r--r--security/tomoyo/tomoyo.c62
-rw-r--r--security/tomoyo/util.c80
17 files changed, 2128 insertions, 454 deletions
diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig
index 7c7f8c16c10f..8eb779b9d77f 100644
--- a/security/tomoyo/Kconfig
+++ b/security/tomoyo/Kconfig
@@ -1,8 +1,10 @@
1config SECURITY_TOMOYO 1config SECURITY_TOMOYO
2 bool "TOMOYO Linux Support" 2 bool "TOMOYO Linux Support"
3 depends on SECURITY 3 depends on SECURITY
4 depends on NET
4 select SECURITYFS 5 select SECURITYFS
5 select SECURITY_PATH 6 select SECURITY_PATH
7 select SECURITY_NETWORK
6 default n 8 default n
7 help 9 help
8 This selects TOMOYO Linux, pathname-based access control. 10 This selects TOMOYO Linux, pathname-based access control.
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 95278b71fc21..56a0c7be409e 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1,4 +1,4 @@
1obj-y = audit.o common.o condition.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o 1obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o
2 2
3$(obj)/policy/profile.conf: 3$(obj)/policy/profile.conf:
4 @mkdir -p $(obj)/policy/ 4 @mkdir -p $(obj)/policy/
@@ -27,7 +27,7 @@ $(obj)/policy/stat.conf:
27 @touch $@ 27 @touch $@
28 28
29$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf 29$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf
30 @echo Generating built-in policy for TOMOYO 2.4.x. 30 @echo Generating built-in policy for TOMOYO 2.5.x.
31 @echo "static char tomoyo_builtin_profile[] __initdata =" > $@.tmp 31 @echo "static char tomoyo_builtin_profile[] __initdata =" > $@.tmp
32 @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp 32 @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp
33 @echo "\"\";" >> $@.tmp 33 @echo "\"\";" >> $@.tmp
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c
index 5dbb1f7617c0..075c3a6d1649 100644
--- a/security/tomoyo/audit.c
+++ b/security/tomoyo/audit.c
@@ -313,6 +313,7 @@ static unsigned int tomoyo_log_count;
313 */ 313 */
314static bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns, 314static bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns,
315 const u8 profile, const u8 index, 315 const u8 profile, const u8 index,
316 const struct tomoyo_acl_info *matched_acl,
316 const bool is_granted) 317 const bool is_granted)
317{ 318{
318 u8 mode; 319 u8 mode;
@@ -324,6 +325,9 @@ static bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns,
324 p = tomoyo_profile(ns, profile); 325 p = tomoyo_profile(ns, profile);
325 if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG]) 326 if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG])
326 return false; 327 return false;
328 if (is_granted && matched_acl && matched_acl->cond &&
329 matched_acl->cond->grant_log != TOMOYO_GRANTLOG_AUTO)
330 return matched_acl->cond->grant_log == TOMOYO_GRANTLOG_YES;
327 mode = p->config[index]; 331 mode = p->config[index];
328 if (mode == TOMOYO_CONFIG_USE_DEFAULT) 332 if (mode == TOMOYO_CONFIG_USE_DEFAULT)
329 mode = p->config[category]; 333 mode = p->config[category];
@@ -350,7 +354,8 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt,
350 char *buf; 354 char *buf;
351 struct tomoyo_log *entry; 355 struct tomoyo_log *entry;
352 bool quota_exceeded = false; 356 bool quota_exceeded = false;
353 if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, r->granted)) 357 if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type,
358 r->matched_acl, r->granted))
354 goto out; 359 goto out;
355 buf = tomoyo_init_log(r, len, fmt, args); 360 buf = tomoyo_init_log(r, len, fmt, args);
356 if (!buf) 361 if (!buf)
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 2e43aec1c36b..150911c7ff08 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -20,6 +20,7 @@ const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = {
20/* String table for /sys/kernel/security/tomoyo/profile */ 20/* String table for /sys/kernel/security/tomoyo/profile */
21const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX 21const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
22 + TOMOYO_MAX_MAC_CATEGORY_INDEX] = { 22 + TOMOYO_MAX_MAC_CATEGORY_INDEX] = {
23 /* CONFIG::file group */
23 [TOMOYO_MAC_FILE_EXECUTE] = "execute", 24 [TOMOYO_MAC_FILE_EXECUTE] = "execute",
24 [TOMOYO_MAC_FILE_OPEN] = "open", 25 [TOMOYO_MAC_FILE_OPEN] = "open",
25 [TOMOYO_MAC_FILE_CREATE] = "create", 26 [TOMOYO_MAC_FILE_CREATE] = "create",
@@ -43,7 +44,28 @@ const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
43 [TOMOYO_MAC_FILE_MOUNT] = "mount", 44 [TOMOYO_MAC_FILE_MOUNT] = "mount",
44 [TOMOYO_MAC_FILE_UMOUNT] = "unmount", 45 [TOMOYO_MAC_FILE_UMOUNT] = "unmount",
45 [TOMOYO_MAC_FILE_PIVOT_ROOT] = "pivot_root", 46 [TOMOYO_MAC_FILE_PIVOT_ROOT] = "pivot_root",
47 /* CONFIG::network group */
48 [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] = "inet_stream_bind",
49 [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] = "inet_stream_listen",
50 [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] = "inet_stream_connect",
51 [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] = "inet_dgram_bind",
52 [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] = "inet_dgram_send",
53 [TOMOYO_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind",
54 [TOMOYO_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send",
55 [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] = "unix_stream_bind",
56 [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] = "unix_stream_listen",
57 [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] = "unix_stream_connect",
58 [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] = "unix_dgram_bind",
59 [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] = "unix_dgram_send",
60 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind",
61 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen",
62 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",
63 /* CONFIG::misc group */
64 [TOMOYO_MAC_ENVIRON] = "env",
65 /* CONFIG group */
46 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", 66 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
67 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_NETWORK] = "network",
68 [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_MISC] = "misc",
47}; 69};
48 70
49/* String table for conditions. */ 71/* String table for conditions. */
@@ -130,10 +152,20 @@ const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
130 [TOMOYO_TYPE_UMOUNT] = "unmount", 152 [TOMOYO_TYPE_UMOUNT] = "unmount",
131}; 153};
132 154
155/* String table for socket's operation. */
156const char * const tomoyo_socket_keyword[TOMOYO_MAX_NETWORK_OPERATION] = {
157 [TOMOYO_NETWORK_BIND] = "bind",
158 [TOMOYO_NETWORK_LISTEN] = "listen",
159 [TOMOYO_NETWORK_CONNECT] = "connect",
160 [TOMOYO_NETWORK_SEND] = "send",
161};
162
133/* String table for categories. */ 163/* String table for categories. */
134static const char * const tomoyo_category_keywords 164static const char * const tomoyo_category_keywords
135[TOMOYO_MAX_MAC_CATEGORY_INDEX] = { 165[TOMOYO_MAX_MAC_CATEGORY_INDEX] = {
136 [TOMOYO_MAC_CATEGORY_FILE] = "file", 166 [TOMOYO_MAC_CATEGORY_FILE] = "file",
167 [TOMOYO_MAC_CATEGORY_NETWORK] = "network",
168 [TOMOYO_MAC_CATEGORY_MISC] = "misc",
137}; 169};
138 170
139/* Permit policy management by non-root user? */ 171/* Permit policy management by non-root user? */
@@ -230,13 +262,17 @@ static void tomoyo_set_string(struct tomoyo_io_buffer *head, const char *string)
230 WARN_ON(1); 262 WARN_ON(1);
231} 263}
232 264
265static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt,
266 ...) __printf(2, 3);
267
233/** 268/**
234 * tomoyo_io_printf - printf() to "struct tomoyo_io_buffer" structure. 269 * tomoyo_io_printf - printf() to "struct tomoyo_io_buffer" structure.
235 * 270 *
236 * @head: Pointer to "struct tomoyo_io_buffer". 271 * @head: Pointer to "struct tomoyo_io_buffer".
237 * @fmt: The printf()'s format string, followed by parameters. 272 * @fmt: The printf()'s format string, followed by parameters.
238 */ 273 */
239void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 274static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt,
275 ...)
240{ 276{
241 va_list args; 277 va_list args;
242 size_t len; 278 size_t len;
@@ -313,7 +349,7 @@ void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns)
313 INIT_LIST_HEAD(&ns->group_list[idx]); 349 INIT_LIST_HEAD(&ns->group_list[idx]);
314 for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) 350 for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++)
315 INIT_LIST_HEAD(&ns->policy_list[idx]); 351 INIT_LIST_HEAD(&ns->policy_list[idx]);
316 ns->profile_version = 20100903; 352 ns->profile_version = 20110903;
317 tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list); 353 tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list);
318 list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list); 354 list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list);
319} 355}
@@ -466,8 +502,10 @@ static struct tomoyo_profile *tomoyo_assign_profile
466 TOMOYO_CONFIG_WANT_REJECT_LOG; 502 TOMOYO_CONFIG_WANT_REJECT_LOG;
467 memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, 503 memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
468 sizeof(ptr->config)); 504 sizeof(ptr->config));
469 ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] = 1024; 505 ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] =
470 ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048; 506 CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG;
507 ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] =
508 CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY;
471 mb(); /* Avoid out-of-order execution. */ 509 mb(); /* Avoid out-of-order execution. */
472 ns->profile_ptr[profile] = ptr; 510 ns->profile_ptr[profile] = ptr;
473 entry = NULL; 511 entry = NULL;
@@ -951,14 +989,12 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
951 (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { 989 (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
952 struct task_struct *p; 990 struct task_struct *p;
953 rcu_read_lock(); 991 rcu_read_lock();
954 read_lock(&tasklist_lock);
955 if (global_pid) 992 if (global_pid)
956 p = find_task_by_pid_ns(pid, &init_pid_ns); 993 p = find_task_by_pid_ns(pid, &init_pid_ns);
957 else 994 else
958 p = find_task_by_vpid(pid); 995 p = find_task_by_vpid(pid);
959 if (p) 996 if (p)
960 domain = tomoyo_real_domain(p); 997 domain = tomoyo_real_domain(p);
961 read_unlock(&tasklist_lock);
962 rcu_read_unlock(); 998 rcu_read_unlock();
963 } else if (!strncmp(data, "domain=", 7)) { 999 } else if (!strncmp(data, "domain=", 7)) {
964 if (tomoyo_domain_def(data + 7)) 1000 if (tomoyo_domain_def(data + 7))
@@ -982,6 +1018,48 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
982} 1018}
983 1019
984/** 1020/**
1021 * tomoyo_same_task_acl - Check for duplicated "struct tomoyo_task_acl" entry.
1022 *
1023 * @a: Pointer to "struct tomoyo_acl_info".
1024 * @b: Pointer to "struct tomoyo_acl_info".
1025 *
1026 * Returns true if @a == @b, false otherwise.
1027 */
1028static bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a,
1029 const struct tomoyo_acl_info *b)
1030{
1031 const struct tomoyo_task_acl *p1 = container_of(a, typeof(*p1), head);
1032 const struct tomoyo_task_acl *p2 = container_of(b, typeof(*p2), head);
1033 return p1->domainname == p2->domainname;
1034}
1035
1036/**
1037 * tomoyo_write_task - Update task related list.
1038 *
1039 * @param: Pointer to "struct tomoyo_acl_param".
1040 *
1041 * Returns 0 on success, negative value otherwise.
1042 *
1043 * Caller holds tomoyo_read_lock().
1044 */
1045static int tomoyo_write_task(struct tomoyo_acl_param *param)
1046{
1047 int error = -EINVAL;
1048 if (tomoyo_str_starts(&param->data, "manual_domain_transition ")) {
1049 struct tomoyo_task_acl e = {
1050 .head.type = TOMOYO_TYPE_MANUAL_TASK_ACL,
1051 .domainname = tomoyo_get_domainname(param),
1052 };
1053 if (e.domainname)
1054 error = tomoyo_update_domain(&e.head, sizeof(e), param,
1055 tomoyo_same_task_acl,
1056 NULL);
1057 tomoyo_put_name(e.domainname);
1058 }
1059 return error;
1060}
1061
1062/**
985 * tomoyo_delete_domain - Delete a domain. 1063 * tomoyo_delete_domain - Delete a domain.
986 * 1064 *
987 * @domainname: The name of domain. 1065 * @domainname: The name of domain.
@@ -1039,11 +1117,16 @@ static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns,
1039 static const struct { 1117 static const struct {
1040 const char *keyword; 1118 const char *keyword;
1041 int (*write) (struct tomoyo_acl_param *); 1119 int (*write) (struct tomoyo_acl_param *);
1042 } tomoyo_callback[1] = { 1120 } tomoyo_callback[5] = {
1043 { "file ", tomoyo_write_file }, 1121 { "file ", tomoyo_write_file },
1122 { "network inet ", tomoyo_write_inet_network },
1123 { "network unix ", tomoyo_write_unix_network },
1124 { "misc ", tomoyo_write_misc },
1125 { "task ", tomoyo_write_task },
1044 }; 1126 };
1045 u8 i; 1127 u8 i;
1046 for (i = 0; i < 1; i++) { 1128
1129 for (i = 0; i < ARRAY_SIZE(tomoyo_callback); i++) {
1047 if (!tomoyo_str_starts(&param.data, 1130 if (!tomoyo_str_starts(&param.data,
1048 tomoyo_callback[i].keyword)) 1131 tomoyo_callback[i].keyword))
1049 continue; 1132 continue;
@@ -1127,6 +1210,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
1127 case 0: 1210 case 0:
1128 head->r.cond_index = 0; 1211 head->r.cond_index = 0;
1129 head->r.cond_step++; 1212 head->r.cond_step++;
1213 if (cond->transit) {
1214 tomoyo_set_space(head);
1215 tomoyo_set_string(head, cond->transit->name);
1216 }
1130 /* fall through */ 1217 /* fall through */
1131 case 1: 1218 case 1:
1132 { 1219 {
@@ -1239,6 +1326,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
1239 head->r.cond_step++; 1326 head->r.cond_step++;
1240 /* fall through */ 1327 /* fall through */
1241 case 3: 1328 case 3:
1329 if (cond->grant_log != TOMOYO_GRANTLOG_AUTO)
1330 tomoyo_io_printf(head, " grant_log=%s",
1331 tomoyo_yesno(cond->grant_log ==
1332 TOMOYO_GRANTLOG_YES));
1242 tomoyo_set_lf(head); 1333 tomoyo_set_lf(head);
1243 return true; 1334 return true;
1244 } 1335 }
@@ -1306,6 +1397,12 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1306 if (first) 1397 if (first)
1307 return true; 1398 return true;
1308 tomoyo_print_name_union(head, &ptr->name); 1399 tomoyo_print_name_union(head, &ptr->name);
1400 } else if (acl_type == TOMOYO_TYPE_MANUAL_TASK_ACL) {
1401 struct tomoyo_task_acl *ptr =
1402 container_of(acl, typeof(*ptr), head);
1403 tomoyo_set_group(head, "task ");
1404 tomoyo_set_string(head, "manual_domain_transition ");
1405 tomoyo_set_string(head, ptr->domainname->name);
1309 } else if (head->r.print_transition_related_only) { 1406 } else if (head->r.print_transition_related_only) {
1310 return true; 1407 return true;
1311 } else if (acl_type == TOMOYO_TYPE_PATH2_ACL) { 1408 } else if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
@@ -1370,6 +1467,60 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1370 tomoyo_print_number_union(head, &ptr->mode); 1467 tomoyo_print_number_union(head, &ptr->mode);
1371 tomoyo_print_number_union(head, &ptr->major); 1468 tomoyo_print_number_union(head, &ptr->major);
1372 tomoyo_print_number_union(head, &ptr->minor); 1469 tomoyo_print_number_union(head, &ptr->minor);
1470 } else if (acl_type == TOMOYO_TYPE_INET_ACL) {
1471 struct tomoyo_inet_acl *ptr =
1472 container_of(acl, typeof(*ptr), head);
1473 const u8 perm = ptr->perm;
1474
1475 for (bit = 0; bit < TOMOYO_MAX_NETWORK_OPERATION; bit++) {
1476 if (!(perm & (1 << bit)))
1477 continue;
1478 if (first) {
1479 tomoyo_set_group(head, "network inet ");
1480 tomoyo_set_string(head, tomoyo_proto_keyword
1481 [ptr->protocol]);
1482 tomoyo_set_space(head);
1483 first = false;
1484 } else {
1485 tomoyo_set_slash(head);
1486 }
1487 tomoyo_set_string(head, tomoyo_socket_keyword[bit]);
1488 }
1489 if (first)
1490 return true;
1491 tomoyo_set_space(head);
1492 if (ptr->address.group) {
1493 tomoyo_set_string(head, "@");
1494 tomoyo_set_string(head, ptr->address.group->group_name
1495 ->name);
1496 } else {
1497 char buf[128];
1498 tomoyo_print_ip(buf, sizeof(buf), &ptr->address);
1499 tomoyo_io_printf(head, "%s", buf);
1500 }
1501 tomoyo_print_number_union(head, &ptr->port);
1502 } else if (acl_type == TOMOYO_TYPE_UNIX_ACL) {
1503 struct tomoyo_unix_acl *ptr =
1504 container_of(acl, typeof(*ptr), head);
1505 const u8 perm = ptr->perm;
1506
1507 for (bit = 0; bit < TOMOYO_MAX_NETWORK_OPERATION; bit++) {
1508 if (!(perm & (1 << bit)))
1509 continue;
1510 if (first) {
1511 tomoyo_set_group(head, "network unix ");
1512 tomoyo_set_string(head, tomoyo_proto_keyword
1513 [ptr->protocol]);
1514 tomoyo_set_space(head);
1515 first = false;
1516 } else {
1517 tomoyo_set_slash(head);
1518 }
1519 tomoyo_set_string(head, tomoyo_socket_keyword[bit]);
1520 }
1521 if (first)
1522 return true;
1523 tomoyo_print_name_union(head, &ptr->name);
1373 } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { 1524 } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) {
1374 struct tomoyo_mount_acl *ptr = 1525 struct tomoyo_mount_acl *ptr =
1375 container_of(acl, typeof(*ptr), head); 1526 container_of(acl, typeof(*ptr), head);
@@ -1378,6 +1529,12 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1378 tomoyo_print_name_union(head, &ptr->dir_name); 1529 tomoyo_print_name_union(head, &ptr->dir_name);
1379 tomoyo_print_name_union(head, &ptr->fs_type); 1530 tomoyo_print_name_union(head, &ptr->fs_type);
1380 tomoyo_print_number_union(head, &ptr->flags); 1531 tomoyo_print_number_union(head, &ptr->flags);
1532 } else if (acl_type == TOMOYO_TYPE_ENV_ACL) {
1533 struct tomoyo_env_acl *ptr =
1534 container_of(acl, typeof(*ptr), head);
1535
1536 tomoyo_set_group(head, "misc env ");
1537 tomoyo_set_string(head, ptr->env->name);
1381 } 1538 }
1382 if (acl->cond) { 1539 if (acl->cond) {
1383 head->r.print_cond_part = true; 1540 head->r.print_cond_part = true;
@@ -1510,14 +1667,12 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
1510 global_pid = true; 1667 global_pid = true;
1511 pid = (unsigned int) simple_strtoul(buf, NULL, 10); 1668 pid = (unsigned int) simple_strtoul(buf, NULL, 10);
1512 rcu_read_lock(); 1669 rcu_read_lock();
1513 read_lock(&tasklist_lock);
1514 if (global_pid) 1670 if (global_pid)
1515 p = find_task_by_pid_ns(pid, &init_pid_ns); 1671 p = find_task_by_pid_ns(pid, &init_pid_ns);
1516 else 1672 else
1517 p = find_task_by_vpid(pid); 1673 p = find_task_by_vpid(pid);
1518 if (p) 1674 if (p)
1519 domain = tomoyo_real_domain(p); 1675 domain = tomoyo_real_domain(p);
1520 read_unlock(&tasklist_lock);
1521 rcu_read_unlock(); 1676 rcu_read_unlock();
1522 if (!domain) 1677 if (!domain)
1523 return; 1678 return;
@@ -1537,8 +1692,9 @@ static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = {
1537 1692
1538/* String table for grouping keywords. */ 1693/* String table for grouping keywords. */
1539static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { 1694static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = {
1540 [TOMOYO_PATH_GROUP] = "path_group ", 1695 [TOMOYO_PATH_GROUP] = "path_group ",
1541 [TOMOYO_NUMBER_GROUP] = "number_group ", 1696 [TOMOYO_NUMBER_GROUP] = "number_group ",
1697 [TOMOYO_ADDRESS_GROUP] = "address_group ",
1542}; 1698};
1543 1699
1544/** 1700/**
@@ -1580,7 +1736,7 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
1580} 1736}
1581 1737
1582/** 1738/**
1583 * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group" list. 1739 * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list.
1584 * 1740 *
1585 * @head: Pointer to "struct tomoyo_io_buffer". 1741 * @head: Pointer to "struct tomoyo_io_buffer".
1586 * @idx: Index number. 1742 * @idx: Index number.
@@ -1617,6 +1773,15 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
1617 (ptr, 1773 (ptr,
1618 struct tomoyo_number_group, 1774 struct tomoyo_number_group,
1619 head)->number); 1775 head)->number);
1776 } else if (idx == TOMOYO_ADDRESS_GROUP) {
1777 char buffer[128];
1778
1779 struct tomoyo_address_group *member =
1780 container_of(ptr, typeof(*member),
1781 head);
1782 tomoyo_print_ip(buffer, sizeof(buffer),
1783 &member->address);
1784 tomoyo_io_printf(head, " %s", buffer);
1620 } 1785 }
1621 tomoyo_set_lf(head); 1786 tomoyo_set_lf(head);
1622 } 1787 }
@@ -2066,27 +2231,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
2066static void tomoyo_read_version(struct tomoyo_io_buffer *head) 2231static void tomoyo_read_version(struct tomoyo_io_buffer *head)
2067{ 2232{
2068 if (!head->r.eof) { 2233 if (!head->r.eof) {
2069 tomoyo_io_printf(head, "2.4.0"); 2234 tomoyo_io_printf(head, "2.5.0");
2070 head->r.eof = true;
2071 }
2072}
2073
2074/**
2075 * tomoyo_read_self_domain - Get the current process's domainname.
2076 *
2077 * @head: Pointer to "struct tomoyo_io_buffer".
2078 *
2079 * Returns the current process's domainname.
2080 */
2081static void tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
2082{
2083 if (!head->r.eof) {
2084 /*
2085 * tomoyo_domain()->domainname != NULL
2086 * because every process belongs to a domain and
2087 * the domain's name cannot be NULL.
2088 */
2089 tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name);
2090 head->r.eof = true; 2235 head->r.eof = true;
2091 } 2236 }
2092} 2237}
@@ -2221,10 +2366,6 @@ int tomoyo_open_control(const u8 type, struct file *file)
2221 head->poll = tomoyo_poll_log; 2366 head->poll = tomoyo_poll_log;
2222 head->read = tomoyo_read_log; 2367 head->read = tomoyo_read_log;
2223 break; 2368 break;
2224 case TOMOYO_SELFDOMAIN:
2225 /* /sys/kernel/security/tomoyo/self_domain */
2226 head->read = tomoyo_read_self_domain;
2227 break;
2228 case TOMOYO_PROCESS_STATUS: 2369 case TOMOYO_PROCESS_STATUS:
2229 /* /sys/kernel/security/tomoyo/.process_status */ 2370 /* /sys/kernel/security/tomoyo/.process_status */
2230 head->write = tomoyo_write_pid; 2371 head->write = tomoyo_write_pid;
@@ -2453,6 +2594,7 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head,
2453 return -EFAULT; 2594 return -EFAULT;
2454 if (mutex_lock_interruptible(&head->io_sem)) 2595 if (mutex_lock_interruptible(&head->io_sem))
2455 return -EINTR; 2596 return -EINTR;
2597 head->read_user_buf_avail = 0;
2456 idx = tomoyo_read_lock(); 2598 idx = tomoyo_read_lock();
2457 /* Read a line and dispatch it to the policy handler. */ 2599 /* Read a line and dispatch it to the policy handler. */
2458 while (avail_len > 0) { 2600 while (avail_len > 0) {
@@ -2562,11 +2704,11 @@ void tomoyo_check_profile(void)
2562 struct tomoyo_domain_info *domain; 2704 struct tomoyo_domain_info *domain;
2563 const int idx = tomoyo_read_lock(); 2705 const int idx = tomoyo_read_lock();
2564 tomoyo_policy_loaded = true; 2706 tomoyo_policy_loaded = true;
2565 printk(KERN_INFO "TOMOYO: 2.4.0\n"); 2707 printk(KERN_INFO "TOMOYO: 2.5.0\n");
2566 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 2708 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
2567 const u8 profile = domain->profile; 2709 const u8 profile = domain->profile;
2568 const struct tomoyo_policy_namespace *ns = domain->ns; 2710 const struct tomoyo_policy_namespace *ns = domain->ns;
2569 if (ns->profile_version != 20100903) 2711 if (ns->profile_version != 20110903)
2570 printk(KERN_ERR 2712 printk(KERN_ERR
2571 "Profile version %u is not supported.\n", 2713 "Profile version %u is not supported.\n",
2572 ns->profile_version); 2714 ns->profile_version);
@@ -2577,9 +2719,9 @@ void tomoyo_check_profile(void)
2577 else 2719 else
2578 continue; 2720 continue;
2579 printk(KERN_ERR 2721 printk(KERN_ERR
2580 "Userland tools for TOMOYO 2.4 must be installed and " 2722 "Userland tools for TOMOYO 2.5 must be installed and "
2581 "policy must be initialized.\n"); 2723 "policy must be initialized.\n");
2582 printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.4/ " 2724 printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.5/ "
2583 "for more information.\n"); 2725 "for more information.\n");
2584 panic("STOP!"); 2726 panic("STOP!");
2585 } 2727 }
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index f7fbaa66e443..ed311d7a8ce0 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -3,7 +3,7 @@
3 * 3 *
4 * Header file for TOMOYO. 4 * Header file for TOMOYO.
5 * 5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION 6 * Copyright (C) 2005-2011 NTT DATA CORPORATION
7 */ 7 */
8 8
9#ifndef _SECURITY_TOMOYO_COMMON_H 9#ifndef _SECURITY_TOMOYO_COMMON_H
@@ -23,6 +23,16 @@
23#include <linux/poll.h> 23#include <linux/poll.h>
24#include <linux/binfmts.h> 24#include <linux/binfmts.h>
25#include <linux/highmem.h> 25#include <linux/highmem.h>
26#include <linux/net.h>
27#include <linux/inet.h>
28#include <linux/in.h>
29#include <linux/in6.h>
30#include <linux/un.h>
31#include <net/sock.h>
32#include <net/af_unix.h>
33#include <net/ip.h>
34#include <net/ipv6.h>
35#include <net/udp.h>
26 36
27/********** Constants definitions. **********/ 37/********** Constants definitions. **********/
28 38
@@ -34,8 +44,17 @@
34#define TOMOYO_HASH_BITS 8 44#define TOMOYO_HASH_BITS 8
35#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) 45#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
36 46
47/*
48 * TOMOYO checks only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET.
49 * Therefore, we don't need SOCK_MAX.
50 */
51#define TOMOYO_SOCK_MAX 6
52
37#define TOMOYO_EXEC_TMPSIZE 4096 53#define TOMOYO_EXEC_TMPSIZE 4096
38 54
55/* Garbage collector is trying to kfree() this element. */
56#define TOMOYO_GC_IN_PROGRESS -1
57
39/* Profile number is an integer between 0 and 255. */ 58/* Profile number is an integer between 0 and 255. */
40#define TOMOYO_MAX_PROFILES 256 59#define TOMOYO_MAX_PROFILES 256
41 60
@@ -136,6 +155,7 @@ enum tomoyo_mode_index {
136/* Index numbers for entry type. */ 155/* Index numbers for entry type. */
137enum tomoyo_policy_id { 156enum tomoyo_policy_id {
138 TOMOYO_ID_GROUP, 157 TOMOYO_ID_GROUP,
158 TOMOYO_ID_ADDRESS_GROUP,
139 TOMOYO_ID_PATH_GROUP, 159 TOMOYO_ID_PATH_GROUP,
140 TOMOYO_ID_NUMBER_GROUP, 160 TOMOYO_ID_NUMBER_GROUP,
141 TOMOYO_ID_TRANSITION_CONTROL, 161 TOMOYO_ID_TRANSITION_CONTROL,
@@ -162,10 +182,21 @@ enum tomoyo_domain_info_flags_index {
162 TOMOYO_MAX_DOMAIN_INFO_FLAGS 182 TOMOYO_MAX_DOMAIN_INFO_FLAGS
163}; 183};
164 184
185/* Index numbers for audit type. */
186enum tomoyo_grant_log {
187 /* Follow profile's configuration. */
188 TOMOYO_GRANTLOG_AUTO,
189 /* Do not generate grant log. */
190 TOMOYO_GRANTLOG_NO,
191 /* Generate grant_log. */
192 TOMOYO_GRANTLOG_YES,
193};
194
165/* Index numbers for group entries. */ 195/* Index numbers for group entries. */
166enum tomoyo_group_id { 196enum tomoyo_group_id {
167 TOMOYO_PATH_GROUP, 197 TOMOYO_PATH_GROUP,
168 TOMOYO_NUMBER_GROUP, 198 TOMOYO_NUMBER_GROUP,
199 TOMOYO_ADDRESS_GROUP,
169 TOMOYO_MAX_GROUP 200 TOMOYO_MAX_GROUP
170}; 201};
171 202
@@ -196,6 +227,10 @@ enum tomoyo_acl_entry_type_index {
196 TOMOYO_TYPE_PATH_NUMBER_ACL, 227 TOMOYO_TYPE_PATH_NUMBER_ACL,
197 TOMOYO_TYPE_MKDEV_ACL, 228 TOMOYO_TYPE_MKDEV_ACL,
198 TOMOYO_TYPE_MOUNT_ACL, 229 TOMOYO_TYPE_MOUNT_ACL,
230 TOMOYO_TYPE_INET_ACL,
231 TOMOYO_TYPE_UNIX_ACL,
232 TOMOYO_TYPE_ENV_ACL,
233 TOMOYO_TYPE_MANUAL_TASK_ACL,
199}; 234};
200 235
201/* Index numbers for access controls with one pathname. */ 236/* Index numbers for access controls with one pathname. */
@@ -228,6 +263,15 @@ enum tomoyo_mkdev_acl_index {
228 TOMOYO_MAX_MKDEV_OPERATION 263 TOMOYO_MAX_MKDEV_OPERATION
229}; 264};
230 265
266/* Index numbers for socket operations. */
267enum tomoyo_network_acl_index {
268 TOMOYO_NETWORK_BIND, /* bind() operation. */
269 TOMOYO_NETWORK_LISTEN, /* listen() operation. */
270 TOMOYO_NETWORK_CONNECT, /* connect() operation. */
271 TOMOYO_NETWORK_SEND, /* send() operation. */
272 TOMOYO_MAX_NETWORK_OPERATION
273};
274
231/* Index numbers for access controls with two pathnames. */ 275/* Index numbers for access controls with two pathnames. */
232enum tomoyo_path2_acl_index { 276enum tomoyo_path2_acl_index {
233 TOMOYO_TYPE_LINK, 277 TOMOYO_TYPE_LINK,
@@ -255,7 +299,6 @@ enum tomoyo_securityfs_interface_index {
255 TOMOYO_EXCEPTIONPOLICY, 299 TOMOYO_EXCEPTIONPOLICY,
256 TOMOYO_PROCESS_STATUS, 300 TOMOYO_PROCESS_STATUS,
257 TOMOYO_STAT, 301 TOMOYO_STAT,
258 TOMOYO_SELFDOMAIN,
259 TOMOYO_AUDIT, 302 TOMOYO_AUDIT,
260 TOMOYO_VERSION, 303 TOMOYO_VERSION,
261 TOMOYO_PROFILE, 304 TOMOYO_PROFILE,
@@ -300,12 +343,30 @@ enum tomoyo_mac_index {
300 TOMOYO_MAC_FILE_MOUNT, 343 TOMOYO_MAC_FILE_MOUNT,
301 TOMOYO_MAC_FILE_UMOUNT, 344 TOMOYO_MAC_FILE_UMOUNT,
302 TOMOYO_MAC_FILE_PIVOT_ROOT, 345 TOMOYO_MAC_FILE_PIVOT_ROOT,
346 TOMOYO_MAC_NETWORK_INET_STREAM_BIND,
347 TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN,
348 TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT,
349 TOMOYO_MAC_NETWORK_INET_DGRAM_BIND,
350 TOMOYO_MAC_NETWORK_INET_DGRAM_SEND,
351 TOMOYO_MAC_NETWORK_INET_RAW_BIND,
352 TOMOYO_MAC_NETWORK_INET_RAW_SEND,
353 TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND,
354 TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN,
355 TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT,
356 TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND,
357 TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND,
358 TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND,
359 TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
360 TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
361 TOMOYO_MAC_ENVIRON,
303 TOMOYO_MAX_MAC_INDEX 362 TOMOYO_MAX_MAC_INDEX
304}; 363};
305 364
306/* Index numbers for category of functionality. */ 365/* Index numbers for category of functionality. */
307enum tomoyo_mac_category_index { 366enum tomoyo_mac_category_index {
308 TOMOYO_MAC_CATEGORY_FILE, 367 TOMOYO_MAC_CATEGORY_FILE,
368 TOMOYO_MAC_CATEGORY_NETWORK,
369 TOMOYO_MAC_CATEGORY_MISC,
309 TOMOYO_MAX_MAC_CATEGORY_INDEX 370 TOMOYO_MAX_MAC_CATEGORY_INDEX
310}; 371};
311 372
@@ -340,7 +401,7 @@ enum tomoyo_pref_index {
340/* Common header for holding ACL entries. */ 401/* Common header for holding ACL entries. */
341struct tomoyo_acl_head { 402struct tomoyo_acl_head {
342 struct list_head list; 403 struct list_head list;
343 bool is_deleted; 404 s8 is_deleted; /* true or false or TOMOYO_GC_IN_PROGRESS */
344} __packed; 405} __packed;
345 406
346/* Common header for shared entries. */ 407/* Common header for shared entries. */
@@ -397,13 +458,36 @@ struct tomoyo_request_info {
397 u8 operation; 458 u8 operation;
398 } path_number; 459 } path_number;
399 struct { 460 struct {
461 const struct tomoyo_path_info *name;
462 } environ;
463 struct {
464 const __be32 *address;
465 u16 port;
466 /* One of values smaller than TOMOYO_SOCK_MAX. */
467 u8 protocol;
468 /* One of values in "enum tomoyo_network_acl_index". */
469 u8 operation;
470 bool is_ipv6;
471 } inet_network;
472 struct {
473 const struct tomoyo_path_info *address;
474 /* One of values smaller than TOMOYO_SOCK_MAX. */
475 u8 protocol;
476 /* One of values in "enum tomoyo_network_acl_index". */
477 u8 operation;
478 } unix_network;
479 struct {
400 const struct tomoyo_path_info *type; 480 const struct tomoyo_path_info *type;
401 const struct tomoyo_path_info *dir; 481 const struct tomoyo_path_info *dir;
402 const struct tomoyo_path_info *dev; 482 const struct tomoyo_path_info *dev;
403 unsigned long flags; 483 unsigned long flags;
404 int need_dev; 484 int need_dev;
405 } mount; 485 } mount;
486 struct {
487 const struct tomoyo_path_info *domainname;
488 } task;
406 } param; 489 } param;
490 struct tomoyo_acl_info *matched_acl;
407 u8 param_type; 491 u8 param_type;
408 bool granted; 492 bool granted;
409 u8 retry; 493 u8 retry;
@@ -442,7 +526,14 @@ struct tomoyo_number_union {
442 u8 value_type[2]; 526 u8 value_type[2];
443}; 527};
444 528
445/* Structure for "path_group"/"number_group" directive. */ 529/* Structure for holding an IP address. */
530struct tomoyo_ipaddr_union {
531 struct in6_addr ip[2]; /* Big endian. */
532 struct tomoyo_group *group; /* Pointer to address group. */
533 bool is_ipv6; /* Valid only if @group == NULL. */
534};
535
536/* Structure for "path_group"/"number_group"/"address_group" directive. */
446struct tomoyo_group { 537struct tomoyo_group {
447 struct tomoyo_shared_acl_head head; 538 struct tomoyo_shared_acl_head head;
448 const struct tomoyo_path_info *group_name; 539 const struct tomoyo_path_info *group_name;
@@ -461,6 +552,13 @@ struct tomoyo_number_group {
461 struct tomoyo_number_union number; 552 struct tomoyo_number_union number;
462}; 553};
463 554
555/* Structure for "address_group" directive. */
556struct tomoyo_address_group {
557 struct tomoyo_acl_head head;
558 /* Structure for holding an IP address. */
559 struct tomoyo_ipaddr_union address;
560};
561
464/* Subset of "struct stat". Used by conditional ACL and audit logs. */ 562/* Subset of "struct stat". Used by conditional ACL and audit logs. */
465struct tomoyo_mini_stat { 563struct tomoyo_mini_stat {
466 uid_t uid; 564 uid_t uid;
@@ -520,6 +618,7 @@ struct tomoyo_execve {
520 struct tomoyo_request_info r; 618 struct tomoyo_request_info r;
521 struct tomoyo_obj_info obj; 619 struct tomoyo_obj_info obj;
522 struct linux_binprm *bprm; 620 struct linux_binprm *bprm;
621 const struct tomoyo_path_info *transition;
523 /* For dumping argv[] and envp[]. */ 622 /* For dumping argv[] and envp[]. */
524 struct tomoyo_page_dump dump; 623 struct tomoyo_page_dump dump;
525 /* For temporary use. */ 624 /* For temporary use. */
@@ -554,6 +653,8 @@ struct tomoyo_condition {
554 u16 names_count; /* Number of "struct tomoyo_name_union names". */ 653 u16 names_count; /* Number of "struct tomoyo_name_union names". */
555 u16 argc; /* Number of "struct tomoyo_argv". */ 654 u16 argc; /* Number of "struct tomoyo_argv". */
556 u16 envc; /* Number of "struct tomoyo_envp". */ 655 u16 envc; /* Number of "struct tomoyo_envp". */
656 u8 grant_log; /* One of values in "enum tomoyo_grant_log". */
657 const struct tomoyo_path_info *transit; /* Maybe NULL. */
557 /* 658 /*
558 * struct tomoyo_condition_element condition[condc]; 659 * struct tomoyo_condition_element condition[condc];
559 * struct tomoyo_number_union values[numbers_count]; 660 * struct tomoyo_number_union values[numbers_count];
@@ -567,7 +668,7 @@ struct tomoyo_condition {
567struct tomoyo_acl_info { 668struct tomoyo_acl_info {
568 struct list_head list; 669 struct list_head list;
569 struct tomoyo_condition *cond; /* Maybe NULL. */ 670 struct tomoyo_condition *cond; /* Maybe NULL. */
570 bool is_deleted; 671 s8 is_deleted; /* true or false or TOMOYO_GC_IN_PROGRESS */
571 u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */ 672 u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */
572} __packed; 673} __packed;
573 674
@@ -587,6 +688,15 @@ struct tomoyo_domain_info {
587}; 688};
588 689
589/* 690/*
691 * Structure for "task manual_domain_transition" directive.
692 */
693struct tomoyo_task_acl {
694 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MANUAL_TASK_ACL */
695 /* Pointer to domainname. */
696 const struct tomoyo_path_info *domainname;
697};
698
699/*
590 * Structure for "file execute", "file read", "file write", "file append", 700 * Structure for "file execute", "file read", "file write", "file append",
591 * "file unlink", "file getattr", "file rmdir", "file truncate", 701 * "file unlink", "file getattr", "file rmdir", "file truncate",
592 * "file symlink", "file chroot" and "file unmount" directive. 702 * "file symlink", "file chroot" and "file unmount" directive.
@@ -638,6 +748,29 @@ struct tomoyo_mount_acl {
638 struct tomoyo_number_union flags; 748 struct tomoyo_number_union flags;
639}; 749};
640 750
751/* Structure for "misc env" directive in domain policy. */
752struct tomoyo_env_acl {
753 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_ENV_ACL */
754 const struct tomoyo_path_info *env; /* environment variable */
755};
756
757/* Structure for "network inet" directive. */
758struct tomoyo_inet_acl {
759 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_INET_ACL */
760 u8 protocol;
761 u8 perm; /* Bitmask of values in "enum tomoyo_network_acl_index" */
762 struct tomoyo_ipaddr_union address;
763 struct tomoyo_number_union port;
764};
765
766/* Structure for "network unix" directive. */
767struct tomoyo_unix_acl {
768 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_UNIX_ACL */
769 u8 protocol;
770 u8 perm; /* Bitmask of values in "enum tomoyo_network_acl_index" */
771 struct tomoyo_name_union name;
772};
773
641/* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */ 774/* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */
642struct tomoyo_acl_param { 775struct tomoyo_acl_param {
643 char *data; 776 char *data;
@@ -773,7 +906,7 @@ struct tomoyo_policy_namespace {
773 struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS]; 906 struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS];
774 /* List for connecting to tomoyo_namespace_list list. */ 907 /* List for connecting to tomoyo_namespace_list list. */
775 struct list_head namespace_list; 908 struct list_head namespace_list;
776 /* Profile version. Currently only 20100903 is defined. */ 909 /* Profile version. Currently only 20110903 is defined. */
777 unsigned int profile_version; 910 unsigned int profile_version;
778 /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */ 911 /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */
779 const char *name; 912 const char *name;
@@ -781,6 +914,8 @@ struct tomoyo_policy_namespace {
781 914
782/********** Function prototypes. **********/ 915/********** Function prototypes. **********/
783 916
917bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address,
918 const struct tomoyo_group *group);
784bool tomoyo_compare_number_union(const unsigned long value, 919bool tomoyo_compare_number_union(const unsigned long value,
785 const struct tomoyo_number_union *ptr); 920 const struct tomoyo_number_union *ptr);
786bool tomoyo_condition(struct tomoyo_request_info *r, 921bool tomoyo_condition(struct tomoyo_request_info *r,
@@ -796,6 +931,8 @@ bool tomoyo_memory_ok(void *ptr);
796bool tomoyo_number_matches_group(const unsigned long min, 931bool tomoyo_number_matches_group(const unsigned long min,
797 const unsigned long max, 932 const unsigned long max,
798 const struct tomoyo_group *group); 933 const struct tomoyo_group *group);
934bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param,
935 struct tomoyo_ipaddr_union *ptr);
799bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, 936bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
800 struct tomoyo_name_union *ptr); 937 struct tomoyo_name_union *ptr);
801bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, 938bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
@@ -805,6 +942,7 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
805bool tomoyo_permstr(const char *string, const char *keyword); 942bool tomoyo_permstr(const char *string, const char *keyword);
806bool tomoyo_str_starts(char **src, const char *find); 943bool tomoyo_str_starts(char **src, const char *find);
807char *tomoyo_encode(const char *str); 944char *tomoyo_encode(const char *str);
945char *tomoyo_encode2(const char *str, int str_len);
808char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, 946char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
809 va_list args); 947 va_list args);
810char *tomoyo_read_token(struct tomoyo_acl_param *param); 948char *tomoyo_read_token(struct tomoyo_acl_param *param);
@@ -814,12 +952,17 @@ const char *tomoyo_get_exe(void);
814const char *tomoyo_yesno(const unsigned int value); 952const char *tomoyo_yesno(const unsigned int value);
815const struct tomoyo_path_info *tomoyo_compare_name_union 953const struct tomoyo_path_info *tomoyo_compare_name_union
816(const struct tomoyo_path_info *name, const struct tomoyo_name_union *ptr); 954(const struct tomoyo_path_info *name, const struct tomoyo_name_union *ptr);
955const struct tomoyo_path_info *tomoyo_get_domainname
956(struct tomoyo_acl_param *param);
817const struct tomoyo_path_info *tomoyo_get_name(const char *name); 957const struct tomoyo_path_info *tomoyo_get_name(const char *name);
818const struct tomoyo_path_info *tomoyo_path_matches_group 958const struct tomoyo_path_info *tomoyo_path_matches_group
819(const struct tomoyo_path_info *pathname, const struct tomoyo_group *group); 959(const struct tomoyo_path_info *pathname, const struct tomoyo_group *group);
820int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 960int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
821 struct path *path, const int flag); 961 struct path *path, const int flag);
822int tomoyo_close_control(struct tomoyo_io_buffer *head); 962int tomoyo_close_control(struct tomoyo_io_buffer *head);
963int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env);
964int tomoyo_execute_permission(struct tomoyo_request_info *r,
965 const struct tomoyo_path_info *filename);
823int tomoyo_find_next_domain(struct linux_binprm *bprm); 966int tomoyo_find_next_domain(struct linux_binprm *bprm);
824int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, 967int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
825 const u8 index); 968 const u8 index);
@@ -838,10 +981,15 @@ int tomoyo_path_number_perm(const u8 operation, struct path *path,
838 unsigned long number); 981 unsigned long number);
839int tomoyo_path_perm(const u8 operation, struct path *path, 982int tomoyo_path_perm(const u8 operation, struct path *path,
840 const char *target); 983 const char *target);
841int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
842 const struct tomoyo_path_info *filename);
843int tomoyo_poll_control(struct file *file, poll_table *wait); 984int tomoyo_poll_control(struct file *file, poll_table *wait);
844int tomoyo_poll_log(struct file *file, poll_table *wait); 985int tomoyo_poll_log(struct file *file, poll_table *wait);
986int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
987 int addr_len);
988int tomoyo_socket_connect_permission(struct socket *sock,
989 struct sockaddr *addr, int addr_len);
990int tomoyo_socket_listen_permission(struct socket *sock);
991int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
992 int size);
845int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) 993int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
846 __printf(2, 3); 994 __printf(2, 3);
847int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 995int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
@@ -860,8 +1008,11 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
860int tomoyo_write_aggregator(struct tomoyo_acl_param *param); 1008int tomoyo_write_aggregator(struct tomoyo_acl_param *param);
861int tomoyo_write_file(struct tomoyo_acl_param *param); 1009int tomoyo_write_file(struct tomoyo_acl_param *param);
862int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); 1010int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type);
1011int tomoyo_write_misc(struct tomoyo_acl_param *param);
1012int tomoyo_write_inet_network(struct tomoyo_acl_param *param);
863int tomoyo_write_transition_control(struct tomoyo_acl_param *param, 1013int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
864 const u8 type); 1014 const u8 type);
1015int tomoyo_write_unix_network(struct tomoyo_acl_param *param);
865ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, 1016ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
866 const int buffer_len); 1017 const int buffer_len);
867ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, 1018ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head,
@@ -891,12 +1042,11 @@ void tomoyo_del_condition(struct list_head *element);
891void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); 1042void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
892void tomoyo_get_attributes(struct tomoyo_obj_info *obj); 1043void tomoyo_get_attributes(struct tomoyo_obj_info *obj);
893void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns); 1044void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns);
894void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
895 __printf(2, 3);
896void tomoyo_load_policy(const char *filename); 1045void tomoyo_load_policy(const char *filename);
897void tomoyo_memory_free(void *ptr);
898void tomoyo_normalize_line(unsigned char *buffer); 1046void tomoyo_normalize_line(unsigned char *buffer);
899void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register); 1047void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register);
1048void tomoyo_print_ip(char *buf, const unsigned int size,
1049 const struct tomoyo_ipaddr_union *ptr);
900void tomoyo_print_ulong(char *buffer, const int buffer_len, 1050void tomoyo_print_ulong(char *buffer, const int buffer_len,
901 const unsigned long value, const u8 type); 1051 const unsigned long value, const u8 type);
902void tomoyo_put_name_union(struct tomoyo_name_union *ptr); 1052void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
@@ -919,6 +1069,8 @@ extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
919 + TOMOYO_MAX_MAC_CATEGORY_INDEX]; 1069 + TOMOYO_MAX_MAC_CATEGORY_INDEX];
920extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE]; 1070extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE];
921extern const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION]; 1071extern const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION];
1072extern const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX];
1073extern const char * const tomoyo_socket_keyword[TOMOYO_MAX_NETWORK_OPERATION];
922extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX]; 1074extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX];
923extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; 1075extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION];
924extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; 1076extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION];
@@ -1098,6 +1250,21 @@ static inline bool tomoyo_same_number_union
1098} 1250}
1099 1251
1100/** 1252/**
1253 * tomoyo_same_ipaddr_union - Check for duplicated "struct tomoyo_ipaddr_union" entry.
1254 *
1255 * @a: Pointer to "struct tomoyo_ipaddr_union".
1256 * @b: Pointer to "struct tomoyo_ipaddr_union".
1257 *
1258 * Returns true if @a == @b, false otherwise.
1259 */
1260static inline bool tomoyo_same_ipaddr_union
1261(const struct tomoyo_ipaddr_union *a, const struct tomoyo_ipaddr_union *b)
1262{
1263 return !memcmp(a->ip, b->ip, sizeof(a->ip)) && a->group == b->group &&
1264 a->is_ipv6 == b->is_ipv6;
1265}
1266
1267/**
1101 * tomoyo_current_namespace - Get "struct tomoyo_policy_namespace" for current thread. 1268 * tomoyo_current_namespace - Get "struct tomoyo_policy_namespace" for current thread.
1102 * 1269 *
1103 * Returns pointer to "struct tomoyo_policy_namespace" for current thread. 1270 * Returns pointer to "struct tomoyo_policy_namespace" for current thread.
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 */
439static 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));
461done:
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;
449rerun: 491rerun:
@@ -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 }
681out2:
682 tomoyo_put_name(e.transit);
624 return NULL; 683 return NULL;
625} 684}
626 685
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index cd0f92d88bb4..9027ac1534af 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -39,6 +39,8 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
39 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 39 if (mutex_lock_interruptible(&tomoyo_policy_lock))
40 return -ENOMEM; 40 return -ENOMEM;
41 list_for_each_entry_rcu(entry, list, list) { 41 list_for_each_entry_rcu(entry, list, list) {
42 if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS)
43 continue;
42 if (!check_duplicate(entry, new_entry)) 44 if (!check_duplicate(entry, new_entry))
43 continue; 45 continue;
44 entry->is_deleted = param->is_delete; 46 entry->is_deleted = param->is_delete;
@@ -102,10 +104,21 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
102 new_entry->cond = tomoyo_get_condition(param); 104 new_entry->cond = tomoyo_get_condition(param);
103 if (!new_entry->cond) 105 if (!new_entry->cond)
104 return -EINVAL; 106 return -EINVAL;
107 /*
108 * Domain transition preference is allowed for only
109 * "file execute" entries.
110 */
111 if (new_entry->cond->transit &&
112 !(new_entry->type == TOMOYO_TYPE_PATH_ACL &&
113 container_of(new_entry, struct tomoyo_path_acl, head)
114 ->perm == 1 << TOMOYO_TYPE_EXECUTE))
115 goto out;
105 } 116 }
106 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 117 if (mutex_lock_interruptible(&tomoyo_policy_lock))
107 goto out; 118 goto out;
108 list_for_each_entry_rcu(entry, list, list) { 119 list_for_each_entry_rcu(entry, list, list) {
120 if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS)
121 continue;
109 if (!tomoyo_same_acl_head(entry, new_entry) || 122 if (!tomoyo_same_acl_head(entry, new_entry) ||
110 !check_duplicate(entry, new_entry)) 123 !check_duplicate(entry, new_entry))
111 continue; 124 continue;
@@ -157,6 +170,7 @@ retry:
157 continue; 170 continue;
158 if (!tomoyo_condition(r, ptr->cond)) 171 if (!tomoyo_condition(r, ptr->cond))
159 continue; 172 continue;
173 r->matched_acl = ptr;
160 r->granted = true; 174 r->granted = true;
161 return; 175 return;
162 } 176 }
@@ -501,7 +515,8 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
501 * that domain. Do not perform domain transition if 515 * that domain. Do not perform domain transition if
502 * profile for that domain is not yet created. 516 * profile for that domain is not yet created.
503 */ 517 */
504 if (!entry->ns->profile_ptr[entry->profile]) 518 if (tomoyo_policy_loaded &&
519 !entry->ns->profile_ptr[entry->profile])
505 return NULL; 520 return NULL;
506 } 521 }
507 return entry; 522 return entry;
@@ -557,12 +572,99 @@ out:
557 tomoyo_write_log(&r, "use_profile %u\n", 572 tomoyo_write_log(&r, "use_profile %u\n",
558 entry->profile); 573 entry->profile);
559 tomoyo_write_log(&r, "use_group %u\n", entry->group); 574 tomoyo_write_log(&r, "use_group %u\n", entry->group);
575 tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES);
560 } 576 }
561 } 577 }
562 return entry; 578 return entry;
563} 579}
564 580
565/** 581/**
582 * tomoyo_environ - Check permission for environment variable names.
583 *
584 * @ee: Pointer to "struct tomoyo_execve".
585 *
586 * Returns 0 on success, negative value otherwise.
587 */
588static int tomoyo_environ(struct tomoyo_execve *ee)
589{
590 struct tomoyo_request_info *r = &ee->r;
591 struct linux_binprm *bprm = ee->bprm;
592 /* env_page.data is allocated by tomoyo_dump_page(). */
593 struct tomoyo_page_dump env_page = { };
594 char *arg_ptr; /* Size is TOMOYO_EXEC_TMPSIZE bytes */
595 int arg_len = 0;
596 unsigned long pos = bprm->p;
597 int offset = pos % PAGE_SIZE;
598 int argv_count = bprm->argc;
599 int envp_count = bprm->envc;
600 int error = -ENOMEM;
601
602 ee->r.type = TOMOYO_MAC_ENVIRON;
603 ee->r.profile = r->domain->profile;
604 ee->r.mode = tomoyo_get_mode(r->domain->ns, ee->r.profile,
605 TOMOYO_MAC_ENVIRON);
606 if (!r->mode || !envp_count)
607 return 0;
608 arg_ptr = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
609 if (!arg_ptr)
610 goto out;
611 while (error == -ENOMEM) {
612 if (!tomoyo_dump_page(bprm, pos, &env_page))
613 goto out;
614 pos += PAGE_SIZE - offset;
615 /* Read. */
616 while (argv_count && offset < PAGE_SIZE) {
617 if (!env_page.data[offset++])
618 argv_count--;
619 }
620 if (argv_count) {
621 offset = 0;
622 continue;
623 }
624 while (offset < PAGE_SIZE) {
625 const unsigned char c = env_page.data[offset++];
626
627 if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
628 if (c == '=') {
629 arg_ptr[arg_len++] = '\0';
630 } else if (c == '\\') {
631 arg_ptr[arg_len++] = '\\';
632 arg_ptr[arg_len++] = '\\';
633 } else if (c > ' ' && c < 127) {
634 arg_ptr[arg_len++] = c;
635 } else {
636 arg_ptr[arg_len++] = '\\';
637 arg_ptr[arg_len++] = (c >> 6) + '0';
638 arg_ptr[arg_len++]
639 = ((c >> 3) & 7) + '0';
640 arg_ptr[arg_len++] = (c & 7) + '0';
641 }
642 } else {
643 arg_ptr[arg_len] = '\0';
644 }
645 if (c)
646 continue;
647 if (tomoyo_env_perm(r, arg_ptr)) {
648 error = -EPERM;
649 break;
650 }
651 if (!--envp_count) {
652 error = 0;
653 break;
654 }
655 arg_len = 0;
656 }
657 offset = 0;
658 }
659out:
660 if (r->mode != TOMOYO_CONFIG_ENFORCING)
661 error = 0;
662 kfree(env_page.data);
663 kfree(arg_ptr);
664 return error;
665}
666
667/**
566 * tomoyo_find_next_domain - Find a domain. 668 * tomoyo_find_next_domain - Find a domain.
567 * 669 *
568 * @bprm: Pointer to "struct linux_binprm". 670 * @bprm: Pointer to "struct linux_binprm".
@@ -577,10 +679,11 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
577 struct tomoyo_domain_info *domain = NULL; 679 struct tomoyo_domain_info *domain = NULL;
578 const char *original_name = bprm->filename; 680 const char *original_name = bprm->filename;
579 int retval = -ENOMEM; 681 int retval = -ENOMEM;
580 bool need_kfree = false;
581 bool reject_on_transition_failure = false; 682 bool reject_on_transition_failure = false;
582 struct tomoyo_path_info rn = { }; /* real name */ 683 const struct tomoyo_path_info *candidate;
684 struct tomoyo_path_info exename;
583 struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS); 685 struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS);
686
584 if (!ee) 687 if (!ee)
585 return -ENOMEM; 688 return -ENOMEM;
586 ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); 689 ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
@@ -594,40 +697,32 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
594 ee->bprm = bprm; 697 ee->bprm = bprm;
595 ee->r.obj = &ee->obj; 698 ee->r.obj = &ee->obj;
596 ee->obj.path1 = bprm->file->f_path; 699 ee->obj.path1 = bprm->file->f_path;
597 retry:
598 if (need_kfree) {
599 kfree(rn.name);
600 need_kfree = false;
601 }
602 /* Get symlink's pathname of program. */ 700 /* Get symlink's pathname of program. */
603 retval = -ENOENT; 701 retval = -ENOENT;
604 rn.name = tomoyo_realpath_nofollow(original_name); 702 exename.name = tomoyo_realpath_nofollow(original_name);
605 if (!rn.name) 703 if (!exename.name)
606 goto out; 704 goto out;
607 tomoyo_fill_path_info(&rn); 705 tomoyo_fill_path_info(&exename);
608 need_kfree = true; 706retry:
609
610 /* Check 'aggregator' directive. */ 707 /* Check 'aggregator' directive. */
611 { 708 {
612 struct tomoyo_aggregator *ptr; 709 struct tomoyo_aggregator *ptr;
613 struct list_head *list = 710 struct list_head *list =
614 &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; 711 &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR];
615 /* Check 'aggregator' directive. */ 712 /* Check 'aggregator' directive. */
713 candidate = &exename;
616 list_for_each_entry_rcu(ptr, list, head.list) { 714 list_for_each_entry_rcu(ptr, list, head.list) {
617 if (ptr->head.is_deleted || 715 if (ptr->head.is_deleted ||
618 !tomoyo_path_matches_pattern(&rn, 716 !tomoyo_path_matches_pattern(&exename,
619 ptr->original_name)) 717 ptr->original_name))
620 continue; 718 continue;
621 kfree(rn.name); 719 candidate = ptr->aggregated_name;
622 need_kfree = false;
623 /* This is OK because it is read only. */
624 rn = *ptr->aggregated_name;
625 break; 720 break;
626 } 721 }
627 } 722 }
628 723
629 /* Check execute permission. */ 724 /* Check execute permission. */
630 retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, &rn); 725 retval = tomoyo_execute_permission(&ee->r, candidate);
631 if (retval == TOMOYO_RETRY_REQUEST) 726 if (retval == TOMOYO_RETRY_REQUEST)
632 goto retry; 727 goto retry;
633 if (retval < 0) 728 if (retval < 0)
@@ -638,20 +733,51 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
638 * wildcard) rather than the pathname passed to execve() 733 * wildcard) rather than the pathname passed to execve()
639 * (which never contains wildcard). 734 * (which never contains wildcard).
640 */ 735 */
641 if (ee->r.param.path.matched_path) { 736 if (ee->r.param.path.matched_path)
642 if (need_kfree) 737 candidate = ee->r.param.path.matched_path;
643 kfree(rn.name);
644 need_kfree = false;
645 /* This is OK because it is read only. */
646 rn = *ee->r.param.path.matched_path;
647 }
648 738
649 /* Calculate domain to transit to. */ 739 /*
740 * Check for domain transition preference if "file execute" matched.
741 * If preference is given, make do_execve() fail if domain transition
742 * has failed, for domain transition preference should be used with
743 * destination domain defined.
744 */
745 if (ee->transition) {
746 const char *domainname = ee->transition->name;
747 reject_on_transition_failure = true;
748 if (!strcmp(domainname, "keep"))
749 goto force_keep_domain;
750 if (!strcmp(domainname, "child"))
751 goto force_child_domain;
752 if (!strcmp(domainname, "reset"))
753 goto force_reset_domain;
754 if (!strcmp(domainname, "initialize"))
755 goto force_initialize_domain;
756 if (!strcmp(domainname, "parent")) {
757 char *cp;
758 strncpy(ee->tmp, old_domain->domainname->name,
759 TOMOYO_EXEC_TMPSIZE - 1);
760 cp = strrchr(ee->tmp, ' ');
761 if (cp)
762 *cp = '\0';
763 } else if (*domainname == '<')
764 strncpy(ee->tmp, domainname, TOMOYO_EXEC_TMPSIZE - 1);
765 else
766 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
767 old_domain->domainname->name, domainname);
768 goto force_jump_domain;
769 }
770 /*
771 * No domain transition preference specified.
772 * Calculate domain to transit to.
773 */
650 switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, 774 switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname,
651 &rn)) { 775 candidate)) {
652 case TOMOYO_TRANSITION_CONTROL_RESET: 776 case TOMOYO_TRANSITION_CONTROL_RESET:
777force_reset_domain:
653 /* Transit to the root of specified namespace. */ 778 /* Transit to the root of specified namespace. */
654 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name); 779 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>",
780 candidate->name);
655 /* 781 /*
656 * Make do_execve() fail if domain transition across namespaces 782 * Make do_execve() fail if domain transition across namespaces
657 * has failed. 783 * has failed.
@@ -659,11 +785,13 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
659 reject_on_transition_failure = true; 785 reject_on_transition_failure = true;
660 break; 786 break;
661 case TOMOYO_TRANSITION_CONTROL_INITIALIZE: 787 case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
788force_initialize_domain:
662 /* Transit to the child of current namespace's root. */ 789 /* Transit to the child of current namespace's root. */
663 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", 790 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
664 old_domain->ns->name, rn.name); 791 old_domain->ns->name, candidate->name);
665 break; 792 break;
666 case TOMOYO_TRANSITION_CONTROL_KEEP: 793 case TOMOYO_TRANSITION_CONTROL_KEEP:
794force_keep_domain:
667 /* Keep current domain. */ 795 /* Keep current domain. */
668 domain = old_domain; 796 domain = old_domain;
669 break; 797 break;
@@ -677,13 +805,15 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
677 * before /sbin/init. 805 * before /sbin/init.
678 */ 806 */
679 domain = old_domain; 807 domain = old_domain;
680 } else { 808 break;
681 /* Normal domain transition. */
682 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
683 old_domain->domainname->name, rn.name);
684 } 809 }
810force_child_domain:
811 /* Normal domain transition. */
812 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
813 old_domain->domainname->name, candidate->name);
685 break; 814 break;
686 } 815 }
816force_jump_domain:
687 if (!domain) 817 if (!domain)
688 domain = tomoyo_assign_domain(ee->tmp, true); 818 domain = tomoyo_assign_domain(ee->tmp, true);
689 if (domain) 819 if (domain)
@@ -711,8 +841,11 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
711 /* Update reference count on "struct tomoyo_domain_info". */ 841 /* Update reference count on "struct tomoyo_domain_info". */
712 atomic_inc(&domain->users); 842 atomic_inc(&domain->users);
713 bprm->cred->security = domain; 843 bprm->cred->security = domain;
714 if (need_kfree) 844 kfree(exename.name);
715 kfree(rn.name); 845 if (!retval) {
846 ee->r.domain = domain;
847 retval = tomoyo_environ(ee);
848 }
716 kfree(ee->tmp); 849 kfree(ee->tmp);
717 kfree(ee->dump.data); 850 kfree(ee->dump.data);
718 kfree(ee); 851 kfree(ee);
@@ -732,7 +865,8 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
732 struct tomoyo_page_dump *dump) 865 struct tomoyo_page_dump *dump)
733{ 866{
734 struct page *page; 867 struct page *page;
735 /* dump->data is released by tomoyo_finish_execve(). */ 868
869 /* dump->data is released by tomoyo_find_next_domain(). */
736 if (!dump->data) { 870 if (!dump->data) {
737 dump->data = kzalloc(PAGE_SIZE, GFP_NOFS); 871 dump->data = kzalloc(PAGE_SIZE, GFP_NOFS);
738 if (!dump->data) 872 if (!dump->data)
@@ -753,6 +887,7 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
753 * So do I. 887 * So do I.
754 */ 888 */
755 char *kaddr = kmap_atomic(page, KM_USER0); 889 char *kaddr = kmap_atomic(page, KM_USER0);
890
756 dump->page = page; 891 dump->page = page;
757 memcpy(dump->data + offset, kaddr + offset, 892 memcpy(dump->data + offset, kaddr + offset,
758 PAGE_SIZE - offset); 893 PAGE_SIZE - offset);
diff --git a/security/tomoyo/environ.c b/security/tomoyo/environ.c
new file mode 100644
index 000000000000..ad4c6e18a437
--- /dev/null
+++ b/security/tomoyo/environ.c
@@ -0,0 +1,122 @@
1/*
2 * security/tomoyo/environ.c
3 *
4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
5 */
6
7#include "common.h"
8
9/**
10 * tomoyo_check_env_acl - Check permission for environment variable's name.
11 *
12 * @r: Pointer to "struct tomoyo_request_info".
13 * @ptr: Pointer to "struct tomoyo_acl_info".
14 *
15 * Returns true if granted, false otherwise.
16 */
17static bool tomoyo_check_env_acl(struct tomoyo_request_info *r,
18 const struct tomoyo_acl_info *ptr)
19{
20 const struct tomoyo_env_acl *acl =
21 container_of(ptr, typeof(*acl), head);
22
23 return tomoyo_path_matches_pattern(r->param.environ.name, acl->env);
24}
25
26/**
27 * tomoyo_audit_env_log - Audit environment variable name log.
28 *
29 * @r: Pointer to "struct tomoyo_request_info".
30 *
31 * Returns 0 on success, negative value otherwise.
32 */
33static int tomoyo_audit_env_log(struct tomoyo_request_info *r)
34{
35 return tomoyo_supervisor(r, "misc env %s\n",
36 r->param.environ.name->name);
37}
38
39/**
40 * tomoyo_env_perm - Check permission for environment variable's name.
41 *
42 * @r: Pointer to "struct tomoyo_request_info".
43 * @env: The name of environment variable.
44 *
45 * Returns 0 on success, negative value otherwise.
46 *
47 * Caller holds tomoyo_read_lock().
48 */
49int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env)
50{
51 struct tomoyo_path_info environ;
52 int error;
53
54 if (!env || !*env)
55 return 0;
56 environ.name = env;
57 tomoyo_fill_path_info(&environ);
58 r->param_type = TOMOYO_TYPE_ENV_ACL;
59 r->param.environ.name = &environ;
60 do {
61 tomoyo_check_acl(r, tomoyo_check_env_acl);
62 error = tomoyo_audit_env_log(r);
63 } while (error == TOMOYO_RETRY_REQUEST);
64 return error;
65}
66
67/**
68 * tomoyo_same_env_acl - Check for duplicated "struct tomoyo_env_acl" entry.
69 *
70 * @a: Pointer to "struct tomoyo_acl_info".
71 * @b: Pointer to "struct tomoyo_acl_info".
72 *
73 * Returns true if @a == @b, false otherwise.
74 */
75static bool tomoyo_same_env_acl(const struct tomoyo_acl_info *a,
76 const struct tomoyo_acl_info *b)
77{
78 const struct tomoyo_env_acl *p1 = container_of(a, typeof(*p1), head);
79 const struct tomoyo_env_acl *p2 = container_of(b, typeof(*p2), head);
80
81 return p1->env == p2->env;
82}
83
84/**
85 * tomoyo_write_env - Write "struct tomoyo_env_acl" list.
86 *
87 * @param: Pointer to "struct tomoyo_acl_param".
88 *
89 * Returns 0 on success, negative value otherwise.
90 *
91 * Caller holds tomoyo_read_lock().
92 */
93static int tomoyo_write_env(struct tomoyo_acl_param *param)
94{
95 struct tomoyo_env_acl e = { .head.type = TOMOYO_TYPE_ENV_ACL };
96 int error = -ENOMEM;
97 const char *data = tomoyo_read_token(param);
98
99 if (!tomoyo_correct_word(data) || strchr(data, '='))
100 return -EINVAL;
101 e.env = tomoyo_get_name(data);
102 if (!e.env)
103 return error;
104 error = tomoyo_update_domain(&e.head, sizeof(e), param,
105 tomoyo_same_env_acl, NULL);
106 tomoyo_put_name(e.env);
107 return error;
108}
109
110/**
111 * tomoyo_write_misc - Update environment variable list.
112 *
113 * @param: Pointer to "struct tomoyo_acl_param".
114 *
115 * Returns 0 on success, negative value otherwise.
116 */
117int tomoyo_write_misc(struct tomoyo_acl_param *param)
118{
119 if (tomoyo_str_starts(&param->data, "env "))
120 return tomoyo_write_env(param);
121 return -EINVAL;
122}
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 743c35f5084a..400390790745 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -555,8 +555,8 @@ static int tomoyo_update_path2_acl(const u8 perm,
555 * 555 *
556 * Caller holds tomoyo_read_lock(). 556 * Caller holds tomoyo_read_lock().
557 */ 557 */
558int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, 558static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
559 const struct tomoyo_path_info *filename) 559 const struct tomoyo_path_info *filename)
560{ 560{
561 int error; 561 int error;
562 562
@@ -570,16 +570,42 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
570 do { 570 do {
571 tomoyo_check_acl(r, tomoyo_check_path_acl); 571 tomoyo_check_acl(r, tomoyo_check_path_acl);
572 error = tomoyo_audit_path_log(r); 572 error = tomoyo_audit_path_log(r);
573 /* 573 } while (error == TOMOYO_RETRY_REQUEST);
574 * Do not retry for execute request, for alias may have
575 * changed.
576 */
577 } while (error == TOMOYO_RETRY_REQUEST &&
578 operation != TOMOYO_TYPE_EXECUTE);
579 return error; 574 return error;
580} 575}
581 576
582/** 577/**
578 * tomoyo_execute_permission - Check permission for execute operation.
579 *
580 * @r: Pointer to "struct tomoyo_request_info".
581 * @filename: Filename to check.
582 *
583 * Returns 0 on success, negative value otherwise.
584 *
585 * Caller holds tomoyo_read_lock().
586 */
587int tomoyo_execute_permission(struct tomoyo_request_info *r,
588 const struct tomoyo_path_info *filename)
589{
590 /*
591 * Unlike other permission checks, this check is done regardless of
592 * profile mode settings in order to check for domain transition
593 * preference.
594 */
595 r->type = TOMOYO_MAC_FILE_EXECUTE;
596 r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
597 r->param_type = TOMOYO_TYPE_PATH_ACL;
598 r->param.path.filename = filename;
599 r->param.path.operation = TOMOYO_TYPE_EXECUTE;
600 tomoyo_check_acl(r, tomoyo_check_path_acl);
601 r->ee->transition = r->matched_acl && r->matched_acl->cond ?
602 r->matched_acl->cond->transit : NULL;
603 if (r->mode != TOMOYO_CONFIG_DISABLED)
604 return tomoyo_audit_path_log(r);
605 return 0;
606}
607
608/**
583 * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry. 609 * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
584 * 610 *
585 * @a: Pointer to "struct tomoyo_acl_info". 611 * @a: Pointer to "struct tomoyo_acl_info".
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index ae135fbbbe95..986a6a756868 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -8,36 +8,26 @@
8#include <linux/kthread.h> 8#include <linux/kthread.h>
9#include <linux/slab.h> 9#include <linux/slab.h>
10 10
11/**
12 * tomoyo_memory_free - Free memory for elements.
13 *
14 * @ptr: Pointer to allocated memory.
15 *
16 * Returns nothing.
17 *
18 * Caller holds tomoyo_policy_lock mutex.
19 */
20static inline void tomoyo_memory_free(void *ptr)
21{
22 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= ksize(ptr);
23 kfree(ptr);
24}
25
11/* The list for "struct tomoyo_io_buffer". */ 26/* The list for "struct tomoyo_io_buffer". */
12static LIST_HEAD(tomoyo_io_buffer_list); 27static LIST_HEAD(tomoyo_io_buffer_list);
13/* Lock for protecting tomoyo_io_buffer_list. */ 28/* Lock for protecting tomoyo_io_buffer_list. */
14static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock); 29static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock);
15 30
16/* Size of an element. */
17static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = {
18 [TOMOYO_ID_GROUP] = sizeof(struct tomoyo_group),
19 [TOMOYO_ID_PATH_GROUP] = sizeof(struct tomoyo_path_group),
20 [TOMOYO_ID_NUMBER_GROUP] = sizeof(struct tomoyo_number_group),
21 [TOMOYO_ID_AGGREGATOR] = sizeof(struct tomoyo_aggregator),
22 [TOMOYO_ID_TRANSITION_CONTROL] =
23 sizeof(struct tomoyo_transition_control),
24 [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager),
25 /* [TOMOYO_ID_CONDITION] = "struct tomoyo_condition"->size, */
26 /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */
27 /* [TOMOYO_ID_ACL] =
28 tomoyo_acl_size["struct tomoyo_acl_info"->type], */
29 [TOMOYO_ID_DOMAIN] = sizeof(struct tomoyo_domain_info),
30};
31
32/* Size of a domain ACL element. */
33static const u8 tomoyo_acl_size[] = {
34 [TOMOYO_TYPE_PATH_ACL] = sizeof(struct tomoyo_path_acl),
35 [TOMOYO_TYPE_PATH2_ACL] = sizeof(struct tomoyo_path2_acl),
36 [TOMOYO_TYPE_PATH_NUMBER_ACL] = sizeof(struct tomoyo_path_number_acl),
37 [TOMOYO_TYPE_MKDEV_ACL] = sizeof(struct tomoyo_mkdev_acl),
38 [TOMOYO_TYPE_MOUNT_ACL] = sizeof(struct tomoyo_mount_acl),
39};
40
41/** 31/**
42 * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not. 32 * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not.
43 * 33 *
@@ -55,15 +45,11 @@ static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element)
55 list_for_each_entry(head, &tomoyo_io_buffer_list, list) { 45 list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
56 head->users++; 46 head->users++;
57 spin_unlock(&tomoyo_io_buffer_list_lock); 47 spin_unlock(&tomoyo_io_buffer_list_lock);
58 if (mutex_lock_interruptible(&head->io_sem)) { 48 mutex_lock(&head->io_sem);
59 in_use = true;
60 goto out;
61 }
62 if (head->r.domain == element || head->r.group == element || 49 if (head->r.domain == element || head->r.group == element ||
63 head->r.acl == element || &head->w.domain->list == element) 50 head->r.acl == element || &head->w.domain->list == element)
64 in_use = true; 51 in_use = true;
65 mutex_unlock(&head->io_sem); 52 mutex_unlock(&head->io_sem);
66out:
67 spin_lock(&tomoyo_io_buffer_list_lock); 53 spin_lock(&tomoyo_io_buffer_list_lock);
68 head->users--; 54 head->users--;
69 if (in_use) 55 if (in_use)
@@ -77,15 +63,14 @@ out:
77 * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not. 63 * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not.
78 * 64 *
79 * @string: String to check. 65 * @string: String to check.
80 * @size: Memory allocated for @string .
81 * 66 *
82 * Returns true if @string is used by /sys/kernel/security/tomoyo/ users, 67 * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
83 * false otherwise. 68 * false otherwise.
84 */ 69 */
85static bool tomoyo_name_used_by_io_buffer(const char *string, 70static bool tomoyo_name_used_by_io_buffer(const char *string)
86 const size_t size)
87{ 71{
88 struct tomoyo_io_buffer *head; 72 struct tomoyo_io_buffer *head;
73 const size_t size = strlen(string) + 1;
89 bool in_use = false; 74 bool in_use = false;
90 75
91 spin_lock(&tomoyo_io_buffer_list_lock); 76 spin_lock(&tomoyo_io_buffer_list_lock);
@@ -93,10 +78,7 @@ static bool tomoyo_name_used_by_io_buffer(const char *string,
93 int i; 78 int i;
94 head->users++; 79 head->users++;
95 spin_unlock(&tomoyo_io_buffer_list_lock); 80 spin_unlock(&tomoyo_io_buffer_list_lock);
96 if (mutex_lock_interruptible(&head->io_sem)) { 81 mutex_lock(&head->io_sem);
97 in_use = true;
98 goto out;
99 }
100 for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) { 82 for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
101 const char *w = head->r.w[i]; 83 const char *w = head->r.w[i];
102 if (w < string || w > string + size) 84 if (w < string || w > string + size)
@@ -105,7 +87,6 @@ static bool tomoyo_name_used_by_io_buffer(const char *string,
105 break; 87 break;
106 } 88 }
107 mutex_unlock(&head->io_sem); 89 mutex_unlock(&head->io_sem);
108out:
109 spin_lock(&tomoyo_io_buffer_list_lock); 90 spin_lock(&tomoyo_io_buffer_list_lock);
110 head->users--; 91 head->users--;
111 if (in_use) 92 if (in_use)
@@ -115,84 +96,6 @@ out:
115 return in_use; 96 return in_use;
116} 97}
117 98
118/* Structure for garbage collection. */
119struct tomoyo_gc {
120 struct list_head list;
121 enum tomoyo_policy_id type;
122 size_t size;
123 struct list_head *element;
124};
125/* List of entries to be deleted. */
126static LIST_HEAD(tomoyo_gc_list);
127/* Length of tomoyo_gc_list. */
128static int tomoyo_gc_list_len;
129
130/**
131 * tomoyo_add_to_gc - Add an entry to to be deleted list.
132 *
133 * @type: One of values in "enum tomoyo_policy_id".
134 * @element: Pointer to "struct list_head".
135 *
136 * Returns true on success, false otherwise.
137 *
138 * Caller holds tomoyo_policy_lock mutex.
139 *
140 * Adding an entry needs kmalloc(). Thus, if we try to add thousands of
141 * entries at once, it will take too long time. Thus, do not add more than 128
142 * entries per a scan. But to be able to handle worst case where all entries
143 * are in-use, we accept one more entry per a scan.
144 *
145 * If we use singly linked list using "struct list_head"->prev (which is
146 * LIST_POISON2), we can avoid kmalloc().
147 */
148static bool tomoyo_add_to_gc(const int type, struct list_head *element)
149{
150 struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
151 if (!entry)
152 return false;
153 entry->type = type;
154 if (type == TOMOYO_ID_ACL)
155 entry->size = tomoyo_acl_size[
156 container_of(element,
157 typeof(struct tomoyo_acl_info),
158 list)->type];
159 else if (type == TOMOYO_ID_NAME)
160 entry->size = strlen(container_of(element,
161 typeof(struct tomoyo_name),
162 head.list)->entry.name) + 1;
163 else if (type == TOMOYO_ID_CONDITION)
164 entry->size =
165 container_of(element, typeof(struct tomoyo_condition),
166 head.list)->size;
167 else
168 entry->size = tomoyo_element_size[type];
169 entry->element = element;
170 list_add(&entry->list, &tomoyo_gc_list);
171 list_del_rcu(element);
172 return tomoyo_gc_list_len++ < 128;
173}
174
175/**
176 * tomoyo_element_linked_by_gc - Validate next element of an entry.
177 *
178 * @element: Pointer to an element.
179 * @size: Size of @element in byte.
180 *
181 * Returns true if @element is linked by other elements in the garbage
182 * collector's queue, false otherwise.
183 */
184static bool tomoyo_element_linked_by_gc(const u8 *element, const size_t size)
185{
186 struct tomoyo_gc *p;
187 list_for_each_entry(p, &tomoyo_gc_list, list) {
188 const u8 *ptr = (const u8 *) p->element->next;
189 if (ptr < element || element + size < ptr)
190 continue;
191 return true;
192 }
193 return false;
194}
195
196/** 99/**
197 * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control". 100 * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
198 * 101 *
@@ -200,7 +103,7 @@ static bool tomoyo_element_linked_by_gc(const u8 *element, const size_t size)
200 * 103 *
201 * Returns nothing. 104 * Returns nothing.
202 */ 105 */
203static void tomoyo_del_transition_control(struct list_head *element) 106static inline void tomoyo_del_transition_control(struct list_head *element)
204{ 107{
205 struct tomoyo_transition_control *ptr = 108 struct tomoyo_transition_control *ptr =
206 container_of(element, typeof(*ptr), head.list); 109 container_of(element, typeof(*ptr), head.list);
@@ -215,7 +118,7 @@ static void tomoyo_del_transition_control(struct list_head *element)
215 * 118 *
216 * Returns nothing. 119 * Returns nothing.
217 */ 120 */
218static void tomoyo_del_aggregator(struct list_head *element) 121static inline void tomoyo_del_aggregator(struct list_head *element)
219{ 122{
220 struct tomoyo_aggregator *ptr = 123 struct tomoyo_aggregator *ptr =
221 container_of(element, typeof(*ptr), head.list); 124 container_of(element, typeof(*ptr), head.list);
@@ -230,7 +133,7 @@ static void tomoyo_del_aggregator(struct list_head *element)
230 * 133 *
231 * Returns nothing. 134 * Returns nothing.
232 */ 135 */
233static void tomoyo_del_manager(struct list_head *element) 136static inline void tomoyo_del_manager(struct list_head *element)
234{ 137{
235 struct tomoyo_manager *ptr = 138 struct tomoyo_manager *ptr =
236 container_of(element, typeof(*ptr), head.list); 139 container_of(element, typeof(*ptr), head.list);
@@ -293,6 +196,38 @@ static void tomoyo_del_acl(struct list_head *element)
293 tomoyo_put_number_union(&entry->flags); 196 tomoyo_put_number_union(&entry->flags);
294 } 197 }
295 break; 198 break;
199 case TOMOYO_TYPE_ENV_ACL:
200 {
201 struct tomoyo_env_acl *entry =
202 container_of(acl, typeof(*entry), head);
203
204 tomoyo_put_name(entry->env);
205 }
206 break;
207 case TOMOYO_TYPE_INET_ACL:
208 {
209 struct tomoyo_inet_acl *entry =
210 container_of(acl, typeof(*entry), head);
211
212 tomoyo_put_group(entry->address.group);
213 tomoyo_put_number_union(&entry->port);
214 }
215 break;
216 case TOMOYO_TYPE_UNIX_ACL:
217 {
218 struct tomoyo_unix_acl *entry =
219 container_of(acl, typeof(*entry), head);
220
221 tomoyo_put_name_union(&entry->name);
222 }
223 break;
224 case TOMOYO_TYPE_MANUAL_TASK_ACL:
225 {
226 struct tomoyo_task_acl *entry =
227 container_of(acl, typeof(*entry), head);
228 tomoyo_put_name(entry->domainname);
229 }
230 break;
296 } 231 }
297} 232}
298 233
@@ -301,44 +236,26 @@ static void tomoyo_del_acl(struct list_head *element)
301 * 236 *
302 * @element: Pointer to "struct list_head". 237 * @element: Pointer to "struct list_head".
303 * 238 *
304 * Returns true if deleted, false otherwise. 239 * Returns nothing.
240 *
241 * Caller holds tomoyo_policy_lock mutex.
305 */ 242 */
306static bool tomoyo_del_domain(struct list_head *element) 243static inline void tomoyo_del_domain(struct list_head *element)
307{ 244{
308 struct tomoyo_domain_info *domain = 245 struct tomoyo_domain_info *domain =
309 container_of(element, typeof(*domain), list); 246 container_of(element, typeof(*domain), list);
310 struct tomoyo_acl_info *acl; 247 struct tomoyo_acl_info *acl;
311 struct tomoyo_acl_info *tmp; 248 struct tomoyo_acl_info *tmp;
312 /* 249 /*
313 * Since we don't protect whole execve() operation using SRCU, 250 * Since this domain is referenced from neither
314 * we need to recheck domain->users at this point. 251 * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete
315 * 252 * elements without checking for is_deleted flag.
316 * (1) Reader starts SRCU section upon execve().
317 * (2) Reader traverses tomoyo_domain_list and finds this domain.
318 * (3) Writer marks this domain as deleted.
319 * (4) Garbage collector removes this domain from tomoyo_domain_list
320 * because this domain is marked as deleted and used by nobody.
321 * (5) Reader saves reference to this domain into
322 * "struct linux_binprm"->cred->security .
323 * (6) Reader finishes SRCU section, although execve() operation has
324 * not finished yet.
325 * (7) Garbage collector waits for SRCU synchronization.
326 * (8) Garbage collector kfree() this domain because this domain is
327 * used by nobody.
328 * (9) Reader finishes execve() operation and restores this domain from
329 * "struct linux_binprm"->cred->security.
330 *
331 * By updating domain->users at (5), we can solve this race problem
332 * by rechecking domain->users at (8).
333 */ 253 */
334 if (atomic_read(&domain->users))
335 return false;
336 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { 254 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
337 tomoyo_del_acl(&acl->list); 255 tomoyo_del_acl(&acl->list);
338 tomoyo_memory_free(acl); 256 tomoyo_memory_free(acl);
339 } 257 }
340 tomoyo_put_name(domain->domainname); 258 tomoyo_put_name(domain->domainname);
341 return true;
342} 259}
343 260
344/** 261/**
@@ -387,10 +304,9 @@ void tomoyo_del_condition(struct list_head *element)
387 * 304 *
388 * Returns nothing. 305 * Returns nothing.
389 */ 306 */
390static void tomoyo_del_name(struct list_head *element) 307static inline void tomoyo_del_name(struct list_head *element)
391{ 308{
392 const struct tomoyo_name *ptr = 309 /* Nothing to do. */
393 container_of(element, typeof(*ptr), head.list);
394} 310}
395 311
396/** 312/**
@@ -400,7 +316,7 @@ static void tomoyo_del_name(struct list_head *element)
400 * 316 *
401 * Returns nothing. 317 * Returns nothing.
402 */ 318 */
403static void tomoyo_del_path_group(struct list_head *element) 319static inline void tomoyo_del_path_group(struct list_head *element)
404{ 320{
405 struct tomoyo_path_group *member = 321 struct tomoyo_path_group *member =
406 container_of(element, typeof(*member), head.list); 322 container_of(element, typeof(*member), head.list);
@@ -414,7 +330,7 @@ static void tomoyo_del_path_group(struct list_head *element)
414 * 330 *
415 * Returns nothing. 331 * Returns nothing.
416 */ 332 */
417static void tomoyo_del_group(struct list_head *element) 333static inline void tomoyo_del_group(struct list_head *element)
418{ 334{
419 struct tomoyo_group *group = 335 struct tomoyo_group *group =
420 container_of(element, typeof(*group), head.list); 336 container_of(element, typeof(*group), head.list);
@@ -422,16 +338,128 @@ static void tomoyo_del_group(struct list_head *element)
422} 338}
423 339
424/** 340/**
341 * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group".
342 *
343 * @element: Pointer to "struct list_head".
344 *
345 * Returns nothing.
346 */
347static inline void tomoyo_del_address_group(struct list_head *element)
348{
349 /* Nothing to do. */
350}
351
352/**
425 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group". 353 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
426 * 354 *
427 * @element: Pointer to "struct list_head". 355 * @element: Pointer to "struct list_head".
428 * 356 *
429 * Returns nothing. 357 * Returns nothing.
430 */ 358 */
431static void tomoyo_del_number_group(struct list_head *element) 359static inline void tomoyo_del_number_group(struct list_head *element)
432{ 360{
433 struct tomoyo_number_group *member = 361 /* Nothing to do. */
434 container_of(element, typeof(*member), head.list); 362}
363
364/**
365 * tomoyo_try_to_gc - Try to kfree() an entry.
366 *
367 * @type: One of values in "enum tomoyo_policy_id".
368 * @element: Pointer to "struct list_head".
369 *
370 * Returns nothing.
371 *
372 * Caller holds tomoyo_policy_lock mutex.
373 */
374static void tomoyo_try_to_gc(const enum tomoyo_policy_id type,
375 struct list_head *element)
376{
377 /*
378 * __list_del_entry() guarantees that the list element became no longer
379 * reachable from the list which the element was originally on (e.g.
380 * tomoyo_domain_list). Also, synchronize_srcu() guarantees that the
381 * list element became no longer referenced by syscall users.
382 */
383 __list_del_entry(element);
384 mutex_unlock(&tomoyo_policy_lock);
385 synchronize_srcu(&tomoyo_ss);
386 /*
387 * However, there are two users which may still be using the list
388 * element. We need to defer until both users forget this element.
389 *
390 * Don't kfree() until "struct tomoyo_io_buffer"->r.{domain,group,acl}
391 * and "struct tomoyo_io_buffer"->w.domain forget this element.
392 */
393 if (tomoyo_struct_used_by_io_buffer(element))
394 goto reinject;
395 switch (type) {
396 case TOMOYO_ID_TRANSITION_CONTROL:
397 tomoyo_del_transition_control(element);
398 break;
399 case TOMOYO_ID_MANAGER:
400 tomoyo_del_manager(element);
401 break;
402 case TOMOYO_ID_AGGREGATOR:
403 tomoyo_del_aggregator(element);
404 break;
405 case TOMOYO_ID_GROUP:
406 tomoyo_del_group(element);
407 break;
408 case TOMOYO_ID_PATH_GROUP:
409 tomoyo_del_path_group(element);
410 break;
411 case TOMOYO_ID_ADDRESS_GROUP:
412 tomoyo_del_address_group(element);
413 break;
414 case TOMOYO_ID_NUMBER_GROUP:
415 tomoyo_del_number_group(element);
416 break;
417 case TOMOYO_ID_CONDITION:
418 tomoyo_del_condition(element);
419 break;
420 case TOMOYO_ID_NAME:
421 /*
422 * Don't kfree() until all "struct tomoyo_io_buffer"->r.w[]
423 * forget this element.
424 */
425 if (tomoyo_name_used_by_io_buffer
426 (container_of(element, typeof(struct tomoyo_name),
427 head.list)->entry.name))
428 goto reinject;
429 tomoyo_del_name(element);
430 break;
431 case TOMOYO_ID_ACL:
432 tomoyo_del_acl(element);
433 break;
434 case TOMOYO_ID_DOMAIN:
435 /*
436 * Don't kfree() until all "struct cred"->security forget this
437 * element.
438 */
439 if (atomic_read(&container_of
440 (element, typeof(struct tomoyo_domain_info),
441 list)->users))
442 goto reinject;
443 break;
444 case TOMOYO_MAX_POLICY:
445 break;
446 }
447 mutex_lock(&tomoyo_policy_lock);
448 if (type == TOMOYO_ID_DOMAIN)
449 tomoyo_del_domain(element);
450 tomoyo_memory_free(element);
451 return;
452reinject:
453 /*
454 * We can safely reinject this element here bacause
455 * (1) Appending list elements and removing list elements are protected
456 * by tomoyo_policy_lock mutex.
457 * (2) Only this function removes list elements and this function is
458 * exclusively executed by tomoyo_gc_mutex mutex.
459 * are true.
460 */
461 mutex_lock(&tomoyo_policy_lock);
462 list_add_rcu(element, element->prev);
435} 463}
436 464
437/** 465/**
@@ -440,19 +468,19 @@ static void tomoyo_del_number_group(struct list_head *element)
440 * @id: One of values in "enum tomoyo_policy_id". 468 * @id: One of values in "enum tomoyo_policy_id".
441 * @member_list: Pointer to "struct list_head". 469 * @member_list: Pointer to "struct list_head".
442 * 470 *
443 * Returns true if some elements are deleted, false otherwise. 471 * Returns nothing.
444 */ 472 */
445static bool tomoyo_collect_member(const enum tomoyo_policy_id id, 473static void tomoyo_collect_member(const enum tomoyo_policy_id id,
446 struct list_head *member_list) 474 struct list_head *member_list)
447{ 475{
448 struct tomoyo_acl_head *member; 476 struct tomoyo_acl_head *member;
449 list_for_each_entry(member, member_list, list) { 477 struct tomoyo_acl_head *tmp;
478 list_for_each_entry_safe(member, tmp, member_list, list) {
450 if (!member->is_deleted) 479 if (!member->is_deleted)
451 continue; 480 continue;
452 if (!tomoyo_add_to_gc(id, &member->list)) 481 member->is_deleted = TOMOYO_GC_IN_PROGRESS;
453 return false; 482 tomoyo_try_to_gc(id, &member->list);
454 } 483 }
455 return true;
456} 484}
457 485
458/** 486/**
@@ -460,22 +488,22 @@ static bool tomoyo_collect_member(const enum tomoyo_policy_id id,
460 * 488 *
461 * @list: Pointer to "struct list_head". 489 * @list: Pointer to "struct list_head".
462 * 490 *
463 * Returns true if some elements are deleted, false otherwise. 491 * Returns nothing.
464 */ 492 */
465static bool tomoyo_collect_acl(struct list_head *list) 493static void tomoyo_collect_acl(struct list_head *list)
466{ 494{
467 struct tomoyo_acl_info *acl; 495 struct tomoyo_acl_info *acl;
468 list_for_each_entry(acl, list, list) { 496 struct tomoyo_acl_info *tmp;
497 list_for_each_entry_safe(acl, tmp, list, list) {
469 if (!acl->is_deleted) 498 if (!acl->is_deleted)
470 continue; 499 continue;
471 if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list)) 500 acl->is_deleted = TOMOYO_GC_IN_PROGRESS;
472 return false; 501 tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list);
473 } 502 }
474 return true;
475} 503}
476 504
477/** 505/**
478 * tomoyo_collect_entry - Scan lists for deleted elements. 506 * tomoyo_collect_entry - Try to kfree() deleted elements.
479 * 507 *
480 * Returns nothing. 508 * Returns nothing.
481 */ 509 */
@@ -484,174 +512,82 @@ static void tomoyo_collect_entry(void)
484 int i; 512 int i;
485 enum tomoyo_policy_id id; 513 enum tomoyo_policy_id id;
486 struct tomoyo_policy_namespace *ns; 514 struct tomoyo_policy_namespace *ns;
487 int idx; 515 mutex_lock(&tomoyo_policy_lock);
488 if (mutex_lock_interruptible(&tomoyo_policy_lock))
489 return;
490 idx = tomoyo_read_lock();
491 { 516 {
492 struct tomoyo_domain_info *domain; 517 struct tomoyo_domain_info *domain;
493 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 518 struct tomoyo_domain_info *tmp;
494 if (!tomoyo_collect_acl(&domain->acl_info_list)) 519 list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list,
495 goto unlock; 520 list) {
521 tomoyo_collect_acl(&domain->acl_info_list);
496 if (!domain->is_deleted || atomic_read(&domain->users)) 522 if (!domain->is_deleted || atomic_read(&domain->users))
497 continue; 523 continue;
498 /* 524 tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list);
499 * Nobody is referring this domain. But somebody may
500 * refer this domain after successful execve().
501 * We recheck domain->users after SRCU synchronization.
502 */
503 if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list))
504 goto unlock;
505 } 525 }
506 } 526 }
507 list_for_each_entry_rcu(ns, &tomoyo_namespace_list, namespace_list) { 527 list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
508 for (id = 0; id < TOMOYO_MAX_POLICY; id++) 528 for (id = 0; id < TOMOYO_MAX_POLICY; id++)
509 if (!tomoyo_collect_member(id, &ns->policy_list[id])) 529 tomoyo_collect_member(id, &ns->policy_list[id]);
510 goto unlock;
511 for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++) 530 for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
512 if (!tomoyo_collect_acl(&ns->acl_group[i])) 531 tomoyo_collect_acl(&ns->acl_group[i]);
513 goto unlock; 532 }
533 {
534 struct tomoyo_shared_acl_head *ptr;
535 struct tomoyo_shared_acl_head *tmp;
536 list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list,
537 list) {
538 if (atomic_read(&ptr->users) > 0)
539 continue;
540 atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
541 tomoyo_try_to_gc(TOMOYO_ID_CONDITION, &ptr->list);
542 }
543 }
544 list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
514 for (i = 0; i < TOMOYO_MAX_GROUP; i++) { 545 for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
515 struct list_head *list = &ns->group_list[i]; 546 struct list_head *list = &ns->group_list[i];
516 struct tomoyo_group *group; 547 struct tomoyo_group *group;
548 struct tomoyo_group *tmp;
517 switch (i) { 549 switch (i) {
518 case 0: 550 case 0:
519 id = TOMOYO_ID_PATH_GROUP; 551 id = TOMOYO_ID_PATH_GROUP;
520 break; 552 break;
521 default: 553 case 1:
522 id = TOMOYO_ID_NUMBER_GROUP; 554 id = TOMOYO_ID_NUMBER_GROUP;
523 break; 555 break;
556 default:
557 id = TOMOYO_ID_ADDRESS_GROUP;
558 break;
524 } 559 }
525 list_for_each_entry(group, list, head.list) { 560 list_for_each_entry_safe(group, tmp, list, head.list) {
526 if (!tomoyo_collect_member 561 tomoyo_collect_member(id, &group->member_list);
527 (id, &group->member_list))
528 goto unlock;
529 if (!list_empty(&group->member_list) || 562 if (!list_empty(&group->member_list) ||
530 atomic_read(&group->head.users)) 563 atomic_read(&group->head.users) > 0)
531 continue; 564 continue;
532 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, 565 atomic_set(&group->head.users,
533 &group->head.list)) 566 TOMOYO_GC_IN_PROGRESS);
534 goto unlock; 567 tomoyo_try_to_gc(TOMOYO_ID_GROUP,
568 &group->head.list);
535 } 569 }
536 } 570 }
537 } 571 }
538 id = TOMOYO_ID_CONDITION; 572 for (i = 0; i < TOMOYO_MAX_HASH; i++) {
539 for (i = 0; i < TOMOYO_MAX_HASH + 1; i++) { 573 struct list_head *list = &tomoyo_name_list[i];
540 struct list_head *list = !i ?
541 &tomoyo_condition_list : &tomoyo_name_list[i - 1];
542 struct tomoyo_shared_acl_head *ptr; 574 struct tomoyo_shared_acl_head *ptr;
543 list_for_each_entry(ptr, list, list) { 575 struct tomoyo_shared_acl_head *tmp;
544 if (atomic_read(&ptr->users)) 576 list_for_each_entry_safe(ptr, tmp, list, list) {
577 if (atomic_read(&ptr->users) > 0)
545 continue; 578 continue;
546 if (!tomoyo_add_to_gc(id, &ptr->list)) 579 atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
547 goto unlock; 580 tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list);
548 } 581 }
549 id = TOMOYO_ID_NAME;
550 } 582 }
551unlock:
552 tomoyo_read_unlock(idx);
553 mutex_unlock(&tomoyo_policy_lock); 583 mutex_unlock(&tomoyo_policy_lock);
554} 584}
555 585
556/** 586/**
557 * tomoyo_kfree_entry - Delete entries in tomoyo_gc_list.
558 *
559 * Returns true if some entries were kfree()d, false otherwise.
560 */
561static bool tomoyo_kfree_entry(void)
562{
563 struct tomoyo_gc *p;
564 struct tomoyo_gc *tmp;
565 bool result = false;
566
567 list_for_each_entry_safe(p, tmp, &tomoyo_gc_list, list) {
568 struct list_head *element = p->element;
569
570 /*
571 * list_del_rcu() in tomoyo_add_to_gc() guarantees that the
572 * list element became no longer reachable from the list which
573 * the element was originally on (e.g. tomoyo_domain_list).
574 * Also, synchronize_srcu() in tomoyo_gc_thread() guarantees
575 * that the list element became no longer referenced by syscall
576 * users.
577 *
578 * However, there are three users which may still be using the
579 * list element. We need to defer until all of these users
580 * forget the list element.
581 *
582 * Firstly, defer until "struct tomoyo_io_buffer"->r.{domain,
583 * group,acl} and "struct tomoyo_io_buffer"->w.domain forget
584 * the list element.
585 */
586 if (tomoyo_struct_used_by_io_buffer(element))
587 continue;
588 /*
589 * Secondly, defer until all other elements in the
590 * tomoyo_gc_list list forget the list element.
591 */
592 if (tomoyo_element_linked_by_gc((const u8 *) element, p->size))
593 continue;
594 switch (p->type) {
595 case TOMOYO_ID_TRANSITION_CONTROL:
596 tomoyo_del_transition_control(element);
597 break;
598 case TOMOYO_ID_AGGREGATOR:
599 tomoyo_del_aggregator(element);
600 break;
601 case TOMOYO_ID_MANAGER:
602 tomoyo_del_manager(element);
603 break;
604 case TOMOYO_ID_CONDITION:
605 tomoyo_del_condition(element);
606 break;
607 case TOMOYO_ID_NAME:
608 /*
609 * Thirdly, defer until all "struct tomoyo_io_buffer"
610 * ->r.w[] forget the list element.
611 */
612 if (tomoyo_name_used_by_io_buffer(
613 container_of(element, typeof(struct tomoyo_name),
614 head.list)->entry.name, p->size))
615 continue;
616 tomoyo_del_name(element);
617 break;
618 case TOMOYO_ID_ACL:
619 tomoyo_del_acl(element);
620 break;
621 case TOMOYO_ID_DOMAIN:
622 if (!tomoyo_del_domain(element))
623 continue;
624 break;
625 case TOMOYO_ID_PATH_GROUP:
626 tomoyo_del_path_group(element);
627 break;
628 case TOMOYO_ID_GROUP:
629 tomoyo_del_group(element);
630 break;
631 case TOMOYO_ID_NUMBER_GROUP:
632 tomoyo_del_number_group(element);
633 break;
634 case TOMOYO_MAX_POLICY:
635 break;
636 }
637 tomoyo_memory_free(element);
638 list_del(&p->list);
639 kfree(p);
640 tomoyo_gc_list_len--;
641 result = true;
642 }
643 return result;
644}
645
646/**
647 * tomoyo_gc_thread - Garbage collector thread function. 587 * tomoyo_gc_thread - Garbage collector thread function.
648 * 588 *
649 * @unused: Unused. 589 * @unused: Unused.
650 * 590 *
651 * In case OOM-killer choose this thread for termination, we create this thread
652 * as a short live thread whenever /sys/kernel/security/tomoyo/ interface was
653 * close()d.
654 *
655 * Returns 0. 591 * Returns 0.
656 */ 592 */
657static int tomoyo_gc_thread(void *unused) 593static int tomoyo_gc_thread(void *unused)
@@ -660,13 +596,7 @@ static int tomoyo_gc_thread(void *unused)
660 static DEFINE_MUTEX(tomoyo_gc_mutex); 596 static DEFINE_MUTEX(tomoyo_gc_mutex);
661 if (!mutex_trylock(&tomoyo_gc_mutex)) 597 if (!mutex_trylock(&tomoyo_gc_mutex))
662 goto out; 598 goto out;
663 daemonize("GC for TOMOYO"); 599 tomoyo_collect_entry();
664 do {
665 tomoyo_collect_entry();
666 if (list_empty(&tomoyo_gc_list))
667 break;
668 synchronize_srcu(&tomoyo_ss);
669 } while (tomoyo_kfree_entry());
670 { 600 {
671 struct tomoyo_io_buffer *head; 601 struct tomoyo_io_buffer *head;
672 struct tomoyo_io_buffer *tmp; 602 struct tomoyo_io_buffer *tmp;
diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c
index 5fb0e1298400..50092534ec54 100644
--- a/security/tomoyo/group.c
+++ b/security/tomoyo/group.c
@@ -42,7 +42,26 @@ static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
42} 42}
43 43
44/** 44/**
45 * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list. 45 * tomoyo_same_address_group - Check for duplicated "struct tomoyo_address_group" entry.
46 *
47 * @a: Pointer to "struct tomoyo_acl_head".
48 * @b: Pointer to "struct tomoyo_acl_head".
49 *
50 * Returns true if @a == @b, false otherwise.
51 */
52static bool tomoyo_same_address_group(const struct tomoyo_acl_head *a,
53 const struct tomoyo_acl_head *b)
54{
55 const struct tomoyo_address_group *p1 = container_of(a, typeof(*p1),
56 head);
57 const struct tomoyo_address_group *p2 = container_of(b, typeof(*p2),
58 head);
59
60 return tomoyo_same_ipaddr_union(&p1->address, &p2->address);
61}
62
63/**
64 * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list.
46 * 65 *
47 * @param: Pointer to "struct tomoyo_acl_param". 66 * @param: Pointer to "struct tomoyo_acl_param".
48 * @type: Type of this group. 67 * @type: Type of this group.
@@ -77,6 +96,14 @@ int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type)
77 * tomoyo_put_number_union() is not needed because 96 * tomoyo_put_number_union() is not needed because
78 * param->data[0] != '@'. 97 * param->data[0] != '@'.
79 */ 98 */
99 } else {
100 struct tomoyo_address_group e = { };
101
102 if (param->data[0] == '@' ||
103 !tomoyo_parse_ipaddr_union(param, &e.address))
104 goto out;
105 error = tomoyo_update_policy(&e.head, sizeof(e), param,
106 tomoyo_same_address_group);
80 } 107 }
81out: 108out:
82 tomoyo_put_group(group); 109 tomoyo_put_group(group);
@@ -137,3 +164,35 @@ bool tomoyo_number_matches_group(const unsigned long min,
137 } 164 }
138 return matched; 165 return matched;
139} 166}
167
168/**
169 * tomoyo_address_matches_group - Check whether the given address matches members of the given address group.
170 *
171 * @is_ipv6: True if @address is an IPv6 address.
172 * @address: An IPv4 or IPv6 address.
173 * @group: Pointer to "struct tomoyo_address_group".
174 *
175 * Returns true if @address matches addresses in @group group, false otherwise.
176 *
177 * Caller holds tomoyo_read_lock().
178 */
179bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address,
180 const struct tomoyo_group *group)
181{
182 struct tomoyo_address_group *member;
183 bool matched = false;
184 const u8 size = is_ipv6 ? 16 : 4;
185
186 list_for_each_entry_rcu(member, &group->member_list, head.list) {
187 if (member->head.is_deleted)
188 continue;
189 if (member->address.is_ipv6 != is_ipv6)
190 continue;
191 if (memcmp(&member->address.ip[0], address, size) > 0 ||
192 memcmp(address, &member->address.ip[1], size) > 0)
193 continue;
194 matched = true;
195 break;
196 }
197 return matched;
198}
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
index 7a56051146c2..0e995716cc25 100644
--- a/security/tomoyo/memory.c
+++ b/security/tomoyo/memory.c
@@ -27,8 +27,6 @@ void tomoyo_warn_oom(const char *function)
27 panic("MAC Initialization failed.\n"); 27 panic("MAC Initialization failed.\n");
28} 28}
29 29
30/* Lock for protecting tomoyo_memory_used. */
31static DEFINE_SPINLOCK(tomoyo_policy_memory_lock);
32/* Memoy currently used by policy/audit log/query. */ 30/* Memoy currently used by policy/audit log/query. */
33unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; 31unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT];
34/* Memory quota for "policy"/"audit log"/"query". */ 32/* Memory quota for "policy"/"audit log"/"query". */
@@ -42,22 +40,19 @@ unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT];
42 * Returns true on success, false otherwise. 40 * Returns true on success, false otherwise.
43 * 41 *
44 * Returns true if @ptr is not NULL and quota not exceeded, false otherwise. 42 * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
43 *
44 * Caller holds tomoyo_policy_lock mutex.
45 */ 45 */
46bool tomoyo_memory_ok(void *ptr) 46bool tomoyo_memory_ok(void *ptr)
47{ 47{
48 if (ptr) { 48 if (ptr) {
49 const size_t s = ksize(ptr); 49 const size_t s = ksize(ptr);
50 bool result;
51 spin_lock(&tomoyo_policy_memory_lock);
52 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s; 50 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s;
53 result = !tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] || 51 if (!tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] ||
54 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <= 52 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <=
55 tomoyo_memory_quota[TOMOYO_MEMORY_POLICY]; 53 tomoyo_memory_quota[TOMOYO_MEMORY_POLICY])
56 if (!result)
57 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
58 spin_unlock(&tomoyo_policy_memory_lock);
59 if (result)
60 return true; 54 return true;
55 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
61 } 56 }
62 tomoyo_warn_oom(__func__); 57 tomoyo_warn_oom(__func__);
63 return false; 58 return false;
@@ -71,6 +66,8 @@ bool tomoyo_memory_ok(void *ptr)
71 * 66 *
72 * Returns pointer to allocated memory on success, NULL otherwise. 67 * Returns pointer to allocated memory on success, NULL otherwise.
73 * @data is zero-cleared on success. 68 * @data is zero-cleared on success.
69 *
70 * Caller holds tomoyo_policy_lock mutex.
74 */ 71 */
75void *tomoyo_commit_ok(void *data, const unsigned int size) 72void *tomoyo_commit_ok(void *data, const unsigned int size)
76{ 73{
@@ -85,20 +82,6 @@ void *tomoyo_commit_ok(void *data, const unsigned int size)
85} 82}
86 83
87/** 84/**
88 * tomoyo_memory_free - Free memory for elements.
89 *
90 * @ptr: Pointer to allocated memory.
91 */
92void tomoyo_memory_free(void *ptr)
93{
94 size_t s = ksize(ptr);
95 spin_lock(&tomoyo_policy_memory_lock);
96 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
97 spin_unlock(&tomoyo_policy_memory_lock);
98 kfree(ptr);
99}
100
101/**
102 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". 85 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
103 * 86 *
104 * @param: Pointer to "struct tomoyo_acl_param". 87 * @param: Pointer to "struct tomoyo_acl_param".
@@ -123,7 +106,8 @@ struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
123 goto out; 106 goto out;
124 list = &param->ns->group_list[idx]; 107 list = &param->ns->group_list[idx];
125 list_for_each_entry(group, list, head.list) { 108 list_for_each_entry(group, list, head.list) {
126 if (e.group_name != group->group_name) 109 if (e.group_name != group->group_name ||
110 atomic_read(&group->head.users) == TOMOYO_GC_IN_PROGRESS)
127 continue; 111 continue;
128 atomic_inc(&group->head.users); 112 atomic_inc(&group->head.users);
129 found = true; 113 found = true;
@@ -175,7 +159,8 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
175 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 159 if (mutex_lock_interruptible(&tomoyo_policy_lock))
176 return NULL; 160 return NULL;
177 list_for_each_entry(ptr, head, head.list) { 161 list_for_each_entry(ptr, head, head.list) {
178 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) 162 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name) ||
163 atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
179 continue; 164 continue;
180 atomic_inc(&ptr->head.users); 165 atomic_inc(&ptr->head.users);
181 goto out; 166 goto out;
diff --git a/security/tomoyo/network.c b/security/tomoyo/network.c
new file mode 100644
index 000000000000..97527710a72a
--- /dev/null
+++ b/security/tomoyo/network.c
@@ -0,0 +1,771 @@
1/*
2 * security/tomoyo/network.c
3 *
4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
5 */
6
7#include "common.h"
8#include <linux/slab.h>
9
10/* Structure for holding inet domain socket's address. */
11struct tomoyo_inet_addr_info {
12 __be16 port; /* In network byte order. */
13 const __be32 *address; /* In network byte order. */
14 bool is_ipv6;
15};
16
17/* Structure for holding unix domain socket's address. */
18struct tomoyo_unix_addr_info {
19 u8 *addr; /* This may not be '\0' terminated string. */
20 unsigned int addr_len;
21};
22
23/* Structure for holding socket address. */
24struct tomoyo_addr_info {
25 u8 protocol;
26 u8 operation;
27 struct tomoyo_inet_addr_info inet;
28 struct tomoyo_unix_addr_info unix0;
29};
30
31/* String table for socket's protocols. */
32const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX] = {
33 [SOCK_STREAM] = "stream",
34 [SOCK_DGRAM] = "dgram",
35 [SOCK_RAW] = "raw",
36 [SOCK_SEQPACKET] = "seqpacket",
37 [0] = " ", /* Dummy for avoiding NULL pointer dereference. */
38 [4] = " ", /* Dummy for avoiding NULL pointer dereference. */
39};
40
41/**
42 * tomoyo_parse_ipaddr_union - Parse an IP address.
43 *
44 * @param: Pointer to "struct tomoyo_acl_param".
45 * @ptr: Pointer to "struct tomoyo_ipaddr_union".
46 *
47 * Returns true on success, false otherwise.
48 */
49bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param,
50 struct tomoyo_ipaddr_union *ptr)
51{
52 u8 * const min = ptr->ip[0].in6_u.u6_addr8;
53 u8 * const max = ptr->ip[1].in6_u.u6_addr8;
54 char *address = tomoyo_read_token(param);
55 const char *end;
56
57 if (!strchr(address, ':') &&
58 in4_pton(address, -1, min, '-', &end) > 0) {
59 ptr->is_ipv6 = false;
60 if (!*end)
61 ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
62 else if (*end++ != '-' ||
63 in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
64 return false;
65 return true;
66 }
67 if (in6_pton(address, -1, min, '-', &end) > 0) {
68 ptr->is_ipv6 = true;
69 if (!*end)
70 memmove(max, min, sizeof(u16) * 8);
71 else if (*end++ != '-' ||
72 in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
73 return false;
74 return true;
75 }
76 return false;
77}
78
79/**
80 * tomoyo_print_ipv4 - Print an IPv4 address.
81 *
82 * @buffer: Buffer to write to.
83 * @buffer_len: Size of @buffer.
84 * @min_ip: Pointer to __be32.
85 * @max_ip: Pointer to __be32.
86 *
87 * Returns nothing.
88 */
89static void tomoyo_print_ipv4(char *buffer, const unsigned int buffer_len,
90 const __be32 *min_ip, const __be32 *max_ip)
91{
92 snprintf(buffer, buffer_len, "%pI4%c%pI4", min_ip,
93 *min_ip == *max_ip ? '\0' : '-', max_ip);
94}
95
96/**
97 * tomoyo_print_ipv6 - Print an IPv6 address.
98 *
99 * @buffer: Buffer to write to.
100 * @buffer_len: Size of @buffer.
101 * @min_ip: Pointer to "struct in6_addr".
102 * @max_ip: Pointer to "struct in6_addr".
103 *
104 * Returns nothing.
105 */
106static void tomoyo_print_ipv6(char *buffer, const unsigned int buffer_len,
107 const struct in6_addr *min_ip,
108 const struct in6_addr *max_ip)
109{
110 snprintf(buffer, buffer_len, "%pI6c%c%pI6c", min_ip,
111 !memcmp(min_ip, max_ip, 16) ? '\0' : '-', max_ip);
112}
113
114/**
115 * tomoyo_print_ip - Print an IP address.
116 *
117 * @buf: Buffer to write to.
118 * @size: Size of @buf.
119 * @ptr: Pointer to "struct ipaddr_union".
120 *
121 * Returns nothing.
122 */
123void tomoyo_print_ip(char *buf, const unsigned int size,
124 const struct tomoyo_ipaddr_union *ptr)
125{
126 if (ptr->is_ipv6)
127 tomoyo_print_ipv6(buf, size, &ptr->ip[0], &ptr->ip[1]);
128 else
129 tomoyo_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0],
130 &ptr->ip[1].s6_addr32[0]);
131}
132
133/*
134 * Mapping table from "enum tomoyo_network_acl_index" to
135 * "enum tomoyo_mac_index" for inet domain socket.
136 */
137static const u8 tomoyo_inet2mac
138[TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = {
139 [SOCK_STREAM] = {
140 [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_STREAM_BIND,
141 [TOMOYO_NETWORK_LISTEN] =
142 TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN,
143 [TOMOYO_NETWORK_CONNECT] =
144 TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT,
145 },
146 [SOCK_DGRAM] = {
147 [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_DGRAM_BIND,
148 [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_DGRAM_SEND,
149 },
150 [SOCK_RAW] = {
151 [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_RAW_BIND,
152 [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_RAW_SEND,
153 },
154};
155
156/*
157 * Mapping table from "enum tomoyo_network_acl_index" to
158 * "enum tomoyo_mac_index" for unix domain socket.
159 */
160static const u8 tomoyo_unix2mac
161[TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = {
162 [SOCK_STREAM] = {
163 [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND,
164 [TOMOYO_NETWORK_LISTEN] =
165 TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN,
166 [TOMOYO_NETWORK_CONNECT] =
167 TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT,
168 },
169 [SOCK_DGRAM] = {
170 [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND,
171 [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND,
172 },
173 [SOCK_SEQPACKET] = {
174 [TOMOYO_NETWORK_BIND] =
175 TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND,
176 [TOMOYO_NETWORK_LISTEN] =
177 TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
178 [TOMOYO_NETWORK_CONNECT] =
179 TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
180 },
181};
182
183/**
184 * tomoyo_same_inet_acl - Check for duplicated "struct tomoyo_inet_acl" entry.
185 *
186 * @a: Pointer to "struct tomoyo_acl_info".
187 * @b: Pointer to "struct tomoyo_acl_info".
188 *
189 * Returns true if @a == @b except permission bits, false otherwise.
190 */
191static bool tomoyo_same_inet_acl(const struct tomoyo_acl_info *a,
192 const struct tomoyo_acl_info *b)
193{
194 const struct tomoyo_inet_acl *p1 = container_of(a, typeof(*p1), head);
195 const struct tomoyo_inet_acl *p2 = container_of(b, typeof(*p2), head);
196
197 return p1->protocol == p2->protocol &&
198 tomoyo_same_ipaddr_union(&p1->address, &p2->address) &&
199 tomoyo_same_number_union(&p1->port, &p2->port);
200}
201
202/**
203 * tomoyo_same_unix_acl - Check for duplicated "struct tomoyo_unix_acl" entry.
204 *
205 * @a: Pointer to "struct tomoyo_acl_info".
206 * @b: Pointer to "struct tomoyo_acl_info".
207 *
208 * Returns true if @a == @b except permission bits, false otherwise.
209 */
210static bool tomoyo_same_unix_acl(const struct tomoyo_acl_info *a,
211 const struct tomoyo_acl_info *b)
212{
213 const struct tomoyo_unix_acl *p1 = container_of(a, typeof(*p1), head);
214 const struct tomoyo_unix_acl *p2 = container_of(b, typeof(*p2), head);
215
216 return p1->protocol == p2->protocol &&
217 tomoyo_same_name_union(&p1->name, &p2->name);
218}
219
220/**
221 * tomoyo_merge_inet_acl - Merge duplicated "struct tomoyo_inet_acl" entry.
222 *
223 * @a: Pointer to "struct tomoyo_acl_info".
224 * @b: Pointer to "struct tomoyo_acl_info".
225 * @is_delete: True for @a &= ~@b, false for @a |= @b.
226 *
227 * Returns true if @a is empty, false otherwise.
228 */
229static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info *a,
230 struct tomoyo_acl_info *b,
231 const bool is_delete)
232{
233 u8 * const a_perm =
234 &container_of(a, struct tomoyo_inet_acl, head)->perm;
235 u8 perm = *a_perm;
236 const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm;
237
238 if (is_delete)
239 perm &= ~b_perm;
240 else
241 perm |= b_perm;
242 *a_perm = perm;
243 return !perm;
244}
245
246/**
247 * tomoyo_merge_unix_acl - Merge duplicated "struct tomoyo_unix_acl" entry.
248 *
249 * @a: Pointer to "struct tomoyo_acl_info".
250 * @b: Pointer to "struct tomoyo_acl_info".
251 * @is_delete: True for @a &= ~@b, false for @a |= @b.
252 *
253 * Returns true if @a is empty, false otherwise.
254 */
255static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info *a,
256 struct tomoyo_acl_info *b,
257 const bool is_delete)
258{
259 u8 * const a_perm =
260 &container_of(a, struct tomoyo_unix_acl, head)->perm;
261 u8 perm = *a_perm;
262 const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm;
263
264 if (is_delete)
265 perm &= ~b_perm;
266 else
267 perm |= b_perm;
268 *a_perm = perm;
269 return !perm;
270}
271
272/**
273 * tomoyo_write_inet_network - Write "struct tomoyo_inet_acl" list.
274 *
275 * @param: Pointer to "struct tomoyo_acl_param".
276 *
277 * Returns 0 on success, negative value otherwise.
278 *
279 * Caller holds tomoyo_read_lock().
280 */
281int tomoyo_write_inet_network(struct tomoyo_acl_param *param)
282{
283 struct tomoyo_inet_acl e = { .head.type = TOMOYO_TYPE_INET_ACL };
284 int error = -EINVAL;
285 u8 type;
286 const char *protocol = tomoyo_read_token(param);
287 const char *operation = tomoyo_read_token(param);
288
289 for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++)
290 if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol]))
291 break;
292 for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++)
293 if (tomoyo_permstr(operation, tomoyo_socket_keyword[type]))
294 e.perm |= 1 << type;
295 if (e.protocol == TOMOYO_SOCK_MAX || !e.perm)
296 return -EINVAL;
297 if (param->data[0] == '@') {
298 param->data++;
299 e.address.group =
300 tomoyo_get_group(param, TOMOYO_ADDRESS_GROUP);
301 if (!e.address.group)
302 return -ENOMEM;
303 } else {
304 if (!tomoyo_parse_ipaddr_union(param, &e.address))
305 goto out;
306 }
307 if (!tomoyo_parse_number_union(param, &e.port) ||
308 e.port.values[1] > 65535)
309 goto out;
310 error = tomoyo_update_domain(&e.head, sizeof(e), param,
311 tomoyo_same_inet_acl,
312 tomoyo_merge_inet_acl);
313out:
314 tomoyo_put_group(e.address.group);
315 tomoyo_put_number_union(&e.port);
316 return error;
317}
318
319/**
320 * tomoyo_write_unix_network - Write "struct tomoyo_unix_acl" list.
321 *
322 * @param: Pointer to "struct tomoyo_acl_param".
323 *
324 * Returns 0 on success, negative value otherwise.
325 */
326int tomoyo_write_unix_network(struct tomoyo_acl_param *param)
327{
328 struct tomoyo_unix_acl e = { .head.type = TOMOYO_TYPE_UNIX_ACL };
329 int error;
330 u8 type;
331 const char *protocol = tomoyo_read_token(param);
332 const char *operation = tomoyo_read_token(param);
333
334 for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++)
335 if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol]))
336 break;
337 for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++)
338 if (tomoyo_permstr(operation, tomoyo_socket_keyword[type]))
339 e.perm |= 1 << type;
340 if (e.protocol == TOMOYO_SOCK_MAX || !e.perm)
341 return -EINVAL;
342 if (!tomoyo_parse_name_union(param, &e.name))
343 return -EINVAL;
344 error = tomoyo_update_domain(&e.head, sizeof(e), param,
345 tomoyo_same_unix_acl,
346 tomoyo_merge_unix_acl);
347 tomoyo_put_name_union(&e.name);
348 return error;
349}
350
351/**
352 * tomoyo_audit_net_log - Audit network log.
353 *
354 * @r: Pointer to "struct tomoyo_request_info".
355 * @family: Name of socket family ("inet" or "unix").
356 * @protocol: Name of protocol in @family.
357 * @operation: Name of socket operation.
358 * @address: Name of address.
359 *
360 * Returns 0 on success, negative value otherwise.
361 */
362static int tomoyo_audit_net_log(struct tomoyo_request_info *r,
363 const char *family, const u8 protocol,
364 const u8 operation, const char *address)
365{
366 return tomoyo_supervisor(r, "network %s %s %s %s\n", family,
367 tomoyo_proto_keyword[protocol],
368 tomoyo_socket_keyword[operation], address);
369}
370
371/**
372 * tomoyo_audit_inet_log - Audit INET network log.
373 *
374 * @r: Pointer to "struct tomoyo_request_info".
375 *
376 * Returns 0 on success, negative value otherwise.
377 */
378static int tomoyo_audit_inet_log(struct tomoyo_request_info *r)
379{
380 char buf[128];
381 int len;
382 const __be32 *address = r->param.inet_network.address;
383
384 if (r->param.inet_network.is_ipv6)
385 tomoyo_print_ipv6(buf, sizeof(buf), (const struct in6_addr *)
386 address, (const struct in6_addr *) address);
387 else
388 tomoyo_print_ipv4(buf, sizeof(buf), address, address);
389 len = strlen(buf);
390 snprintf(buf + len, sizeof(buf) - len, " %u",
391 r->param.inet_network.port);
392 return tomoyo_audit_net_log(r, "inet", r->param.inet_network.protocol,
393 r->param.inet_network.operation, buf);
394}
395
396/**
397 * tomoyo_audit_unix_log - Audit UNIX network log.
398 *
399 * @r: Pointer to "struct tomoyo_request_info".
400 *
401 * Returns 0 on success, negative value otherwise.
402 */
403static int tomoyo_audit_unix_log(struct tomoyo_request_info *r)
404{
405 return tomoyo_audit_net_log(r, "unix", r->param.unix_network.protocol,
406 r->param.unix_network.operation,
407 r->param.unix_network.address->name);
408}
409
410/**
411 * tomoyo_check_inet_acl - Check permission for inet domain socket operation.
412 *
413 * @r: Pointer to "struct tomoyo_request_info".
414 * @ptr: Pointer to "struct tomoyo_acl_info".
415 *
416 * Returns true if granted, false otherwise.
417 */
418static bool tomoyo_check_inet_acl(struct tomoyo_request_info *r,
419 const struct tomoyo_acl_info *ptr)
420{
421 const struct tomoyo_inet_acl *acl =
422 container_of(ptr, typeof(*acl), head);
423 const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4;
424
425 if (!(acl->perm & (1 << r->param.inet_network.operation)) ||
426 !tomoyo_compare_number_union(r->param.inet_network.port,
427 &acl->port))
428 return false;
429 if (acl->address.group)
430 return tomoyo_address_matches_group
431 (r->param.inet_network.is_ipv6,
432 r->param.inet_network.address, acl->address.group);
433 return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 &&
434 memcmp(&acl->address.ip[0],
435 r->param.inet_network.address, size) <= 0 &&
436 memcmp(r->param.inet_network.address,
437 &acl->address.ip[1], size) <= 0;
438}
439
440/**
441 * tomoyo_check_unix_acl - Check permission for unix domain socket operation.
442 *
443 * @r: Pointer to "struct tomoyo_request_info".
444 * @ptr: Pointer to "struct tomoyo_acl_info".
445 *
446 * Returns true if granted, false otherwise.
447 */
448static bool tomoyo_check_unix_acl(struct tomoyo_request_info *r,
449 const struct tomoyo_acl_info *ptr)
450{
451 const struct tomoyo_unix_acl *acl =
452 container_of(ptr, typeof(*acl), head);
453
454 return (acl->perm & (1 << r->param.unix_network.operation)) &&
455 tomoyo_compare_name_union(r->param.unix_network.address,
456 &acl->name);
457}
458
459/**
460 * tomoyo_inet_entry - Check permission for INET network operation.
461 *
462 * @address: Pointer to "struct tomoyo_addr_info".
463 *
464 * Returns 0 on success, negative value otherwise.
465 */
466static int tomoyo_inet_entry(const struct tomoyo_addr_info *address)
467{
468 const int idx = tomoyo_read_lock();
469 struct tomoyo_request_info r;
470 int error = 0;
471 const u8 type = tomoyo_inet2mac[address->protocol][address->operation];
472
473 if (type && tomoyo_init_request_info(&r, NULL, type)
474 != TOMOYO_CONFIG_DISABLED) {
475 r.param_type = TOMOYO_TYPE_INET_ACL;
476 r.param.inet_network.protocol = address->protocol;
477 r.param.inet_network.operation = address->operation;
478 r.param.inet_network.is_ipv6 = address->inet.is_ipv6;
479 r.param.inet_network.address = address->inet.address;
480 r.param.inet_network.port = ntohs(address->inet.port);
481 do {
482 tomoyo_check_acl(&r, tomoyo_check_inet_acl);
483 error = tomoyo_audit_inet_log(&r);
484 } while (error == TOMOYO_RETRY_REQUEST);
485 }
486 tomoyo_read_unlock(idx);
487 return error;
488}
489
490/**
491 * tomoyo_check_inet_address - Check permission for inet domain socket's operation.
492 *
493 * @addr: Pointer to "struct sockaddr".
494 * @addr_len: Size of @addr.
495 * @port: Port number.
496 * @address: Pointer to "struct tomoyo_addr_info".
497 *
498 * Returns 0 on success, negative value otherwise.
499 */
500static int tomoyo_check_inet_address(const struct sockaddr *addr,
501 const unsigned int addr_len,
502 const u16 port,
503 struct tomoyo_addr_info *address)
504{
505 struct tomoyo_inet_addr_info *i = &address->inet;
506
507 switch (addr->sa_family) {
508 case AF_INET6:
509 if (addr_len < SIN6_LEN_RFC2133)
510 goto skip;
511 i->is_ipv6 = true;
512 i->address = (__be32 *)
513 ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
514 i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
515 break;
516 case AF_INET:
517 if (addr_len < sizeof(struct sockaddr_in))
518 goto skip;
519 i->is_ipv6 = false;
520 i->address = (__be32 *)
521 &((struct sockaddr_in *) addr)->sin_addr;
522 i->port = ((struct sockaddr_in *) addr)->sin_port;
523 break;
524 default:
525 goto skip;
526 }
527 if (address->protocol == SOCK_RAW)
528 i->port = htons(port);
529 return tomoyo_inet_entry(address);
530skip:
531 return 0;
532}
533
534/**
535 * tomoyo_unix_entry - Check permission for UNIX network operation.
536 *
537 * @address: Pointer to "struct tomoyo_addr_info".
538 *
539 * Returns 0 on success, negative value otherwise.
540 */
541static int tomoyo_unix_entry(const struct tomoyo_addr_info *address)
542{
543 const int idx = tomoyo_read_lock();
544 struct tomoyo_request_info r;
545 int error = 0;
546 const u8 type = tomoyo_unix2mac[address->protocol][address->operation];
547
548 if (type && tomoyo_init_request_info(&r, NULL, type)
549 != TOMOYO_CONFIG_DISABLED) {
550 char *buf = address->unix0.addr;
551 int len = address->unix0.addr_len - sizeof(sa_family_t);
552
553 if (len <= 0) {
554 buf = "anonymous";
555 len = 9;
556 } else if (buf[0]) {
557 len = strnlen(buf, len);
558 }
559 buf = tomoyo_encode2(buf, len);
560 if (buf) {
561 struct tomoyo_path_info addr;
562
563 addr.name = buf;
564 tomoyo_fill_path_info(&addr);
565 r.param_type = TOMOYO_TYPE_UNIX_ACL;
566 r.param.unix_network.protocol = address->protocol;
567 r.param.unix_network.operation = address->operation;
568 r.param.unix_network.address = &addr;
569 do {
570 tomoyo_check_acl(&r, tomoyo_check_unix_acl);
571 error = tomoyo_audit_unix_log(&r);
572 } while (error == TOMOYO_RETRY_REQUEST);
573 kfree(buf);
574 } else
575 error = -ENOMEM;
576 }
577 tomoyo_read_unlock(idx);
578 return error;
579}
580
581/**
582 * tomoyo_check_unix_address - Check permission for unix domain socket's operation.
583 *
584 * @addr: Pointer to "struct sockaddr".
585 * @addr_len: Size of @addr.
586 * @address: Pointer to "struct tomoyo_addr_info".
587 *
588 * Returns 0 on success, negative value otherwise.
589 */
590static int tomoyo_check_unix_address(struct sockaddr *addr,
591 const unsigned int addr_len,
592 struct tomoyo_addr_info *address)
593{
594 struct tomoyo_unix_addr_info *u = &address->unix0;
595
596 if (addr->sa_family != AF_UNIX)
597 return 0;
598 u->addr = ((struct sockaddr_un *) addr)->sun_path;
599 u->addr_len = addr_len;
600 return tomoyo_unix_entry(address);
601}
602
603/**
604 * tomoyo_kernel_service - Check whether I'm kernel service or not.
605 *
606 * Returns true if I'm kernel service, false otherwise.
607 */
608static bool tomoyo_kernel_service(void)
609{
610 /* Nothing to do if I am a kernel service. */
611 return segment_eq(get_fs(), KERNEL_DS);
612}
613
614/**
615 * tomoyo_sock_family - Get socket's family.
616 *
617 * @sk: Pointer to "struct sock".
618 *
619 * Returns one of PF_INET, PF_INET6, PF_UNIX or 0.
620 */
621static u8 tomoyo_sock_family(struct sock *sk)
622{
623 u8 family;
624
625 if (tomoyo_kernel_service())
626 return 0;
627 family = sk->sk_family;
628 switch (family) {
629 case PF_INET:
630 case PF_INET6:
631 case PF_UNIX:
632 return family;
633 default:
634 return 0;
635 }
636}
637
638/**
639 * tomoyo_socket_listen_permission - Check permission for listening a socket.
640 *
641 * @sock: Pointer to "struct socket".
642 *
643 * Returns 0 on success, negative value otherwise.
644 */
645int tomoyo_socket_listen_permission(struct socket *sock)
646{
647 struct tomoyo_addr_info address;
648 const u8 family = tomoyo_sock_family(sock->sk);
649 const unsigned int type = sock->type;
650 struct sockaddr_storage addr;
651 int addr_len;
652
653 if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
654 return 0;
655 {
656 const int error = sock->ops->getname(sock, (struct sockaddr *)
657 &addr, &addr_len, 0);
658
659 if (error)
660 return error;
661 }
662 address.protocol = type;
663 address.operation = TOMOYO_NETWORK_LISTEN;
664 if (family == PF_UNIX)
665 return tomoyo_check_unix_address((struct sockaddr *) &addr,
666 addr_len, &address);
667 return tomoyo_check_inet_address((struct sockaddr *) &addr, addr_len,
668 0, &address);
669}
670
671/**
672 * tomoyo_socket_connect_permission - Check permission for setting the remote address of a socket.
673 *
674 * @sock: Pointer to "struct socket".
675 * @addr: Pointer to "struct sockaddr".
676 * @addr_len: Size of @addr.
677 *
678 * Returns 0 on success, negative value otherwise.
679 */
680int tomoyo_socket_connect_permission(struct socket *sock,
681 struct sockaddr *addr, int addr_len)
682{
683 struct tomoyo_addr_info address;
684 const u8 family = tomoyo_sock_family(sock->sk);
685 const unsigned int type = sock->type;
686
687 if (!family)
688 return 0;
689 address.protocol = type;
690 switch (type) {
691 case SOCK_DGRAM:
692 case SOCK_RAW:
693 address.operation = TOMOYO_NETWORK_SEND;
694 break;
695 case SOCK_STREAM:
696 case SOCK_SEQPACKET:
697 address.operation = TOMOYO_NETWORK_CONNECT;
698 break;
699 default:
700 return 0;
701 }
702 if (family == PF_UNIX)
703 return tomoyo_check_unix_address(addr, addr_len, &address);
704 return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
705 &address);
706}
707
708/**
709 * tomoyo_socket_bind_permission - Check permission for setting the local address of a socket.
710 *
711 * @sock: Pointer to "struct socket".
712 * @addr: Pointer to "struct sockaddr".
713 * @addr_len: Size of @addr.
714 *
715 * Returns 0 on success, negative value otherwise.
716 */
717int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
718 int addr_len)
719{
720 struct tomoyo_addr_info address;
721 const u8 family = tomoyo_sock_family(sock->sk);
722 const unsigned int type = sock->type;
723
724 if (!family)
725 return 0;
726 switch (type) {
727 case SOCK_STREAM:
728 case SOCK_DGRAM:
729 case SOCK_RAW:
730 case SOCK_SEQPACKET:
731 address.protocol = type;
732 address.operation = TOMOYO_NETWORK_BIND;
733 break;
734 default:
735 return 0;
736 }
737 if (family == PF_UNIX)
738 return tomoyo_check_unix_address(addr, addr_len, &address);
739 return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
740 &address);
741}
742
743/**
744 * tomoyo_socket_sendmsg_permission - Check permission for sending a datagram.
745 *
746 * @sock: Pointer to "struct socket".
747 * @msg: Pointer to "struct msghdr".
748 * @size: Unused.
749 *
750 * Returns 0 on success, negative value otherwise.
751 */
752int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
753 int size)
754{
755 struct tomoyo_addr_info address;
756 const u8 family = tomoyo_sock_family(sock->sk);
757 const unsigned int type = sock->type;
758
759 if (!msg->msg_name || !family ||
760 (type != SOCK_DGRAM && type != SOCK_RAW))
761 return 0;
762 address.protocol = type;
763 address.operation = TOMOYO_NETWORK_SEND;
764 if (family == PF_UNIX)
765 return tomoyo_check_unix_address((struct sockaddr *)
766 msg->msg_name,
767 msg->msg_namelen, &address);
768 return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name,
769 msg->msg_namelen,
770 sock->sk->sk_protocol, &address);
771}
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 6c601bd300f3..738bbdf8d4c7 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -15,17 +15,19 @@
15#include "../../fs/internal.h" 15#include "../../fs/internal.h"
16 16
17/** 17/**
18 * tomoyo_encode: Convert binary string to ascii string. 18 * tomoyo_encode2 - Encode binary string to ascii string.
19 * 19 *
20 * @str: String in binary format. 20 * @str: String in binary format.
21 * @str_len: Size of @str in byte.
21 * 22 *
22 * Returns pointer to @str in ascii format on success, NULL otherwise. 23 * Returns pointer to @str in ascii format on success, NULL otherwise.
23 * 24 *
24 * This function uses kzalloc(), so caller must kfree() if this function 25 * This function uses kzalloc(), so caller must kfree() if this function
25 * didn't return NULL. 26 * didn't return NULL.
26 */ 27 */
27char *tomoyo_encode(const char *str) 28char *tomoyo_encode2(const char *str, int str_len)
28{ 29{
30 int i;
29 int len = 0; 31 int len = 0;
30 const char *p = str; 32 const char *p = str;
31 char *cp; 33 char *cp;
@@ -33,8 +35,9 @@ char *tomoyo_encode(const char *str)
33 35
34 if (!p) 36 if (!p)
35 return NULL; 37 return NULL;
36 while (*p) { 38 for (i = 0; i < str_len; i++) {
37 const unsigned char c = *p++; 39 const unsigned char c = p[i];
40
38 if (c == '\\') 41 if (c == '\\')
39 len += 2; 42 len += 2;
40 else if (c > ' ' && c < 127) 43 else if (c > ' ' && c < 127)
@@ -49,8 +52,8 @@ char *tomoyo_encode(const char *str)
49 return NULL; 52 return NULL;
50 cp0 = cp; 53 cp0 = cp;
51 p = str; 54 p = str;
52 while (*p) { 55 for (i = 0; i < str_len; i++) {
53 const unsigned char c = *p++; 56 const unsigned char c = p[i];
54 57
55 if (c == '\\') { 58 if (c == '\\') {
56 *cp++ = '\\'; 59 *cp++ = '\\';
@@ -68,6 +71,21 @@ char *tomoyo_encode(const char *str)
68} 71}
69 72
70/** 73/**
74 * tomoyo_encode - Encode binary string to ascii string.
75 *
76 * @str: String in binary format.
77 *
78 * Returns pointer to @str in ascii format on success, NULL otherwise.
79 *
80 * This function uses kzalloc(), so caller must kfree() if this function
81 * didn't return NULL.
82 */
83char *tomoyo_encode(const char *str)
84{
85 return str ? tomoyo_encode2(str, strlen(str)) : NULL;
86}
87
88/**
71 * tomoyo_get_absolute_path - Get the path of a dentry but ignores chroot'ed root. 89 * tomoyo_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
72 * 90 *
73 * @path: Pointer to "struct path". 91 * @path: Pointer to "struct path".
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
index a49c3bfd4dd5..2672ac4f3beb 100644
--- a/security/tomoyo/securityfs_if.c
+++ b/security/tomoyo/securityfs_if.c
@@ -8,6 +8,124 @@
8#include "common.h" 8#include "common.h"
9 9
10/** 10/**
11 * tomoyo_check_task_acl - Check permission for task operation.
12 *
13 * @r: Pointer to "struct tomoyo_request_info".
14 * @ptr: Pointer to "struct tomoyo_acl_info".
15 *
16 * Returns true if granted, false otherwise.
17 */
18static bool tomoyo_check_task_acl(struct tomoyo_request_info *r,
19 const struct tomoyo_acl_info *ptr)
20{
21 const struct tomoyo_task_acl *acl = container_of(ptr, typeof(*acl),
22 head);
23 return !tomoyo_pathcmp(r->param.task.domainname, acl->domainname);
24}
25
26/**
27 * tomoyo_write_self - write() for /sys/kernel/security/tomoyo/self_domain interface.
28 *
29 * @file: Pointer to "struct file".
30 * @buf: Domainname to transit to.
31 * @count: Size of @buf.
32 * @ppos: Unused.
33 *
34 * Returns @count on success, negative value otherwise.
35 *
36 * If domain transition was permitted but the domain transition failed, this
37 * function returns error rather than terminating current thread with SIGKILL.
38 */
39static ssize_t tomoyo_write_self(struct file *file, const char __user *buf,
40 size_t count, loff_t *ppos)
41{
42 char *data;
43 int error;
44 if (!count || count >= TOMOYO_EXEC_TMPSIZE - 10)
45 return -ENOMEM;
46 data = kzalloc(count + 1, GFP_NOFS);
47 if (!data)
48 return -ENOMEM;
49 if (copy_from_user(data, buf, count)) {
50 error = -EFAULT;
51 goto out;
52 }
53 tomoyo_normalize_line(data);
54 if (tomoyo_correct_domain(data)) {
55 const int idx = tomoyo_read_lock();
56 struct tomoyo_path_info name;
57 struct tomoyo_request_info r;
58 name.name = data;
59 tomoyo_fill_path_info(&name);
60 /* Check "task manual_domain_transition" permission. */
61 tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
62 r.param_type = TOMOYO_TYPE_MANUAL_TASK_ACL;
63 r.param.task.domainname = &name;
64 tomoyo_check_acl(&r, tomoyo_check_task_acl);
65 if (!r.granted)
66 error = -EPERM;
67 else {
68 struct tomoyo_domain_info *new_domain =
69 tomoyo_assign_domain(data, true);
70 if (!new_domain) {
71 error = -ENOENT;
72 } else {
73 struct cred *cred = prepare_creds();
74 if (!cred) {
75 error = -ENOMEM;
76 } else {
77 struct tomoyo_domain_info *old_domain =
78 cred->security;
79 cred->security = new_domain;
80 atomic_inc(&new_domain->users);
81 atomic_dec(&old_domain->users);
82 commit_creds(cred);
83 error = 0;
84 }
85 }
86 }
87 tomoyo_read_unlock(idx);
88 } else
89 error = -EINVAL;
90out:
91 kfree(data);
92 return error ? error : count;
93}
94
95/**
96 * tomoyo_read_self - read() for /sys/kernel/security/tomoyo/self_domain interface.
97 *
98 * @file: Pointer to "struct file".
99 * @buf: Domainname which current thread belongs to.
100 * @count: Size of @buf.
101 * @ppos: Bytes read by now.
102 *
103 * Returns read size on success, negative value otherwise.
104 */
105static ssize_t tomoyo_read_self(struct file *file, char __user *buf,
106 size_t count, loff_t *ppos)
107{
108 const char *domain = tomoyo_domain()->domainname->name;
109 loff_t len = strlen(domain);
110 loff_t pos = *ppos;
111 if (pos >= len || !count)
112 return 0;
113 len -= pos;
114 if (count < len)
115 len = count;
116 if (copy_to_user(buf, domain + pos, len))
117 return -EFAULT;
118 *ppos += len;
119 return len;
120}
121
122/* Operations for /sys/kernel/security/tomoyo/self_domain interface. */
123static const struct file_operations tomoyo_self_operations = {
124 .write = tomoyo_write_self,
125 .read = tomoyo_read_self,
126};
127
128/**
11 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. 129 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
12 * 130 *
13 * @inode: Pointer to "struct inode". 131 * @inode: Pointer to "struct inode".
@@ -135,8 +253,6 @@ static int __init tomoyo_initerface_init(void)
135 TOMOYO_EXCEPTIONPOLICY); 253 TOMOYO_EXCEPTIONPOLICY);
136 tomoyo_create_entry("audit", 0400, tomoyo_dir, 254 tomoyo_create_entry("audit", 0400, tomoyo_dir,
137 TOMOYO_AUDIT); 255 TOMOYO_AUDIT);
138 tomoyo_create_entry("self_domain", 0400, tomoyo_dir,
139 TOMOYO_SELFDOMAIN);
140 tomoyo_create_entry(".process_status", 0600, tomoyo_dir, 256 tomoyo_create_entry(".process_status", 0600, tomoyo_dir,
141 TOMOYO_PROCESS_STATUS); 257 TOMOYO_PROCESS_STATUS);
142 tomoyo_create_entry("stat", 0644, tomoyo_dir, 258 tomoyo_create_entry("stat", 0644, tomoyo_dir,
@@ -147,6 +263,9 @@ static int __init tomoyo_initerface_init(void)
147 TOMOYO_MANAGER); 263 TOMOYO_MANAGER);
148 tomoyo_create_entry("version", 0400, tomoyo_dir, 264 tomoyo_create_entry("version", 0400, tomoyo_dir,
149 TOMOYO_VERSION); 265 TOMOYO_VERSION);
266 securityfs_create_file("self_domain", 0666, tomoyo_dir, NULL,
267 &tomoyo_self_operations);
268 tomoyo_load_builtin_policy();
150 return 0; 269 return 0;
151} 270}
152 271
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index f776400a8f31..4b327b691745 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -442,6 +442,64 @@ static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path)
442 return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); 442 return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path);
443} 443}
444 444
445/**
446 * tomoyo_socket_listen - Check permission for listen().
447 *
448 * @sock: Pointer to "struct socket".
449 * @backlog: Backlog parameter.
450 *
451 * Returns 0 on success, negative value otherwise.
452 */
453static int tomoyo_socket_listen(struct socket *sock, int backlog)
454{
455 return tomoyo_socket_listen_permission(sock);
456}
457
458/**
459 * tomoyo_socket_connect - Check permission for connect().
460 *
461 * @sock: Pointer to "struct socket".
462 * @addr: Pointer to "struct sockaddr".
463 * @addr_len: Size of @addr.
464 *
465 * Returns 0 on success, negative value otherwise.
466 */
467static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr,
468 int addr_len)
469{
470 return tomoyo_socket_connect_permission(sock, addr, addr_len);
471}
472
473/**
474 * tomoyo_socket_bind - Check permission for bind().
475 *
476 * @sock: Pointer to "struct socket".
477 * @addr: Pointer to "struct sockaddr".
478 * @addr_len: Size of @addr.
479 *
480 * Returns 0 on success, negative value otherwise.
481 */
482static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr,
483 int addr_len)
484{
485 return tomoyo_socket_bind_permission(sock, addr, addr_len);
486}
487
488/**
489 * tomoyo_socket_sendmsg - Check permission for sendmsg().
490 *
491 * @sock: Pointer to "struct socket".
492 * @msg: Pointer to "struct msghdr".
493 * @size: Size of message.
494 *
495 * Returns 0 on success, negative value otherwise.
496 */
497static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
498 int size)
499{
500 return tomoyo_socket_sendmsg_permission(sock, msg, size);
501}
502
445/* 503/*
446 * tomoyo_security_ops is a "struct security_operations" which is used for 504 * tomoyo_security_ops is a "struct security_operations" which is used for
447 * registering TOMOYO. 505 * registering TOMOYO.
@@ -472,6 +530,10 @@ static struct security_operations tomoyo_security_ops = {
472 .sb_mount = tomoyo_sb_mount, 530 .sb_mount = tomoyo_sb_mount,
473 .sb_umount = tomoyo_sb_umount, 531 .sb_umount = tomoyo_sb_umount,
474 .sb_pivotroot = tomoyo_sb_pivotroot, 532 .sb_pivotroot = tomoyo_sb_pivotroot,
533 .socket_bind = tomoyo_socket_bind,
534 .socket_connect = tomoyo_socket_connect,
535 .socket_listen = tomoyo_socket_listen,
536 .socket_sendmsg = tomoyo_socket_sendmsg,
475}; 537};
476 538
477/* Lock for GC. */ 539/* Lock for GC. */
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index c36bd1107fc8..4a9b4b2eb755 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -42,6 +42,39 @@ const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = {
42 [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE, 42 [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE,
43 [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE, 43 [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE,
44 [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE, 44 [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE,
45 /* CONFIG::network group */
46 [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] =
47 TOMOYO_MAC_CATEGORY_NETWORK,
48 [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] =
49 TOMOYO_MAC_CATEGORY_NETWORK,
50 [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] =
51 TOMOYO_MAC_CATEGORY_NETWORK,
52 [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] =
53 TOMOYO_MAC_CATEGORY_NETWORK,
54 [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] =
55 TOMOYO_MAC_CATEGORY_NETWORK,
56 [TOMOYO_MAC_NETWORK_INET_RAW_BIND] =
57 TOMOYO_MAC_CATEGORY_NETWORK,
58 [TOMOYO_MAC_NETWORK_INET_RAW_SEND] =
59 TOMOYO_MAC_CATEGORY_NETWORK,
60 [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] =
61 TOMOYO_MAC_CATEGORY_NETWORK,
62 [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] =
63 TOMOYO_MAC_CATEGORY_NETWORK,
64 [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] =
65 TOMOYO_MAC_CATEGORY_NETWORK,
66 [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] =
67 TOMOYO_MAC_CATEGORY_NETWORK,
68 [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] =
69 TOMOYO_MAC_CATEGORY_NETWORK,
70 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] =
71 TOMOYO_MAC_CATEGORY_NETWORK,
72 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] =
73 TOMOYO_MAC_CATEGORY_NETWORK,
74 [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] =
75 TOMOYO_MAC_CATEGORY_NETWORK,
76 /* CONFIG::misc group */
77 [TOMOYO_MAC_ENVIRON] = TOMOYO_MAC_CATEGORY_MISC,
45}; 78};
46 79
47/** 80/**
@@ -126,6 +159,31 @@ char *tomoyo_read_token(struct tomoyo_acl_param *param)
126} 159}
127 160
128/** 161/**
162 * tomoyo_get_domainname - Read a domainname from a line.
163 *
164 * @param: Pointer to "struct tomoyo_acl_param".
165 *
166 * Returns a domainname on success, NULL otherwise.
167 */
168const struct tomoyo_path_info *tomoyo_get_domainname
169(struct tomoyo_acl_param *param)
170{
171 char *start = param->data;
172 char *pos = start;
173 while (*pos) {
174 if (*pos++ != ' ' || *pos++ == '/')
175 continue;
176 pos -= 2;
177 *pos++ = '\0';
178 break;
179 }
180 param->data = pos;
181 if (tomoyo_correct_domain(start))
182 return tomoyo_get_name(start);
183 return NULL;
184}
185
186/**
129 * tomoyo_parse_ulong - Parse an "unsigned long" value. 187 * tomoyo_parse_ulong - Parse an "unsigned long" value.
130 * 188 *
131 * @result: Pointer to "unsigned long". 189 * @result: Pointer to "unsigned long".
@@ -920,14 +978,17 @@ int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
920 const u8 index) 978 const u8 index)
921{ 979{
922 u8 mode; 980 u8 mode;
923 const u8 category = TOMOYO_MAC_CATEGORY_FILE; 981 struct tomoyo_profile *p;
982
924 if (!tomoyo_policy_loaded) 983 if (!tomoyo_policy_loaded)
925 return TOMOYO_CONFIG_DISABLED; 984 return TOMOYO_CONFIG_DISABLED;
926 mode = tomoyo_profile(ns, profile)->config[index]; 985 p = tomoyo_profile(ns, profile);
986 mode = p->config[index];
927 if (mode == TOMOYO_CONFIG_USE_DEFAULT) 987 if (mode == TOMOYO_CONFIG_USE_DEFAULT)
928 mode = tomoyo_profile(ns, profile)->config[category]; 988 mode = p->config[tomoyo_index2category[index]
989 + TOMOYO_MAX_MAC_INDEX];
929 if (mode == TOMOYO_CONFIG_USE_DEFAULT) 990 if (mode == TOMOYO_CONFIG_USE_DEFAULT)
930 mode = tomoyo_profile(ns, profile)->default_config; 991 mode = p->default_config;
931 return mode & 3; 992 return mode & 3;
932} 993}
933 994
@@ -996,6 +1057,17 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
996 perm = container_of(ptr, struct tomoyo_mkdev_acl, 1057 perm = container_of(ptr, struct tomoyo_mkdev_acl,
997 head)->perm; 1058 head)->perm;
998 break; 1059 break;
1060 case TOMOYO_TYPE_INET_ACL:
1061 perm = container_of(ptr, struct tomoyo_inet_acl,
1062 head)->perm;
1063 break;
1064 case TOMOYO_TYPE_UNIX_ACL:
1065 perm = container_of(ptr, struct tomoyo_unix_acl,
1066 head)->perm;
1067 break;
1068 case TOMOYO_TYPE_MANUAL_TASK_ACL:
1069 perm = 0;
1070 break;
999 default: 1071 default:
1000 perm = 1; 1072 perm = 1;
1001 } 1073 }