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.c250
1 files changed, 129 insertions, 121 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 6f3fe76a1fde..1c6f8238ec47 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -45,6 +45,37 @@ static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
45 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", 45 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
46}; 46};
47 47
48void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
49{
50 if (!ptr)
51 return;
52 if (ptr->is_group)
53 tomoyo_put_path_group(ptr->group);
54 else
55 tomoyo_put_name(ptr->filename);
56}
57
58bool tomoyo_compare_name_union(const struct tomoyo_path_info *name,
59 const struct tomoyo_name_union *ptr)
60{
61 if (ptr->is_group)
62 return tomoyo_path_matches_group(name, ptr->group, 1);
63 return tomoyo_path_matches_pattern(name, ptr->filename);
64}
65
66static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info
67 *name,
68 const struct tomoyo_name_union
69 *ptr, const bool may_use_pattern)
70{
71 if (ptr->is_group)
72 return tomoyo_path_matches_group(name, ptr->group,
73 may_use_pattern);
74 if (may_use_pattern || !ptr->filename->is_patterned)
75 return tomoyo_path_matches_pattern(name, ptr->filename);
76 return false;
77}
78
48/** 79/**
49 * tomoyo_path2keyword - Get the name of single path operation. 80 * tomoyo_path2keyword - Get the name of single path operation.
50 * 81 *
@@ -100,7 +131,7 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
100{ 131{
101 int error; 132 int error;
102 struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), 133 struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf),
103 GFP_KERNEL); 134 GFP_NOFS);
104 135
105 if (!buf) 136 if (!buf)
106 return NULL; 137 return NULL;
@@ -164,36 +195,36 @@ LIST_HEAD(tomoyo_globally_readable_list);
164static int tomoyo_update_globally_readable_entry(const char *filename, 195static int tomoyo_update_globally_readable_entry(const char *filename,
165 const bool is_delete) 196 const bool is_delete)
166{ 197{
167 struct tomoyo_globally_readable_file_entry *entry = NULL;
168 struct tomoyo_globally_readable_file_entry *ptr; 198 struct tomoyo_globally_readable_file_entry *ptr;
169 const struct tomoyo_path_info *saved_filename; 199 struct tomoyo_globally_readable_file_entry e = { };
170 int error = is_delete ? -ENOENT : -ENOMEM; 200 int error = is_delete ? -ENOENT : -ENOMEM;
171 201
172 if (!tomoyo_is_correct_path(filename, 1, 0, -1)) 202 if (!tomoyo_is_correct_path(filename, 1, 0, -1))
173 return -EINVAL; 203 return -EINVAL;
174 saved_filename = tomoyo_get_name(filename); 204 e.filename = tomoyo_get_name(filename);
175 if (!saved_filename) 205 if (!e.filename)
176 return -ENOMEM; 206 return -ENOMEM;
177 if (!is_delete) 207 if (mutex_lock_interruptible(&tomoyo_policy_lock))
178 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 208 goto out;
179 mutex_lock(&tomoyo_policy_lock);
180 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 209 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
181 if (ptr->filename != saved_filename) 210 if (ptr->filename != e.filename)
182 continue; 211 continue;
183 ptr->is_deleted = is_delete; 212 ptr->is_deleted = is_delete;
184 error = 0; 213 error = 0;
185 break; 214 break;
186 } 215 }
187 if (!is_delete && error && tomoyo_memory_ok(entry)) { 216 if (!is_delete && error) {
188 entry->filename = saved_filename; 217 struct tomoyo_globally_readable_file_entry *entry =
189 saved_filename = NULL; 218 tomoyo_commit_ok(&e, sizeof(e));
190 list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); 219 if (entry) {
191 entry = NULL; 220 list_add_tail_rcu(&entry->list,
192 error = 0; 221 &tomoyo_globally_readable_list);
222 error = 0;
223 }
193 } 224 }
194 mutex_unlock(&tomoyo_policy_lock); 225 mutex_unlock(&tomoyo_policy_lock);
195 tomoyo_put_name(saved_filename); 226 out:
196 kfree(entry); 227 tomoyo_put_name(e.filename);
197 return error; 228 return error;
198} 229}
199 230
@@ -311,37 +342,34 @@ LIST_HEAD(tomoyo_pattern_list);
311static int tomoyo_update_file_pattern_entry(const char *pattern, 342static int tomoyo_update_file_pattern_entry(const char *pattern,
312 const bool is_delete) 343 const bool is_delete)
313{ 344{
314 struct tomoyo_pattern_entry *entry = NULL;
315 struct tomoyo_pattern_entry *ptr; 345 struct tomoyo_pattern_entry *ptr;
316 const struct tomoyo_path_info *saved_pattern; 346 struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) };
317 int error = is_delete ? -ENOENT : -ENOMEM; 347 int error = is_delete ? -ENOENT : -ENOMEM;
318 348
319 saved_pattern = tomoyo_get_name(pattern); 349 if (!e.pattern)
320 if (!saved_pattern)
321 return error; 350 return error;
322 if (!saved_pattern->is_patterned) 351 if (!e.pattern->is_patterned)
352 goto out;
353 if (mutex_lock_interruptible(&tomoyo_policy_lock))
323 goto out; 354 goto out;
324 if (!is_delete)
325 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
326 mutex_lock(&tomoyo_policy_lock);
327 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 355 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
328 if (saved_pattern != ptr->pattern) 356 if (e.pattern != ptr->pattern)
329 continue; 357 continue;
330 ptr->is_deleted = is_delete; 358 ptr->is_deleted = is_delete;
331 error = 0; 359 error = 0;
332 break; 360 break;
333 } 361 }
334 if (!is_delete && error && tomoyo_memory_ok(entry)) { 362 if (!is_delete && error) {
335 entry->pattern = saved_pattern; 363 struct tomoyo_pattern_entry *entry =
336 saved_pattern = NULL; 364 tomoyo_commit_ok(&e, sizeof(e));
337 list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); 365 if (entry) {
338 entry = NULL; 366 list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
339 error = 0; 367 error = 0;
368 }
340 } 369 }
341 mutex_unlock(&tomoyo_policy_lock); 370 mutex_unlock(&tomoyo_policy_lock);
342 out: 371 out:
343 kfree(entry); 372 tomoyo_put_name(e.pattern);
344 tomoyo_put_name(saved_pattern);
345 return error; 373 return error;
346} 374}
347 375
@@ -464,36 +492,36 @@ LIST_HEAD(tomoyo_no_rewrite_list);
464static int tomoyo_update_no_rewrite_entry(const char *pattern, 492static int tomoyo_update_no_rewrite_entry(const char *pattern,
465 const bool is_delete) 493 const bool is_delete)
466{ 494{
467 struct tomoyo_no_rewrite_entry *entry = NULL;
468 struct tomoyo_no_rewrite_entry *ptr; 495 struct tomoyo_no_rewrite_entry *ptr;
469 const struct tomoyo_path_info *saved_pattern; 496 struct tomoyo_no_rewrite_entry e = { };
470 int error = is_delete ? -ENOENT : -ENOMEM; 497 int error = is_delete ? -ENOENT : -ENOMEM;
471 498
472 if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) 499 if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
473 return -EINVAL; 500 return -EINVAL;
474 saved_pattern = tomoyo_get_name(pattern); 501 e.pattern = tomoyo_get_name(pattern);
475 if (!saved_pattern) 502 if (!e.pattern)
476 return error; 503 return error;
477 if (!is_delete) 504 if (mutex_lock_interruptible(&tomoyo_policy_lock))
478 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 505 goto out;
479 mutex_lock(&tomoyo_policy_lock);
480 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 506 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
481 if (ptr->pattern != saved_pattern) 507 if (ptr->pattern != e.pattern)
482 continue; 508 continue;
483 ptr->is_deleted = is_delete; 509 ptr->is_deleted = is_delete;
484 error = 0; 510 error = 0;
485 break; 511 break;
486 } 512 }
487 if (!is_delete && error && tomoyo_memory_ok(entry)) { 513 if (!is_delete && error) {
488 entry->pattern = saved_pattern; 514 struct tomoyo_no_rewrite_entry *entry =
489 saved_pattern = NULL; 515 tomoyo_commit_ok(&e, sizeof(e));
490 list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); 516 if (entry) {
491 entry = NULL; 517 list_add_tail_rcu(&entry->list,
492 error = 0; 518 &tomoyo_no_rewrite_list);
519 error = 0;
520 }
493 } 521 }
494 mutex_unlock(&tomoyo_policy_lock); 522 mutex_unlock(&tomoyo_policy_lock);
495 tomoyo_put_name(saved_pattern); 523 out:
496 kfree(entry); 524 tomoyo_put_name(e.pattern);
497 return error; 525 return error;
498} 526}
499 527
@@ -640,13 +668,9 @@ static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain,
640 if (!(acl->perm_high & (perm >> 16))) 668 if (!(acl->perm_high & (perm >> 16)))
641 continue; 669 continue;
642 } 670 }
643 if (may_use_pattern || !acl->filename->is_patterned) { 671 if (!tomoyo_compare_name_union_pattern(filename, &acl->name,
644 if (!tomoyo_path_matches_pattern(filename, 672 may_use_pattern))
645 acl->filename))
646 continue;
647 } else {
648 continue; 673 continue;
649 }
650 error = 0; 674 error = 0;
651 break; 675 break;
652 } 676 }
@@ -805,70 +829,64 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
805 struct tomoyo_domain_info *const domain, 829 struct tomoyo_domain_info *const domain,
806 const bool is_delete) 830 const bool is_delete)
807{ 831{
808 static const u32 rw_mask = 832 static const u32 tomoyo_rw_mask =
809 (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); 833 (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
810 const struct tomoyo_path_info *saved_filename; 834 const u32 perm = 1 << type;
811 struct tomoyo_acl_info *ptr; 835 struct tomoyo_acl_info *ptr;
812 struct tomoyo_path_acl *entry = NULL; 836 struct tomoyo_path_acl e = {
837 .head.type = TOMOYO_TYPE_PATH_ACL,
838 .perm_high = perm >> 16,
839 .perm = perm
840 };
813 int error = is_delete ? -ENOENT : -ENOMEM; 841 int error = is_delete ? -ENOENT : -ENOMEM;
814 const u32 perm = 1 << type;
815 842
843 if (type == TOMOYO_TYPE_READ_WRITE)
844 e.perm |= tomoyo_rw_mask;
816 if (!domain) 845 if (!domain)
817 return -EINVAL; 846 return -EINVAL;
818 if (!tomoyo_is_correct_path(filename, 0, 0, 0)) 847 if (!tomoyo_parse_name_union(filename, &e.name))
819 return -EINVAL; 848 return -EINVAL;
820 saved_filename = tomoyo_get_name(filename); 849 if (mutex_lock_interruptible(&tomoyo_policy_lock))
821 if (!saved_filename) 850 goto out;
822 return -ENOMEM;
823 if (!is_delete)
824 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
825 mutex_lock(&tomoyo_policy_lock);
826 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 851 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
827 struct tomoyo_path_acl *acl = 852 struct tomoyo_path_acl *acl =
828 container_of(ptr, struct tomoyo_path_acl, head); 853 container_of(ptr, struct tomoyo_path_acl, head);
829 if (ptr->type != TOMOYO_TYPE_PATH_ACL) 854 if (!tomoyo_is_same_path_acl(acl, &e))
830 continue;
831 if (acl->filename != saved_filename)
832 continue; 855 continue;
833 if (is_delete) { 856 if (is_delete) {
834 if (perm <= 0xFFFF) 857 if (perm <= 0xFFFF)
835 acl->perm &= ~perm; 858 acl->perm &= ~perm;
836 else 859 else
837 acl->perm_high &= ~(perm >> 16); 860 acl->perm_high &= ~(perm >> 16);
838 if ((acl->perm & rw_mask) != rw_mask) 861 if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask)
839 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); 862 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
840 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) 863 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
841 acl->perm &= ~rw_mask; 864 acl->perm &= ~tomoyo_rw_mask;
842 } else { 865 } else {
843 if (perm <= 0xFFFF) 866 if (perm <= 0xFFFF)
844 acl->perm |= perm; 867 acl->perm |= perm;
845 else 868 else
846 acl->perm_high |= (perm >> 16); 869 acl->perm_high |= (perm >> 16);
847 if ((acl->perm & rw_mask) == rw_mask) 870 if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask)
848 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; 871 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
849 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) 872 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
850 acl->perm |= rw_mask; 873 acl->perm |= tomoyo_rw_mask;
851 } 874 }
852 error = 0; 875 error = 0;
853 break; 876 break;
854 } 877 }
855 if (!is_delete && error && tomoyo_memory_ok(entry)) { 878 if (!is_delete && error) {
856 entry->head.type = TOMOYO_TYPE_PATH_ACL; 879 struct tomoyo_path_acl *entry =
857 if (perm <= 0xFFFF) 880 tomoyo_commit_ok(&e, sizeof(e));
858 entry->perm = perm; 881 if (entry) {
859 else 882 list_add_tail_rcu(&entry->head.list,
860 entry->perm_high = (perm >> 16); 883 &domain->acl_info_list);
861 if (perm == (1 << TOMOYO_TYPE_READ_WRITE)) 884 error = 0;
862 entry->perm |= rw_mask; 885 }
863 entry->filename = saved_filename;
864 saved_filename = NULL;
865 list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
866 entry = NULL;
867 error = 0;
868 } 886 }
869 mutex_unlock(&tomoyo_policy_lock); 887 mutex_unlock(&tomoyo_policy_lock);
870 kfree(entry); 888 out:
871 tomoyo_put_name(saved_filename); 889 tomoyo_put_name_union(&e.name);
872 return error; 890 return error;
873} 891}
874 892
@@ -890,32 +908,25 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
890 struct tomoyo_domain_info *const domain, 908 struct tomoyo_domain_info *const domain,
891 const bool is_delete) 909 const bool is_delete)
892{ 910{
893 const struct tomoyo_path_info *saved_filename1; 911 const u8 perm = 1 << type;
894 const struct tomoyo_path_info *saved_filename2; 912 struct tomoyo_path2_acl e = {
913 .head.type = TOMOYO_TYPE_PATH2_ACL,
914 .perm = perm
915 };
895 struct tomoyo_acl_info *ptr; 916 struct tomoyo_acl_info *ptr;
896 struct tomoyo_path2_acl *entry = NULL;
897 int error = is_delete ? -ENOENT : -ENOMEM; 917 int error = is_delete ? -ENOENT : -ENOMEM;
898 const u8 perm = 1 << type;
899 918
900 if (!domain) 919 if (!domain)
901 return -EINVAL; 920 return -EINVAL;
902 if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || 921 if (!tomoyo_parse_name_union(filename1, &e.name1) ||
903 !tomoyo_is_correct_path(filename2, 0, 0, 0)) 922 !tomoyo_parse_name_union(filename2, &e.name2))
904 return -EINVAL; 923 goto out;
905 saved_filename1 = tomoyo_get_name(filename1); 924 if (mutex_lock_interruptible(&tomoyo_policy_lock))
906 saved_filename2 = tomoyo_get_name(filename2);
907 if (!saved_filename1 || !saved_filename2)
908 goto out; 925 goto out;
909 if (!is_delete)
910 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
911 mutex_lock(&tomoyo_policy_lock);
912 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 926 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
913 struct tomoyo_path2_acl *acl = 927 struct tomoyo_path2_acl *acl =
914 container_of(ptr, struct tomoyo_path2_acl, head); 928 container_of(ptr, struct tomoyo_path2_acl, head);
915 if (ptr->type != TOMOYO_TYPE_PATH2_ACL) 929 if (!tomoyo_is_same_path2_acl(acl, &e))
916 continue;
917 if (acl->filename1 != saved_filename1 ||
918 acl->filename2 != saved_filename2)
919 continue; 930 continue;
920 if (is_delete) 931 if (is_delete)
921 acl->perm &= ~perm; 932 acl->perm &= ~perm;
@@ -924,22 +935,19 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
924 error = 0; 935 error = 0;
925 break; 936 break;
926 } 937 }
927 if (!is_delete && error && tomoyo_memory_ok(entry)) { 938 if (!is_delete && error) {
928 entry->head.type = TOMOYO_TYPE_PATH2_ACL; 939 struct tomoyo_path2_acl *entry =
929 entry->perm = perm; 940 tomoyo_commit_ok(&e, sizeof(e));
930 entry->filename1 = saved_filename1; 941 if (entry) {
931 saved_filename1 = NULL; 942 list_add_tail_rcu(&entry->head.list,
932 entry->filename2 = saved_filename2; 943 &domain->acl_info_list);
933 saved_filename2 = NULL; 944 error = 0;
934 list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); 945 }
935 entry = NULL;
936 error = 0;
937 } 946 }
938 mutex_unlock(&tomoyo_policy_lock); 947 mutex_unlock(&tomoyo_policy_lock);
939 out: 948 out:
940 tomoyo_put_name(saved_filename1); 949 tomoyo_put_name_union(&e.name1);
941 tomoyo_put_name(saved_filename2); 950 tomoyo_put_name_union(&e.name2);
942 kfree(entry);
943 return error; 951 return error;
944} 952}
945 953
@@ -992,9 +1000,9 @@ static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain,
992 acl = container_of(ptr, struct tomoyo_path2_acl, head); 1000 acl = container_of(ptr, struct tomoyo_path2_acl, head);
993 if (!(acl->perm & perm)) 1001 if (!(acl->perm & perm))
994 continue; 1002 continue;
995 if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) 1003 if (!tomoyo_compare_name_union(filename1, &acl->name1))
996 continue; 1004 continue;
997 if (!tomoyo_path_matches_pattern(filename2, acl->filename2)) 1005 if (!tomoyo_compare_name_union(filename2, &acl->name2))
998 continue; 1006 continue;
999 error = 0; 1007 error = 0;
1000 break; 1008 break;