diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/tomoyo/audit.c | 21 | ||||
-rw-r--r-- | security/tomoyo/common.c | 66 | ||||
-rw-r--r-- | security/tomoyo/common.h | 24 | ||||
-rw-r--r-- | security/tomoyo/condition.c | 116 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 5 |
5 files changed, 228 insertions, 4 deletions
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c index 4973edd40718..b33a20accbef 100644 --- a/security/tomoyo/audit.c +++ b/security/tomoyo/audit.c | |||
@@ -140,6 +140,8 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
140 | { | 140 | { |
141 | char *buf = NULL; | 141 | char *buf = NULL; |
142 | const char *header = NULL; | 142 | const char *header = NULL; |
143 | char *realpath = NULL; | ||
144 | const char *symlink = NULL; | ||
143 | int pos; | 145 | int pos; |
144 | const char *domainname = r->domain->domainname->name; | 146 | const char *domainname = r->domain->domainname->name; |
145 | header = tomoyo_print_header(r); | 147 | header = tomoyo_print_header(r); |
@@ -147,15 +149,34 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
147 | return NULL; | 149 | return NULL; |
148 | /* +10 is for '\n' etc. and '\0'. */ | 150 | /* +10 is for '\n' etc. and '\0'. */ |
149 | len += strlen(domainname) + strlen(header) + 10; | 151 | len += strlen(domainname) + strlen(header) + 10; |
152 | if (r->ee) { | ||
153 | struct file *file = r->ee->bprm->file; | ||
154 | realpath = tomoyo_realpath_from_path(&file->f_path); | ||
155 | if (!realpath) | ||
156 | goto out; | ||
157 | /* +80 is for " exec={ realpath=\"%s\" }" */ | ||
158 | len += strlen(realpath) + 80; | ||
159 | } else if (r->obj && r->obj->symlink_target) { | ||
160 | symlink = r->obj->symlink_target->name; | ||
161 | /* +18 is for " symlink.target=\"%s\"" */ | ||
162 | len += 18 + strlen(symlink); | ||
163 | } | ||
150 | len = tomoyo_round2(len); | 164 | len = tomoyo_round2(len); |
151 | buf = kzalloc(len, GFP_NOFS); | 165 | buf = kzalloc(len, GFP_NOFS); |
152 | if (!buf) | 166 | if (!buf) |
153 | goto out; | 167 | goto out; |
154 | len--; | 168 | len--; |
155 | pos = snprintf(buf, len, "%s", header); | 169 | pos = snprintf(buf, len, "%s", header); |
170 | if (realpath) { | ||
171 | pos += snprintf(buf + pos, len - pos, | ||
172 | " exec={ realpath=\"%s\" }", realpath); | ||
173 | } else if (symlink) | ||
174 | pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"", | ||
175 | symlink); | ||
156 | pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname); | 176 | pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname); |
157 | vsnprintf(buf + pos, len - pos, fmt, args); | 177 | vsnprintf(buf + pos, len - pos, fmt, args); |
158 | out: | 178 | out: |
179 | kfree(realpath); | ||
159 | kfree(header); | 180 | kfree(header); |
160 | return buf; | 181 | return buf; |
161 | } | 182 | } |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ec02d2ab08c3..69d6b59f5937 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -79,6 +79,8 @@ const char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = { | |||
79 | [TOMOYO_MODE_OTHERS_READ] = "others_read", | 79 | [TOMOYO_MODE_OTHERS_READ] = "others_read", |
80 | [TOMOYO_MODE_OTHERS_WRITE] = "others_write", | 80 | [TOMOYO_MODE_OTHERS_WRITE] = "others_write", |
81 | [TOMOYO_MODE_OTHERS_EXECUTE] = "others_execute", | 81 | [TOMOYO_MODE_OTHERS_EXECUTE] = "others_execute", |
82 | [TOMOYO_EXEC_REALPATH] = "exec.realpath", | ||
83 | [TOMOYO_SYMLINK_TARGET] = "symlink.target", | ||
82 | [TOMOYO_PATH1_UID] = "path1.uid", | 84 | [TOMOYO_PATH1_UID] = "path1.uid", |
83 | [TOMOYO_PATH1_GID] = "path1.gid", | 85 | [TOMOYO_PATH1_GID] = "path1.gid", |
84 | [TOMOYO_PATH1_INO] = "path1.ino", | 86 | [TOMOYO_PATH1_INO] = "path1.ino", |
@@ -353,6 +355,27 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head, | |||
353 | } | 355 | } |
354 | 356 | ||
355 | /** | 357 | /** |
358 | * tomoyo_print_name_union_quoted - Print a tomoyo_name_union with a quote. | ||
359 | * | ||
360 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
361 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
362 | * | ||
363 | * Returns nothing. | ||
364 | */ | ||
365 | static void tomoyo_print_name_union_quoted(struct tomoyo_io_buffer *head, | ||
366 | const struct tomoyo_name_union *ptr) | ||
367 | { | ||
368 | if (ptr->group) { | ||
369 | tomoyo_set_string(head, "@"); | ||
370 | tomoyo_set_string(head, ptr->group->group_name->name); | ||
371 | } else { | ||
372 | tomoyo_set_string(head, "\""); | ||
373 | tomoyo_set_string(head, ptr->filename->name); | ||
374 | tomoyo_set_string(head, "\""); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | /** | ||
356 | * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space. | 379 | * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space. |
357 | * | 380 | * |
358 | * @head: Pointer to "struct tomoyo_io_buffer". | 381 | * @head: Pointer to "struct tomoyo_io_buffer". |
@@ -1101,6 +1124,9 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
1101 | (typeof(condp)) (cond + 1); | 1124 | (typeof(condp)) (cond + 1); |
1102 | const struct tomoyo_number_union *numbers_p = | 1125 | const struct tomoyo_number_union *numbers_p = |
1103 | (typeof(numbers_p)) (condp + condc); | 1126 | (typeof(numbers_p)) (condp + condc); |
1127 | const struct tomoyo_name_union *names_p = | ||
1128 | (typeof(names_p)) | ||
1129 | (numbers_p + cond->numbers_count); | ||
1104 | u16 skip; | 1130 | u16 skip; |
1105 | for (skip = 0; skip < head->r.cond_index; skip++) { | 1131 | for (skip = 0; skip < head->r.cond_index; skip++) { |
1106 | const u8 left = condp->left; | 1132 | const u8 left = condp->left; |
@@ -1112,6 +1138,9 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
1112 | break; | 1138 | break; |
1113 | } | 1139 | } |
1114 | switch (right) { | 1140 | switch (right) { |
1141 | case TOMOYO_NAME_UNION: | ||
1142 | names_p++; | ||
1143 | break; | ||
1115 | case TOMOYO_NUMBER_UNION: | 1144 | case TOMOYO_NUMBER_UNION: |
1116 | numbers_p++; | 1145 | numbers_p++; |
1117 | break; | 1146 | break; |
@@ -1138,6 +1167,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
1138 | } | 1167 | } |
1139 | tomoyo_set_string(head, match ? "=" : "!="); | 1168 | tomoyo_set_string(head, match ? "=" : "!="); |
1140 | switch (right) { | 1169 | switch (right) { |
1170 | case TOMOYO_NAME_UNION: | ||
1171 | tomoyo_print_name_union_quoted | ||
1172 | (head, names_p++); | ||
1173 | break; | ||
1141 | case TOMOYO_NUMBER_UNION: | 1174 | case TOMOYO_NUMBER_UNION: |
1142 | tomoyo_print_number_union_nospace | 1175 | tomoyo_print_number_union_nospace |
1143 | (head, numbers_p++); | 1176 | (head, numbers_p++); |
@@ -1666,6 +1699,22 @@ static DEFINE_SPINLOCK(tomoyo_query_list_lock); | |||
1666 | static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); | 1699 | static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); |
1667 | 1700 | ||
1668 | /** | 1701 | /** |
1702 | * tomoyo_truncate - Truncate a line. | ||
1703 | * | ||
1704 | * @str: String to truncate. | ||
1705 | * | ||
1706 | * Returns length of truncated @str. | ||
1707 | */ | ||
1708 | static int tomoyo_truncate(char *str) | ||
1709 | { | ||
1710 | char *start = str; | ||
1711 | while (*(unsigned char *) str > (unsigned char) ' ') | ||
1712 | str++; | ||
1713 | *str = '\0'; | ||
1714 | return strlen(start) + 1; | ||
1715 | } | ||
1716 | |||
1717 | /** | ||
1669 | * tomoyo_add_entry - Add an ACL to current thread's domain. Used by learning mode. | 1718 | * tomoyo_add_entry - Add an ACL to current thread's domain. Used by learning mode. |
1670 | * | 1719 | * |
1671 | * @domain: Pointer to "struct tomoyo_domain_info". | 1720 | * @domain: Pointer to "struct tomoyo_domain_info". |
@@ -1676,6 +1725,8 @@ static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); | |||
1676 | static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) | 1725 | static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) |
1677 | { | 1726 | { |
1678 | char *buffer; | 1727 | char *buffer; |
1728 | char *realpath = NULL; | ||
1729 | char *symlink = NULL; | ||
1679 | char *cp = strchr(header, '\n'); | 1730 | char *cp = strchr(header, '\n'); |
1680 | int len; | 1731 | int len; |
1681 | if (!cp) | 1732 | if (!cp) |
@@ -1685,10 +1736,25 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) | |||
1685 | return; | 1736 | return; |
1686 | *cp++ = '\0'; | 1737 | *cp++ = '\0'; |
1687 | len = strlen(cp) + 1; | 1738 | len = strlen(cp) + 1; |
1739 | /* strstr() will return NULL if ordering is wrong. */ | ||
1740 | if (*cp == 'f') { | ||
1741 | realpath = strstr(header, " exec={ realpath=\""); | ||
1742 | if (realpath) { | ||
1743 | realpath += 8; | ||
1744 | len += tomoyo_truncate(realpath) + 6; | ||
1745 | } | ||
1746 | symlink = strstr(header, " symlink.target=\""); | ||
1747 | if (symlink) | ||
1748 | len += tomoyo_truncate(symlink + 1) + 1; | ||
1749 | } | ||
1688 | buffer = kmalloc(len, GFP_NOFS); | 1750 | buffer = kmalloc(len, GFP_NOFS); |
1689 | if (!buffer) | 1751 | if (!buffer) |
1690 | return; | 1752 | return; |
1691 | snprintf(buffer, len - 1, "%s", cp); | 1753 | snprintf(buffer, len - 1, "%s", cp); |
1754 | if (realpath) | ||
1755 | tomoyo_addprintf(buffer, len, " exec.%s", realpath); | ||
1756 | if (symlink) | ||
1757 | tomoyo_addprintf(buffer, len, "%s", symlink); | ||
1692 | tomoyo_normalize_line(buffer); | 1758 | tomoyo_normalize_line(buffer); |
1693 | if (!tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer, | 1759 | if (!tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer, |
1694 | false)) | 1760 | false)) |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 5a0fcedb332b..7e56e6b364e5 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -73,6 +73,8 @@ enum tomoyo_conditions_index { | |||
73 | TOMOYO_MODE_OTHERS_READ, /* S_IROTH */ | 73 | TOMOYO_MODE_OTHERS_READ, /* S_IROTH */ |
74 | TOMOYO_MODE_OTHERS_WRITE, /* S_IWOTH */ | 74 | TOMOYO_MODE_OTHERS_WRITE, /* S_IWOTH */ |
75 | TOMOYO_MODE_OTHERS_EXECUTE, /* S_IXOTH */ | 75 | TOMOYO_MODE_OTHERS_EXECUTE, /* S_IXOTH */ |
76 | TOMOYO_EXEC_REALPATH, | ||
77 | TOMOYO_SYMLINK_TARGET, | ||
76 | TOMOYO_PATH1_UID, | 78 | TOMOYO_PATH1_UID, |
77 | TOMOYO_PATH1_GID, | 79 | TOMOYO_PATH1_GID, |
78 | TOMOYO_PATH1_INO, | 80 | TOMOYO_PATH1_INO, |
@@ -101,6 +103,7 @@ enum tomoyo_conditions_index { | |||
101 | TOMOYO_PATH2_PARENT_PERM, | 103 | TOMOYO_PATH2_PARENT_PERM, |
102 | TOMOYO_MAX_CONDITION_KEYWORD, | 104 | TOMOYO_MAX_CONDITION_KEYWORD, |
103 | TOMOYO_NUMBER_UNION, | 105 | TOMOYO_NUMBER_UNION, |
106 | TOMOYO_NAME_UNION, | ||
104 | }; | 107 | }; |
105 | 108 | ||
106 | 109 | ||
@@ -351,6 +354,11 @@ struct tomoyo_request_info { | |||
351 | * NULL if not dealing files. | 354 | * NULL if not dealing files. |
352 | */ | 355 | */ |
353 | struct tomoyo_obj_info *obj; | 356 | struct tomoyo_obj_info *obj; |
357 | /* | ||
358 | * For holding parameters specific to execve() request. | ||
359 | * NULL if not dealing do_execve(). | ||
360 | */ | ||
361 | struct tomoyo_execve *ee; | ||
354 | struct tomoyo_domain_info *domain; | 362 | struct tomoyo_domain_info *domain; |
355 | /* For holding parameters. */ | 363 | /* For holding parameters. */ |
356 | union { | 364 | union { |
@@ -476,6 +484,20 @@ struct tomoyo_obj_info { | |||
476 | * parent directory. | 484 | * parent directory. |
477 | */ | 485 | */ |
478 | struct tomoyo_mini_stat stat[TOMOYO_MAX_PATH_STAT]; | 486 | struct tomoyo_mini_stat stat[TOMOYO_MAX_PATH_STAT]; |
487 | /* | ||
488 | * Content of symbolic link to be created. NULL for operations other | ||
489 | * than symlink(). | ||
490 | */ | ||
491 | struct tomoyo_path_info *symlink_target; | ||
492 | }; | ||
493 | |||
494 | /* Structure for execve() operation. */ | ||
495 | struct tomoyo_execve { | ||
496 | struct tomoyo_request_info r; | ||
497 | struct tomoyo_obj_info obj; | ||
498 | struct linux_binprm *bprm; | ||
499 | /* For temporary use. */ | ||
500 | char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ | ||
479 | }; | 501 | }; |
480 | 502 | ||
481 | /* Structure for entries which follows "struct tomoyo_condition". */ | 503 | /* Structure for entries which follows "struct tomoyo_condition". */ |
@@ -494,9 +516,11 @@ struct tomoyo_condition { | |||
494 | u32 size; /* Memory size allocated for this entry. */ | 516 | u32 size; /* Memory size allocated for this entry. */ |
495 | u16 condc; /* Number of conditions in this struct. */ | 517 | u16 condc; /* Number of conditions in this struct. */ |
496 | u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ | 518 | u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ |
519 | u16 names_count; /* Number of "struct tomoyo_name_union names". */ | ||
497 | /* | 520 | /* |
498 | * struct tomoyo_condition_element condition[condc]; | 521 | * struct tomoyo_condition_element condition[condc]; |
499 | * struct tomoyo_number_union values[numbers_count]; | 522 | * struct tomoyo_number_union values[numbers_count]; |
523 | * struct tomoyo_name_union names[names_count]; | ||
500 | */ | 524 | */ |
501 | }; | 525 | }; |
502 | 526 | ||
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c index ac7ebeb47d7d..790b9872cc37 100644 --- a/security/tomoyo/condition.c +++ b/security/tomoyo/condition.c | |||
@@ -11,6 +11,68 @@ | |||
11 | LIST_HEAD(tomoyo_condition_list); | 11 | LIST_HEAD(tomoyo_condition_list); |
12 | 12 | ||
13 | /** | 13 | /** |
14 | * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition". | ||
15 | * | ||
16 | * @file: Pointer to "struct file". | ||
17 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
18 | * @match: True if "exec.realpath=", false if "exec.realpath!=". | ||
19 | * | ||
20 | * Returns true on success, false otherwise. | ||
21 | */ | ||
22 | static bool tomoyo_scan_exec_realpath(struct file *file, | ||
23 | const struct tomoyo_name_union *ptr, | ||
24 | const bool match) | ||
25 | { | ||
26 | bool result; | ||
27 | struct tomoyo_path_info exe; | ||
28 | if (!file) | ||
29 | return false; | ||
30 | exe.name = tomoyo_realpath_from_path(&file->f_path); | ||
31 | if (!exe.name) | ||
32 | return false; | ||
33 | tomoyo_fill_path_info(&exe); | ||
34 | result = tomoyo_compare_name_union(&exe, ptr); | ||
35 | kfree(exe.name); | ||
36 | return result == match; | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * tomoyo_get_dqword - tomoyo_get_name() for a quoted string. | ||
41 | * | ||
42 | * @start: String to save. | ||
43 | * | ||
44 | * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. | ||
45 | */ | ||
46 | static const struct tomoyo_path_info *tomoyo_get_dqword(char *start) | ||
47 | { | ||
48 | char *cp = start + strlen(start) - 1; | ||
49 | if (cp == start || *start++ != '"' || *cp != '"') | ||
50 | return NULL; | ||
51 | *cp = '\0'; | ||
52 | if (*start && !tomoyo_correct_word(start)) | ||
53 | return NULL; | ||
54 | return tomoyo_get_name(start); | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * tomoyo_parse_name_union_quoted - Parse a quoted word. | ||
59 | * | ||
60 | * @param: Pointer to "struct tomoyo_acl_param". | ||
61 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
62 | * | ||
63 | * Returns true on success, false otherwise. | ||
64 | */ | ||
65 | static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param, | ||
66 | struct tomoyo_name_union *ptr) | ||
67 | { | ||
68 | char *filename = param->data; | ||
69 | if (*filename == '@') | ||
70 | return tomoyo_parse_name_union(param, ptr); | ||
71 | ptr->filename = tomoyo_get_dqword(filename); | ||
72 | return ptr->filename != NULL; | ||
73 | } | ||
74 | |||
75 | /** | ||
14 | * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry. | 76 | * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry. |
15 | * | 77 | * |
16 | * @a: Pointer to "struct tomoyo_condition". | 78 | * @a: Pointer to "struct tomoyo_condition". |
@@ -23,6 +85,7 @@ static inline bool tomoyo_same_condition(const struct tomoyo_condition *a, | |||
23 | { | 85 | { |
24 | return a->size == b->size && a->condc == b->condc && | 86 | return a->size == b->size && a->condc == b->condc && |
25 | a->numbers_count == b->numbers_count && | 87 | a->numbers_count == b->numbers_count && |
88 | a->names_count == b->names_count && | ||
26 | !memcmp(a + 1, b + 1, a->size - sizeof(*a)); | 89 | !memcmp(a + 1, b + 1, a->size - sizeof(*a)); |
27 | } | 90 | } |
28 | 91 | ||
@@ -114,6 +177,7 @@ struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param) | |||
114 | struct tomoyo_condition *entry = NULL; | 177 | struct tomoyo_condition *entry = NULL; |
115 | struct tomoyo_condition_element *condp = NULL; | 178 | struct tomoyo_condition_element *condp = NULL; |
116 | struct tomoyo_number_union *numbers_p = NULL; | 179 | struct tomoyo_number_union *numbers_p = NULL; |
180 | struct tomoyo_name_union *names_p = NULL; | ||
117 | struct tomoyo_condition e = { }; | 181 | struct tomoyo_condition e = { }; |
118 | char * const start_of_string = param->data; | 182 | char * const start_of_string = param->data; |
119 | char * const end_of_string = start_of_string + strlen(start_of_string); | 183 | char * const end_of_string = start_of_string + strlen(start_of_string); |
@@ -178,6 +242,20 @@ rerun: | |||
178 | e.condc++; | 242 | e.condc++; |
179 | else | 243 | else |
180 | e.condc--; | 244 | e.condc--; |
245 | if (left == TOMOYO_EXEC_REALPATH || | ||
246 | left == TOMOYO_SYMLINK_TARGET) { | ||
247 | if (!names_p) { | ||
248 | e.names_count++; | ||
249 | } else { | ||
250 | e.names_count--; | ||
251 | right = TOMOYO_NAME_UNION; | ||
252 | param->data = right_word; | ||
253 | if (!tomoyo_parse_name_union_quoted(param, | ||
254 | names_p++)) | ||
255 | goto out; | ||
256 | } | ||
257 | goto store_value; | ||
258 | } | ||
181 | right = tomoyo_condition_type(right_word); | 259 | right = tomoyo_condition_type(right_word); |
182 | if (right == TOMOYO_MAX_CONDITION_KEYWORD) { | 260 | if (right == TOMOYO_MAX_CONDITION_KEYWORD) { |
183 | if (!numbers_p) { | 261 | if (!numbers_p) { |
@@ -191,6 +269,7 @@ rerun: | |||
191 | goto out; | 269 | goto out; |
192 | } | 270 | } |
193 | } | 271 | } |
272 | store_value: | ||
194 | if (!condp) { | 273 | if (!condp) { |
195 | dprintk(KERN_WARNING "%u: dry_run left=%u right=%u " | 274 | dprintk(KERN_WARNING "%u: dry_run left=%u right=%u " |
196 | "match=%u\n", __LINE__, left, right, !is_not); | 275 | "match=%u\n", __LINE__, left, right, !is_not); |
@@ -204,21 +283,23 @@ rerun: | |||
204 | condp->equals); | 283 | condp->equals); |
205 | condp++; | 284 | condp++; |
206 | } | 285 | } |
207 | dprintk(KERN_INFO "%u: cond=%u numbers=%u\n", | 286 | dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u\n", |
208 | __LINE__, e.condc, e.numbers_count); | 287 | __LINE__, e.condc, e.numbers_count, e.names_count); |
209 | if (entry) { | 288 | if (entry) { |
210 | BUG_ON(e.numbers_count | e.condc); | 289 | BUG_ON(e.names_count | e.numbers_count | e.condc); |
211 | return tomoyo_commit_condition(entry); | 290 | return tomoyo_commit_condition(entry); |
212 | } | 291 | } |
213 | e.size = sizeof(*entry) | 292 | e.size = sizeof(*entry) |
214 | + e.condc * sizeof(struct tomoyo_condition_element) | 293 | + e.condc * sizeof(struct tomoyo_condition_element) |
215 | + e.numbers_count * sizeof(struct tomoyo_number_union); | 294 | + e.numbers_count * sizeof(struct tomoyo_number_union) |
295 | + e.names_count * sizeof(struct tomoyo_name_union); | ||
216 | entry = kzalloc(e.size, GFP_NOFS); | 296 | entry = kzalloc(e.size, GFP_NOFS); |
217 | if (!entry) | 297 | if (!entry) |
218 | return NULL; | 298 | return NULL; |
219 | *entry = e; | 299 | *entry = e; |
220 | condp = (struct tomoyo_condition_element *) (entry + 1); | 300 | condp = (struct tomoyo_condition_element *) (entry + 1); |
221 | numbers_p = (struct tomoyo_number_union *) (condp + e.condc); | 301 | numbers_p = (struct tomoyo_number_union *) (condp + e.condc); |
302 | names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count); | ||
222 | { | 303 | { |
223 | bool flag = false; | 304 | bool flag = false; |
224 | for (pos = start_of_string; pos < end_of_string; pos++) { | 305 | for (pos = start_of_string; pos < end_of_string; pos++) { |
@@ -309,6 +390,7 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
309 | unsigned long max_v[2] = { 0, 0 }; | 390 | unsigned long max_v[2] = { 0, 0 }; |
310 | const struct tomoyo_condition_element *condp; | 391 | const struct tomoyo_condition_element *condp; |
311 | const struct tomoyo_number_union *numbers_p; | 392 | const struct tomoyo_number_union *numbers_p; |
393 | const struct tomoyo_name_union *names_p; | ||
312 | struct tomoyo_obj_info *obj; | 394 | struct tomoyo_obj_info *obj; |
313 | u16 condc; | 395 | u16 condc; |
314 | if (!cond) | 396 | if (!cond) |
@@ -317,6 +399,8 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
317 | obj = r->obj; | 399 | obj = r->obj; |
318 | condp = (struct tomoyo_condition_element *) (cond + 1); | 400 | condp = (struct tomoyo_condition_element *) (cond + 1); |
319 | numbers_p = (const struct tomoyo_number_union *) (condp + condc); | 401 | numbers_p = (const struct tomoyo_number_union *) (condp + condc); |
402 | names_p = (const struct tomoyo_name_union *) | ||
403 | (numbers_p + cond->numbers_count); | ||
320 | for (i = 0; i < condc; i++) { | 404 | for (i = 0; i < condc; i++) { |
321 | const bool match = condp->equals; | 405 | const bool match = condp->equals; |
322 | const u8 left = condp->left; | 406 | const u8 left = condp->left; |
@@ -324,6 +408,30 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
324 | bool is_bitop[2] = { false, false }; | 408 | bool is_bitop[2] = { false, false }; |
325 | u8 j; | 409 | u8 j; |
326 | condp++; | 410 | condp++; |
411 | /* Check string expressions. */ | ||
412 | if (right == TOMOYO_NAME_UNION) { | ||
413 | const struct tomoyo_name_union *ptr = names_p++; | ||
414 | switch (left) { | ||
415 | struct tomoyo_path_info *symlink; | ||
416 | struct tomoyo_execve *ee; | ||
417 | struct file *file; | ||
418 | case TOMOYO_SYMLINK_TARGET: | ||
419 | symlink = obj ? obj->symlink_target : NULL; | ||
420 | if (!symlink || | ||
421 | !tomoyo_compare_name_union(symlink, ptr) | ||
422 | == match) | ||
423 | goto out; | ||
424 | break; | ||
425 | case TOMOYO_EXEC_REALPATH: | ||
426 | ee = r->ee; | ||
427 | file = ee ? ee->bprm->file : NULL; | ||
428 | if (!tomoyo_scan_exec_realpath(file, ptr, | ||
429 | match)) | ||
430 | goto out; | ||
431 | break; | ||
432 | } | ||
433 | continue; | ||
434 | } | ||
327 | /* Check numeric or bit-op expressions. */ | 435 | /* Check numeric or bit-op expressions. */ |
328 | for (j = 0; j < 2; j++) { | 436 | for (j = 0; j < 2; j++) { |
329 | const u8 index = j ? right : left; | 437 | const u8 index = j ? right : left; |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 21fccd67c255..e0502b6d5866 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -357,13 +357,18 @@ void tomoyo_del_condition(struct list_head *element) | |||
357 | head.list); | 357 | head.list); |
358 | const u16 condc = cond->condc; | 358 | const u16 condc = cond->condc; |
359 | const u16 numbers_count = cond->numbers_count; | 359 | const u16 numbers_count = cond->numbers_count; |
360 | const u16 names_count = cond->names_count; | ||
360 | unsigned int i; | 361 | unsigned int i; |
361 | const struct tomoyo_condition_element *condp | 362 | const struct tomoyo_condition_element *condp |
362 | = (const struct tomoyo_condition_element *) (cond + 1); | 363 | = (const struct tomoyo_condition_element *) (cond + 1); |
363 | struct tomoyo_number_union *numbers_p | 364 | struct tomoyo_number_union *numbers_p |
364 | = (struct tomoyo_number_union *) (condp + condc); | 365 | = (struct tomoyo_number_union *) (condp + condc); |
366 | struct tomoyo_name_union *names_p | ||
367 | = (struct tomoyo_name_union *) (numbers_p + numbers_count); | ||
365 | for (i = 0; i < numbers_count; i++) | 368 | for (i = 0; i < numbers_count; i++) |
366 | tomoyo_put_number_union(numbers_p++); | 369 | tomoyo_put_number_union(numbers_p++); |
370 | for (i = 0; i < names_count; i++) | ||
371 | tomoyo_put_name_union(names_p++); | ||
367 | } | 372 | } |
368 | 373 | ||
369 | /** | 374 | /** |