diff options
Diffstat (limited to 'security/tomoyo/file.c')
-rw-r--r-- | security/tomoyo/file.c | 368 |
1 files changed, 36 insertions, 332 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index d64e8ecb6fb3..41ed7de44ef1 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -11,15 +11,15 @@ | |||
11 | 11 | ||
12 | /* Keyword array for operations with one pathname. */ | 12 | /* Keyword array for operations with one pathname. */ |
13 | const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { | 13 | const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { |
14 | [TOMOYO_TYPE_READ_WRITE] = "read/write", | ||
15 | [TOMOYO_TYPE_EXECUTE] = "execute", | 14 | [TOMOYO_TYPE_EXECUTE] = "execute", |
16 | [TOMOYO_TYPE_READ] = "read", | 15 | [TOMOYO_TYPE_READ] = "read", |
17 | [TOMOYO_TYPE_WRITE] = "write", | 16 | [TOMOYO_TYPE_WRITE] = "write", |
17 | [TOMOYO_TYPE_APPEND] = "append", | ||
18 | [TOMOYO_TYPE_UNLINK] = "unlink", | 18 | [TOMOYO_TYPE_UNLINK] = "unlink", |
19 | [TOMOYO_TYPE_GETATTR] = "getattr", | ||
19 | [TOMOYO_TYPE_RMDIR] = "rmdir", | 20 | [TOMOYO_TYPE_RMDIR] = "rmdir", |
20 | [TOMOYO_TYPE_TRUNCATE] = "truncate", | 21 | [TOMOYO_TYPE_TRUNCATE] = "truncate", |
21 | [TOMOYO_TYPE_SYMLINK] = "symlink", | 22 | [TOMOYO_TYPE_SYMLINK] = "symlink", |
22 | [TOMOYO_TYPE_REWRITE] = "rewrite", | ||
23 | [TOMOYO_TYPE_CHROOT] = "chroot", | 23 | [TOMOYO_TYPE_CHROOT] = "chroot", |
24 | [TOMOYO_TYPE_UMOUNT] = "unmount", | 24 | [TOMOYO_TYPE_UMOUNT] = "unmount", |
25 | }; | 25 | }; |
@@ -50,15 +50,15 @@ const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { | 52 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { |
53 | [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN, | ||
54 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, | 53 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, |
55 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, | 54 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, |
56 | [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, | 55 | [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, |
56 | [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN, | ||
57 | [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, | 57 | [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, |
58 | [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR, | ||
58 | [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, | 59 | [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, |
59 | [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, | 60 | [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, |
60 | [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, | 61 | [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, |
61 | [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE, | ||
62 | [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, | 62 | [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, |
63 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, | 63 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, |
64 | }; | 64 | }; |
@@ -132,24 +132,6 @@ static void tomoyo_add_slash(struct tomoyo_path_info *buf) | |||
132 | } | 132 | } |
133 | 133 | ||
134 | /** | 134 | /** |
135 | * tomoyo_strendswith - Check whether the token ends with the given token. | ||
136 | * | ||
137 | * @name: The token to check. | ||
138 | * @tail: The token to find. | ||
139 | * | ||
140 | * Returns true if @name ends with @tail, false otherwise. | ||
141 | */ | ||
142 | static bool tomoyo_strendswith(const char *name, const char *tail) | ||
143 | { | ||
144 | int len; | ||
145 | |||
146 | if (!name || !tail) | ||
147 | return false; | ||
148 | len = strlen(name) - strlen(tail); | ||
149 | return len >= 0 && !strcmp(name + len, tail); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * tomoyo_get_realpath - Get realpath. | 135 | * tomoyo_get_realpath - Get realpath. |
154 | * | 136 | * |
155 | * @buf: Pointer to "struct tomoyo_path_info". | 137 | * @buf: Pointer to "struct tomoyo_path_info". |
@@ -182,7 +164,7 @@ static int tomoyo_audit_path_log(struct tomoyo_request_info *r) | |||
182 | return 0; | 164 | return 0; |
183 | tomoyo_warn_log(r, "%s %s", operation, filename->name); | 165 | tomoyo_warn_log(r, "%s %s", operation, filename->name); |
184 | return tomoyo_supervisor(r, "allow_%s %s\n", operation, | 166 | return tomoyo_supervisor(r, "allow_%s %s\n", operation, |
185 | tomoyo_pattern(filename)); | 167 | filename->name); |
186 | } | 168 | } |
187 | 169 | ||
188 | /** | 170 | /** |
@@ -202,8 +184,7 @@ static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) | |||
202 | tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, | 184 | tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, |
203 | filename2->name); | 185 | filename2->name); |
204 | return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, | 186 | return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, |
205 | tomoyo_pattern(filename1), | 187 | filename1->name, filename2->name); |
206 | tomoyo_pattern(filename2)); | ||
207 | } | 188 | } |
208 | 189 | ||
209 | /** | 190 | /** |
@@ -225,7 +206,7 @@ static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) | |||
225 | tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, | 206 | tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, |
226 | major, minor); | 207 | major, minor); |
227 | return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, | 208 | return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, |
228 | tomoyo_pattern(filename), mode, major, minor); | 209 | filename->name, mode, major, minor); |
229 | } | 210 | } |
230 | 211 | ||
231 | /** | 212 | /** |
@@ -264,247 +245,7 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) | |||
264 | radix); | 245 | radix); |
265 | tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); | 246 | tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); |
266 | return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, | 247 | return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, |
267 | tomoyo_pattern(filename), buffer); | 248 | filename->name, buffer); |
268 | } | ||
269 | |||
270 | static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a, | ||
271 | const struct tomoyo_acl_head *b) | ||
272 | { | ||
273 | return container_of(a, struct tomoyo_readable_file, | ||
274 | head)->filename == | ||
275 | container_of(b, struct tomoyo_readable_file, | ||
276 | head)->filename; | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list. | ||
281 | * | ||
282 | * @filename: Filename unconditionally permitted to open() for reading. | ||
283 | * @is_delete: True if it is a delete request. | ||
284 | * | ||
285 | * Returns 0 on success, negative value otherwise. | ||
286 | * | ||
287 | * Caller holds tomoyo_read_lock(). | ||
288 | */ | ||
289 | static int tomoyo_update_globally_readable_entry(const char *filename, | ||
290 | const bool is_delete) | ||
291 | { | ||
292 | struct tomoyo_readable_file e = { }; | ||
293 | int error; | ||
294 | |||
295 | if (!tomoyo_correct_word(filename)) | ||
296 | return -EINVAL; | ||
297 | e.filename = tomoyo_get_name(filename); | ||
298 | if (!e.filename) | ||
299 | return -ENOMEM; | ||
300 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | ||
301 | &tomoyo_policy_list | ||
302 | [TOMOYO_ID_GLOBALLY_READABLE], | ||
303 | tomoyo_same_globally_readable); | ||
304 | tomoyo_put_name(e.filename); | ||
305 | return error; | ||
306 | } | ||
307 | |||
308 | /** | ||
309 | * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. | ||
310 | * | ||
311 | * @filename: The filename to check. | ||
312 | * | ||
313 | * Returns true if any domain can open @filename for reading, false otherwise. | ||
314 | * | ||
315 | * Caller holds tomoyo_read_lock(). | ||
316 | */ | ||
317 | static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * | ||
318 | filename) | ||
319 | { | ||
320 | struct tomoyo_readable_file *ptr; | ||
321 | bool found = false; | ||
322 | |||
323 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list | ||
324 | [TOMOYO_ID_GLOBALLY_READABLE], head.list) { | ||
325 | if (!ptr->head.is_deleted && | ||
326 | tomoyo_path_matches_pattern(filename, ptr->filename)) { | ||
327 | found = true; | ||
328 | break; | ||
329 | } | ||
330 | } | ||
331 | return found; | ||
332 | } | ||
333 | |||
334 | /** | ||
335 | * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list. | ||
336 | * | ||
337 | * @data: String to parse. | ||
338 | * @is_delete: True if it is a delete request. | ||
339 | * | ||
340 | * Returns 0 on success, negative value otherwise. | ||
341 | * | ||
342 | * Caller holds tomoyo_read_lock(). | ||
343 | */ | ||
344 | int tomoyo_write_globally_readable(char *data, const bool is_delete) | ||
345 | { | ||
346 | return tomoyo_update_globally_readable_entry(data, is_delete); | ||
347 | } | ||
348 | |||
349 | static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a, | ||
350 | const struct tomoyo_acl_head *b) | ||
351 | { | ||
352 | return container_of(a, struct tomoyo_no_pattern, head)->pattern == | ||
353 | container_of(b, struct tomoyo_no_pattern, head)->pattern; | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list. | ||
358 | * | ||
359 | * @pattern: Pathname pattern. | ||
360 | * @is_delete: True if it is a delete request. | ||
361 | * | ||
362 | * Returns 0 on success, negative value otherwise. | ||
363 | * | ||
364 | * Caller holds tomoyo_read_lock(). | ||
365 | */ | ||
366 | static int tomoyo_update_file_pattern_entry(const char *pattern, | ||
367 | const bool is_delete) | ||
368 | { | ||
369 | struct tomoyo_no_pattern e = { }; | ||
370 | int error; | ||
371 | |||
372 | if (!tomoyo_correct_word(pattern)) | ||
373 | return -EINVAL; | ||
374 | e.pattern = tomoyo_get_name(pattern); | ||
375 | if (!e.pattern) | ||
376 | return -ENOMEM; | ||
377 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | ||
378 | &tomoyo_policy_list[TOMOYO_ID_PATTERN], | ||
379 | tomoyo_same_pattern); | ||
380 | tomoyo_put_name(e.pattern); | ||
381 | return error; | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * tomoyo_pattern - Get patterned pathname. | ||
386 | * | ||
387 | * @filename: The filename to find patterned pathname. | ||
388 | * | ||
389 | * Returns pointer to pathname pattern if matched, @filename otherwise. | ||
390 | * | ||
391 | * Caller holds tomoyo_read_lock(). | ||
392 | */ | ||
393 | const char *tomoyo_pattern(const struct tomoyo_path_info *filename) | ||
394 | { | ||
395 | struct tomoyo_no_pattern *ptr; | ||
396 | const struct tomoyo_path_info *pattern = NULL; | ||
397 | |||
398 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN], | ||
399 | head.list) { | ||
400 | if (ptr->head.is_deleted) | ||
401 | continue; | ||
402 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | ||
403 | continue; | ||
404 | pattern = ptr->pattern; | ||
405 | if (tomoyo_strendswith(pattern->name, "/\\*")) { | ||
406 | /* Do nothing. Try to find the better match. */ | ||
407 | } else { | ||
408 | /* This would be the better match. Use this. */ | ||
409 | break; | ||
410 | } | ||
411 | } | ||
412 | if (pattern) | ||
413 | filename = pattern; | ||
414 | return filename->name; | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list. | ||
419 | * | ||
420 | * @data: String to parse. | ||
421 | * @is_delete: True if it is a delete request. | ||
422 | * | ||
423 | * Returns 0 on success, negative value otherwise. | ||
424 | * | ||
425 | * Caller holds tomoyo_read_lock(). | ||
426 | */ | ||
427 | int tomoyo_write_pattern(char *data, const bool is_delete) | ||
428 | { | ||
429 | return tomoyo_update_file_pattern_entry(data, is_delete); | ||
430 | } | ||
431 | |||
432 | static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a, | ||
433 | const struct tomoyo_acl_head *b) | ||
434 | { | ||
435 | return container_of(a, struct tomoyo_no_rewrite, head)->pattern | ||
436 | == container_of(b, struct tomoyo_no_rewrite, head) | ||
437 | ->pattern; | ||
438 | } | ||
439 | |||
440 | /** | ||
441 | * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list. | ||
442 | * | ||
443 | * @pattern: Pathname pattern that are not rewritable by default. | ||
444 | * @is_delete: True if it is a delete request. | ||
445 | * | ||
446 | * Returns 0 on success, negative value otherwise. | ||
447 | * | ||
448 | * Caller holds tomoyo_read_lock(). | ||
449 | */ | ||
450 | static int tomoyo_update_no_rewrite_entry(const char *pattern, | ||
451 | const bool is_delete) | ||
452 | { | ||
453 | struct tomoyo_no_rewrite e = { }; | ||
454 | int error; | ||
455 | |||
456 | if (!tomoyo_correct_word(pattern)) | ||
457 | return -EINVAL; | ||
458 | e.pattern = tomoyo_get_name(pattern); | ||
459 | if (!e.pattern) | ||
460 | return -ENOMEM; | ||
461 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | ||
462 | &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], | ||
463 | tomoyo_same_no_rewrite); | ||
464 | tomoyo_put_name(e.pattern); | ||
465 | return error; | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. | ||
470 | * | ||
471 | * @filename: Filename to check. | ||
472 | * | ||
473 | * Returns true if @filename is specified by "deny_rewrite" directive, | ||
474 | * false otherwise. | ||
475 | * | ||
476 | * Caller holds tomoyo_read_lock(). | ||
477 | */ | ||
478 | static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) | ||
479 | { | ||
480 | struct tomoyo_no_rewrite *ptr; | ||
481 | bool found = false; | ||
482 | |||
483 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], | ||
484 | head.list) { | ||
485 | if (ptr->head.is_deleted) | ||
486 | continue; | ||
487 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | ||
488 | continue; | ||
489 | found = true; | ||
490 | break; | ||
491 | } | ||
492 | return found; | ||
493 | } | ||
494 | |||
495 | /** | ||
496 | * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list. | ||
497 | * | ||
498 | * @data: String to parse. | ||
499 | * @is_delete: True if it is a delete request. | ||
500 | * | ||
501 | * Returns 0 on success, negative value otherwise. | ||
502 | * | ||
503 | * Caller holds tomoyo_read_lock(). | ||
504 | */ | ||
505 | int tomoyo_write_no_rewrite(char *data, const bool is_delete) | ||
506 | { | ||
507 | return tomoyo_update_no_rewrite_entry(data, is_delete); | ||
508 | } | 249 | } |
509 | 250 | ||
510 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, | 251 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, |
@@ -569,6 +310,15 @@ static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, | |||
569 | tomoyo_same_name_union(&p1->name, &p2->name); | 310 | tomoyo_same_name_union(&p1->name, &p2->name); |
570 | } | 311 | } |
571 | 312 | ||
313 | /** | ||
314 | * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry. | ||
315 | * | ||
316 | * @a: Pointer to "struct tomoyo_acl_info". | ||
317 | * @b: Pointer to "struct tomoyo_acl_info". | ||
318 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | ||
319 | * | ||
320 | * Returns true if @a is empty, false otherwise. | ||
321 | */ | ||
572 | static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, | 322 | static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, |
573 | struct tomoyo_acl_info *b, | 323 | struct tomoyo_acl_info *b, |
574 | const bool is_delete) | 324 | const bool is_delete) |
@@ -577,19 +327,10 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, | |||
577 | ->perm; | 327 | ->perm; |
578 | u16 perm = *a_perm; | 328 | u16 perm = *a_perm; |
579 | const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; | 329 | const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; |
580 | if (is_delete) { | 330 | if (is_delete) |
581 | perm &= ~b_perm; | 331 | perm &= ~b_perm; |
582 | if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK) | 332 | else |
583 | perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); | ||
584 | else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE))) | ||
585 | perm &= ~TOMOYO_RW_MASK; | ||
586 | } else { | ||
587 | perm |= b_perm; | 333 | perm |= b_perm; |
588 | if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK) | ||
589 | perm |= (1 << TOMOYO_TYPE_READ_WRITE); | ||
590 | else if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) | ||
591 | perm |= TOMOYO_RW_MASK; | ||
592 | } | ||
593 | *a_perm = perm; | 334 | *a_perm = perm; |
594 | return !perm; | 335 | return !perm; |
595 | } | 336 | } |
@@ -615,8 +356,6 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
615 | .perm = 1 << type | 356 | .perm = 1 << type |
616 | }; | 357 | }; |
617 | int error; | 358 | int error; |
618 | if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE)) | ||
619 | e.perm |= TOMOYO_RW_MASK; | ||
620 | if (!tomoyo_parse_name_union(filename, &e.name)) | 359 | if (!tomoyo_parse_name_union(filename, &e.name)) |
621 | return -EINVAL; | 360 | return -EINVAL; |
622 | error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 361 | error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, |
@@ -775,7 +514,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
775 | { | 514 | { |
776 | int error; | 515 | int error; |
777 | 516 | ||
778 | next: | ||
779 | r->type = tomoyo_p2mac[operation]; | 517 | r->type = tomoyo_p2mac[operation]; |
780 | r->mode = tomoyo_get_mode(r->profile, r->type); | 518 | r->mode = tomoyo_get_mode(r->profile, r->type); |
781 | if (r->mode == TOMOYO_CONFIG_DISABLED) | 519 | if (r->mode == TOMOYO_CONFIG_DISABLED) |
@@ -785,10 +523,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
785 | r->param.path.operation = operation; | 523 | r->param.path.operation = operation; |
786 | do { | 524 | do { |
787 | tomoyo_check_acl(r, tomoyo_check_path_acl); | 525 | tomoyo_check_acl(r, tomoyo_check_path_acl); |
788 | if (!r->granted && operation == TOMOYO_TYPE_READ && | ||
789 | !r->domain->ignore_global_allow_read && | ||
790 | tomoyo_globally_readable_file(filename)) | ||
791 | r->granted = true; | ||
792 | error = tomoyo_audit_path_log(r); | 526 | error = tomoyo_audit_path_log(r); |
793 | /* | 527 | /* |
794 | * Do not retry for execute request, for alias may have | 528 | * Do not retry for execute request, for alias may have |
@@ -796,16 +530,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
796 | */ | 530 | */ |
797 | } while (error == TOMOYO_RETRY_REQUEST && | 531 | } while (error == TOMOYO_RETRY_REQUEST && |
798 | operation != TOMOYO_TYPE_EXECUTE); | 532 | operation != TOMOYO_TYPE_EXECUTE); |
799 | /* | ||
800 | * Since "allow_truncate" doesn't imply "allow_rewrite" permission, | ||
801 | * we need to check "allow_rewrite" permission if the filename is | ||
802 | * specified by "deny_rewrite" keyword. | ||
803 | */ | ||
804 | if (!error && operation == TOMOYO_TYPE_TRUNCATE && | ||
805 | tomoyo_no_rewrite_file(filename)) { | ||
806 | operation = TOMOYO_TYPE_REWRITE; | ||
807 | goto next; | ||
808 | } | ||
809 | return error; | 533 | return error; |
810 | } | 534 | } |
811 | 535 | ||
@@ -932,43 +656,26 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
932 | struct tomoyo_request_info r; | 656 | struct tomoyo_request_info r; |
933 | int idx; | 657 | int idx; |
934 | 658 | ||
935 | if (!path->mnt || | 659 | if (!path->mnt) |
936 | (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))) | ||
937 | return 0; | 660 | return 0; |
938 | buf.name = NULL; | 661 | buf.name = NULL; |
939 | r.mode = TOMOYO_CONFIG_DISABLED; | 662 | r.mode = TOMOYO_CONFIG_DISABLED; |
940 | idx = tomoyo_read_lock(); | 663 | idx = tomoyo_read_lock(); |
941 | /* | 664 | if (acc_mode && |
942 | * If the filename is specified by "deny_rewrite" keyword, | 665 | tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) |
943 | * we need to check "allow_rewrite" permission when the filename is not | ||
944 | * opened for append mode or the filename is truncated at open time. | ||
945 | */ | ||
946 | if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND) | ||
947 | && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE) | ||
948 | != TOMOYO_CONFIG_DISABLED) { | 666 | != TOMOYO_CONFIG_DISABLED) { |
949 | if (!tomoyo_get_realpath(&buf, path)) { | 667 | if (!tomoyo_get_realpath(&buf, path)) { |
950 | error = -ENOMEM; | 668 | error = -ENOMEM; |
951 | goto out; | 669 | goto out; |
952 | } | 670 | } |
953 | if (tomoyo_no_rewrite_file(&buf)) | 671 | if (acc_mode & MAY_READ) |
954 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, | 672 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, |
673 | &buf); | ||
674 | if (!error && (acc_mode & MAY_WRITE)) | ||
675 | error = tomoyo_path_permission(&r, (flag & O_APPEND) ? | ||
676 | TOMOYO_TYPE_APPEND : | ||
677 | TOMOYO_TYPE_WRITE, | ||
955 | &buf); | 678 | &buf); |
956 | } | ||
957 | if (!error && acc_mode && | ||
958 | tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) | ||
959 | != TOMOYO_CONFIG_DISABLED) { | ||
960 | u8 operation; | ||
961 | if (!buf.name && !tomoyo_get_realpath(&buf, path)) { | ||
962 | error = -ENOMEM; | ||
963 | goto out; | ||
964 | } | ||
965 | if (acc_mode == (MAY_READ | MAY_WRITE)) | ||
966 | operation = TOMOYO_TYPE_READ_WRITE; | ||
967 | else if (acc_mode == MAY_READ) | ||
968 | operation = TOMOYO_TYPE_READ; | ||
969 | else | ||
970 | operation = TOMOYO_TYPE_WRITE; | ||
971 | error = tomoyo_path_permission(&r, operation, &buf); | ||
972 | } | 679 | } |
973 | out: | 680 | out: |
974 | kfree(buf.name); | 681 | kfree(buf.name); |
@@ -979,7 +686,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
979 | } | 686 | } |
980 | 687 | ||
981 | /** | 688 | /** |
982 | * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount". | 689 | * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount". |
983 | * | 690 | * |
984 | * @operation: Type of operation. | 691 | * @operation: Type of operation. |
985 | * @path: Pointer to "struct path". | 692 | * @path: Pointer to "struct path". |
@@ -988,9 +695,10 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
988 | */ | 695 | */ |
989 | int tomoyo_path_perm(const u8 operation, struct path *path) | 696 | int tomoyo_path_perm(const u8 operation, struct path *path) |
990 | { | 697 | { |
991 | int error = -ENOMEM; | ||
992 | struct tomoyo_path_info buf; | ||
993 | struct tomoyo_request_info r; | 698 | struct tomoyo_request_info r; |
699 | int error; | ||
700 | struct tomoyo_path_info buf; | ||
701 | bool is_enforce; | ||
994 | int idx; | 702 | int idx; |
995 | 703 | ||
996 | if (!path->mnt) | 704 | if (!path->mnt) |
@@ -998,17 +706,13 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
998 | if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) | 706 | if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) |
999 | == TOMOYO_CONFIG_DISABLED) | 707 | == TOMOYO_CONFIG_DISABLED) |
1000 | return 0; | 708 | return 0; |
709 | is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); | ||
710 | error = -ENOMEM; | ||
1001 | buf.name = NULL; | 711 | buf.name = NULL; |
1002 | idx = tomoyo_read_lock(); | 712 | idx = tomoyo_read_lock(); |
1003 | if (!tomoyo_get_realpath(&buf, path)) | 713 | if (!tomoyo_get_realpath(&buf, path)) |
1004 | goto out; | 714 | goto out; |
1005 | switch (operation) { | 715 | switch (operation) { |
1006 | case TOMOYO_TYPE_REWRITE: | ||
1007 | if (!tomoyo_no_rewrite_file(&buf)) { | ||
1008 | error = 0; | ||
1009 | goto out; | ||
1010 | } | ||
1011 | break; | ||
1012 | case TOMOYO_TYPE_RMDIR: | 716 | case TOMOYO_TYPE_RMDIR: |
1013 | case TOMOYO_TYPE_CHROOT: | 717 | case TOMOYO_TYPE_CHROOT: |
1014 | tomoyo_add_slash(&buf); | 718 | tomoyo_add_slash(&buf); |
@@ -1018,7 +722,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1018 | out: | 722 | out: |
1019 | kfree(buf.name); | 723 | kfree(buf.name); |
1020 | tomoyo_read_unlock(idx); | 724 | tomoyo_read_unlock(idx); |
1021 | if (r.mode != TOMOYO_CONFIG_ENFORCING) | 725 | if (!is_enforce) |
1022 | error = 0; | 726 | error = 0; |
1023 | return error; | 727 | return error; |
1024 | } | 728 | } |