diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-07-08 00:21:37 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-07-10 21:05:32 -0400 |
commit | 2066a36125fcbf5220990173b9d8e8bc49ad7538 (patch) | |
tree | c8ea3a6d92a8b4b68cda986601336e8e8f58553e /security | |
parent | 5c4274f13819b40e726f6ee4ef13b4952cff5010 (diff) |
TOMOYO: Allow using UID/GID etc. of current thread as conditions.
This patch adds support for permission checks using current thread's UID/GID
etc. in addition to pathnames.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/tomoyo/Makefile | 2 | ||||
-rw-r--r-- | security/tomoyo/audit.c | 32 | ||||
-rw-r--r-- | security/tomoyo/common.c | 146 | ||||
-rw-r--r-- | security/tomoyo/common.h | 97 | ||||
-rw-r--r-- | security/tomoyo/condition.c | 349 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 21 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 39 | ||||
-rw-r--r-- | security/tomoyo/util.c | 2 |
8 files changed, 651 insertions, 37 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 04f676a940ae..95278b71fc21 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-y = audit.o common.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 | 1 | obj-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 |
2 | 2 | ||
3 | $(obj)/policy/profile.conf: | 3 | $(obj)/policy/profile.conf: |
4 | @mkdir -p $(obj)/policy/ | 4 | @mkdir -p $(obj)/policy/ |
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c index 967b5648dce3..9381d0e7f78f 100644 --- a/security/tomoyo/audit.c +++ b/security/tomoyo/audit.c | |||
@@ -25,7 +25,7 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
25 | const pid_t gpid = task_pid_nr(current); | 25 | const pid_t gpid = task_pid_nr(current); |
26 | static const int tomoyo_buffer_len = 4096; | 26 | static const int tomoyo_buffer_len = 4096; |
27 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); | 27 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); |
28 | pid_t ppid; | 28 | int pos; |
29 | if (!buffer) | 29 | if (!buffer) |
30 | return NULL; | 30 | return NULL; |
31 | { | 31 | { |
@@ -33,21 +33,21 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
33 | do_gettimeofday(&tv); | 33 | do_gettimeofday(&tv); |
34 | tomoyo_convert_time(tv.tv_sec, &stamp); | 34 | tomoyo_convert_time(tv.tv_sec, &stamp); |
35 | } | 35 | } |
36 | rcu_read_lock(); | 36 | pos = snprintf(buffer, tomoyo_buffer_len - 1, |
37 | ppid = task_tgid_vnr(current->real_parent); | 37 | "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " |
38 | rcu_read_unlock(); | 38 | "granted=%s (global-pid=%u) task={ pid=%u ppid=%u " |
39 | snprintf(buffer, tomoyo_buffer_len - 1, | 39 | "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u " |
40 | "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " | 40 | "fsuid=%u fsgid=%u }", stamp.year, stamp.month, |
41 | "granted=%s (global-pid=%u) task={ pid=%u ppid=%u " | 41 | stamp.day, stamp.hour, stamp.min, stamp.sec, r->profile, |
42 | "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u " | 42 | tomoyo_mode[r->mode], tomoyo_yesno(r->granted), gpid, |
43 | "fsuid=%u fsgid=%u }", | 43 | tomoyo_sys_getpid(), tomoyo_sys_getppid(), |
44 | stamp.year, stamp.month, stamp.day, stamp.hour, | 44 | current_uid(), current_gid(), current_euid(), |
45 | stamp.min, stamp.sec, r->profile, tomoyo_mode[r->mode], | 45 | current_egid(), current_suid(), current_sgid(), |
46 | tomoyo_yesno(r->granted), gpid, task_tgid_vnr(current), ppid, | 46 | current_fsuid(), current_fsgid()); |
47 | current_uid(), current_gid(), current_euid(), current_egid(), | 47 | if (pos < tomoyo_buffer_len - 1) |
48 | current_suid(), current_sgid(), current_fsuid(), | 48 | return buffer; |
49 | current_fsgid()); | 49 | kfree(buffer); |
50 | return buffer; | 50 | return NULL; |
51 | } | 51 | } |
52 | 52 | ||
53 | /** | 53 | /** |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index b340137a9216..32ce1705b85a 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -48,6 +48,20 @@ const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX | |||
48 | [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", | 48 | [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", |
49 | }; | 49 | }; |
50 | 50 | ||
51 | /* String table for conditions. */ | ||
52 | const char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = { | ||
53 | [TOMOYO_TASK_UID] = "task.uid", | ||
54 | [TOMOYO_TASK_EUID] = "task.euid", | ||
55 | [TOMOYO_TASK_SUID] = "task.suid", | ||
56 | [TOMOYO_TASK_FSUID] = "task.fsuid", | ||
57 | [TOMOYO_TASK_GID] = "task.gid", | ||
58 | [TOMOYO_TASK_EGID] = "task.egid", | ||
59 | [TOMOYO_TASK_SGID] = "task.sgid", | ||
60 | [TOMOYO_TASK_FSGID] = "task.fsgid", | ||
61 | [TOMOYO_TASK_PID] = "task.pid", | ||
62 | [TOMOYO_TASK_PPID] = "task.ppid", | ||
63 | }; | ||
64 | |||
51 | /* String table for PREFERENCE keyword. */ | 65 | /* String table for PREFERENCE keyword. */ |
52 | static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = { | 66 | static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = { |
53 | [TOMOYO_PREF_MAX_AUDIT_LOG] = "max_audit_log", | 67 | [TOMOYO_PREF_MAX_AUDIT_LOG] = "max_audit_log", |
@@ -294,15 +308,16 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head, | |||
294 | } | 308 | } |
295 | 309 | ||
296 | /** | 310 | /** |
297 | * tomoyo_print_number_union - Print a tomoyo_number_union. | 311 | * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space. |
298 | * | 312 | * |
299 | * @head: Pointer to "struct tomoyo_io_buffer". | 313 | * @head: Pointer to "struct tomoyo_io_buffer". |
300 | * @ptr: Pointer to "struct tomoyo_number_union". | 314 | * @ptr: Pointer to "struct tomoyo_number_union". |
315 | * | ||
316 | * Returns nothing. | ||
301 | */ | 317 | */ |
302 | static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, | 318 | static void tomoyo_print_number_union_nospace |
303 | const struct tomoyo_number_union *ptr) | 319 | (struct tomoyo_io_buffer *head, const struct tomoyo_number_union *ptr) |
304 | { | 320 | { |
305 | tomoyo_set_space(head); | ||
306 | if (ptr->group) { | 321 | if (ptr->group) { |
307 | tomoyo_set_string(head, "@"); | 322 | tomoyo_set_string(head, "@"); |
308 | tomoyo_set_string(head, ptr->group->group_name->name); | 323 | tomoyo_set_string(head, ptr->group->group_name->name); |
@@ -325,8 +340,8 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, | |||
325 | "0%lo", min); | 340 | "0%lo", min); |
326 | break; | 341 | break; |
327 | default: | 342 | default: |
328 | tomoyo_addprintf(buffer, sizeof(buffer), | 343 | tomoyo_addprintf(buffer, sizeof(buffer), "%lu", |
329 | "%lu", min); | 344 | min); |
330 | break; | 345 | break; |
331 | } | 346 | } |
332 | if (min == max && min_type == max_type) | 347 | if (min == max && min_type == max_type) |
@@ -340,6 +355,21 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, | |||
340 | } | 355 | } |
341 | 356 | ||
342 | /** | 357 | /** |
358 | * tomoyo_print_number_union - Print a tomoyo_number_union. | ||
359 | * | ||
360 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
361 | * @ptr: Pointer to "struct tomoyo_number_union". | ||
362 | * | ||
363 | * Returns nothing. | ||
364 | */ | ||
365 | static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, | ||
366 | const struct tomoyo_number_union *ptr) | ||
367 | { | ||
368 | tomoyo_set_space(head); | ||
369 | tomoyo_print_number_union_nospace(head, ptr); | ||
370 | } | ||
371 | |||
372 | /** | ||
343 | * tomoyo_assign_profile - Create a new profile. | 373 | * tomoyo_assign_profile - Create a new profile. |
344 | * | 374 | * |
345 | * @ns: Pointer to "struct tomoyo_policy_namespace". | 375 | * @ns: Pointer to "struct tomoyo_policy_namespace". |
@@ -1004,6 +1034,91 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
1004 | } | 1034 | } |
1005 | 1035 | ||
1006 | /** | 1036 | /** |
1037 | * tomoyo_print_condition - Print condition part. | ||
1038 | * | ||
1039 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
1040 | * @cond: Pointer to "struct tomoyo_condition". | ||
1041 | * | ||
1042 | * Returns true on success, false otherwise. | ||
1043 | */ | ||
1044 | static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | ||
1045 | const struct tomoyo_condition *cond) | ||
1046 | { | ||
1047 | switch (head->r.cond_step) { | ||
1048 | case 0: | ||
1049 | head->r.cond_index = 0; | ||
1050 | head->r.cond_step++; | ||
1051 | /* fall through */ | ||
1052 | case 1: | ||
1053 | { | ||
1054 | const u16 condc = cond->condc; | ||
1055 | const struct tomoyo_condition_element *condp = | ||
1056 | (typeof(condp)) (cond + 1); | ||
1057 | const struct tomoyo_number_union *numbers_p = | ||
1058 | (typeof(numbers_p)) (condp + condc); | ||
1059 | u16 skip; | ||
1060 | for (skip = 0; skip < head->r.cond_index; skip++) { | ||
1061 | const u8 left = condp->left; | ||
1062 | const u8 right = condp->right; | ||
1063 | condp++; | ||
1064 | switch (left) { | ||
1065 | case TOMOYO_NUMBER_UNION: | ||
1066 | numbers_p++; | ||
1067 | break; | ||
1068 | } | ||
1069 | switch (right) { | ||
1070 | case TOMOYO_NUMBER_UNION: | ||
1071 | numbers_p++; | ||
1072 | break; | ||
1073 | } | ||
1074 | } | ||
1075 | while (head->r.cond_index < condc) { | ||
1076 | const u8 match = condp->equals; | ||
1077 | const u8 left = condp->left; | ||
1078 | const u8 right = condp->right; | ||
1079 | if (!tomoyo_flush(head)) | ||
1080 | return false; | ||
1081 | condp++; | ||
1082 | head->r.cond_index++; | ||
1083 | tomoyo_set_space(head); | ||
1084 | switch (left) { | ||
1085 | case TOMOYO_NUMBER_UNION: | ||
1086 | tomoyo_print_number_union_nospace | ||
1087 | (head, numbers_p++); | ||
1088 | break; | ||
1089 | default: | ||
1090 | tomoyo_set_string(head, | ||
1091 | tomoyo_condition_keyword[left]); | ||
1092 | break; | ||
1093 | } | ||
1094 | tomoyo_set_string(head, match ? "=" : "!="); | ||
1095 | switch (right) { | ||
1096 | case TOMOYO_NUMBER_UNION: | ||
1097 | tomoyo_print_number_union_nospace | ||
1098 | (head, numbers_p++); | ||
1099 | break; | ||
1100 | default: | ||
1101 | tomoyo_set_string(head, | ||
1102 | tomoyo_condition_keyword[right]); | ||
1103 | break; | ||
1104 | } | ||
1105 | } | ||
1106 | } | ||
1107 | head->r.cond_step++; | ||
1108 | /* fall through */ | ||
1109 | case 2: | ||
1110 | if (!tomoyo_flush(head)) | ||
1111 | break; | ||
1112 | head->r.cond_step++; | ||
1113 | /* fall through */ | ||
1114 | case 3: | ||
1115 | tomoyo_set_lf(head); | ||
1116 | return true; | ||
1117 | } | ||
1118 | return false; | ||
1119 | } | ||
1120 | |||
1121 | /** | ||
1007 | * tomoyo_set_group - Print "acl_group " header keyword and category name. | 1122 | * tomoyo_set_group - Print "acl_group " header keyword and category name. |
1008 | * | 1123 | * |
1009 | * @head: Pointer to "struct tomoyo_io_buffer". | 1124 | * @head: Pointer to "struct tomoyo_io_buffer". |
@@ -1037,6 +1152,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
1037 | bool first = true; | 1152 | bool first = true; |
1038 | u8 bit; | 1153 | u8 bit; |
1039 | 1154 | ||
1155 | if (head->r.print_cond_part) | ||
1156 | goto print_cond_part; | ||
1040 | if (acl->is_deleted) | 1157 | if (acl->is_deleted) |
1041 | return true; | 1158 | return true; |
1042 | if (!tomoyo_flush(head)) | 1159 | if (!tomoyo_flush(head)) |
@@ -1135,7 +1252,18 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
1135 | tomoyo_print_name_union(head, &ptr->fs_type); | 1252 | tomoyo_print_name_union(head, &ptr->fs_type); |
1136 | tomoyo_print_number_union(head, &ptr->flags); | 1253 | tomoyo_print_number_union(head, &ptr->flags); |
1137 | } | 1254 | } |
1138 | tomoyo_set_lf(head); | 1255 | if (acl->cond) { |
1256 | head->r.print_cond_part = true; | ||
1257 | head->r.cond_step = 0; | ||
1258 | if (!tomoyo_flush(head)) | ||
1259 | return false; | ||
1260 | print_cond_part: | ||
1261 | if (!tomoyo_print_condition(head, acl->cond)) | ||
1262 | return false; | ||
1263 | head->r.print_cond_part = false; | ||
1264 | } else { | ||
1265 | tomoyo_set_lf(head); | ||
1266 | } | ||
1139 | return true; | 1267 | return true; |
1140 | } | 1268 | } |
1141 | 1269 | ||
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index beb7d0eb5222..958d433b0115 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -21,7 +21,8 @@ | |||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/cred.h> | 22 | #include <linux/cred.h> |
23 | #include <linux/poll.h> | 23 | #include <linux/poll.h> |
24 | struct linux_binprm; | 24 | #include <linux/binfmts.h> |
25 | #include <linux/highmem.h> | ||
25 | 26 | ||
26 | /********** Constants definitions. **********/ | 27 | /********** Constants definitions. **********/ |
27 | 28 | ||
@@ -41,6 +42,22 @@ struct linux_binprm; | |||
41 | /* Group number is an integer between 0 and 255. */ | 42 | /* Group number is an integer between 0 and 255. */ |
42 | #define TOMOYO_MAX_ACL_GROUPS 256 | 43 | #define TOMOYO_MAX_ACL_GROUPS 256 |
43 | 44 | ||
45 | /* Index numbers for "struct tomoyo_condition". */ | ||
46 | enum tomoyo_conditions_index { | ||
47 | TOMOYO_TASK_UID, /* current_uid() */ | ||
48 | TOMOYO_TASK_EUID, /* current_euid() */ | ||
49 | TOMOYO_TASK_SUID, /* current_suid() */ | ||
50 | TOMOYO_TASK_FSUID, /* current_fsuid() */ | ||
51 | TOMOYO_TASK_GID, /* current_gid() */ | ||
52 | TOMOYO_TASK_EGID, /* current_egid() */ | ||
53 | TOMOYO_TASK_SGID, /* current_sgid() */ | ||
54 | TOMOYO_TASK_FSGID, /* current_fsgid() */ | ||
55 | TOMOYO_TASK_PID, /* sys_getpid() */ | ||
56 | TOMOYO_TASK_PPID, /* sys_getppid() */ | ||
57 | TOMOYO_MAX_CONDITION_KEYWORD, | ||
58 | TOMOYO_NUMBER_UNION, | ||
59 | }; | ||
60 | |||
44 | /* Index numbers for operation mode. */ | 61 | /* Index numbers for operation mode. */ |
45 | enum tomoyo_mode_index { | 62 | enum tomoyo_mode_index { |
46 | TOMOYO_CONFIG_DISABLED, | 63 | TOMOYO_CONFIG_DISABLED, |
@@ -61,6 +78,7 @@ enum tomoyo_policy_id { | |||
61 | TOMOYO_ID_TRANSITION_CONTROL, | 78 | TOMOYO_ID_TRANSITION_CONTROL, |
62 | TOMOYO_ID_AGGREGATOR, | 79 | TOMOYO_ID_AGGREGATOR, |
63 | TOMOYO_ID_MANAGER, | 80 | TOMOYO_ID_MANAGER, |
81 | TOMOYO_ID_CONDITION, | ||
64 | TOMOYO_ID_NAME, | 82 | TOMOYO_ID_NAME, |
65 | TOMOYO_ID_ACL, | 83 | TOMOYO_ID_ACL, |
66 | TOMOYO_ID_DOMAIN, | 84 | TOMOYO_ID_DOMAIN, |
@@ -370,9 +388,32 @@ struct tomoyo_number_group { | |||
370 | struct tomoyo_number_union number; | 388 | struct tomoyo_number_union number; |
371 | }; | 389 | }; |
372 | 390 | ||
391 | /* Structure for entries which follows "struct tomoyo_condition". */ | ||
392 | struct tomoyo_condition_element { | ||
393 | /* Left hand operand. */ | ||
394 | u8 left; | ||
395 | /* Right hand operand. */ | ||
396 | u8 right; | ||
397 | /* Equation operator. True if equals or overlaps, false otherwise. */ | ||
398 | bool equals; | ||
399 | }; | ||
400 | |||
401 | /* Structure for optional arguments. */ | ||
402 | struct tomoyo_condition { | ||
403 | struct tomoyo_shared_acl_head head; | ||
404 | u32 size; /* Memory size allocated for this entry. */ | ||
405 | u16 condc; /* Number of conditions in this struct. */ | ||
406 | u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ | ||
407 | /* | ||
408 | * struct tomoyo_condition_element condition[condc]; | ||
409 | * struct tomoyo_number_union values[numbers_count]; | ||
410 | */ | ||
411 | }; | ||
412 | |||
373 | /* Common header for individual entries. */ | 413 | /* Common header for individual entries. */ |
374 | struct tomoyo_acl_info { | 414 | struct tomoyo_acl_info { |
375 | struct list_head list; | 415 | struct list_head list; |
416 | struct tomoyo_condition *cond; /* Maybe NULL. */ | ||
376 | bool is_deleted; | 417 | bool is_deleted; |
377 | u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */ | 418 | u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */ |
378 | } __packed; | 419 | } __packed; |
@@ -475,12 +516,15 @@ struct tomoyo_io_buffer { | |||
475 | unsigned int step; | 516 | unsigned int step; |
476 | unsigned int query_index; | 517 | unsigned int query_index; |
477 | u16 index; | 518 | u16 index; |
519 | u16 cond_index; | ||
478 | u8 acl_group_index; | 520 | u8 acl_group_index; |
521 | u8 cond_step; | ||
479 | u8 bit; | 522 | u8 bit; |
480 | u8 w_pos; | 523 | u8 w_pos; |
481 | bool eof; | 524 | bool eof; |
482 | bool print_this_domain_only; | 525 | bool print_this_domain_only; |
483 | bool print_transition_related_only; | 526 | bool print_transition_related_only; |
527 | bool print_cond_part; | ||
484 | const char *w[TOMOYO_MAX_IO_READ_QUEUE]; | 528 | const char *w[TOMOYO_MAX_IO_READ_QUEUE]; |
485 | } r; | 529 | } r; |
486 | struct { | 530 | struct { |
@@ -586,6 +630,8 @@ struct tomoyo_policy_namespace { | |||
586 | 630 | ||
587 | bool tomoyo_compare_number_union(const unsigned long value, | 631 | bool tomoyo_compare_number_union(const unsigned long value, |
588 | const struct tomoyo_number_union *ptr); | 632 | const struct tomoyo_number_union *ptr); |
633 | bool tomoyo_condition(struct tomoyo_request_info *r, | ||
634 | const struct tomoyo_condition *cond); | ||
589 | bool tomoyo_correct_domain(const unsigned char *domainname); | 635 | bool tomoyo_correct_domain(const unsigned char *domainname); |
590 | bool tomoyo_correct_path(const char *filename); | 636 | bool tomoyo_correct_path(const char *filename); |
591 | bool tomoyo_correct_word(const char *string); | 637 | bool tomoyo_correct_word(const char *string); |
@@ -664,6 +710,7 @@ ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | |||
664 | const int buffer_len); | 710 | const int buffer_len); |
665 | ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, | 711 | ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, |
666 | const char __user *buffer, const int buffer_len); | 712 | const char __user *buffer, const int buffer_len); |
713 | struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param); | ||
667 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | 714 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, |
668 | const bool transit); | 715 | const bool transit); |
669 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | 716 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); |
@@ -675,6 +722,7 @@ struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, | |||
675 | const u8 profile); | 722 | const u8 profile); |
676 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | 723 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, |
677 | const u8 index); | 724 | const u8 index); |
725 | u8 tomoyo_parse_ulong(unsigned long *result, char **str); | ||
678 | void *tomoyo_commit_ok(void *data, const unsigned int size); | 726 | void *tomoyo_commit_ok(void *data, const unsigned int size); |
679 | void __init tomoyo_load_builtin_policy(void); | 727 | void __init tomoyo_load_builtin_policy(void); |
680 | void __init tomoyo_mm_init(void); | 728 | void __init tomoyo_mm_init(void); |
@@ -683,6 +731,7 @@ void tomoyo_check_acl(struct tomoyo_request_info *r, | |||
683 | const struct tomoyo_acl_info *)); | 731 | const struct tomoyo_acl_info *)); |
684 | void tomoyo_check_profile(void); | 732 | void tomoyo_check_profile(void); |
685 | void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); | 733 | void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); |
734 | void tomoyo_del_condition(struct list_head *element); | ||
686 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | 735 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); |
687 | void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns); | 736 | void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns); |
688 | void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | 737 | void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) |
@@ -706,6 +755,8 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, | |||
706 | /********** External variable definitions. **********/ | 755 | /********** External variable definitions. **********/ |
707 | 756 | ||
708 | extern bool tomoyo_policy_loaded; | 757 | extern bool tomoyo_policy_loaded; |
758 | extern const char * const tomoyo_condition_keyword | ||
759 | [TOMOYO_MAX_CONDITION_KEYWORD]; | ||
709 | extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; | 760 | extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; |
710 | extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX | 761 | extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX |
711 | + TOMOYO_MAX_MAC_CATEGORY_INDEX]; | 762 | + TOMOYO_MAX_MAC_CATEGORY_INDEX]; |
@@ -715,6 +766,7 @@ extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX]; | |||
715 | extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; | 766 | extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; |
716 | extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; | 767 | extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; |
717 | extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; | 768 | extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; |
769 | extern struct list_head tomoyo_condition_list; | ||
718 | extern struct list_head tomoyo_domain_list; | 770 | extern struct list_head tomoyo_domain_list; |
719 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; | 771 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; |
720 | extern struct list_head tomoyo_namespace_list; | 772 | extern struct list_head tomoyo_namespace_list; |
@@ -750,6 +802,36 @@ static inline void tomoyo_read_unlock(int idx) | |||
750 | } | 802 | } |
751 | 803 | ||
752 | /** | 804 | /** |
805 | * tomoyo_sys_getppid - Copy of getppid(). | ||
806 | * | ||
807 | * Returns parent process's PID. | ||
808 | * | ||
809 | * Alpha does not have getppid() defined. To be able to build this module on | ||
810 | * Alpha, I have to copy getppid() from kernel/timer.c. | ||
811 | */ | ||
812 | static inline pid_t tomoyo_sys_getppid(void) | ||
813 | { | ||
814 | pid_t pid; | ||
815 | rcu_read_lock(); | ||
816 | pid = task_tgid_vnr(current->real_parent); | ||
817 | rcu_read_unlock(); | ||
818 | return pid; | ||
819 | } | ||
820 | |||
821 | /** | ||
822 | * tomoyo_sys_getpid - Copy of getpid(). | ||
823 | * | ||
824 | * Returns current thread's PID. | ||
825 | * | ||
826 | * Alpha does not have getpid() defined. To be able to build this module on | ||
827 | * Alpha, I have to copy getpid() from kernel/timer.c. | ||
828 | */ | ||
829 | static inline pid_t tomoyo_sys_getpid(void) | ||
830 | { | ||
831 | return task_tgid_vnr(current); | ||
832 | } | ||
833 | |||
834 | /** | ||
753 | * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure. | 835 | * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure. |
754 | * | 836 | * |
755 | * @a: Pointer to "struct tomoyo_path_info". | 837 | * @a: Pointer to "struct tomoyo_path_info". |
@@ -780,6 +862,19 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name) | |||
780 | } | 862 | } |
781 | 863 | ||
782 | /** | 864 | /** |
865 | * tomoyo_put_condition - Drop reference on "struct tomoyo_condition". | ||
866 | * | ||
867 | * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. | ||
868 | * | ||
869 | * Returns nothing. | ||
870 | */ | ||
871 | static inline void tomoyo_put_condition(struct tomoyo_condition *cond) | ||
872 | { | ||
873 | if (cond) | ||
874 | atomic_dec(&cond->head.users); | ||
875 | } | ||
876 | |||
877 | /** | ||
783 | * tomoyo_put_group - Drop reference on "struct tomoyo_group". | 878 | * tomoyo_put_group - Drop reference on "struct tomoyo_group". |
784 | * | 879 | * |
785 | * @group: Pointer to "struct tomoyo_group". Maybe NULL. | 880 | * @group: Pointer to "struct tomoyo_group". Maybe NULL. |
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c new file mode 100644 index 000000000000..0692df3cddcc --- /dev/null +++ b/security/tomoyo/condition.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * security/tomoyo/condition.c | ||
3 | * | ||
4 | * Copyright (C) 2005-2011 NTT DATA CORPORATION | ||
5 | */ | ||
6 | |||
7 | #include "common.h" | ||
8 | #include <linux/slab.h> | ||
9 | |||
10 | /* List of "struct tomoyo_condition". */ | ||
11 | LIST_HEAD(tomoyo_condition_list); | ||
12 | |||
13 | /** | ||
14 | * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry. | ||
15 | * | ||
16 | * @a: Pointer to "struct tomoyo_condition". | ||
17 | * @b: Pointer to "struct tomoyo_condition". | ||
18 | * | ||
19 | * Returns true if @a == @b, false otherwise. | ||
20 | */ | ||
21 | static inline bool tomoyo_same_condition(const struct tomoyo_condition *a, | ||
22 | const struct tomoyo_condition *b) | ||
23 | { | ||
24 | return a->size == b->size && a->condc == b->condc && | ||
25 | a->numbers_count == b->numbers_count && | ||
26 | !memcmp(a + 1, b + 1, a->size - sizeof(*a)); | ||
27 | } | ||
28 | |||
29 | /** | ||
30 | * tomoyo_condition_type - Get condition type. | ||
31 | * | ||
32 | * @word: Keyword string. | ||
33 | * | ||
34 | * Returns one of values in "enum tomoyo_conditions_index" on success, | ||
35 | * TOMOYO_MAX_CONDITION_KEYWORD otherwise. | ||
36 | */ | ||
37 | static u8 tomoyo_condition_type(const char *word) | ||
38 | { | ||
39 | u8 i; | ||
40 | for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) { | ||
41 | if (!strcmp(word, tomoyo_condition_keyword[i])) | ||
42 | break; | ||
43 | } | ||
44 | return i; | ||
45 | } | ||
46 | |||
47 | /* Define this to enable debug mode. */ | ||
48 | /* #define DEBUG_CONDITION */ | ||
49 | |||
50 | #ifdef DEBUG_CONDITION | ||
51 | #define dprintk printk | ||
52 | #else | ||
53 | #define dprintk(...) do { } while (0) | ||
54 | #endif | ||
55 | |||
56 | /** | ||
57 | * tomoyo_commit_condition - Commit "struct tomoyo_condition". | ||
58 | * | ||
59 | * @entry: Pointer to "struct tomoyo_condition". | ||
60 | * | ||
61 | * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise. | ||
62 | * | ||
63 | * This function merges duplicated entries. This function returns NULL if | ||
64 | * @entry is not duplicated but memory quota for policy has exceeded. | ||
65 | */ | ||
66 | static struct tomoyo_condition *tomoyo_commit_condition | ||
67 | (struct tomoyo_condition *entry) | ||
68 | { | ||
69 | struct tomoyo_condition *ptr; | ||
70 | bool found = false; | ||
71 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) { | ||
72 | dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); | ||
73 | ptr = NULL; | ||
74 | found = true; | ||
75 | goto out; | ||
76 | } | ||
77 | list_for_each_entry_rcu(ptr, &tomoyo_condition_list, head.list) { | ||
78 | if (!tomoyo_same_condition(ptr, entry)) | ||
79 | continue; | ||
80 | /* Same entry found. Share this entry. */ | ||
81 | atomic_inc(&ptr->head.users); | ||
82 | found = true; | ||
83 | break; | ||
84 | } | ||
85 | if (!found) { | ||
86 | if (tomoyo_memory_ok(entry)) { | ||
87 | atomic_set(&entry->head.users, 1); | ||
88 | list_add_rcu(&entry->head.list, | ||
89 | &tomoyo_condition_list); | ||
90 | } else { | ||
91 | found = true; | ||
92 | ptr = NULL; | ||
93 | } | ||
94 | } | ||
95 | mutex_unlock(&tomoyo_policy_lock); | ||
96 | out: | ||
97 | if (found) { | ||
98 | tomoyo_del_condition(&entry->head.list); | ||
99 | kfree(entry); | ||
100 | entry = ptr; | ||
101 | } | ||
102 | return entry; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * tomoyo_get_condition - Parse condition part. | ||
107 | * | ||
108 | * @param: Pointer to "struct tomoyo_acl_param". | ||
109 | * | ||
110 | * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise. | ||
111 | */ | ||
112 | struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param) | ||
113 | { | ||
114 | struct tomoyo_condition *entry = NULL; | ||
115 | struct tomoyo_condition_element *condp = NULL; | ||
116 | struct tomoyo_number_union *numbers_p = NULL; | ||
117 | struct tomoyo_condition e = { }; | ||
118 | char * const start_of_string = param->data; | ||
119 | char * const end_of_string = start_of_string + strlen(start_of_string); | ||
120 | char *pos; | ||
121 | rerun: | ||
122 | pos = start_of_string; | ||
123 | while (1) { | ||
124 | u8 left = -1; | ||
125 | u8 right = -1; | ||
126 | char *left_word = pos; | ||
127 | char *cp; | ||
128 | char *right_word; | ||
129 | bool is_not; | ||
130 | if (!*left_word) | ||
131 | break; | ||
132 | /* | ||
133 | * Since left-hand condition does not allow use of "path_group" | ||
134 | * or "number_group" and environment variable's names do not | ||
135 | * accept '=', it is guaranteed that the original line consists | ||
136 | * of one or more repetition of $left$operator$right blocks | ||
137 | * where "$left is free from '=' and ' '" and "$operator is | ||
138 | * either '=' or '!='" and "$right is free from ' '". | ||
139 | * Therefore, we can reconstruct the original line at the end | ||
140 | * of dry run even if we overwrite $operator with '\0'. | ||
141 | */ | ||
142 | cp = strchr(pos, ' '); | ||
143 | if (cp) { | ||
144 | *cp = '\0'; /* Will restore later. */ | ||
145 | pos = cp + 1; | ||
146 | } else { | ||
147 | pos = ""; | ||
148 | } | ||
149 | right_word = strchr(left_word, '='); | ||
150 | if (!right_word || right_word == left_word) | ||
151 | goto out; | ||
152 | is_not = *(right_word - 1) == '!'; | ||
153 | if (is_not) | ||
154 | *(right_word++ - 1) = '\0'; /* Will restore later. */ | ||
155 | else if (*(right_word + 1) != '=') | ||
156 | *right_word++ = '\0'; /* Will restore later. */ | ||
157 | else | ||
158 | goto out; | ||
159 | dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word, | ||
160 | is_not ? "!" : "", right_word); | ||
161 | left = tomoyo_condition_type(left_word); | ||
162 | dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word, | ||
163 | left); | ||
164 | if (left == TOMOYO_MAX_CONDITION_KEYWORD) { | ||
165 | if (!numbers_p) { | ||
166 | e.numbers_count++; | ||
167 | } else { | ||
168 | e.numbers_count--; | ||
169 | left = TOMOYO_NUMBER_UNION; | ||
170 | param->data = left_word; | ||
171 | if (*left_word == '@' || | ||
172 | !tomoyo_parse_number_union(param, | ||
173 | numbers_p++)) | ||
174 | goto out; | ||
175 | } | ||
176 | } | ||
177 | if (!condp) | ||
178 | e.condc++; | ||
179 | else | ||
180 | e.condc--; | ||
181 | right = tomoyo_condition_type(right_word); | ||
182 | if (right == TOMOYO_MAX_CONDITION_KEYWORD) { | ||
183 | if (!numbers_p) { | ||
184 | e.numbers_count++; | ||
185 | } else { | ||
186 | e.numbers_count--; | ||
187 | right = TOMOYO_NUMBER_UNION; | ||
188 | param->data = right_word; | ||
189 | if (!tomoyo_parse_number_union(param, | ||
190 | numbers_p++)) | ||
191 | goto out; | ||
192 | } | ||
193 | } | ||
194 | if (!condp) { | ||
195 | dprintk(KERN_WARNING "%u: dry_run left=%u right=%u " | ||
196 | "match=%u\n", __LINE__, left, right, !is_not); | ||
197 | continue; | ||
198 | } | ||
199 | condp->left = left; | ||
200 | condp->right = right; | ||
201 | condp->equals = !is_not; | ||
202 | dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n", | ||
203 | __LINE__, condp->left, condp->right, | ||
204 | condp->equals); | ||
205 | condp++; | ||
206 | } | ||
207 | dprintk(KERN_INFO "%u: cond=%u numbers=%u\n", | ||
208 | __LINE__, e.condc, e.numbers_count); | ||
209 | if (entry) { | ||
210 | BUG_ON(e.numbers_count | e.condc); | ||
211 | return tomoyo_commit_condition(entry); | ||
212 | } | ||
213 | e.size = sizeof(*entry) | ||
214 | + e.condc * sizeof(struct tomoyo_condition_element) | ||
215 | + e.numbers_count * sizeof(struct tomoyo_number_union); | ||
216 | entry = kzalloc(e.size, GFP_NOFS); | ||
217 | if (!entry) | ||
218 | return NULL; | ||
219 | *entry = e; | ||
220 | condp = (struct tomoyo_condition_element *) (entry + 1); | ||
221 | numbers_p = (struct tomoyo_number_union *) (condp + e.condc); | ||
222 | { | ||
223 | bool flag = false; | ||
224 | for (pos = start_of_string; pos < end_of_string; pos++) { | ||
225 | if (*pos) | ||
226 | continue; | ||
227 | if (flag) /* Restore " ". */ | ||
228 | *pos = ' '; | ||
229 | else if (*(pos + 1) == '=') /* Restore "!=". */ | ||
230 | *pos = '!'; | ||
231 | else /* Restore "=". */ | ||
232 | *pos = '='; | ||
233 | flag = !flag; | ||
234 | } | ||
235 | } | ||
236 | goto rerun; | ||
237 | out: | ||
238 | dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); | ||
239 | if (entry) { | ||
240 | tomoyo_del_condition(&entry->head.list); | ||
241 | kfree(entry); | ||
242 | } | ||
243 | return NULL; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * tomoyo_condition - Check condition part. | ||
248 | * | ||
249 | * @r: Pointer to "struct tomoyo_request_info". | ||
250 | * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. | ||
251 | * | ||
252 | * Returns true on success, false otherwise. | ||
253 | * | ||
254 | * Caller holds tomoyo_read_lock(). | ||
255 | */ | ||
256 | bool tomoyo_condition(struct tomoyo_request_info *r, | ||
257 | const struct tomoyo_condition *cond) | ||
258 | { | ||
259 | u32 i; | ||
260 | unsigned long min_v[2] = { 0, 0 }; | ||
261 | unsigned long max_v[2] = { 0, 0 }; | ||
262 | const struct tomoyo_condition_element *condp; | ||
263 | const struct tomoyo_number_union *numbers_p; | ||
264 | u16 condc; | ||
265 | if (!cond) | ||
266 | return true; | ||
267 | condc = cond->condc; | ||
268 | condp = (struct tomoyo_condition_element *) (cond + 1); | ||
269 | numbers_p = (const struct tomoyo_number_union *) (condp + condc); | ||
270 | for (i = 0; i < condc; i++) { | ||
271 | const bool match = condp->equals; | ||
272 | const u8 left = condp->left; | ||
273 | const u8 right = condp->right; | ||
274 | u8 j; | ||
275 | condp++; | ||
276 | /* Check numeric or bit-op expressions. */ | ||
277 | for (j = 0; j < 2; j++) { | ||
278 | const u8 index = j ? right : left; | ||
279 | unsigned long value = 0; | ||
280 | switch (index) { | ||
281 | case TOMOYO_TASK_UID: | ||
282 | value = current_uid(); | ||
283 | break; | ||
284 | case TOMOYO_TASK_EUID: | ||
285 | value = current_euid(); | ||
286 | break; | ||
287 | case TOMOYO_TASK_SUID: | ||
288 | value = current_suid(); | ||
289 | break; | ||
290 | case TOMOYO_TASK_FSUID: | ||
291 | value = current_fsuid(); | ||
292 | break; | ||
293 | case TOMOYO_TASK_GID: | ||
294 | value = current_gid(); | ||
295 | break; | ||
296 | case TOMOYO_TASK_EGID: | ||
297 | value = current_egid(); | ||
298 | break; | ||
299 | case TOMOYO_TASK_SGID: | ||
300 | value = current_sgid(); | ||
301 | break; | ||
302 | case TOMOYO_TASK_FSGID: | ||
303 | value = current_fsgid(); | ||
304 | break; | ||
305 | case TOMOYO_TASK_PID: | ||
306 | value = tomoyo_sys_getpid(); | ||
307 | break; | ||
308 | case TOMOYO_TASK_PPID: | ||
309 | value = tomoyo_sys_getppid(); | ||
310 | break; | ||
311 | case TOMOYO_NUMBER_UNION: | ||
312 | /* Fetch values later. */ | ||
313 | break; | ||
314 | default: | ||
315 | break; | ||
316 | } | ||
317 | max_v[j] = value; | ||
318 | min_v[j] = value; | ||
319 | } | ||
320 | if (left == TOMOYO_NUMBER_UNION) { | ||
321 | /* Fetch values now. */ | ||
322 | const struct tomoyo_number_union *ptr = numbers_p++; | ||
323 | min_v[0] = ptr->values[0]; | ||
324 | max_v[0] = ptr->values[1]; | ||
325 | } | ||
326 | if (right == TOMOYO_NUMBER_UNION) { | ||
327 | /* Fetch values now. */ | ||
328 | const struct tomoyo_number_union *ptr = numbers_p++; | ||
329 | if (ptr->group) { | ||
330 | if (tomoyo_number_matches_group(min_v[0], | ||
331 | max_v[0], | ||
332 | ptr->group) | ||
333 | == match) | ||
334 | continue; | ||
335 | } else { | ||
336 | if ((min_v[0] <= ptr->values[1] && | ||
337 | max_v[0] >= ptr->values[0]) == match) | ||
338 | continue; | ||
339 | } | ||
340 | goto out; | ||
341 | } | ||
342 | /* Normal value range comparison. */ | ||
343 | if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match) | ||
344 | continue; | ||
345 | out: | ||
346 | return false; | ||
347 | } | ||
348 | return true; | ||
349 | } | ||
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 7893127d8770..0f02c7852090 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -69,7 +69,7 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | |||
69 | static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, | 69 | static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, |
70 | const struct tomoyo_acl_info *b) | 70 | const struct tomoyo_acl_info *b) |
71 | { | 71 | { |
72 | return a->type == b->type; | 72 | return a->type == b->type && a->cond == b->cond; |
73 | } | 73 | } |
74 | 74 | ||
75 | /** | 75 | /** |
@@ -100,8 +100,13 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | |||
100 | struct tomoyo_acl_info *entry; | 100 | struct tomoyo_acl_info *entry; |
101 | struct list_head * const list = param->list; | 101 | struct list_head * const list = param->list; |
102 | 102 | ||
103 | if (param->data[0]) { | ||
104 | new_entry->cond = tomoyo_get_condition(param); | ||
105 | if (!new_entry->cond) | ||
106 | return -EINVAL; | ||
107 | } | ||
103 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 108 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
104 | return error; | 109 | goto out; |
105 | list_for_each_entry_rcu(entry, list, list) { | 110 | list_for_each_entry_rcu(entry, list, list) { |
106 | if (!tomoyo_same_acl_head(entry, new_entry) || | 111 | if (!tomoyo_same_acl_head(entry, new_entry) || |
107 | !check_duplicate(entry, new_entry)) | 112 | !check_duplicate(entry, new_entry)) |
@@ -122,6 +127,8 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | |||
122 | } | 127 | } |
123 | } | 128 | } |
124 | mutex_unlock(&tomoyo_policy_lock); | 129 | mutex_unlock(&tomoyo_policy_lock); |
130 | out: | ||
131 | tomoyo_put_condition(new_entry->cond); | ||
125 | return error; | 132 | return error; |
126 | } | 133 | } |
127 | 134 | ||
@@ -148,10 +155,12 @@ retry: | |||
148 | list_for_each_entry_rcu(ptr, list, list) { | 155 | list_for_each_entry_rcu(ptr, list, list) { |
149 | if (ptr->is_deleted || ptr->type != r->param_type) | 156 | if (ptr->is_deleted || ptr->type != r->param_type) |
150 | continue; | 157 | continue; |
151 | if (check_entry(r, ptr)) { | 158 | if (!check_entry(r, ptr)) |
152 | r->granted = true; | 159 | continue; |
153 | return; | 160 | if (!tomoyo_condition(r, ptr->cond)) |
154 | } | 161 | continue; |
162 | r->granted = true; | ||
163 | return; | ||
155 | } | 164 | } |
156 | if (!retried) { | 165 | if (!retried) { |
157 | retried = true; | 166 | retried = true; |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 1e1a6c8c832c..21fccd67c255 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -25,6 +25,7 @@ static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = { | |||
25 | [TOMOYO_ID_TRANSITION_CONTROL] = | 25 | [TOMOYO_ID_TRANSITION_CONTROL] = |
26 | sizeof(struct tomoyo_transition_control), | 26 | sizeof(struct tomoyo_transition_control), |
27 | [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager), | 27 | [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager), |
28 | /* [TOMOYO_ID_CONDITION] = "struct tomoyo_condition"->size, */ | ||
28 | /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */ | 29 | /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */ |
29 | /* [TOMOYO_ID_ACL] = | 30 | /* [TOMOYO_ID_ACL] = |
30 | tomoyo_acl_size["struct tomoyo_acl_info"->type], */ | 31 | tomoyo_acl_size["struct tomoyo_acl_info"->type], */ |
@@ -162,6 +163,10 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element) | |||
162 | entry->size = strlen(container_of(element, | 163 | entry->size = strlen(container_of(element, |
163 | typeof(struct tomoyo_name), | 164 | typeof(struct tomoyo_name), |
164 | head.list)->entry.name) + 1; | 165 | head.list)->entry.name) + 1; |
166 | else if (type == TOMOYO_ID_CONDITION) | ||
167 | entry->size = | ||
168 | container_of(element, typeof(struct tomoyo_condition), | ||
169 | head.list)->size; | ||
165 | else | 170 | else |
166 | entry->size = tomoyo_element_size[type]; | 171 | entry->size = tomoyo_element_size[type]; |
167 | entry->element = element; | 172 | entry->element = element; |
@@ -246,6 +251,7 @@ static void tomoyo_del_acl(struct list_head *element) | |||
246 | { | 251 | { |
247 | struct tomoyo_acl_info *acl = | 252 | struct tomoyo_acl_info *acl = |
248 | container_of(element, typeof(*acl), list); | 253 | container_of(element, typeof(*acl), list); |
254 | tomoyo_put_condition(acl->cond); | ||
249 | switch (acl->type) { | 255 | switch (acl->type) { |
250 | case TOMOYO_TYPE_PATH_ACL: | 256 | case TOMOYO_TYPE_PATH_ACL: |
251 | { | 257 | { |
@@ -338,6 +344,27 @@ static bool tomoyo_del_domain(struct list_head *element) | |||
338 | return true; | 344 | return true; |
339 | } | 345 | } |
340 | 346 | ||
347 | /** | ||
348 | * tomoyo_del_condition - Delete members in "struct tomoyo_condition". | ||
349 | * | ||
350 | * @element: Pointer to "struct list_head". | ||
351 | * | ||
352 | * Returns nothing. | ||
353 | */ | ||
354 | void tomoyo_del_condition(struct list_head *element) | ||
355 | { | ||
356 | struct tomoyo_condition *cond = container_of(element, typeof(*cond), | ||
357 | head.list); | ||
358 | const u16 condc = cond->condc; | ||
359 | const u16 numbers_count = cond->numbers_count; | ||
360 | unsigned int i; | ||
361 | const struct tomoyo_condition_element *condp | ||
362 | = (const struct tomoyo_condition_element *) (cond + 1); | ||
363 | struct tomoyo_number_union *numbers_p | ||
364 | = (struct tomoyo_number_union *) (condp + condc); | ||
365 | for (i = 0; i < numbers_count; i++) | ||
366 | tomoyo_put_number_union(numbers_p++); | ||
367 | } | ||
341 | 368 | ||
342 | /** | 369 | /** |
343 | * tomoyo_del_name - Delete members in "struct tomoyo_name". | 370 | * tomoyo_del_name - Delete members in "struct tomoyo_name". |
@@ -494,15 +521,18 @@ static void tomoyo_collect_entry(void) | |||
494 | } | 521 | } |
495 | } | 522 | } |
496 | } | 523 | } |
497 | for (i = 0; i < TOMOYO_MAX_HASH; i++) { | 524 | id = TOMOYO_ID_CONDITION; |
498 | struct list_head *list = &tomoyo_name_list[i]; | 525 | for (i = 0; i < TOMOYO_MAX_HASH + 1; i++) { |
526 | struct list_head *list = !i ? | ||
527 | &tomoyo_condition_list : &tomoyo_name_list[i - 1]; | ||
499 | struct tomoyo_shared_acl_head *ptr; | 528 | struct tomoyo_shared_acl_head *ptr; |
500 | list_for_each_entry(ptr, list, list) { | 529 | list_for_each_entry(ptr, list, list) { |
501 | if (atomic_read(&ptr->users)) | 530 | if (atomic_read(&ptr->users)) |
502 | continue; | 531 | continue; |
503 | if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list)) | 532 | if (!tomoyo_add_to_gc(id, &ptr->list)) |
504 | goto unlock; | 533 | goto unlock; |
505 | } | 534 | } |
535 | id = TOMOYO_ID_NAME; | ||
506 | } | 536 | } |
507 | unlock: | 537 | unlock: |
508 | tomoyo_read_unlock(idx); | 538 | tomoyo_read_unlock(idx); |
@@ -557,6 +587,9 @@ static bool tomoyo_kfree_entry(void) | |||
557 | case TOMOYO_ID_MANAGER: | 587 | case TOMOYO_ID_MANAGER: |
558 | tomoyo_del_manager(element); | 588 | tomoyo_del_manager(element); |
559 | break; | 589 | break; |
590 | case TOMOYO_ID_CONDITION: | ||
591 | tomoyo_del_condition(element); | ||
592 | break; | ||
560 | case TOMOYO_ID_NAME: | 593 | case TOMOYO_ID_NAME: |
561 | /* | 594 | /* |
562 | * Thirdly, defer until all "struct tomoyo_io_buffer" | 595 | * Thirdly, defer until all "struct tomoyo_io_buffer" |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 7ff54c95e1f2..e25f7ffd5ba7 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
@@ -138,7 +138,7 @@ char *tomoyo_read_token(struct tomoyo_acl_param *param) | |||
138 | * The @src is updated to point the first character after the value | 138 | * The @src is updated to point the first character after the value |
139 | * on success. | 139 | * on success. |
140 | */ | 140 | */ |
141 | static u8 tomoyo_parse_ulong(unsigned long *result, char **str) | 141 | u8 tomoyo_parse_ulong(unsigned long *result, char **str) |
142 | { | 142 | { |
143 | const char *cp = *str; | 143 | const char *cp = *str; |
144 | char *ep; | 144 | char *ep; |