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.c234
1 files changed, 99 insertions, 135 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 84c821a245ca..f4a27714e077 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -215,38 +215,34 @@ static LIST_HEAD(tomoyo_globally_readable_list);
215static int tomoyo_update_globally_readable_entry(const char *filename, 215static int tomoyo_update_globally_readable_entry(const char *filename,
216 const bool is_delete) 216 const bool is_delete)
217{ 217{
218 struct tomoyo_globally_readable_file_entry *new_entry; 218 struct tomoyo_globally_readable_file_entry *entry = NULL;
219 struct tomoyo_globally_readable_file_entry *ptr; 219 struct tomoyo_globally_readable_file_entry *ptr;
220 const struct tomoyo_path_info *saved_filename; 220 const struct tomoyo_path_info *saved_filename;
221 int error = -ENOMEM; 221 int error = is_delete ? -ENOENT : -ENOMEM;
222 222
223 if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) 223 if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
224 return -EINVAL; 224 return -EINVAL;
225 saved_filename = tomoyo_save_name(filename); 225 saved_filename = tomoyo_save_name(filename);
226 if (!saved_filename) 226 if (!saved_filename)
227 return -ENOMEM; 227 return -ENOMEM;
228 new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); 228 if (!is_delete)
229 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
229 mutex_lock(&tomoyo_policy_lock); 230 mutex_lock(&tomoyo_policy_lock);
230 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 231 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
231 if (ptr->filename != saved_filename) 232 if (ptr->filename != saved_filename)
232 continue; 233 continue;
233 ptr->is_deleted = is_delete; 234 ptr->is_deleted = is_delete;
234 error = 0; 235 error = 0;
235 goto out; 236 break;
236 } 237 }
237 if (is_delete) { 238 if (!is_delete && error && tomoyo_memory_ok(entry)) {
238 error = -ENOENT; 239 entry->filename = saved_filename;
239 goto out; 240 list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list);
241 entry = NULL;
242 error = 0;
240 } 243 }
241 if (!tomoyo_memory_ok(new_entry))
242 goto out;
243 new_entry->filename = saved_filename;
244 list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list);
245 new_entry = NULL;
246 error = 0;
247 out:
248 mutex_unlock(&tomoyo_policy_lock); 244 mutex_unlock(&tomoyo_policy_lock);
249 kfree(new_entry); 245 kfree(entry);
250 return error; 246 return error;
251} 247}
252 248
@@ -364,38 +360,35 @@ static LIST_HEAD(tomoyo_pattern_list);
364static int tomoyo_update_file_pattern_entry(const char *pattern, 360static int tomoyo_update_file_pattern_entry(const char *pattern,
365 const bool is_delete) 361 const bool is_delete)
366{ 362{
367 struct tomoyo_pattern_entry *new_entry; 363 struct tomoyo_pattern_entry *entry = NULL;
368 struct tomoyo_pattern_entry *ptr; 364 struct tomoyo_pattern_entry *ptr;
369 const struct tomoyo_path_info *saved_pattern; 365 const struct tomoyo_path_info *saved_pattern;
370 int error = -ENOMEM; 366 int error = is_delete ? -ENOENT : -ENOMEM;
371 367
372 if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
373 return -EINVAL;
374 saved_pattern = tomoyo_save_name(pattern); 368 saved_pattern = tomoyo_save_name(pattern);
375 if (!saved_pattern) 369 if (!saved_pattern)
376 return -ENOMEM; 370 return error;
377 new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); 371 if (!saved_pattern->is_patterned)
372 goto out;
373 if (!is_delete)
374 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
378 mutex_lock(&tomoyo_policy_lock); 375 mutex_lock(&tomoyo_policy_lock);
379 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 376 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
380 if (saved_pattern != ptr->pattern) 377 if (saved_pattern != ptr->pattern)
381 continue; 378 continue;
382 ptr->is_deleted = is_delete; 379 ptr->is_deleted = is_delete;
383 error = 0; 380 error = 0;
384 goto out; 381 break;
385 } 382 }
386 if (is_delete) { 383 if (!is_delete && error && tomoyo_memory_ok(entry)) {
387 error = -ENOENT; 384 entry->pattern = saved_pattern;
388 goto out; 385 list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
386 entry = NULL;
387 error = 0;
389 } 388 }
390 if (!tomoyo_memory_ok(new_entry))
391 goto out;
392 new_entry->pattern = saved_pattern;
393 list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list);
394 new_entry = NULL;
395 error = 0;
396 out:
397 mutex_unlock(&tomoyo_policy_lock); 389 mutex_unlock(&tomoyo_policy_lock);
398 kfree(new_entry); 390 out:
391 kfree(entry);
399 return error; 392 return error;
400} 393}
401 394
@@ -518,37 +511,34 @@ static LIST_HEAD(tomoyo_no_rewrite_list);
518static int tomoyo_update_no_rewrite_entry(const char *pattern, 511static int tomoyo_update_no_rewrite_entry(const char *pattern,
519 const bool is_delete) 512 const bool is_delete)
520{ 513{
521 struct tomoyo_no_rewrite_entry *new_entry, *ptr; 514 struct tomoyo_no_rewrite_entry *entry = NULL;
515 struct tomoyo_no_rewrite_entry *ptr;
522 const struct tomoyo_path_info *saved_pattern; 516 const struct tomoyo_path_info *saved_pattern;
523 int error = -ENOMEM; 517 int error = is_delete ? -ENOENT : -ENOMEM;
524 518
525 if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) 519 if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
526 return -EINVAL; 520 return -EINVAL;
527 saved_pattern = tomoyo_save_name(pattern); 521 saved_pattern = tomoyo_save_name(pattern);
528 if (!saved_pattern) 522 if (!saved_pattern)
529 return -ENOMEM; 523 return error;
530 new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); 524 if (!is_delete)
525 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
531 mutex_lock(&tomoyo_policy_lock); 526 mutex_lock(&tomoyo_policy_lock);
532 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 527 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
533 if (ptr->pattern != saved_pattern) 528 if (ptr->pattern != saved_pattern)
534 continue; 529 continue;
535 ptr->is_deleted = is_delete; 530 ptr->is_deleted = is_delete;
536 error = 0; 531 error = 0;
537 goto out; 532 break;
538 } 533 }
539 if (is_delete) { 534 if (!is_delete && error && tomoyo_memory_ok(entry)) {
540 error = -ENOENT; 535 entry->pattern = saved_pattern;
541 goto out; 536 list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list);
537 entry = NULL;
538 error = 0;
542 } 539 }
543 if (!tomoyo_memory_ok(new_entry))
544 goto out;
545 new_entry->pattern = saved_pattern;
546 list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list);
547 new_entry = NULL;
548 error = 0;
549 out:
550 mutex_unlock(&tomoyo_policy_lock); 540 mutex_unlock(&tomoyo_policy_lock);
551 kfree(new_entry); 541 kfree(entry);
552 return error; 542 return error;
553} 543}
554 544
@@ -869,8 +859,8 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
869 (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); 859 (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
870 const struct tomoyo_path_info *saved_filename; 860 const struct tomoyo_path_info *saved_filename;
871 struct tomoyo_acl_info *ptr; 861 struct tomoyo_acl_info *ptr;
872 struct tomoyo_single_path_acl_record *acl; 862 struct tomoyo_single_path_acl_record *entry = NULL;
873 int error = -ENOMEM; 863 int error = is_delete ? -ENOENT : -ENOMEM;
874 const u32 perm = 1 << type; 864 const u32 perm = 1 << type;
875 865
876 if (!domain) 866 if (!domain)
@@ -880,67 +870,55 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
880 saved_filename = tomoyo_save_name(filename); 870 saved_filename = tomoyo_save_name(filename);
881 if (!saved_filename) 871 if (!saved_filename)
882 return -ENOMEM; 872 return -ENOMEM;
873 if (!is_delete)
874 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
883 mutex_lock(&tomoyo_policy_lock); 875 mutex_lock(&tomoyo_policy_lock);
884 if (is_delete)
885 goto delete;
886 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 876 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
877 struct tomoyo_single_path_acl_record *acl =
878 container_of(ptr, struct tomoyo_single_path_acl_record,
879 head);
887 if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) 880 if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL)
888 continue; 881 continue;
889 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
890 head);
891 if (acl->filename != saved_filename) 882 if (acl->filename != saved_filename)
892 continue; 883 continue;
893 if (perm <= 0xFFFF) 884 if (is_delete) {
894 acl->perm |= perm; 885 if (perm <= 0xFFFF)
895 else 886 acl->perm &= ~perm;
896 acl->perm_high |= (perm >> 16); 887 else
897 if ((acl->perm & rw_mask) == rw_mask) 888 acl->perm_high &= ~(perm >> 16);
898 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; 889 if ((acl->perm & rw_mask) != rw_mask)
899 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) 890 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
900 acl->perm |= rw_mask; 891 else if (!(acl->perm &
892 (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
893 acl->perm &= ~rw_mask;
894 } else {
895 if (perm <= 0xFFFF)
896 acl->perm |= perm;
897 else
898 acl->perm_high |= (perm >> 16);
899 if ((acl->perm & rw_mask) == rw_mask)
900 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
901 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
902 acl->perm |= rw_mask;
903 }
901 error = 0; 904 error = 0;
902 goto out; 905 break;
903 }
904 /* Not found. Append it to the tail. */
905 acl = kmalloc(sizeof(*acl), GFP_KERNEL);
906 if (!tomoyo_memory_ok(acl)) {
907 kfree(acl);
908 acl = NULL;
909 goto out;
910 } 906 }
911 acl->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; 907 if (!is_delete && error && tomoyo_memory_ok(entry)) {
912 if (perm <= 0xFFFF) 908 entry->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL;
913 acl->perm = perm;
914 else
915 acl->perm_high = (perm >> 16);
916 if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
917 acl->perm |= rw_mask;
918 acl->filename = saved_filename;
919 list_add_tail_rcu(&acl->head.list, &domain->acl_info_list);
920 error = 0;
921 goto out;
922 delete:
923 error = -ENOENT;
924 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
925 if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL)
926 continue;
927 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
928 head);
929 if (acl->filename != saved_filename)
930 continue;
931 if (perm <= 0xFFFF) 909 if (perm <= 0xFFFF)
932 acl->perm &= ~perm; 910 entry->perm = perm;
933 else 911 else
934 acl->perm_high &= ~(perm >> 16); 912 entry->perm_high = (perm >> 16);
935 if ((acl->perm & rw_mask) != rw_mask) 913 if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
936 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); 914 entry->perm |= rw_mask;
937 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) 915 entry->filename = saved_filename;
938 acl->perm &= ~rw_mask; 916 list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
917 entry = NULL;
939 error = 0; 918 error = 0;
940 break;
941 } 919 }
942 out:
943 mutex_unlock(&tomoyo_policy_lock); 920 mutex_unlock(&tomoyo_policy_lock);
921 kfree(entry);
944 return error; 922 return error;
945} 923}
946 924
@@ -965,8 +943,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
965 const struct tomoyo_path_info *saved_filename1; 943 const struct tomoyo_path_info *saved_filename1;
966 const struct tomoyo_path_info *saved_filename2; 944 const struct tomoyo_path_info *saved_filename2;
967 struct tomoyo_acl_info *ptr; 945 struct tomoyo_acl_info *ptr;
968 struct tomoyo_double_path_acl_record *acl; 946 struct tomoyo_double_path_acl_record *entry = NULL;
969 int error = -ENOMEM; 947 int error = is_delete ? -ENOENT : -ENOMEM;
970 const u8 perm = 1 << type; 948 const u8 perm = 1 << type;
971 949
972 if (!domain) 950 if (!domain)
@@ -977,52 +955,38 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
977 saved_filename1 = tomoyo_save_name(filename1); 955 saved_filename1 = tomoyo_save_name(filename1);
978 saved_filename2 = tomoyo_save_name(filename2); 956 saved_filename2 = tomoyo_save_name(filename2);
979 if (!saved_filename1 || !saved_filename2) 957 if (!saved_filename1 || !saved_filename2)
980 return -ENOMEM; 958 goto out;
959 if (!is_delete)
960 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
981 mutex_lock(&tomoyo_policy_lock); 961 mutex_lock(&tomoyo_policy_lock);
982 if (is_delete)
983 goto delete;
984 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 962 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
963 struct tomoyo_double_path_acl_record *acl =
964 container_of(ptr, struct tomoyo_double_path_acl_record,
965 head);
985 if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) 966 if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL)
986 continue; 967 continue;
987 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
988 head);
989 if (acl->filename1 != saved_filename1 || 968 if (acl->filename1 != saved_filename1 ||
990 acl->filename2 != saved_filename2) 969 acl->filename2 != saved_filename2)
991 continue; 970 continue;
992 acl->perm |= perm; 971 if (is_delete)
972 acl->perm &= ~perm;
973 else
974 acl->perm |= perm;
993 error = 0; 975 error = 0;
994 goto out; 976 break;
995 }
996 /* Not found. Append it to the tail. */
997 acl = kmalloc(sizeof(*acl), GFP_KERNEL);
998 if (!tomoyo_memory_ok(acl)) {
999 kfree(acl);
1000 acl = NULL;
1001 goto out;
1002 } 977 }
1003 acl->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; 978 if (!is_delete && error && tomoyo_memory_ok(entry)) {
1004 acl->perm = perm; 979 entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL;
1005 acl->filename1 = saved_filename1; 980 entry->perm = perm;
1006 acl->filename2 = saved_filename2; 981 entry->filename1 = saved_filename1;
1007 list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); 982 entry->filename2 = saved_filename2;
1008 error = 0; 983 list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
1009 goto out; 984 entry = NULL;
1010 delete:
1011 error = -ENOENT;
1012 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1013 if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL)
1014 continue;
1015 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
1016 head);
1017 if (acl->filename1 != saved_filename1 ||
1018 acl->filename2 != saved_filename2)
1019 continue;
1020 acl->perm &= ~perm;
1021 error = 0; 985 error = 0;
1022 break;
1023 } 986 }
1024 out:
1025 mutex_unlock(&tomoyo_policy_lock); 987 mutex_unlock(&tomoyo_policy_lock);
988 out:
989 kfree(entry);
1026 return error; 990 return error;
1027} 991}
1028 992