diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-07-08 00:24:54 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-07-10 21:05:33 -0400 |
commit | 5b636857fee642694e287e3a181b523b16098c93 (patch) | |
tree | 24afcc11fc35350a29f5d6d73d376a551c5569b8 /security/tomoyo | |
parent | 2ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563 (diff) |
TOMOYO: Allow using argv[]/envp[] of execve() as conditions.
This patch adds support for permission checks using argv[]/envp[] of execve()
request. Hooks are in the last patch of this pathset.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo')
-rw-r--r-- | security/tomoyo/audit.c | 111 | ||||
-rw-r--r-- | security/tomoyo/common.c | 48 | ||||
-rw-r--r-- | security/tomoyo/common.h | 45 | ||||
-rw-r--r-- | security/tomoyo/condition.c | 337 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 46 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 12 |
6 files changed, 589 insertions, 10 deletions
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c index b33a20accbef..eefedd9e48e6 100644 --- a/security/tomoyo/audit.c +++ b/security/tomoyo/audit.c | |||
@@ -10,6 +10,104 @@ | |||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | 11 | ||
12 | /** | 12 | /** |
13 | * tomoyo_print_bprm - Print "struct linux_binprm" for auditing. | ||
14 | * | ||
15 | * @bprm: Pointer to "struct linux_binprm". | ||
16 | * @dump: Pointer to "struct tomoyo_page_dump". | ||
17 | * | ||
18 | * Returns the contents of @bprm on success, NULL otherwise. | ||
19 | * | ||
20 | * This function uses kzalloc(), so caller must kfree() if this function | ||
21 | * didn't return NULL. | ||
22 | */ | ||
23 | static char *tomoyo_print_bprm(struct linux_binprm *bprm, | ||
24 | struct tomoyo_page_dump *dump) | ||
25 | { | ||
26 | static const int tomoyo_buffer_len = 4096 * 2; | ||
27 | char *buffer = kzalloc(tomoyo_buffer_len, GFP_NOFS); | ||
28 | char *cp; | ||
29 | char *last_start; | ||
30 | int len; | ||
31 | unsigned long pos = bprm->p; | ||
32 | int offset = pos % PAGE_SIZE; | ||
33 | int argv_count = bprm->argc; | ||
34 | int envp_count = bprm->envc; | ||
35 | bool truncated = false; | ||
36 | if (!buffer) | ||
37 | return NULL; | ||
38 | len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ "); | ||
39 | cp = buffer + len; | ||
40 | if (!argv_count) { | ||
41 | memmove(cp, "} envp[]={ ", 11); | ||
42 | cp += 11; | ||
43 | } | ||
44 | last_start = cp; | ||
45 | while (argv_count || envp_count) { | ||
46 | if (!tomoyo_dump_page(bprm, pos, dump)) | ||
47 | goto out; | ||
48 | pos += PAGE_SIZE - offset; | ||
49 | /* Read. */ | ||
50 | while (offset < PAGE_SIZE) { | ||
51 | const char *kaddr = dump->data; | ||
52 | const unsigned char c = kaddr[offset++]; | ||
53 | if (cp == last_start) | ||
54 | *cp++ = '"'; | ||
55 | if (cp >= buffer + tomoyo_buffer_len - 32) { | ||
56 | /* Reserve some room for "..." string. */ | ||
57 | truncated = true; | ||
58 | } else if (c == '\\') { | ||
59 | *cp++ = '\\'; | ||
60 | *cp++ = '\\'; | ||
61 | } else if (c > ' ' && c < 127) { | ||
62 | *cp++ = c; | ||
63 | } else if (!c) { | ||
64 | *cp++ = '"'; | ||
65 | *cp++ = ' '; | ||
66 | last_start = cp; | ||
67 | } else { | ||
68 | *cp++ = '\\'; | ||
69 | *cp++ = (c >> 6) + '0'; | ||
70 | *cp++ = ((c >> 3) & 7) + '0'; | ||
71 | *cp++ = (c & 7) + '0'; | ||
72 | } | ||
73 | if (c) | ||
74 | continue; | ||
75 | if (argv_count) { | ||
76 | if (--argv_count == 0) { | ||
77 | if (truncated) { | ||
78 | cp = last_start; | ||
79 | memmove(cp, "... ", 4); | ||
80 | cp += 4; | ||
81 | } | ||
82 | memmove(cp, "} envp[]={ ", 11); | ||
83 | cp += 11; | ||
84 | last_start = cp; | ||
85 | truncated = false; | ||
86 | } | ||
87 | } else if (envp_count) { | ||
88 | if (--envp_count == 0) { | ||
89 | if (truncated) { | ||
90 | cp = last_start; | ||
91 | memmove(cp, "... ", 4); | ||
92 | cp += 4; | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | if (!argv_count && !envp_count) | ||
97 | break; | ||
98 | } | ||
99 | offset = 0; | ||
100 | } | ||
101 | *cp++ = '}'; | ||
102 | *cp = '\0'; | ||
103 | return buffer; | ||
104 | out: | ||
105 | snprintf(buffer, tomoyo_buffer_len - 1, | ||
106 | "argv[]={ ... } envp[]= { ... }"); | ||
107 | return buffer; | ||
108 | } | ||
109 | |||
110 | /** | ||
13 | * tomoyo_filetype - Get string representation of file type. | 111 | * tomoyo_filetype - Get string representation of file type. |
14 | * | 112 | * |
15 | * @mode: Mode value for stat(). | 113 | * @mode: Mode value for stat(). |
@@ -139,6 +237,7 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
139 | va_list args) | 237 | va_list args) |
140 | { | 238 | { |
141 | char *buf = NULL; | 239 | char *buf = NULL; |
240 | char *bprm_info = NULL; | ||
142 | const char *header = NULL; | 241 | const char *header = NULL; |
143 | char *realpath = NULL; | 242 | char *realpath = NULL; |
144 | const char *symlink = NULL; | 243 | const char *symlink = NULL; |
@@ -152,10 +251,11 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
152 | if (r->ee) { | 251 | if (r->ee) { |
153 | struct file *file = r->ee->bprm->file; | 252 | struct file *file = r->ee->bprm->file; |
154 | realpath = tomoyo_realpath_from_path(&file->f_path); | 253 | realpath = tomoyo_realpath_from_path(&file->f_path); |
155 | if (!realpath) | 254 | bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump); |
255 | if (!realpath || !bprm_info) | ||
156 | goto out; | 256 | goto out; |
157 | /* +80 is for " exec={ realpath=\"%s\" }" */ | 257 | /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */ |
158 | len += strlen(realpath) + 80; | 258 | len += strlen(realpath) + 80 + strlen(bprm_info); |
159 | } else if (r->obj && r->obj->symlink_target) { | 259 | } else if (r->obj && r->obj->symlink_target) { |
160 | symlink = r->obj->symlink_target->name; | 260 | symlink = r->obj->symlink_target->name; |
161 | /* +18 is for " symlink.target=\"%s\"" */ | 261 | /* +18 is for " symlink.target=\"%s\"" */ |
@@ -168,8 +268,10 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
168 | len--; | 268 | len--; |
169 | pos = snprintf(buf, len, "%s", header); | 269 | pos = snprintf(buf, len, "%s", header); |
170 | if (realpath) { | 270 | if (realpath) { |
271 | struct linux_binprm *bprm = r->ee->bprm; | ||
171 | pos += snprintf(buf + pos, len - pos, | 272 | pos += snprintf(buf + pos, len - pos, |
172 | " exec={ realpath=\"%s\" }", realpath); | 273 | " exec={ realpath=\"%s\" argc=%d envc=%d %s }", |
274 | realpath, bprm->argc, bprm->envc, bprm_info); | ||
173 | } else if (symlink) | 275 | } else if (symlink) |
174 | pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"", | 276 | pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"", |
175 | symlink); | 277 | symlink); |
@@ -177,6 +279,7 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |||
177 | vsnprintf(buf + pos, len - pos, fmt, args); | 279 | vsnprintf(buf + pos, len - pos, fmt, args); |
178 | out: | 280 | out: |
179 | kfree(realpath); | 281 | kfree(realpath); |
282 | kfree(bprm_info); | ||
180 | kfree(header); | 283 | kfree(header); |
181 | return buf; | 284 | return buf; |
182 | } | 285 | } |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 69d6b59f5937..4f9047e94bd1 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -60,6 +60,8 @@ const char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = { | |||
60 | [TOMOYO_TASK_FSGID] = "task.fsgid", | 60 | [TOMOYO_TASK_FSGID] = "task.fsgid", |
61 | [TOMOYO_TASK_PID] = "task.pid", | 61 | [TOMOYO_TASK_PID] = "task.pid", |
62 | [TOMOYO_TASK_PPID] = "task.ppid", | 62 | [TOMOYO_TASK_PPID] = "task.ppid", |
63 | [TOMOYO_EXEC_ARGC] = "exec.argc", | ||
64 | [TOMOYO_EXEC_ENVC] = "exec.envc", | ||
63 | [TOMOYO_TYPE_IS_SOCKET] = "socket", | 65 | [TOMOYO_TYPE_IS_SOCKET] = "socket", |
64 | [TOMOYO_TYPE_IS_SYMLINK] = "symlink", | 66 | [TOMOYO_TYPE_IS_SYMLINK] = "symlink", |
65 | [TOMOYO_TYPE_IS_FILE] = "file", | 67 | [TOMOYO_TYPE_IS_FILE] = "file", |
@@ -1127,12 +1129,22 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
1127 | const struct tomoyo_name_union *names_p = | 1129 | const struct tomoyo_name_union *names_p = |
1128 | (typeof(names_p)) | 1130 | (typeof(names_p)) |
1129 | (numbers_p + cond->numbers_count); | 1131 | (numbers_p + cond->numbers_count); |
1132 | const struct tomoyo_argv *argv = | ||
1133 | (typeof(argv)) (names_p + cond->names_count); | ||
1134 | const struct tomoyo_envp *envp = | ||
1135 | (typeof(envp)) (argv + cond->argc); | ||
1130 | u16 skip; | 1136 | u16 skip; |
1131 | for (skip = 0; skip < head->r.cond_index; skip++) { | 1137 | for (skip = 0; skip < head->r.cond_index; skip++) { |
1132 | const u8 left = condp->left; | 1138 | const u8 left = condp->left; |
1133 | const u8 right = condp->right; | 1139 | const u8 right = condp->right; |
1134 | condp++; | 1140 | condp++; |
1135 | switch (left) { | 1141 | switch (left) { |
1142 | case TOMOYO_ARGV_ENTRY: | ||
1143 | argv++; | ||
1144 | continue; | ||
1145 | case TOMOYO_ENVP_ENTRY: | ||
1146 | envp++; | ||
1147 | continue; | ||
1136 | case TOMOYO_NUMBER_UNION: | 1148 | case TOMOYO_NUMBER_UNION: |
1137 | numbers_p++; | 1149 | numbers_p++; |
1138 | break; | 1150 | break; |
@@ -1156,6 +1168,34 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, | |||
1156 | head->r.cond_index++; | 1168 | head->r.cond_index++; |
1157 | tomoyo_set_space(head); | 1169 | tomoyo_set_space(head); |
1158 | switch (left) { | 1170 | switch (left) { |
1171 | case TOMOYO_ARGV_ENTRY: | ||
1172 | tomoyo_io_printf(head, | ||
1173 | "exec.argv[%lu]%s=\"", | ||
1174 | argv->index, argv-> | ||
1175 | is_not ? "!" : ""); | ||
1176 | tomoyo_set_string(head, | ||
1177 | argv->value->name); | ||
1178 | tomoyo_set_string(head, "\""); | ||
1179 | argv++; | ||
1180 | continue; | ||
1181 | case TOMOYO_ENVP_ENTRY: | ||
1182 | tomoyo_set_string(head, | ||
1183 | "exec.envp[\""); | ||
1184 | tomoyo_set_string(head, | ||
1185 | envp->name->name); | ||
1186 | tomoyo_io_printf(head, "\"]%s=", envp-> | ||
1187 | is_not ? "!" : ""); | ||
1188 | if (envp->value) { | ||
1189 | tomoyo_set_string(head, "\""); | ||
1190 | tomoyo_set_string(head, envp-> | ||
1191 | value->name); | ||
1192 | tomoyo_set_string(head, "\""); | ||
1193 | } else { | ||
1194 | tomoyo_set_string(head, | ||
1195 | "NULL"); | ||
1196 | } | ||
1197 | envp++; | ||
1198 | continue; | ||
1159 | case TOMOYO_NUMBER_UNION: | 1199 | case TOMOYO_NUMBER_UNION: |
1160 | tomoyo_print_number_union_nospace | 1200 | tomoyo_print_number_union_nospace |
1161 | (head, numbers_p++); | 1201 | (head, numbers_p++); |
@@ -1726,6 +1766,7 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) | |||
1726 | { | 1766 | { |
1727 | char *buffer; | 1767 | char *buffer; |
1728 | char *realpath = NULL; | 1768 | char *realpath = NULL; |
1769 | char *argv0 = NULL; | ||
1729 | char *symlink = NULL; | 1770 | char *symlink = NULL; |
1730 | char *cp = strchr(header, '\n'); | 1771 | char *cp = strchr(header, '\n'); |
1731 | int len; | 1772 | int len; |
@@ -1738,6 +1779,11 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) | |||
1738 | len = strlen(cp) + 1; | 1779 | len = strlen(cp) + 1; |
1739 | /* strstr() will return NULL if ordering is wrong. */ | 1780 | /* strstr() will return NULL if ordering is wrong. */ |
1740 | if (*cp == 'f') { | 1781 | if (*cp == 'f') { |
1782 | argv0 = strstr(header, " argv[]={ \""); | ||
1783 | if (argv0) { | ||
1784 | argv0 += 10; | ||
1785 | len += tomoyo_truncate(argv0) + 14; | ||
1786 | } | ||
1741 | realpath = strstr(header, " exec={ realpath=\""); | 1787 | realpath = strstr(header, " exec={ realpath=\""); |
1742 | if (realpath) { | 1788 | if (realpath) { |
1743 | realpath += 8; | 1789 | realpath += 8; |
@@ -1753,6 +1799,8 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) | |||
1753 | snprintf(buffer, len - 1, "%s", cp); | 1799 | snprintf(buffer, len - 1, "%s", cp); |
1754 | if (realpath) | 1800 | if (realpath) |
1755 | tomoyo_addprintf(buffer, len, " exec.%s", realpath); | 1801 | tomoyo_addprintf(buffer, len, " exec.%s", realpath); |
1802 | if (argv0) | ||
1803 | tomoyo_addprintf(buffer, len, " exec.argv[0]=%s", argv0); | ||
1756 | if (symlink) | 1804 | if (symlink) |
1757 | tomoyo_addprintf(buffer, len, "%s", symlink); | 1805 | tomoyo_addprintf(buffer, len, "%s", symlink); |
1758 | tomoyo_normalize_line(buffer); | 1806 | tomoyo_normalize_line(buffer); |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 7e56e6b364e5..6c013b177791 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -54,6 +54,8 @@ enum tomoyo_conditions_index { | |||
54 | TOMOYO_TASK_FSGID, /* current_fsgid() */ | 54 | TOMOYO_TASK_FSGID, /* current_fsgid() */ |
55 | TOMOYO_TASK_PID, /* sys_getpid() */ | 55 | TOMOYO_TASK_PID, /* sys_getpid() */ |
56 | TOMOYO_TASK_PPID, /* sys_getppid() */ | 56 | TOMOYO_TASK_PPID, /* sys_getppid() */ |
57 | TOMOYO_EXEC_ARGC, /* "struct linux_binprm *"->argc */ | ||
58 | TOMOYO_EXEC_ENVC, /* "struct linux_binprm *"->envc */ | ||
57 | TOMOYO_TYPE_IS_SOCKET, /* S_IFSOCK */ | 59 | TOMOYO_TYPE_IS_SOCKET, /* S_IFSOCK */ |
58 | TOMOYO_TYPE_IS_SYMLINK, /* S_IFLNK */ | 60 | TOMOYO_TYPE_IS_SYMLINK, /* S_IFLNK */ |
59 | TOMOYO_TYPE_IS_FILE, /* S_IFREG */ | 61 | TOMOYO_TYPE_IS_FILE, /* S_IFREG */ |
@@ -104,6 +106,8 @@ enum tomoyo_conditions_index { | |||
104 | TOMOYO_MAX_CONDITION_KEYWORD, | 106 | TOMOYO_MAX_CONDITION_KEYWORD, |
105 | TOMOYO_NUMBER_UNION, | 107 | TOMOYO_NUMBER_UNION, |
106 | TOMOYO_NAME_UNION, | 108 | TOMOYO_NAME_UNION, |
109 | TOMOYO_ARGV_ENTRY, | ||
110 | TOMOYO_ENVP_ENTRY, | ||
107 | }; | 111 | }; |
108 | 112 | ||
109 | 113 | ||
@@ -467,6 +471,12 @@ struct tomoyo_mini_stat { | |||
467 | dev_t rdev; | 471 | dev_t rdev; |
468 | }; | 472 | }; |
469 | 473 | ||
474 | /* Structure for dumping argv[] and envp[] of "struct linux_binprm". */ | ||
475 | struct tomoyo_page_dump { | ||
476 | struct page *page; /* Previously dumped page. */ | ||
477 | char *data; /* Contents of "page". Size is PAGE_SIZE. */ | ||
478 | }; | ||
479 | |||
470 | /* Structure for attribute checks in addition to pathname checks. */ | 480 | /* Structure for attribute checks in addition to pathname checks. */ |
471 | struct tomoyo_obj_info { | 481 | struct tomoyo_obj_info { |
472 | /* | 482 | /* |
@@ -491,20 +501,45 @@ struct tomoyo_obj_info { | |||
491 | struct tomoyo_path_info *symlink_target; | 501 | struct tomoyo_path_info *symlink_target; |
492 | }; | 502 | }; |
493 | 503 | ||
504 | /* Structure for argv[]. */ | ||
505 | struct tomoyo_argv { | ||
506 | unsigned long index; | ||
507 | const struct tomoyo_path_info *value; | ||
508 | bool is_not; | ||
509 | }; | ||
510 | |||
511 | /* Structure for envp[]. */ | ||
512 | struct tomoyo_envp { | ||
513 | const struct tomoyo_path_info *name; | ||
514 | const struct tomoyo_path_info *value; | ||
515 | bool is_not; | ||
516 | }; | ||
517 | |||
494 | /* Structure for execve() operation. */ | 518 | /* Structure for execve() operation. */ |
495 | struct tomoyo_execve { | 519 | struct tomoyo_execve { |
496 | struct tomoyo_request_info r; | 520 | struct tomoyo_request_info r; |
497 | struct tomoyo_obj_info obj; | 521 | struct tomoyo_obj_info obj; |
498 | struct linux_binprm *bprm; | 522 | struct linux_binprm *bprm; |
523 | /* For dumping argv[] and envp[]. */ | ||
524 | struct tomoyo_page_dump dump; | ||
499 | /* For temporary use. */ | 525 | /* For temporary use. */ |
500 | char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ | 526 | char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ |
501 | }; | 527 | }; |
502 | 528 | ||
503 | /* Structure for entries which follows "struct tomoyo_condition". */ | 529 | /* Structure for entries which follows "struct tomoyo_condition". */ |
504 | struct tomoyo_condition_element { | 530 | struct tomoyo_condition_element { |
505 | /* Left hand operand. */ | 531 | /* |
532 | * Left hand operand. A "struct tomoyo_argv" for TOMOYO_ARGV_ENTRY, a | ||
533 | * "struct tomoyo_envp" for TOMOYO_ENVP_ENTRY is attached to the tail | ||
534 | * of the array of this struct. | ||
535 | */ | ||
506 | u8 left; | 536 | u8 left; |
507 | /* Right hand operand. */ | 537 | /* |
538 | * Right hand operand. A "struct tomoyo_number_union" for | ||
539 | * TOMOYO_NUMBER_UNION, a "struct tomoyo_name_union" for | ||
540 | * TOMOYO_NAME_UNION is attached to the tail of the array of this | ||
541 | * struct. | ||
542 | */ | ||
508 | u8 right; | 543 | u8 right; |
509 | /* Equation operator. True if equals or overlaps, false otherwise. */ | 544 | /* Equation operator. True if equals or overlaps, false otherwise. */ |
510 | bool equals; | 545 | bool equals; |
@@ -517,10 +552,14 @@ struct tomoyo_condition { | |||
517 | u16 condc; /* Number of conditions in this struct. */ | 552 | u16 condc; /* Number of conditions in this struct. */ |
518 | u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ | 553 | u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ |
519 | u16 names_count; /* Number of "struct tomoyo_name_union names". */ | 554 | u16 names_count; /* Number of "struct tomoyo_name_union names". */ |
555 | u16 argc; /* Number of "struct tomoyo_argv". */ | ||
556 | u16 envc; /* Number of "struct tomoyo_envp". */ | ||
520 | /* | 557 | /* |
521 | * struct tomoyo_condition_element condition[condc]; | 558 | * struct tomoyo_condition_element condition[condc]; |
522 | * struct tomoyo_number_union values[numbers_count]; | 559 | * struct tomoyo_number_union values[numbers_count]; |
523 | * struct tomoyo_name_union names[names_count]; | 560 | * struct tomoyo_name_union names[names_count]; |
561 | * struct tomoyo_argv argv[argc]; | ||
562 | * struct tomoyo_envp envp[envc]; | ||
524 | */ | 563 | */ |
525 | }; | 564 | }; |
526 | 565 | ||
@@ -751,6 +790,8 @@ bool tomoyo_correct_path(const char *filename); | |||
751 | bool tomoyo_correct_word(const char *string); | 790 | bool tomoyo_correct_word(const char *string); |
752 | bool tomoyo_domain_def(const unsigned char *buffer); | 791 | bool tomoyo_domain_def(const unsigned char *buffer); |
753 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); | 792 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); |
793 | bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, | ||
794 | struct tomoyo_page_dump *dump); | ||
754 | bool tomoyo_memory_ok(void *ptr); | 795 | bool tomoyo_memory_ok(void *ptr); |
755 | bool tomoyo_number_matches_group(const unsigned long min, | 796 | bool tomoyo_number_matches_group(const unsigned long min, |
756 | const unsigned long max, | 797 | const unsigned long max, |
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c index 790b9872cc37..8a05f71eaf67 100644 --- a/security/tomoyo/condition.c +++ b/security/tomoyo/condition.c | |||
@@ -11,6 +11,209 @@ | |||
11 | LIST_HEAD(tomoyo_condition_list); | 11 | LIST_HEAD(tomoyo_condition_list); |
12 | 12 | ||
13 | /** | 13 | /** |
14 | * tomoyo_argv - Check argv[] in "struct linux_binbrm". | ||
15 | * | ||
16 | * @index: Index number of @arg_ptr. | ||
17 | * @arg_ptr: Contents of argv[@index]. | ||
18 | * @argc: Length of @argv. | ||
19 | * @argv: Pointer to "struct tomoyo_argv". | ||
20 | * @checked: Set to true if @argv[@index] was found. | ||
21 | * | ||
22 | * Returns true on success, false otherwise. | ||
23 | */ | ||
24 | static bool tomoyo_argv(const unsigned int index, const char *arg_ptr, | ||
25 | const int argc, const struct tomoyo_argv *argv, | ||
26 | u8 *checked) | ||
27 | { | ||
28 | int i; | ||
29 | struct tomoyo_path_info arg; | ||
30 | arg.name = arg_ptr; | ||
31 | for (i = 0; i < argc; argv++, checked++, i++) { | ||
32 | bool result; | ||
33 | if (index != argv->index) | ||
34 | continue; | ||
35 | *checked = 1; | ||
36 | tomoyo_fill_path_info(&arg); | ||
37 | result = tomoyo_path_matches_pattern(&arg, argv->value); | ||
38 | if (argv->is_not) | ||
39 | result = !result; | ||
40 | if (!result) | ||
41 | return false; | ||
42 | } | ||
43 | return true; | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * tomoyo_envp - Check envp[] in "struct linux_binbrm". | ||
48 | * | ||
49 | * @env_name: The name of environment variable. | ||
50 | * @env_value: The value of environment variable. | ||
51 | * @envc: Length of @envp. | ||
52 | * @envp: Pointer to "struct tomoyo_envp". | ||
53 | * @checked: Set to true if @envp[@env_name] was found. | ||
54 | * | ||
55 | * Returns true on success, false otherwise. | ||
56 | */ | ||
57 | static bool tomoyo_envp(const char *env_name, const char *env_value, | ||
58 | const int envc, const struct tomoyo_envp *envp, | ||
59 | u8 *checked) | ||
60 | { | ||
61 | int i; | ||
62 | struct tomoyo_path_info name; | ||
63 | struct tomoyo_path_info value; | ||
64 | name.name = env_name; | ||
65 | tomoyo_fill_path_info(&name); | ||
66 | value.name = env_value; | ||
67 | tomoyo_fill_path_info(&value); | ||
68 | for (i = 0; i < envc; envp++, checked++, i++) { | ||
69 | bool result; | ||
70 | if (!tomoyo_path_matches_pattern(&name, envp->name)) | ||
71 | continue; | ||
72 | *checked = 1; | ||
73 | if (envp->value) { | ||
74 | result = tomoyo_path_matches_pattern(&value, | ||
75 | envp->value); | ||
76 | if (envp->is_not) | ||
77 | result = !result; | ||
78 | } else { | ||
79 | result = true; | ||
80 | if (!envp->is_not) | ||
81 | result = !result; | ||
82 | } | ||
83 | if (!result) | ||
84 | return false; | ||
85 | } | ||
86 | return true; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * tomoyo_scan_bprm - Scan "struct linux_binprm". | ||
91 | * | ||
92 | * @ee: Pointer to "struct tomoyo_execve". | ||
93 | * @argc: Length of @argc. | ||
94 | * @argv: Pointer to "struct tomoyo_argv". | ||
95 | * @envc: Length of @envp. | ||
96 | * @envp: Poiner to "struct tomoyo_envp". | ||
97 | * | ||
98 | * Returns true on success, false otherwise. | ||
99 | */ | ||
100 | static bool tomoyo_scan_bprm(struct tomoyo_execve *ee, | ||
101 | const u16 argc, const struct tomoyo_argv *argv, | ||
102 | const u16 envc, const struct tomoyo_envp *envp) | ||
103 | { | ||
104 | struct linux_binprm *bprm = ee->bprm; | ||
105 | struct tomoyo_page_dump *dump = &ee->dump; | ||
106 | char *arg_ptr = ee->tmp; | ||
107 | int arg_len = 0; | ||
108 | unsigned long pos = bprm->p; | ||
109 | int offset = pos % PAGE_SIZE; | ||
110 | int argv_count = bprm->argc; | ||
111 | int envp_count = bprm->envc; | ||
112 | bool result = true; | ||
113 | u8 local_checked[32]; | ||
114 | u8 *checked; | ||
115 | if (argc + envc <= sizeof(local_checked)) { | ||
116 | checked = local_checked; | ||
117 | memset(local_checked, 0, sizeof(local_checked)); | ||
118 | } else { | ||
119 | checked = kzalloc(argc + envc, GFP_NOFS); | ||
120 | if (!checked) | ||
121 | return false; | ||
122 | } | ||
123 | while (argv_count || envp_count) { | ||
124 | if (!tomoyo_dump_page(bprm, pos, dump)) { | ||
125 | result = false; | ||
126 | goto out; | ||
127 | } | ||
128 | pos += PAGE_SIZE - offset; | ||
129 | while (offset < PAGE_SIZE) { | ||
130 | /* Read. */ | ||
131 | const char *kaddr = dump->data; | ||
132 | const unsigned char c = kaddr[offset++]; | ||
133 | if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) { | ||
134 | if (c == '\\') { | ||
135 | arg_ptr[arg_len++] = '\\'; | ||
136 | arg_ptr[arg_len++] = '\\'; | ||
137 | } else if (c > ' ' && c < 127) { | ||
138 | arg_ptr[arg_len++] = c; | ||
139 | } else { | ||
140 | arg_ptr[arg_len++] = '\\'; | ||
141 | arg_ptr[arg_len++] = (c >> 6) + '0'; | ||
142 | arg_ptr[arg_len++] = | ||
143 | ((c >> 3) & 7) + '0'; | ||
144 | arg_ptr[arg_len++] = (c & 7) + '0'; | ||
145 | } | ||
146 | } else { | ||
147 | arg_ptr[arg_len] = '\0'; | ||
148 | } | ||
149 | if (c) | ||
150 | continue; | ||
151 | /* Check. */ | ||
152 | if (argv_count) { | ||
153 | if (!tomoyo_argv(bprm->argc - argv_count, | ||
154 | arg_ptr, argc, argv, | ||
155 | checked)) { | ||
156 | result = false; | ||
157 | break; | ||
158 | } | ||
159 | argv_count--; | ||
160 | } else if (envp_count) { | ||
161 | char *cp = strchr(arg_ptr, '='); | ||
162 | if (cp) { | ||
163 | *cp = '\0'; | ||
164 | if (!tomoyo_envp(arg_ptr, cp + 1, | ||
165 | envc, envp, | ||
166 | checked + argc)) { | ||
167 | result = false; | ||
168 | break; | ||
169 | } | ||
170 | } | ||
171 | envp_count--; | ||
172 | } else { | ||
173 | break; | ||
174 | } | ||
175 | arg_len = 0; | ||
176 | } | ||
177 | offset = 0; | ||
178 | if (!result) | ||
179 | break; | ||
180 | } | ||
181 | out: | ||
182 | if (result) { | ||
183 | int i; | ||
184 | /* Check not-yet-checked entries. */ | ||
185 | for (i = 0; i < argc; i++) { | ||
186 | if (checked[i]) | ||
187 | continue; | ||
188 | /* | ||
189 | * Return true only if all unchecked indexes in | ||
190 | * bprm->argv[] are not matched. | ||
191 | */ | ||
192 | if (argv[i].is_not) | ||
193 | continue; | ||
194 | result = false; | ||
195 | break; | ||
196 | } | ||
197 | for (i = 0; i < envc; envp++, i++) { | ||
198 | if (checked[argc + i]) | ||
199 | continue; | ||
200 | /* | ||
201 | * Return true only if all unchecked environ variables | ||
202 | * in bprm->envp[] are either undefined or not matched. | ||
203 | */ | ||
204 | if ((!envp->value && !envp->is_not) || | ||
205 | (envp->value && envp->is_not)) | ||
206 | continue; | ||
207 | result = false; | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | if (checked != local_checked) | ||
212 | kfree(checked); | ||
213 | return result; | ||
214 | } | ||
215 | |||
216 | /** | ||
14 | * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition". | 217 | * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition". |
15 | * | 218 | * |
16 | * @file: Pointer to "struct file". | 219 | * @file: Pointer to "struct file". |
@@ -73,6 +276,64 @@ static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param, | |||
73 | } | 276 | } |
74 | 277 | ||
75 | /** | 278 | /** |
279 | * tomoyo_parse_argv - Parse an argv[] condition part. | ||
280 | * | ||
281 | * @left: Lefthand value. | ||
282 | * @right: Righthand value. | ||
283 | * @argv: Pointer to "struct tomoyo_argv". | ||
284 | * | ||
285 | * Returns true on success, false otherwise. | ||
286 | */ | ||
287 | static bool tomoyo_parse_argv(char *left, char *right, | ||
288 | struct tomoyo_argv *argv) | ||
289 | { | ||
290 | if (tomoyo_parse_ulong(&argv->index, &left) != | ||
291 | TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left) | ||
292 | return false; | ||
293 | argv->value = tomoyo_get_dqword(right); | ||
294 | return argv->value != NULL; | ||
295 | } | ||
296 | |||
297 | /** | ||
298 | * tomoyo_parse_envp - Parse an envp[] condition part. | ||
299 | * | ||
300 | * @left: Lefthand value. | ||
301 | * @right: Righthand value. | ||
302 | * @envp: Pointer to "struct tomoyo_envp". | ||
303 | * | ||
304 | * Returns true on success, false otherwise. | ||
305 | */ | ||
306 | static bool tomoyo_parse_envp(char *left, char *right, | ||
307 | struct tomoyo_envp *envp) | ||
308 | { | ||
309 | const struct tomoyo_path_info *name; | ||
310 | const struct tomoyo_path_info *value; | ||
311 | char *cp = left + strlen(left) - 1; | ||
312 | if (*cp-- != ']' || *cp != '"') | ||
313 | goto out; | ||
314 | *cp = '\0'; | ||
315 | if (!tomoyo_correct_word(left)) | ||
316 | goto out; | ||
317 | name = tomoyo_get_name(left); | ||
318 | if (!name) | ||
319 | goto out; | ||
320 | if (!strcmp(right, "NULL")) { | ||
321 | value = NULL; | ||
322 | } else { | ||
323 | value = tomoyo_get_dqword(right); | ||
324 | if (!value) { | ||
325 | tomoyo_put_name(name); | ||
326 | goto out; | ||
327 | } | ||
328 | } | ||
329 | envp->name = name; | ||
330 | envp->value = value; | ||
331 | return true; | ||
332 | out: | ||
333 | return false; | ||
334 | } | ||
335 | |||
336 | /** | ||
76 | * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry. | 337 | * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry. |
77 | * | 338 | * |
78 | * @a: Pointer to "struct tomoyo_condition". | 339 | * @a: Pointer to "struct tomoyo_condition". |
@@ -86,6 +347,7 @@ static inline bool tomoyo_same_condition(const struct tomoyo_condition *a, | |||
86 | return a->size == b->size && a->condc == b->condc && | 347 | return a->size == b->size && a->condc == b->condc && |
87 | a->numbers_count == b->numbers_count && | 348 | a->numbers_count == b->numbers_count && |
88 | a->names_count == b->names_count && | 349 | a->names_count == b->names_count && |
350 | a->argc == b->argc && a->envc == b->envc && | ||
89 | !memcmp(a + 1, b + 1, a->size - sizeof(*a)); | 351 | !memcmp(a + 1, b + 1, a->size - sizeof(*a)); |
90 | } | 352 | } |
91 | 353 | ||
@@ -178,6 +440,8 @@ struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param) | |||
178 | struct tomoyo_condition_element *condp = NULL; | 440 | struct tomoyo_condition_element *condp = NULL; |
179 | struct tomoyo_number_union *numbers_p = NULL; | 441 | struct tomoyo_number_union *numbers_p = NULL; |
180 | struct tomoyo_name_union *names_p = NULL; | 442 | struct tomoyo_name_union *names_p = NULL; |
443 | struct tomoyo_argv *argv = NULL; | ||
444 | struct tomoyo_envp *envp = NULL; | ||
181 | struct tomoyo_condition e = { }; | 445 | struct tomoyo_condition e = { }; |
182 | char * const start_of_string = param->data; | 446 | char * const start_of_string = param->data; |
183 | char * const end_of_string = start_of_string + strlen(start_of_string); | 447 | char * const end_of_string = start_of_string + strlen(start_of_string); |
@@ -222,6 +486,36 @@ rerun: | |||
222 | goto out; | 486 | goto out; |
223 | dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word, | 487 | dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word, |
224 | is_not ? "!" : "", right_word); | 488 | is_not ? "!" : "", right_word); |
489 | if (!strncmp(left_word, "exec.argv[", 10)) { | ||
490 | if (!argv) { | ||
491 | e.argc++; | ||
492 | e.condc++; | ||
493 | } else { | ||
494 | e.argc--; | ||
495 | e.condc--; | ||
496 | left = TOMOYO_ARGV_ENTRY; | ||
497 | argv->is_not = is_not; | ||
498 | if (!tomoyo_parse_argv(left_word + 10, | ||
499 | right_word, argv++)) | ||
500 | goto out; | ||
501 | } | ||
502 | goto store_value; | ||
503 | } | ||
504 | if (!strncmp(left_word, "exec.envp[\"", 11)) { | ||
505 | if (!envp) { | ||
506 | e.envc++; | ||
507 | e.condc++; | ||
508 | } else { | ||
509 | e.envc--; | ||
510 | e.condc--; | ||
511 | left = TOMOYO_ENVP_ENTRY; | ||
512 | envp->is_not = is_not; | ||
513 | if (!tomoyo_parse_envp(left_word + 11, | ||
514 | right_word, envp++)) | ||
515 | goto out; | ||
516 | } | ||
517 | goto store_value; | ||
518 | } | ||
225 | left = tomoyo_condition_type(left_word); | 519 | left = tomoyo_condition_type(left_word); |
226 | dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word, | 520 | dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word, |
227 | left); | 521 | left); |
@@ -283,16 +577,20 @@ store_value: | |||
283 | condp->equals); | 577 | condp->equals); |
284 | condp++; | 578 | condp++; |
285 | } | 579 | } |
286 | dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u\n", | 580 | dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n", |
287 | __LINE__, e.condc, e.numbers_count, e.names_count); | 581 | __LINE__, e.condc, e.numbers_count, e.names_count, e.argc, |
582 | e.envc); | ||
288 | if (entry) { | 583 | if (entry) { |
289 | BUG_ON(e.names_count | e.numbers_count | e.condc); | 584 | BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc | |
585 | e.condc); | ||
290 | return tomoyo_commit_condition(entry); | 586 | return tomoyo_commit_condition(entry); |
291 | } | 587 | } |
292 | e.size = sizeof(*entry) | 588 | e.size = sizeof(*entry) |
293 | + e.condc * sizeof(struct tomoyo_condition_element) | 589 | + e.condc * sizeof(struct tomoyo_condition_element) |
294 | + e.numbers_count * sizeof(struct tomoyo_number_union) | 590 | + e.numbers_count * sizeof(struct tomoyo_number_union) |
295 | + e.names_count * sizeof(struct tomoyo_name_union); | 591 | + e.names_count * sizeof(struct tomoyo_name_union) |
592 | + e.argc * sizeof(struct tomoyo_argv) | ||
593 | + e.envc * sizeof(struct tomoyo_envp); | ||
296 | entry = kzalloc(e.size, GFP_NOFS); | 594 | entry = kzalloc(e.size, GFP_NOFS); |
297 | if (!entry) | 595 | if (!entry) |
298 | return NULL; | 596 | return NULL; |
@@ -300,6 +598,8 @@ store_value: | |||
300 | condp = (struct tomoyo_condition_element *) (entry + 1); | 598 | condp = (struct tomoyo_condition_element *) (entry + 1); |
301 | numbers_p = (struct tomoyo_number_union *) (condp + e.condc); | 599 | numbers_p = (struct tomoyo_number_union *) (condp + e.condc); |
302 | names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count); | 600 | names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count); |
601 | argv = (struct tomoyo_argv *) (names_p + e.names_count); | ||
602 | envp = (struct tomoyo_envp *) (argv + e.argc); | ||
303 | { | 603 | { |
304 | bool flag = false; | 604 | bool flag = false; |
305 | for (pos = start_of_string; pos < end_of_string; pos++) { | 605 | for (pos = start_of_string; pos < end_of_string; pos++) { |
@@ -391,16 +691,29 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
391 | const struct tomoyo_condition_element *condp; | 691 | const struct tomoyo_condition_element *condp; |
392 | const struct tomoyo_number_union *numbers_p; | 692 | const struct tomoyo_number_union *numbers_p; |
393 | const struct tomoyo_name_union *names_p; | 693 | const struct tomoyo_name_union *names_p; |
694 | const struct tomoyo_argv *argv; | ||
695 | const struct tomoyo_envp *envp; | ||
394 | struct tomoyo_obj_info *obj; | 696 | struct tomoyo_obj_info *obj; |
395 | u16 condc; | 697 | u16 condc; |
698 | u16 argc; | ||
699 | u16 envc; | ||
700 | struct linux_binprm *bprm = NULL; | ||
396 | if (!cond) | 701 | if (!cond) |
397 | return true; | 702 | return true; |
398 | condc = cond->condc; | 703 | condc = cond->condc; |
704 | argc = cond->argc; | ||
705 | envc = cond->envc; | ||
399 | obj = r->obj; | 706 | obj = r->obj; |
707 | if (r->ee) | ||
708 | bprm = r->ee->bprm; | ||
709 | if (!bprm && (argc || envc)) | ||
710 | return false; | ||
400 | condp = (struct tomoyo_condition_element *) (cond + 1); | 711 | condp = (struct tomoyo_condition_element *) (cond + 1); |
401 | numbers_p = (const struct tomoyo_number_union *) (condp + condc); | 712 | numbers_p = (const struct tomoyo_number_union *) (condp + condc); |
402 | names_p = (const struct tomoyo_name_union *) | 713 | names_p = (const struct tomoyo_name_union *) |
403 | (numbers_p + cond->numbers_count); | 714 | (numbers_p + cond->numbers_count); |
715 | argv = (const struct tomoyo_argv *) (names_p + cond->names_count); | ||
716 | envp = (const struct tomoyo_envp *) (argv + argc); | ||
404 | for (i = 0; i < condc; i++) { | 717 | for (i = 0; i < condc; i++) { |
405 | const bool match = condp->equals; | 718 | const bool match = condp->equals; |
406 | const u8 left = condp->left; | 719 | const u8 left = condp->left; |
@@ -408,6 +721,9 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
408 | bool is_bitop[2] = { false, false }; | 721 | bool is_bitop[2] = { false, false }; |
409 | u8 j; | 722 | u8 j; |
410 | condp++; | 723 | condp++; |
724 | /* Check argv[] and envp[] later. */ | ||
725 | if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY) | ||
726 | continue; | ||
411 | /* Check string expressions. */ | 727 | /* Check string expressions. */ |
412 | if (right == TOMOYO_NAME_UNION) { | 728 | if (right == TOMOYO_NAME_UNION) { |
413 | const struct tomoyo_name_union *ptr = names_p++; | 729 | const struct tomoyo_name_union *ptr = names_p++; |
@@ -524,6 +840,16 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
524 | case TOMOYO_MODE_OTHERS_EXECUTE: | 840 | case TOMOYO_MODE_OTHERS_EXECUTE: |
525 | value = S_IXOTH; | 841 | value = S_IXOTH; |
526 | break; | 842 | break; |
843 | case TOMOYO_EXEC_ARGC: | ||
844 | if (!bprm) | ||
845 | goto out; | ||
846 | value = bprm->argc; | ||
847 | break; | ||
848 | case TOMOYO_EXEC_ENVC: | ||
849 | if (!bprm) | ||
850 | goto out; | ||
851 | value = bprm->envc; | ||
852 | break; | ||
527 | case TOMOYO_NUMBER_UNION: | 853 | case TOMOYO_NUMBER_UNION: |
528 | /* Fetch values later. */ | 854 | /* Fetch values later. */ |
529 | break; | 855 | break; |
@@ -702,5 +1028,8 @@ bool tomoyo_condition(struct tomoyo_request_info *r, | |||
702 | out: | 1028 | out: |
703 | return false; | 1029 | return false; |
704 | } | 1030 | } |
1031 | /* Check argv[] and envp[] now. */ | ||
1032 | if (r->ee && (argc || envc)) | ||
1033 | return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp); | ||
705 | return true; | 1034 | return true; |
706 | } | 1035 | } |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 0f02c7852090..565249c42e39 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -713,3 +713,49 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
713 | kfree(tmp); | 713 | kfree(tmp); |
714 | return retval; | 714 | return retval; |
715 | } | 715 | } |
716 | |||
717 | /** | ||
718 | * tomoyo_dump_page - Dump a page to buffer. | ||
719 | * | ||
720 | * @bprm: Pointer to "struct linux_binprm". | ||
721 | * @pos: Location to dump. | ||
722 | * @dump: Poiner to "struct tomoyo_page_dump". | ||
723 | * | ||
724 | * Returns true on success, false otherwise. | ||
725 | */ | ||
726 | bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, | ||
727 | struct tomoyo_page_dump *dump) | ||
728 | { | ||
729 | struct page *page; | ||
730 | /* dump->data is released by tomoyo_finish_execve(). */ | ||
731 | if (!dump->data) { | ||
732 | dump->data = kzalloc(PAGE_SIZE, GFP_NOFS); | ||
733 | if (!dump->data) | ||
734 | return false; | ||
735 | } | ||
736 | /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */ | ||
737 | #ifdef CONFIG_MMU | ||
738 | if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) | ||
739 | return false; | ||
740 | #else | ||
741 | page = bprm->page[pos / PAGE_SIZE]; | ||
742 | #endif | ||
743 | if (page != dump->page) { | ||
744 | const unsigned int offset = pos % PAGE_SIZE; | ||
745 | /* | ||
746 | * Maybe kmap()/kunmap() should be used here. | ||
747 | * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic(). | ||
748 | * So do I. | ||
749 | */ | ||
750 | char *kaddr = kmap_atomic(page, KM_USER0); | ||
751 | dump->page = page; | ||
752 | memcpy(dump->data + offset, kaddr + offset, | ||
753 | PAGE_SIZE - offset); | ||
754 | kunmap_atomic(kaddr, KM_USER0); | ||
755 | } | ||
756 | /* Same with put_arg_page(page) in fs/exec.c */ | ||
757 | #ifdef CONFIG_MMU | ||
758 | put_page(page); | ||
759 | #endif | ||
760 | return true; | ||
761 | } | ||
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index e0502b6d5866..1ac3312059f6 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -358,6 +358,8 @@ void tomoyo_del_condition(struct list_head *element) | |||
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 | const u16 names_count = cond->names_count; |
361 | const u16 argc = cond->argc; | ||
362 | const u16 envc = cond->envc; | ||
361 | unsigned int i; | 363 | unsigned int i; |
362 | const struct tomoyo_condition_element *condp | 364 | const struct tomoyo_condition_element *condp |
363 | = (const struct tomoyo_condition_element *) (cond + 1); | 365 | = (const struct tomoyo_condition_element *) (cond + 1); |
@@ -365,10 +367,20 @@ void tomoyo_del_condition(struct list_head *element) | |||
365 | = (struct tomoyo_number_union *) (condp + condc); | 367 | = (struct tomoyo_number_union *) (condp + condc); |
366 | struct tomoyo_name_union *names_p | 368 | struct tomoyo_name_union *names_p |
367 | = (struct tomoyo_name_union *) (numbers_p + numbers_count); | 369 | = (struct tomoyo_name_union *) (numbers_p + numbers_count); |
370 | const struct tomoyo_argv *argv | ||
371 | = (const struct tomoyo_argv *) (names_p + names_count); | ||
372 | const struct tomoyo_envp *envp | ||
373 | = (const struct tomoyo_envp *) (argv + argc); | ||
368 | for (i = 0; i < numbers_count; i++) | 374 | for (i = 0; i < numbers_count; i++) |
369 | tomoyo_put_number_union(numbers_p++); | 375 | tomoyo_put_number_union(numbers_p++); |
370 | for (i = 0; i < names_count; i++) | 376 | for (i = 0; i < names_count; i++) |
371 | tomoyo_put_name_union(names_p++); | 377 | tomoyo_put_name_union(names_p++); |
378 | for (i = 0; i < argc; argv++, i++) | ||
379 | tomoyo_put_name(argv->value); | ||
380 | for (i = 0; i < envc; envp++, i++) { | ||
381 | tomoyo_put_name(envp->name); | ||
382 | tomoyo_put_name(envp->value); | ||
383 | } | ||
372 | } | 384 | } |
373 | 385 | ||
374 | /** | 386 | /** |