aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/file.c
diff options
context:
space:
mode:
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}