diff options
Diffstat (limited to 'security/tomoyo/file.c')
-rw-r--r-- | security/tomoyo/file.c | 156 |
1 files changed, 125 insertions, 31 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 2316da8ec5bc..5ae3a571559f 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -14,21 +14,50 @@ | |||
14 | #include "realpath.h" | 14 | #include "realpath.h" |
15 | #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) | 15 | #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) |
16 | 16 | ||
17 | /* Structure for "allow_read" keyword. */ | 17 | /* |
18 | * tomoyo_globally_readable_file_entry is a structure which is used for holding | ||
19 | * "allow_read" entries. | ||
20 | * It has following fields. | ||
21 | * | ||
22 | * (1) "list" which is linked to tomoyo_globally_readable_list . | ||
23 | * (2) "filename" is a pathname which is allowed to open(O_RDONLY). | ||
24 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
25 | * otherwise. | ||
26 | */ | ||
18 | struct tomoyo_globally_readable_file_entry { | 27 | struct tomoyo_globally_readable_file_entry { |
19 | struct list_head list; | 28 | struct list_head list; |
20 | const struct tomoyo_path_info *filename; | 29 | const struct tomoyo_path_info *filename; |
21 | bool is_deleted; | 30 | bool is_deleted; |
22 | }; | 31 | }; |
23 | 32 | ||
24 | /* Structure for "file_pattern" keyword. */ | 33 | /* |
34 | * tomoyo_pattern_entry is a structure which is used for holding | ||
35 | * "tomoyo_pattern_list" entries. | ||
36 | * It has following fields. | ||
37 | * | ||
38 | * (1) "list" which is linked to tomoyo_pattern_list . | ||
39 | * (2) "pattern" is a pathname pattern which is used for converting pathnames | ||
40 | * to pathname patterns during learning mode. | ||
41 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
42 | * otherwise. | ||
43 | */ | ||
25 | struct tomoyo_pattern_entry { | 44 | struct tomoyo_pattern_entry { |
26 | struct list_head list; | 45 | struct list_head list; |
27 | const struct tomoyo_path_info *pattern; | 46 | const struct tomoyo_path_info *pattern; |
28 | bool is_deleted; | 47 | bool is_deleted; |
29 | }; | 48 | }; |
30 | 49 | ||
31 | /* Structure for "deny_rewrite" keyword. */ | 50 | /* |
51 | * tomoyo_no_rewrite_entry is a structure which is used for holding | ||
52 | * "deny_rewrite" entries. | ||
53 | * It has following fields. | ||
54 | * | ||
55 | * (1) "list" which is linked to tomoyo_no_rewrite_list . | ||
56 | * (2) "pattern" is a pathname which is by default not permitted to modify | ||
57 | * already existing content. | ||
58 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
59 | * otherwise. | ||
60 | */ | ||
32 | struct tomoyo_no_rewrite_entry { | 61 | struct tomoyo_no_rewrite_entry { |
33 | struct list_head list; | 62 | struct list_head list; |
34 | const struct tomoyo_path_info *pattern; | 63 | const struct tomoyo_path_info *pattern; |
@@ -141,7 +170,31 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
141 | struct tomoyo_domain_info * | 170 | struct tomoyo_domain_info * |
142 | const domain, const bool is_delete); | 171 | const domain, const bool is_delete); |
143 | 172 | ||
144 | /* The list for "struct tomoyo_globally_readable_file_entry". */ | 173 | /* |
174 | * tomoyo_globally_readable_list is used for holding list of pathnames which | ||
175 | * are by default allowed to be open()ed for reading by any process. | ||
176 | * | ||
177 | * An entry is added by | ||
178 | * | ||
179 | * # echo 'allow_read /lib/libc-2.5.so' > \ | ||
180 | * /sys/kernel/security/tomoyo/exception_policy | ||
181 | * | ||
182 | * and is deleted by | ||
183 | * | ||
184 | * # echo 'delete allow_read /lib/libc-2.5.so' > \ | ||
185 | * /sys/kernel/security/tomoyo/exception_policy | ||
186 | * | ||
187 | * and all entries are retrieved by | ||
188 | * | ||
189 | * # grep ^allow_read /sys/kernel/security/tomoyo/exception_policy | ||
190 | * | ||
191 | * In the example above, any process is allowed to | ||
192 | * open("/lib/libc-2.5.so", O_RDONLY). | ||
193 | * One exception is, if the domain which current process belongs to is marked | ||
194 | * as "ignore_global_allow_read", current process can't do so unless explicitly | ||
195 | * given "allow_read /lib/libc-2.5.so" to the domain which current process | ||
196 | * belongs to. | ||
197 | */ | ||
145 | static LIST_HEAD(tomoyo_globally_readable_list); | 198 | static LIST_HEAD(tomoyo_globally_readable_list); |
146 | static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); | 199 | static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); |
147 | 200 | ||
@@ -166,7 +219,6 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
166 | saved_filename = tomoyo_save_name(filename); | 219 | saved_filename = tomoyo_save_name(filename); |
167 | if (!saved_filename) | 220 | if (!saved_filename) |
168 | return -ENOMEM; | 221 | return -ENOMEM; |
169 | /***** EXCLUSIVE SECTION START *****/ | ||
170 | down_write(&tomoyo_globally_readable_list_lock); | 222 | down_write(&tomoyo_globally_readable_list_lock); |
171 | list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { | 223 | list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { |
172 | if (ptr->filename != saved_filename) | 224 | if (ptr->filename != saved_filename) |
@@ -187,7 +239,6 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
187 | error = 0; | 239 | error = 0; |
188 | out: | 240 | out: |
189 | up_write(&tomoyo_globally_readable_list_lock); | 241 | up_write(&tomoyo_globally_readable_list_lock); |
190 | /***** EXCLUSIVE SECTION END *****/ | ||
191 | return error; | 242 | return error; |
192 | } | 243 | } |
193 | 244 | ||
@@ -249,17 +300,44 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | |||
249 | list); | 300 | list); |
250 | if (ptr->is_deleted) | 301 | if (ptr->is_deleted) |
251 | continue; | 302 | continue; |
252 | if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n", | 303 | done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n", |
253 | ptr->filename->name)) { | 304 | ptr->filename->name); |
254 | done = false; | 305 | if (!done) |
255 | break; | 306 | break; |
256 | } | ||
257 | } | 307 | } |
258 | up_read(&tomoyo_globally_readable_list_lock); | 308 | up_read(&tomoyo_globally_readable_list_lock); |
259 | return done; | 309 | return done; |
260 | } | 310 | } |
261 | 311 | ||
262 | /* The list for "struct tomoyo_pattern_entry". */ | 312 | /* tomoyo_pattern_list is used for holding list of pathnames which are used for |
313 | * converting pathnames to pathname patterns during learning mode. | ||
314 | * | ||
315 | * An entry is added by | ||
316 | * | ||
317 | * # echo 'file_pattern /proc/\$/mounts' > \ | ||
318 | * /sys/kernel/security/tomoyo/exception_policy | ||
319 | * | ||
320 | * and is deleted by | ||
321 | * | ||
322 | * # echo 'delete file_pattern /proc/\$/mounts' > \ | ||
323 | * /sys/kernel/security/tomoyo/exception_policy | ||
324 | * | ||
325 | * and all entries are retrieved by | ||
326 | * | ||
327 | * # grep ^file_pattern /sys/kernel/security/tomoyo/exception_policy | ||
328 | * | ||
329 | * In the example above, if a process which belongs to a domain which is in | ||
330 | * learning mode requested open("/proc/1/mounts", O_RDONLY), | ||
331 | * "allow_read /proc/\$/mounts" is automatically added to the domain which that | ||
332 | * process belongs to. | ||
333 | * | ||
334 | * It is not a desirable behavior that we have to use /proc/\$/ instead of | ||
335 | * /proc/self/ when current process needs to access only current process's | ||
336 | * information. As of now, LSM version of TOMOYO is using __d_path() for | ||
337 | * calculating pathname. Non LSM version of TOMOYO is using its own function | ||
338 | * which pretends as if /proc/self/ is not a symlink; so that we can forbid | ||
339 | * current process from accessing other process's information. | ||
340 | */ | ||
263 | static LIST_HEAD(tomoyo_pattern_list); | 341 | static LIST_HEAD(tomoyo_pattern_list); |
264 | static DECLARE_RWSEM(tomoyo_pattern_list_lock); | 342 | static DECLARE_RWSEM(tomoyo_pattern_list_lock); |
265 | 343 | ||
@@ -284,7 +362,6 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
284 | saved_pattern = tomoyo_save_name(pattern); | 362 | saved_pattern = tomoyo_save_name(pattern); |
285 | if (!saved_pattern) | 363 | if (!saved_pattern) |
286 | return -ENOMEM; | 364 | return -ENOMEM; |
287 | /***** EXCLUSIVE SECTION START *****/ | ||
288 | down_write(&tomoyo_pattern_list_lock); | 365 | down_write(&tomoyo_pattern_list_lock); |
289 | list_for_each_entry(ptr, &tomoyo_pattern_list, list) { | 366 | list_for_each_entry(ptr, &tomoyo_pattern_list, list) { |
290 | if (saved_pattern != ptr->pattern) | 367 | if (saved_pattern != ptr->pattern) |
@@ -305,7 +382,6 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
305 | error = 0; | 382 | error = 0; |
306 | out: | 383 | out: |
307 | up_write(&tomoyo_pattern_list_lock); | 384 | up_write(&tomoyo_pattern_list_lock); |
308 | /***** EXCLUSIVE SECTION END *****/ | ||
309 | return error; | 385 | return error; |
310 | } | 386 | } |
311 | 387 | ||
@@ -373,17 +449,44 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | |||
373 | ptr = list_entry(pos, struct tomoyo_pattern_entry, list); | 449 | ptr = list_entry(pos, struct tomoyo_pattern_entry, list); |
374 | if (ptr->is_deleted) | 450 | if (ptr->is_deleted) |
375 | continue; | 451 | continue; |
376 | if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN "%s\n", | 452 | done = tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN |
377 | ptr->pattern->name)) { | 453 | "%s\n", ptr->pattern->name); |
378 | done = false; | 454 | if (!done) |
379 | break; | 455 | break; |
380 | } | ||
381 | } | 456 | } |
382 | up_read(&tomoyo_pattern_list_lock); | 457 | up_read(&tomoyo_pattern_list_lock); |
383 | return done; | 458 | return done; |
384 | } | 459 | } |
385 | 460 | ||
386 | /* The list for "struct tomoyo_no_rewrite_entry". */ | 461 | /* |
462 | * tomoyo_no_rewrite_list is used for holding list of pathnames which are by | ||
463 | * default forbidden to modify already written content of a file. | ||
464 | * | ||
465 | * An entry is added by | ||
466 | * | ||
467 | * # echo 'deny_rewrite /var/log/messages' > \ | ||
468 | * /sys/kernel/security/tomoyo/exception_policy | ||
469 | * | ||
470 | * and is deleted by | ||
471 | * | ||
472 | * # echo 'delete deny_rewrite /var/log/messages' > \ | ||
473 | * /sys/kernel/security/tomoyo/exception_policy | ||
474 | * | ||
475 | * and all entries are retrieved by | ||
476 | * | ||
477 | * # grep ^deny_rewrite /sys/kernel/security/tomoyo/exception_policy | ||
478 | * | ||
479 | * In the example above, if a process requested to rewrite /var/log/messages , | ||
480 | * the process can't rewrite unless the domain which that process belongs to | ||
481 | * has "allow_rewrite /var/log/messages" entry. | ||
482 | * | ||
483 | * It is not a desirable behavior that we have to add "\040(deleted)" suffix | ||
484 | * when we want to allow rewriting already unlink()ed file. As of now, | ||
485 | * LSM version of TOMOYO is using __d_path() for calculating pathname. | ||
486 | * Non LSM version of TOMOYO is using its own function which doesn't append | ||
487 | * " (deleted)" suffix if the file is already unlink()ed; so that we don't | ||
488 | * need to worry whether the file is already unlink()ed or not. | ||
489 | */ | ||
387 | static LIST_HEAD(tomoyo_no_rewrite_list); | 490 | static LIST_HEAD(tomoyo_no_rewrite_list); |
388 | static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); | 491 | static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); |
389 | 492 | ||
@@ -407,7 +510,6 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
407 | saved_pattern = tomoyo_save_name(pattern); | 510 | saved_pattern = tomoyo_save_name(pattern); |
408 | if (!saved_pattern) | 511 | if (!saved_pattern) |
409 | return -ENOMEM; | 512 | return -ENOMEM; |
410 | /***** EXCLUSIVE SECTION START *****/ | ||
411 | down_write(&tomoyo_no_rewrite_list_lock); | 513 | down_write(&tomoyo_no_rewrite_list_lock); |
412 | list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { | 514 | list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { |
413 | if (ptr->pattern != saved_pattern) | 515 | if (ptr->pattern != saved_pattern) |
@@ -428,7 +530,6 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
428 | error = 0; | 530 | error = 0; |
429 | out: | 531 | out: |
430 | up_write(&tomoyo_no_rewrite_list_lock); | 532 | up_write(&tomoyo_no_rewrite_list_lock); |
431 | /***** EXCLUSIVE SECTION END *****/ | ||
432 | return error; | 533 | return error; |
433 | } | 534 | } |
434 | 535 | ||
@@ -489,11 +590,10 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
489 | ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); | 590 | ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); |
490 | if (ptr->is_deleted) | 591 | if (ptr->is_deleted) |
491 | continue; | 592 | continue; |
492 | if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE "%s\n", | 593 | done = tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE |
493 | ptr->pattern->name)) { | 594 | "%s\n", ptr->pattern->name); |
494 | done = false; | 595 | if (!done) |
495 | break; | 596 | break; |
496 | } | ||
497 | } | 597 | } |
498 | up_read(&tomoyo_no_rewrite_list_lock); | 598 | up_read(&tomoyo_no_rewrite_list_lock); |
499 | return done; | 599 | return done; |
@@ -745,7 +845,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
745 | saved_filename = tomoyo_save_name(filename); | 845 | saved_filename = tomoyo_save_name(filename); |
746 | if (!saved_filename) | 846 | if (!saved_filename) |
747 | return -ENOMEM; | 847 | return -ENOMEM; |
748 | /***** EXCLUSIVE SECTION START *****/ | ||
749 | down_write(&tomoyo_domain_acl_info_list_lock); | 848 | down_write(&tomoyo_domain_acl_info_list_lock); |
750 | if (is_delete) | 849 | if (is_delete) |
751 | goto delete; | 850 | goto delete; |
@@ -800,7 +899,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
800 | } | 899 | } |
801 | out: | 900 | out: |
802 | up_write(&tomoyo_domain_acl_info_list_lock); | 901 | up_write(&tomoyo_domain_acl_info_list_lock); |
803 | /***** EXCLUSIVE SECTION END *****/ | ||
804 | return error; | 902 | return error; |
805 | } | 903 | } |
806 | 904 | ||
@@ -836,7 +934,6 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
836 | saved_filename2 = tomoyo_save_name(filename2); | 934 | saved_filename2 = tomoyo_save_name(filename2); |
837 | if (!saved_filename1 || !saved_filename2) | 935 | if (!saved_filename1 || !saved_filename2) |
838 | return -ENOMEM; | 936 | return -ENOMEM; |
839 | /***** EXCLUSIVE SECTION START *****/ | ||
840 | down_write(&tomoyo_domain_acl_info_list_lock); | 937 | down_write(&tomoyo_domain_acl_info_list_lock); |
841 | if (is_delete) | 938 | if (is_delete) |
842 | goto delete; | 939 | goto delete; |
@@ -884,7 +981,6 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
884 | } | 981 | } |
885 | out: | 982 | out: |
886 | up_write(&tomoyo_domain_acl_info_list_lock); | 983 | up_write(&tomoyo_domain_acl_info_list_lock); |
887 | /***** EXCLUSIVE SECTION END *****/ | ||
888 | return error; | 984 | return error; |
889 | } | 985 | } |
890 | 986 | ||
@@ -1025,13 +1121,11 @@ int tomoyo_check_file_perm(struct tomoyo_domain_info *domain, | |||
1025 | * | 1121 | * |
1026 | * @domain: Pointer to "struct tomoyo_domain_info". | 1122 | * @domain: Pointer to "struct tomoyo_domain_info". |
1027 | * @filename: Check permission for "execute". | 1123 | * @filename: Check permission for "execute". |
1028 | * @tmp: Buffer for temporary use. | ||
1029 | * | 1124 | * |
1030 | * Returns 0 on success, negativevalue otherwise. | 1125 | * Returns 0 on success, negativevalue otherwise. |
1031 | */ | 1126 | */ |
1032 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | 1127 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, |
1033 | const struct tomoyo_path_info *filename, | 1128 | const struct tomoyo_path_info *filename) |
1034 | struct tomoyo_page_buffer *tmp) | ||
1035 | { | 1129 | { |
1036 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1130 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1037 | 1131 | ||