aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/file.c
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2011-06-26 10:15:31 -0400
committerJames Morris <jmorris@namei.org>2011-06-28 19:31:19 -0400
commit7c75964f432d14062d8eccfc916aa290f56b5aab (patch)
tree8aecdb96f9f079dd36735c3acccb79f3d10d6559 /security/tomoyo/file.c
parent1252cc3b232e582e887623dc5f70979418caaaa2 (diff)
TOMOYO: Cleanup part 1.
In order to synchronize with TOMOYO 1.8's syntax, (1) Remove special handling for allow_read/write permission. (2) Replace deny_rewrite/allow_rewrite permission with allow_append permission. (3) Remove file_pattern keyword. (4) Remove allow_read permission from exception policy. (5) Allow creating domains in enforcing mode without calling supervisor. (6) Add permission check for opening directory for reading. (7) Add permission check for stat() operation. (8) Make "cat < /sys/kernel/security/tomoyo/self_domain" behave as if "cat /sys/kernel/security/tomoyo/self_domain". 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/file.c')
-rw-r--r--security/tomoyo/file.c368
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. */
13const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 13const 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
52static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { 52static 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 */
142static 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
270static 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 */
289static 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 */
317static 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 */
344int tomoyo_write_globally_readable(char *data, const bool is_delete)
345{
346 return tomoyo_update_globally_readable_entry(data, is_delete);
347}
348
349static 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 */
366static 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 */
393const 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 */
427int tomoyo_write_pattern(char *data, const bool is_delete)
428{
429 return tomoyo_update_file_pattern_entry(data, is_delete);
430}
431
432static 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 */
450static 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 */
478static 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 */
505int 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
510static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, 251static 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 */
572static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, 322static 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 */
989int tomoyo_path_perm(const u8 operation, struct path *path) 696int 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}