1
2
3
4
5
6
7
8
9
10
11
12#include "common.h"
13#include "tomoyo.h"
14#include "realpath.h"
15#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
16
17
18
19
20
21
22
23
24
25
26
27struct tomoyo_globally_readable_file_entry {
28 struct list_head list;
29 const struct tomoyo_path_info *filename;
30 bool is_deleted;
31};
32
33
34
35
36
37
38
39
40
41
42
43
44struct tomoyo_pattern_entry {
45 struct list_head list;
46 const struct tomoyo_path_info *pattern;
47 bool is_deleted;
48};
49
50
51
52
53
54
55
56
57
58
59
60
61struct tomoyo_no_rewrite_entry {
62 struct list_head list;
63 const struct tomoyo_path_info *pattern;
64 bool is_deleted;
65};
66
67
68static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
69 [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
70 [TOMOYO_TYPE_EXECUTE_ACL] = "execute",
71 [TOMOYO_TYPE_READ_ACL] = "read",
72 [TOMOYO_TYPE_WRITE_ACL] = "write",
73 [TOMOYO_TYPE_CREATE_ACL] = "create",
74 [TOMOYO_TYPE_UNLINK_ACL] = "unlink",
75 [TOMOYO_TYPE_MKDIR_ACL] = "mkdir",
76 [TOMOYO_TYPE_RMDIR_ACL] = "rmdir",
77 [TOMOYO_TYPE_MKFIFO_ACL] = "mkfifo",
78 [TOMOYO_TYPE_MKSOCK_ACL] = "mksock",
79 [TOMOYO_TYPE_MKBLOCK_ACL] = "mkblock",
80 [TOMOYO_TYPE_MKCHAR_ACL] = "mkchar",
81 [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate",
82 [TOMOYO_TYPE_SYMLINK_ACL] = "symlink",
83 [TOMOYO_TYPE_REWRITE_ACL] = "rewrite",
84};
85
86
87static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
88 [TOMOYO_TYPE_LINK_ACL] = "link",
89 [TOMOYO_TYPE_RENAME_ACL] = "rename",
90};
91
92
93
94
95
96
97
98
99const char *tomoyo_sp2keyword(const u8 operation)
100{
101 return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
102 ? tomoyo_sp_keyword[operation] : NULL;
103}
104
105
106
107
108
109
110
111
112const char *tomoyo_dp2keyword(const u8 operation)
113{
114 return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
115 ? tomoyo_dp_keyword[operation] : NULL;
116}
117
118
119
120
121
122
123
124
125
126static bool tomoyo_strendswith(const char *name, const char *tail)
127{
128 int len;
129
130 if (!name || !tail)
131 return false;
132 len = strlen(name) - strlen(tail);
133 return len >= 0 && !strcmp(name + len, tail);
134}
135
136
137
138
139
140
141
142
143static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
144{
145 int error;
146 struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
147
148 if (!buf)
149 return NULL;
150
151 error = tomoyo_realpath_from_path2(path, buf->body,
152 sizeof(buf->body) - 2);
153 if (!error) {
154 buf->head.name = buf->body;
155 tomoyo_fill_path_info(&buf->head);
156 return &buf->head;
157 }
158 tomoyo_free(buf);
159 return NULL;
160}
161
162
163DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
164
165static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
166 const char *filename2,
167 struct tomoyo_domain_info *
168 const domain, const bool is_delete);
169static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
170 struct tomoyo_domain_info *
171 const domain, const bool is_delete);
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198static LIST_HEAD(tomoyo_globally_readable_list);
199static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
200
201
202
203
204
205
206
207
208
209static int tomoyo_update_globally_readable_entry(const char *filename,
210 const bool is_delete)
211{
212 struct tomoyo_globally_readable_file_entry *new_entry;
213 struct tomoyo_globally_readable_file_entry *ptr;
214 const struct tomoyo_path_info *saved_filename;
215 int error = -ENOMEM;
216
217 if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
218 return -EINVAL;
219 saved_filename = tomoyo_save_name(filename);
220 if (!saved_filename)
221 return -ENOMEM;
222 down_write(&tomoyo_globally_readable_list_lock);
223 list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
224 if (ptr->filename != saved_filename)
225 continue;
226 ptr->is_deleted = is_delete;
227 error = 0;
228 goto out;
229 }
230 if (is_delete) {
231 error = -ENOENT;
232 goto out;
233 }
234 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
235 if (!new_entry)
236 goto out;
237 new_entry->filename = saved_filename;
238 list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
239 error = 0;
240 out:
241 up_write(&tomoyo_globally_readable_list_lock);
242 return error;
243}
244
245
246
247
248
249
250
251
252static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
253 filename)
254{
255 struct tomoyo_globally_readable_file_entry *ptr;
256 bool found = false;
257 down_read(&tomoyo_globally_readable_list_lock);
258 list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
259 if (!ptr->is_deleted &&
260 tomoyo_path_matches_pattern(filename, ptr->filename)) {
261 found = true;
262 break;
263 }
264 }
265 up_read(&tomoyo_globally_readable_list_lock);
266 return found;
267}
268
269
270
271
272
273
274
275
276
277int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
278{
279 return tomoyo_update_globally_readable_entry(data, is_delete);
280}
281
282
283
284
285
286
287
288
289bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
290{
291 struct list_head *pos;
292 bool done = true;
293
294 down_read(&tomoyo_globally_readable_list_lock);
295 list_for_each_cookie(pos, head->read_var2,
296 &tomoyo_globally_readable_list) {
297 struct tomoyo_globally_readable_file_entry *ptr;
298 ptr = list_entry(pos,
299 struct tomoyo_globally_readable_file_entry,
300 list);
301 if (ptr->is_deleted)
302 continue;
303 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
304 ptr->filename->name);
305 if (!done)
306 break;
307 }
308 up_read(&tomoyo_globally_readable_list_lock);
309 return done;
310}
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341static LIST_HEAD(tomoyo_pattern_list);
342static DECLARE_RWSEM(tomoyo_pattern_list_lock);
343
344
345
346
347
348
349
350
351
352static int tomoyo_update_file_pattern_entry(const char *pattern,
353 const bool is_delete)
354{
355 struct tomoyo_pattern_entry *new_entry;
356 struct tomoyo_pattern_entry *ptr;
357 const struct tomoyo_path_info *saved_pattern;
358 int error = -ENOMEM;
359
360 if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
361 return -EINVAL;
362 saved_pattern = tomoyo_save_name(pattern);
363 if (!saved_pattern)
364 return -ENOMEM;
365 down_write(&tomoyo_pattern_list_lock);
366 list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
367 if (saved_pattern != ptr->pattern)
368 continue;
369 ptr->is_deleted = is_delete;
370 error = 0;
371 goto out;
372 }
373 if (is_delete) {
374 error = -ENOENT;
375 goto out;
376 }
377 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
378 if (!new_entry)
379 goto out;
380 new_entry->pattern = saved_pattern;
381 list_add_tail(&new_entry->list, &tomoyo_pattern_list);
382 error = 0;
383 out:
384 up_write(&tomoyo_pattern_list_lock);
385 return error;
386}
387
388
389
390
391
392
393
394
395static const struct tomoyo_path_info *
396tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
397{
398 struct tomoyo_pattern_entry *ptr;
399 const struct tomoyo_path_info *pattern = NULL;
400
401 down_read(&tomoyo_pattern_list_lock);
402 list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
403 if (ptr->is_deleted)
404 continue;
405 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
406 continue;
407 pattern = ptr->pattern;
408 if (tomoyo_strendswith(pattern->name, "/\\*")) {
409
410 } else {
411
412 break;
413 }
414 }
415 up_read(&tomoyo_pattern_list_lock);
416 if (pattern)
417 filename = pattern;
418 return filename;
419}
420
421
422
423
424
425
426
427
428
429int tomoyo_write_pattern_policy(char *data, const bool is_delete)
430{
431 return tomoyo_update_file_pattern_entry(data, is_delete);
432}
433
434
435
436
437
438
439
440
441bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
442{
443 struct list_head *pos;
444 bool done = true;
445
446 down_read(&tomoyo_pattern_list_lock);
447 list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
448 struct tomoyo_pattern_entry *ptr;
449 ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
450 if (ptr->is_deleted)
451 continue;
452 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN
453 "%s\n", ptr->pattern->name);
454 if (!done)
455 break;
456 }
457 up_read(&tomoyo_pattern_list_lock);
458 return done;
459}
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490static LIST_HEAD(tomoyo_no_rewrite_list);
491static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
492
493
494
495
496
497
498
499
500
501static int tomoyo_update_no_rewrite_entry(const char *pattern,
502 const bool is_delete)
503{
504 struct tomoyo_no_rewrite_entry *new_entry, *ptr;
505 const struct tomoyo_path_info *saved_pattern;
506 int error = -ENOMEM;
507
508 if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
509 return -EINVAL;
510 saved_pattern = tomoyo_save_name(pattern);
511 if (!saved_pattern)
512 return -ENOMEM;
513 down_write(&tomoyo_no_rewrite_list_lock);
514 list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
515 if (ptr->pattern != saved_pattern)
516 continue;
517 ptr->is_deleted = is_delete;
518 error = 0;
519 goto out;
520 }
521 if (is_delete) {
522 error = -ENOENT;
523 goto out;
524 }
525 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
526 if (!new_entry)
527 goto out;
528 new_entry->pattern = saved_pattern;
529 list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
530 error = 0;
531 out:
532 up_write(&tomoyo_no_rewrite_list_lock);
533 return error;
534}
535
536
537
538
539
540
541
542
543
544static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
545{
546 struct tomoyo_no_rewrite_entry *ptr;
547 bool found = false;
548
549 down_read(&tomoyo_no_rewrite_list_lock);
550 list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
551 if (ptr->is_deleted)
552 continue;
553 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
554 continue;
555 found = true;
556 break;
557 }
558 up_read(&tomoyo_no_rewrite_list_lock);
559 return found;
560}
561
562
563
564
565
566
567
568
569
570int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
571{
572 return tomoyo_update_no_rewrite_entry(data, is_delete);
573}
574
575
576
577
578
579
580
581
582bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
583{
584 struct list_head *pos;
585 bool done = true;
586
587 down_read(&tomoyo_no_rewrite_list_lock);
588 list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
589 struct tomoyo_no_rewrite_entry *ptr;
590 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
591 if (ptr->is_deleted)
592 continue;
593 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE
594 "%s\n", ptr->pattern->name);
595 if (!done)
596 break;
597 }
598 up_read(&tomoyo_no_rewrite_list_lock);
599 return done;
600}
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617static int tomoyo_update_file_acl(const char *filename, u8 perm,
618 struct tomoyo_domain_info * const domain,
619 const bool is_delete)
620{
621 if (perm > 7 || !perm) {
622 printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
623 __func__, perm, filename);
624 return -EINVAL;
625 }
626 if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
627
628
629
630
631 return 0;
632 if (perm & 4)
633 tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
634 domain, is_delete);
635 if (perm & 2)
636 tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
637 domain, is_delete);
638 if (perm & 1)
639 tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
640 filename, domain, is_delete);
641 return 0;
642}
643
644
645
646
647
648
649
650
651
652
653
654static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
655 domain,
656 const struct tomoyo_path_info *
657 filename,
658 const u16 perm,
659 const bool may_use_pattern)
660{
661 struct tomoyo_acl_info *ptr;
662 int error = -EPERM;
663
664 down_read(&tomoyo_domain_acl_info_list_lock);
665 list_for_each_entry(ptr, &domain->acl_info_list, list) {
666 struct tomoyo_single_path_acl_record *acl;
667 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
668 continue;
669 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
670 head);
671 if (!(acl->perm & perm))
672 continue;
673 if (may_use_pattern || !acl->filename->is_patterned) {
674 if (!tomoyo_path_matches_pattern(filename,
675 acl->filename))
676 continue;
677 } else {
678 continue;
679 }
680 error = 0;
681 break;
682 }
683 up_read(&tomoyo_domain_acl_info_list_lock);
684 return error;
685}
686
687
688
689
690
691
692
693
694
695
696static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
697 const struct tomoyo_path_info *filename,
698 const u8 operation)
699{
700 u16 perm = 0;
701
702 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
703 return 0;
704 if (operation == 6)
705 perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
706 else if (operation == 4)
707 perm = 1 << TOMOYO_TYPE_READ_ACL;
708 else if (operation == 2)
709 perm = 1 << TOMOYO_TYPE_WRITE_ACL;
710 else if (operation == 1)
711 perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
712 else
713 BUG();
714 return tomoyo_check_single_path_acl2(domain, filename, perm,
715 operation != 1);
716}
717
718
719
720
721
722
723
724
725
726
727
728
729static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
730 const struct tomoyo_path_info *filename,
731 const u8 perm, const char *operation,
732 const u8 mode)
733{
734 const bool is_enforce = (mode == 3);
735 const char *msg = "<unknown>";
736 int error = 0;
737
738 if (!filename)
739 return 0;
740 error = tomoyo_check_file_acl(domain, filename, perm);
741 if (error && perm == 4 &&
742 (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
743 && tomoyo_is_globally_readable_file(filename))
744 error = 0;
745 if (perm == 6)
746 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
747 else if (perm == 4)
748 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
749 else if (perm == 2)
750 msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
751 else if (perm == 1)
752 msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
753 else
754 BUG();
755 if (!error)
756 return 0;
757 if (tomoyo_verbose_mode(domain))
758 printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
759 "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
760 filename->name, tomoyo_get_last_name(domain));
761 if (is_enforce)
762 return error;
763 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
764
765 const struct tomoyo_path_info *patterned_file = (perm != 1) ?
766 tomoyo_get_file_pattern(filename) : filename;
767 tomoyo_update_file_acl(patterned_file->name, perm,
768 domain, false);
769 }
770 return 0;
771}
772
773
774
775
776
777
778
779
780
781
782int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
783 const bool is_delete)
784{
785 char *filename = strchr(data, ' ');
786 char *filename2;
787 unsigned int perm;
788 u8 type;
789
790 if (!filename)
791 return -EINVAL;
792 *filename++ = '\0';
793 if (sscanf(data, "%u", &perm) == 1)
794 return tomoyo_update_file_acl(filename, (u8) perm, domain,
795 is_delete);
796 if (strncmp(data, "allow_", 6))
797 goto out;
798 data += 6;
799 for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
800 if (strcmp(data, tomoyo_sp_keyword[type]))
801 continue;
802 return tomoyo_update_single_path_acl(type, filename,
803 domain, is_delete);
804 }
805 filename2 = strchr(filename, ' ');
806 if (!filename2)
807 goto out;
808 *filename2++ = '\0';
809 for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
810 if (strcmp(data, tomoyo_dp_keyword[type]))
811 continue;
812 return tomoyo_update_double_path_acl(type, filename, filename2,
813 domain, is_delete);
814 }
815 out:
816 return -EINVAL;
817}
818
819
820
821
822
823
824
825
826
827
828
829static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
830 struct tomoyo_domain_info *
831 const domain, const bool is_delete)
832{
833 static const u16 rw_mask =
834 (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
835 const struct tomoyo_path_info *saved_filename;
836 struct tomoyo_acl_info *ptr;
837 struct tomoyo_single_path_acl_record *acl;
838 int error = -ENOMEM;
839 const u16 perm = 1 << type;
840
841 if (!domain)
842 return -EINVAL;
843 if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
844 return -EINVAL;
845 saved_filename = tomoyo_save_name(filename);
846 if (!saved_filename)
847 return -ENOMEM;
848 down_write(&tomoyo_domain_acl_info_list_lock);
849 if (is_delete)
850 goto delete;
851 list_for_each_entry(ptr, &domain->acl_info_list, list) {
852 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
853 continue;
854 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
855 head);
856 if (acl->filename != saved_filename)
857 continue;
858
859 if (ptr->type & TOMOYO_ACL_DELETED)
860 acl->perm = 0;
861 acl->perm |= perm;
862 if ((acl->perm & rw_mask) == rw_mask)
863 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
864 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
865 acl->perm |= rw_mask;
866 ptr->type &= ~TOMOYO_ACL_DELETED;
867 error = 0;
868 goto out;
869 }
870
871 acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
872 if (!acl)
873 goto out;
874 acl->perm = perm;
875 if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
876 acl->perm |= rw_mask;
877 acl->filename = saved_filename;
878 list_add_tail(&acl->head.list, &domain->acl_info_list);
879 error = 0;
880 goto out;
881 delete:
882 error = -ENOENT;
883 list_for_each_entry(ptr, &domain->acl_info_list, list) {
884 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
885 continue;
886 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
887 head);
888 if (acl->filename != saved_filename)
889 continue;
890 acl->perm &= ~perm;
891 if ((acl->perm & rw_mask) != rw_mask)
892 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
893 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
894 acl->perm &= ~rw_mask;
895 if (!acl->perm)
896 ptr->type |= TOMOYO_ACL_DELETED;
897 error = 0;
898 break;
899 }
900 out:
901 up_write(&tomoyo_domain_acl_info_list_lock);
902 return error;
903}
904
905
906
907
908
909
910
911
912
913
914
915
916static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
917 const char *filename2,
918 struct tomoyo_domain_info *
919 const domain, const bool is_delete)
920{
921 const struct tomoyo_path_info *saved_filename1;
922 const struct tomoyo_path_info *saved_filename2;
923 struct tomoyo_acl_info *ptr;
924 struct tomoyo_double_path_acl_record *acl;
925 int error = -ENOMEM;
926 const u8 perm = 1 << type;
927
928 if (!domain)
929 return -EINVAL;
930 if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
931 !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
932 return -EINVAL;
933 saved_filename1 = tomoyo_save_name(filename1);
934 saved_filename2 = tomoyo_save_name(filename2);
935 if (!saved_filename1 || !saved_filename2)
936 return -ENOMEM;
937 down_write(&tomoyo_domain_acl_info_list_lock);
938 if (is_delete)
939 goto delete;
940 list_for_each_entry(ptr, &domain->acl_info_list, list) {
941 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
942 continue;
943 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
944 head);
945 if (acl->filename1 != saved_filename1 ||
946 acl->filename2 != saved_filename2)
947 continue;
948
949 if (ptr->type & TOMOYO_ACL_DELETED)
950 acl->perm = 0;
951 acl->perm |= perm;
952 ptr->type &= ~TOMOYO_ACL_DELETED;
953 error = 0;
954 goto out;
955 }
956
957 acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
958 if (!acl)
959 goto out;
960 acl->perm = perm;
961 acl->filename1 = saved_filename1;
962 acl->filename2 = saved_filename2;
963 list_add_tail(&acl->head.list, &domain->acl_info_list);
964 error = 0;
965 goto out;
966 delete:
967 error = -ENOENT;
968 list_for_each_entry(ptr, &domain->acl_info_list, list) {
969 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
970 continue;
971 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
972 head);
973 if (acl->filename1 != saved_filename1 ||
974 acl->filename2 != saved_filename2)
975 continue;
976 acl->perm &= ~perm;
977 if (!acl->perm)
978 ptr->type |= TOMOYO_ACL_DELETED;
979 error = 0;
980 break;
981 }
982 out:
983 up_write(&tomoyo_domain_acl_info_list_lock);
984 return error;
985}
986
987
988
989
990
991
992
993
994
995
996static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
997 const u8 type,
998 const struct tomoyo_path_info *filename)
999{
1000 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
1001 return 0;
1002 return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
1003}
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
1016 const u8 type,
1017 const struct tomoyo_path_info *
1018 filename1,
1019 const struct tomoyo_path_info *
1020 filename2)
1021{
1022 struct tomoyo_acl_info *ptr;
1023 const u8 perm = 1 << type;
1024 int error = -EPERM;
1025
1026 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
1027 return 0;
1028 down_read(&tomoyo_domain_acl_info_list_lock);
1029 list_for_each_entry(ptr, &domain->acl_info_list, list) {
1030 struct tomoyo_double_path_acl_record *acl;
1031 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
1032 continue;
1033 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
1034 head);
1035 if (!(acl->perm & perm))
1036 continue;
1037 if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
1038 continue;
1039 if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
1040 continue;
1041 error = 0;
1042 break;
1043 }
1044 up_read(&tomoyo_domain_acl_info_list_lock);
1045 return error;
1046}
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
1059 const domain, u8 operation,
1060 const struct tomoyo_path_info *
1061 filename, const u8 mode)
1062{
1063 const char *msg;
1064 int error;
1065 const bool is_enforce = (mode == 3);
1066
1067 if (!mode)
1068 return 0;
1069 next:
1070 error = tomoyo_check_single_path_acl(domain, operation, filename);
1071 msg = tomoyo_sp2keyword(operation);
1072 if (!error)
1073 goto ok;
1074 if (tomoyo_verbose_mode(domain))
1075 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
1076 tomoyo_get_msg(is_enforce), msg, filename->name,
1077 tomoyo_get_last_name(domain));
1078 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1079 const char *name = tomoyo_get_file_pattern(filename)->name;
1080 tomoyo_update_single_path_acl(operation, name, domain, false);
1081 }
1082 if (!is_enforce)
1083 error = 0;
1084 ok:
1085
1086
1087
1088
1089
1090 if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
1091 tomoyo_is_no_rewrite_file(filename)) {
1092 operation = TOMOYO_TYPE_REWRITE_ACL;
1093 goto next;
1094 }
1095 return error;
1096}
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
1107 const char *filename, const u8 perm)
1108{
1109 struct tomoyo_path_info name;
1110 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1111
1112 if (!mode)
1113 return 0;
1114 name.name = filename;
1115 tomoyo_fill_path_info(&name);
1116 return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
1117}
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
1128 const struct tomoyo_path_info *filename)
1129{
1130 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1131
1132 if (!mode)
1133 return 0;
1134 return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode);
1135}
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1147 struct path *path, const int flag)
1148{
1149 const u8 acc_mode = ACC_MODE(flag);
1150 int error = -ENOMEM;
1151 struct tomoyo_path_info *buf;
1152 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1153 const bool is_enforce = (mode == 3);
1154
1155 if (!mode || !path->mnt)
1156 return 0;
1157 if (acc_mode == 0)
1158 return 0;
1159 if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1160
1161
1162
1163
1164 return 0;
1165 buf = tomoyo_get_path(path);
1166 if (!buf)
1167 goto out;
1168 error = 0;
1169
1170
1171
1172
1173
1174 if ((acc_mode & MAY_WRITE) &&
1175 ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1176 (tomoyo_is_no_rewrite_file(buf))) {
1177 error = tomoyo_check_single_path_permission2(domain,
1178 TOMOYO_TYPE_REWRITE_ACL,
1179 buf, mode);
1180 }
1181 if (!error)
1182 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1183 mode);
1184 if (!error && (flag & O_TRUNC))
1185 error = tomoyo_check_single_path_permission2(domain,
1186 TOMOYO_TYPE_TRUNCATE_ACL,
1187 buf, mode);
1188 out:
1189 tomoyo_free(buf);
1190 if (!is_enforce)
1191 error = 0;
1192 return error;
1193}
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
1205 const u8 operation, struct path *path)
1206{
1207 int error = -ENOMEM;
1208 struct tomoyo_path_info *buf;
1209 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1210 const bool is_enforce = (mode == 3);
1211
1212 if (!mode || !path->mnt)
1213 return 0;
1214 buf = tomoyo_get_path(path);
1215 if (!buf)
1216 goto out;
1217 switch (operation) {
1218 case TOMOYO_TYPE_MKDIR_ACL:
1219 case TOMOYO_TYPE_RMDIR_ACL:
1220 if (!buf->is_dir) {
1221
1222
1223
1224 strcat((char *) buf->name, "/");
1225 tomoyo_fill_path_info(buf);
1226 }
1227 }
1228 error = tomoyo_check_single_path_permission2(domain, operation, buf,
1229 mode);
1230 out:
1231 tomoyo_free(buf);
1232 if (!is_enforce)
1233 error = 0;
1234 return error;
1235}
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
1246 struct file *filp)
1247{
1248 int error = -ENOMEM;
1249 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1250 const bool is_enforce = (mode == 3);
1251 struct tomoyo_path_info *buf;
1252
1253 if (!mode || !filp->f_path.mnt)
1254 return 0;
1255 buf = tomoyo_get_path(&filp->f_path);
1256 if (!buf)
1257 goto out;
1258 if (!tomoyo_is_no_rewrite_file(buf)) {
1259 error = 0;
1260 goto out;
1261 }
1262 error = tomoyo_check_single_path_permission2(domain,
1263 TOMOYO_TYPE_REWRITE_ACL,
1264 buf, mode);
1265 out:
1266 tomoyo_free(buf);
1267 if (!is_enforce)
1268 error = 0;
1269 return error;
1270}
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
1283 const u8 operation, struct path *path1,
1284 struct path *path2)
1285{
1286 int error = -ENOMEM;
1287 struct tomoyo_path_info *buf1, *buf2;
1288 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1289 const bool is_enforce = (mode == 3);
1290 const char *msg;
1291
1292 if (!mode || !path1->mnt || !path2->mnt)
1293 return 0;
1294 buf1 = tomoyo_get_path(path1);
1295 buf2 = tomoyo_get_path(path2);
1296 if (!buf1 || !buf2)
1297 goto out;
1298 {
1299 struct dentry *dentry = path1->dentry;
1300 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1301
1302
1303
1304 if (!buf1->is_dir) {
1305 strcat((char *) buf1->name, "/");
1306 tomoyo_fill_path_info(buf1);
1307 }
1308 if (!buf2->is_dir) {
1309 strcat((char *) buf2->name, "/");
1310 tomoyo_fill_path_info(buf2);
1311 }
1312 }
1313 }
1314 error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
1315 msg = tomoyo_dp2keyword(operation);
1316 if (!error)
1317 goto out;
1318 if (tomoyo_verbose_mode(domain))
1319 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
1320 "denied for %s\n", tomoyo_get_msg(is_enforce),
1321 msg, buf1->name, buf2->name,
1322 tomoyo_get_last_name(domain));
1323 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1324 const char *name1 = tomoyo_get_file_pattern(buf1)->name;
1325 const char *name2 = tomoyo_get_file_pattern(buf2)->name;
1326 tomoyo_update_double_path_acl(operation, name1, name2, domain,
1327 false);
1328 }
1329 out:
1330 tomoyo_free(buf1);
1331 tomoyo_free(buf2);
1332 if (!is_enforce)
1333 error = 0;
1334 return error;
1335}
1336