aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/tomoyo/common.c32
-rw-r--r--security/tomoyo/common.h26
-rw-r--r--security/tomoyo/domain.c124
-rw-r--r--security/tomoyo/file.c181
-rw-r--r--security/tomoyo/realpath.c19
5 files changed, 190 insertions, 192 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 8f34036fd31c..62e089c50ae8 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1071,46 +1071,42 @@ LIST_HEAD(tomoyo_policy_manager_list);
1071static int tomoyo_update_manager_entry(const char *manager, 1071static int tomoyo_update_manager_entry(const char *manager,
1072 const bool is_delete) 1072 const bool is_delete)
1073{ 1073{
1074 struct tomoyo_policy_manager_entry *entry = NULL;
1075 struct tomoyo_policy_manager_entry *ptr; 1074 struct tomoyo_policy_manager_entry *ptr;
1076 const struct tomoyo_path_info *saved_manager; 1075 struct tomoyo_policy_manager_entry e = { };
1077 int error = is_delete ? -ENOENT : -ENOMEM; 1076 int error = is_delete ? -ENOENT : -ENOMEM;
1078 bool is_domain = false;
1079 1077
1080 if (tomoyo_is_domain_def(manager)) { 1078 if (tomoyo_is_domain_def(manager)) {
1081 if (!tomoyo_is_correct_domain(manager)) 1079 if (!tomoyo_is_correct_domain(manager))
1082 return -EINVAL; 1080 return -EINVAL;
1083 is_domain = true; 1081 e.is_domain = true;
1084 } else { 1082 } else {
1085 if (!tomoyo_is_correct_path(manager, 1, -1, -1)) 1083 if (!tomoyo_is_correct_path(manager, 1, -1, -1))
1086 return -EINVAL; 1084 return -EINVAL;
1087 } 1085 }
1088 saved_manager = tomoyo_get_name(manager); 1086 e.manager = tomoyo_get_name(manager);
1089 if (!saved_manager) 1087 if (!e.manager)
1090 return -ENOMEM; 1088 return -ENOMEM;
1091 if (!is_delete)
1092 entry = kmalloc(sizeof(*entry), GFP_NOFS);
1093 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 1089 if (mutex_lock_interruptible(&tomoyo_policy_lock))
1094 goto out; 1090 goto out;
1095 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { 1091 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1096 if (ptr->manager != saved_manager) 1092 if (ptr->manager != e.manager)
1097 continue; 1093 continue;
1098 ptr->is_deleted = is_delete; 1094 ptr->is_deleted = is_delete;
1099 error = 0; 1095 error = 0;
1100 break; 1096 break;
1101 } 1097 }
1102 if (!is_delete && error && tomoyo_memory_ok(entry)) { 1098 if (!is_delete && error) {
1103 entry->manager = saved_manager; 1099 struct tomoyo_policy_manager_entry *entry =
1104 saved_manager = NULL; 1100 tomoyo_commit_ok(&e, sizeof(e));
1105 entry->is_domain = is_domain; 1101 if (entry) {
1106 list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); 1102 list_add_tail_rcu(&entry->list,
1107 entry = NULL; 1103 &tomoyo_policy_manager_list);
1108 error = 0; 1104 error = 0;
1105 }
1109 } 1106 }
1110 mutex_unlock(&tomoyo_policy_lock); 1107 mutex_unlock(&tomoyo_policy_lock);
1111 out: 1108 out:
1112 tomoyo_put_name(saved_manager); 1109 tomoyo_put_name(e.manager);
1113 kfree(entry);
1114 return error; 1110 return error;
1115} 1111}
1116 1112
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 52c9502ed675..c95f48609461 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -616,6 +616,7 @@ char *tomoyo_realpath_from_path(struct path *path);
616 616
617/* Check memory quota. */ 617/* Check memory quota. */
618bool tomoyo_memory_ok(void *ptr); 618bool tomoyo_memory_ok(void *ptr);
619void *tomoyo_commit_ok(void *data, const unsigned int size);
619 620
620/* 621/*
621 * Keep the given name on the RAM. 622 * Keep the given name on the RAM.
@@ -735,6 +736,31 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
735 return task_cred_xxx(task, security); 736 return task_cred_xxx(task, security);
736} 737}
737 738
739static inline bool tomoyo_is_same_domain_initializer_entry
740(const struct tomoyo_domain_initializer_entry *p1,
741 const struct tomoyo_domain_initializer_entry *p2)
742{
743 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
744 && p1->domainname == p2->domainname
745 && p1->program == p2->program;
746}
747
748static inline bool tomoyo_is_same_domain_keeper_entry
749(const struct tomoyo_domain_keeper_entry *p1,
750 const struct tomoyo_domain_keeper_entry *p2)
751{
752 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
753 && p1->domainname == p2->domainname
754 && p1->program == p2->program;
755}
756
757static inline bool tomoyo_is_same_alias_entry
758(const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2)
759{
760 return p1->original_name == p2->original_name &&
761 p1->aliased_name == p2->aliased_name;
762}
763
738/** 764/**
739 * list_for_each_cookie - iterate over a list with cookie. 765 * list_for_each_cookie - iterate over a list with cookie.
740 * @pos: the &struct list_head to use as a loop cursor. 766 * @pos: the &struct list_head to use as a loop cursor.
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index a1723bbcde0e..cd8ba4446763 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -130,58 +130,47 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
130 const bool is_not, 130 const bool is_not,
131 const bool is_delete) 131 const bool is_delete)
132{ 132{
133 struct tomoyo_domain_initializer_entry *entry = NULL;
134 struct tomoyo_domain_initializer_entry *ptr; 133 struct tomoyo_domain_initializer_entry *ptr;
135 const struct tomoyo_path_info *saved_program = NULL; 134 struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
136 const struct tomoyo_path_info *saved_domainname = NULL;
137 int error = is_delete ? -ENOENT : -ENOMEM; 135 int error = is_delete ? -ENOENT : -ENOMEM;
138 bool is_last_name = false;
139 136
140 if (!tomoyo_is_correct_path(program, 1, -1, -1)) 137 if (!tomoyo_is_correct_path(program, 1, -1, -1))
141 return -EINVAL; /* No patterns allowed. */ 138 return -EINVAL; /* No patterns allowed. */
142 if (domainname) { 139 if (domainname) {
143 if (!tomoyo_is_domain_def(domainname) && 140 if (!tomoyo_is_domain_def(domainname) &&
144 tomoyo_is_correct_path(domainname, 1, -1, -1)) 141 tomoyo_is_correct_path(domainname, 1, -1, -1))
145 is_last_name = true; 142 e.is_last_name = true;
146 else if (!tomoyo_is_correct_domain(domainname)) 143 else if (!tomoyo_is_correct_domain(domainname))
147 return -EINVAL; 144 return -EINVAL;
148 saved_domainname = tomoyo_get_name(domainname); 145 e.domainname = tomoyo_get_name(domainname);
149 if (!saved_domainname) 146 if (!e.domainname)
150 goto out; 147 goto out;
151 } 148 }
152 saved_program = tomoyo_get_name(program); 149 e.program = tomoyo_get_name(program);
153 if (!saved_program) 150 if (!e.program)
154 goto out; 151 goto out;
155 if (!is_delete)
156 entry = kmalloc(sizeof(*entry), GFP_NOFS);
157 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 152 if (mutex_lock_interruptible(&tomoyo_policy_lock))
158 goto out; 153 goto out;
159 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 154 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
160 if (ptr->is_not != is_not || 155 if (!tomoyo_is_same_domain_initializer_entry(ptr, &e))
161 ptr->domainname != saved_domainname ||
162 ptr->program != saved_program)
163 continue; 156 continue;
164 ptr->is_deleted = is_delete; 157 ptr->is_deleted = is_delete;
165 error = 0; 158 error = 0;
166 break; 159 break;
167 } 160 }
168 if (!is_delete && error && tomoyo_memory_ok(entry)) { 161 if (!is_delete && error) {
169 entry->domainname = saved_domainname; 162 struct tomoyo_domain_initializer_entry *entry =
170 saved_domainname = NULL; 163 tomoyo_commit_ok(&e, sizeof(e));
171 entry->program = saved_program; 164 if (entry) {
172 saved_program = NULL; 165 list_add_tail_rcu(&entry->list,
173 entry->is_not = is_not; 166 &tomoyo_domain_initializer_list);
174 entry->is_last_name = is_last_name; 167 error = 0;
175 list_add_tail_rcu(&entry->list, 168 }
176 &tomoyo_domain_initializer_list);
177 entry = NULL;
178 error = 0;
179 } 169 }
180 mutex_unlock(&tomoyo_policy_lock); 170 mutex_unlock(&tomoyo_policy_lock);
181 out: 171 out:
182 tomoyo_put_name(saved_domainname); 172 tomoyo_put_name(e.domainname);
183 tomoyo_put_name(saved_program); 173 tomoyo_put_name(e.program);
184 kfree(entry);
185 return error; 174 return error;
186} 175}
187 176
@@ -351,57 +340,47 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
351 const bool is_not, 340 const bool is_not,
352 const bool is_delete) 341 const bool is_delete)
353{ 342{
354 struct tomoyo_domain_keeper_entry *entry = NULL;
355 struct tomoyo_domain_keeper_entry *ptr; 343 struct tomoyo_domain_keeper_entry *ptr;
356 const struct tomoyo_path_info *saved_domainname = NULL; 344 struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
357 const struct tomoyo_path_info *saved_program = NULL;
358 int error = is_delete ? -ENOENT : -ENOMEM; 345 int error = is_delete ? -ENOENT : -ENOMEM;
359 bool is_last_name = false;
360 346
361 if (!tomoyo_is_domain_def(domainname) && 347 if (!tomoyo_is_domain_def(domainname) &&
362 tomoyo_is_correct_path(domainname, 1, -1, -1)) 348 tomoyo_is_correct_path(domainname, 1, -1, -1))
363 is_last_name = true; 349 e.is_last_name = true;
364 else if (!tomoyo_is_correct_domain(domainname)) 350 else if (!tomoyo_is_correct_domain(domainname))
365 return -EINVAL; 351 return -EINVAL;
366 if (program) { 352 if (program) {
367 if (!tomoyo_is_correct_path(program, 1, -1, -1)) 353 if (!tomoyo_is_correct_path(program, 1, -1, -1))
368 return -EINVAL; 354 return -EINVAL;
369 saved_program = tomoyo_get_name(program); 355 e.program = tomoyo_get_name(program);
370 if (!saved_program) 356 if (!e.program)
371 goto out; 357 goto out;
372 } 358 }
373 saved_domainname = tomoyo_get_name(domainname); 359 e.domainname = tomoyo_get_name(domainname);
374 if (!saved_domainname) 360 if (!e.domainname)
375 goto out; 361 goto out;
376 if (!is_delete)
377 entry = kmalloc(sizeof(*entry), GFP_NOFS);
378 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 362 if (mutex_lock_interruptible(&tomoyo_policy_lock))
379 goto out; 363 goto out;
380 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 364 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
381 if (ptr->is_not != is_not || 365 if (!tomoyo_is_same_domain_keeper_entry(ptr, &e))
382 ptr->domainname != saved_domainname ||
383 ptr->program != saved_program)
384 continue; 366 continue;
385 ptr->is_deleted = is_delete; 367 ptr->is_deleted = is_delete;
386 error = 0; 368 error = 0;
387 break; 369 break;
388 } 370 }
389 if (!is_delete && error && tomoyo_memory_ok(entry)) { 371 if (!is_delete && error) {
390 entry->domainname = saved_domainname; 372 struct tomoyo_domain_keeper_entry *entry =
391 saved_domainname = NULL; 373 tomoyo_commit_ok(&e, sizeof(e));
392 entry->program = saved_program; 374 if (entry) {
393 saved_program = NULL; 375 list_add_tail_rcu(&entry->list,
394 entry->is_not = is_not; 376 &tomoyo_domain_keeper_list);
395 entry->is_last_name = is_last_name; 377 error = 0;
396 list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); 378 }
397 entry = NULL;
398 error = 0;
399 } 379 }
400 mutex_unlock(&tomoyo_policy_lock); 380 mutex_unlock(&tomoyo_policy_lock);
401 out: 381 out:
402 tomoyo_put_name(saved_domainname); 382 tomoyo_put_name(e.domainname);
403 tomoyo_put_name(saved_program); 383 tomoyo_put_name(e.program);
404 kfree(entry);
405 return error; 384 return error;
406} 385}
407 386
@@ -553,45 +532,38 @@ static int tomoyo_update_alias_entry(const char *original_name,
553 const char *aliased_name, 532 const char *aliased_name,
554 const bool is_delete) 533 const bool is_delete)
555{ 534{
556 struct tomoyo_alias_entry *entry = NULL;
557 struct tomoyo_alias_entry *ptr; 535 struct tomoyo_alias_entry *ptr;
558 const struct tomoyo_path_info *saved_original_name; 536 struct tomoyo_alias_entry e = { };
559 const struct tomoyo_path_info *saved_aliased_name;
560 int error = is_delete ? -ENOENT : -ENOMEM; 537 int error = is_delete ? -ENOENT : -ENOMEM;
561 538
562 if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || 539 if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
563 !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) 540 !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
564 return -EINVAL; /* No patterns allowed. */ 541 return -EINVAL; /* No patterns allowed. */
565 saved_original_name = tomoyo_get_name(original_name); 542 e.original_name = tomoyo_get_name(original_name);
566 saved_aliased_name = tomoyo_get_name(aliased_name); 543 e.aliased_name = tomoyo_get_name(aliased_name);
567 if (!saved_original_name || !saved_aliased_name) 544 if (!e.original_name || !e.aliased_name)
568 goto out; 545 goto out;
569 if (!is_delete)
570 entry = kmalloc(sizeof(*entry), GFP_NOFS);
571 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 546 if (mutex_lock_interruptible(&tomoyo_policy_lock))
572 goto out; 547 goto out;
573 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 548 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
574 if (ptr->original_name != saved_original_name || 549 if (!tomoyo_is_same_alias_entry(ptr, &e))
575 ptr->aliased_name != saved_aliased_name)
576 continue; 550 continue;
577 ptr->is_deleted = is_delete; 551 ptr->is_deleted = is_delete;
578 error = 0; 552 error = 0;
579 break; 553 break;
580 } 554 }
581 if (!is_delete && error && tomoyo_memory_ok(entry)) { 555 if (!is_delete && error) {
582 entry->original_name = saved_original_name; 556 struct tomoyo_alias_entry *entry =
583 saved_original_name = NULL; 557 tomoyo_commit_ok(&e, sizeof(e));
584 entry->aliased_name = saved_aliased_name; 558 if (entry) {
585 saved_aliased_name = NULL; 559 list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
586 list_add_tail_rcu(&entry->list, &tomoyo_alias_list); 560 error = 0;
587 entry = NULL; 561 }
588 error = 0;
589 } 562 }
590 mutex_unlock(&tomoyo_policy_lock); 563 mutex_unlock(&tomoyo_policy_lock);
591 out: 564 out:
592 tomoyo_put_name(saved_original_name); 565 tomoyo_put_name(e.original_name);
593 tomoyo_put_name(saved_aliased_name); 566 tomoyo_put_name(e.aliased_name);
594 kfree(entry);
595 return error; 567 return error;
596} 568}
597 569
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 060bbf3870ce..6651cac87625 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -164,38 +164,36 @@ LIST_HEAD(tomoyo_globally_readable_list);
164static int tomoyo_update_globally_readable_entry(const char *filename, 164static int tomoyo_update_globally_readable_entry(const char *filename,
165 const bool is_delete) 165 const bool is_delete)
166{ 166{
167 struct tomoyo_globally_readable_file_entry *entry = NULL;
168 struct tomoyo_globally_readable_file_entry *ptr; 167 struct tomoyo_globally_readable_file_entry *ptr;
169 const struct tomoyo_path_info *saved_filename; 168 struct tomoyo_globally_readable_file_entry e = { };
170 int error = is_delete ? -ENOENT : -ENOMEM; 169 int error = is_delete ? -ENOENT : -ENOMEM;
171 170
172 if (!tomoyo_is_correct_path(filename, 1, 0, -1)) 171 if (!tomoyo_is_correct_path(filename, 1, 0, -1))
173 return -EINVAL; 172 return -EINVAL;
174 saved_filename = tomoyo_get_name(filename); 173 e.filename = tomoyo_get_name(filename);
175 if (!saved_filename) 174 if (!e.filename)
176 return -ENOMEM; 175 return -ENOMEM;
177 if (!is_delete)
178 entry = kmalloc(sizeof(*entry), GFP_NOFS);
179 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 176 if (mutex_lock_interruptible(&tomoyo_policy_lock))
180 goto out; 177 goto out;
181 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { 178 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
182 if (ptr->filename != saved_filename) 179 if (ptr->filename != e.filename)
183 continue; 180 continue;
184 ptr->is_deleted = is_delete; 181 ptr->is_deleted = is_delete;
185 error = 0; 182 error = 0;
186 break; 183 break;
187 } 184 }
188 if (!is_delete && error && tomoyo_memory_ok(entry)) { 185 if (!is_delete && error) {
189 entry->filename = saved_filename; 186 struct tomoyo_globally_readable_file_entry *entry =
190 saved_filename = NULL; 187 tomoyo_commit_ok(&e, sizeof(e));
191 list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); 188 if (entry) {
192 entry = NULL; 189 list_add_tail_rcu(&entry->list,
193 error = 0; 190 &tomoyo_globally_readable_list);
191 error = 0;
192 }
194 } 193 }
195 mutex_unlock(&tomoyo_policy_lock); 194 mutex_unlock(&tomoyo_policy_lock);
196 out: 195 out:
197 tomoyo_put_name(saved_filename); 196 tomoyo_put_name(e.filename);
198 kfree(entry);
199 return error; 197 return error;
200} 198}
201 199
@@ -313,38 +311,34 @@ LIST_HEAD(tomoyo_pattern_list);
313static int tomoyo_update_file_pattern_entry(const char *pattern, 311static int tomoyo_update_file_pattern_entry(const char *pattern,
314 const bool is_delete) 312 const bool is_delete)
315{ 313{
316 struct tomoyo_pattern_entry *entry = NULL;
317 struct tomoyo_pattern_entry *ptr; 314 struct tomoyo_pattern_entry *ptr;
318 const struct tomoyo_path_info *saved_pattern; 315 struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) };
319 int error = is_delete ? -ENOENT : -ENOMEM; 316 int error = is_delete ? -ENOENT : -ENOMEM;
320 317
321 saved_pattern = tomoyo_get_name(pattern); 318 if (!e.pattern)
322 if (!saved_pattern)
323 return error; 319 return error;
324 if (!saved_pattern->is_patterned) 320 if (!e.pattern->is_patterned)
325 goto out; 321 goto out;
326 if (!is_delete)
327 entry = kmalloc(sizeof(*entry), GFP_NOFS);
328 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 322 if (mutex_lock_interruptible(&tomoyo_policy_lock))
329 goto out; 323 goto out;
330 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { 324 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
331 if (saved_pattern != ptr->pattern) 325 if (e.pattern != ptr->pattern)
332 continue; 326 continue;
333 ptr->is_deleted = is_delete; 327 ptr->is_deleted = is_delete;
334 error = 0; 328 error = 0;
335 break; 329 break;
336 } 330 }
337 if (!is_delete && error && tomoyo_memory_ok(entry)) { 331 if (!is_delete && error) {
338 entry->pattern = saved_pattern; 332 struct tomoyo_pattern_entry *entry =
339 saved_pattern = NULL; 333 tomoyo_commit_ok(&e, sizeof(e));
340 list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); 334 if (entry) {
341 entry = NULL; 335 list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
342 error = 0; 336 error = 0;
337 }
343 } 338 }
344 mutex_unlock(&tomoyo_policy_lock); 339 mutex_unlock(&tomoyo_policy_lock);
345 out: 340 out:
346 kfree(entry); 341 tomoyo_put_name(e.pattern);
347 tomoyo_put_name(saved_pattern);
348 return error; 342 return error;
349} 343}
350 344
@@ -467,38 +461,36 @@ LIST_HEAD(tomoyo_no_rewrite_list);
467static int tomoyo_update_no_rewrite_entry(const char *pattern, 461static int tomoyo_update_no_rewrite_entry(const char *pattern,
468 const bool is_delete) 462 const bool is_delete)
469{ 463{
470 struct tomoyo_no_rewrite_entry *entry = NULL;
471 struct tomoyo_no_rewrite_entry *ptr; 464 struct tomoyo_no_rewrite_entry *ptr;
472 const struct tomoyo_path_info *saved_pattern; 465 struct tomoyo_no_rewrite_entry e = { };
473 int error = is_delete ? -ENOENT : -ENOMEM; 466 int error = is_delete ? -ENOENT : -ENOMEM;
474 467
475 if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) 468 if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
476 return -EINVAL; 469 return -EINVAL;
477 saved_pattern = tomoyo_get_name(pattern); 470 e.pattern = tomoyo_get_name(pattern);
478 if (!saved_pattern) 471 if (!e.pattern)
479 return error; 472 return error;
480 if (!is_delete)
481 entry = kmalloc(sizeof(*entry), GFP_NOFS);
482 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 473 if (mutex_lock_interruptible(&tomoyo_policy_lock))
483 goto out; 474 goto out;
484 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { 475 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
485 if (ptr->pattern != saved_pattern) 476 if (ptr->pattern != e.pattern)
486 continue; 477 continue;
487 ptr->is_deleted = is_delete; 478 ptr->is_deleted = is_delete;
488 error = 0; 479 error = 0;
489 break; 480 break;
490 } 481 }
491 if (!is_delete && error && tomoyo_memory_ok(entry)) { 482 if (!is_delete && error) {
492 entry->pattern = saved_pattern; 483 struct tomoyo_no_rewrite_entry *entry =
493 saved_pattern = NULL; 484 tomoyo_commit_ok(&e, sizeof(e));
494 list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); 485 if (entry) {
495 entry = NULL; 486 list_add_tail_rcu(&entry->list,
496 error = 0; 487 &tomoyo_no_rewrite_list);
488 error = 0;
489 }
497 } 490 }
498 mutex_unlock(&tomoyo_policy_lock); 491 mutex_unlock(&tomoyo_policy_lock);
499 out: 492 out:
500 tomoyo_put_name(saved_pattern); 493 tomoyo_put_name(e.pattern);
501 kfree(entry);
502 return error; 494 return error;
503} 495}
504 496
@@ -810,23 +802,26 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
810 struct tomoyo_domain_info *const domain, 802 struct tomoyo_domain_info *const domain,
811 const bool is_delete) 803 const bool is_delete)
812{ 804{
813 static const u32 rw_mask = 805 static const u32 tomoyo_rw_mask =
814 (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); 806 (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
815 const struct tomoyo_path_info *saved_filename; 807 const u32 perm = 1 << type;
816 struct tomoyo_acl_info *ptr; 808 struct tomoyo_acl_info *ptr;
817 struct tomoyo_path_acl *entry = NULL; 809 struct tomoyo_path_acl e = {
810 .head.type = TOMOYO_TYPE_PATH_ACL,
811 .perm_high = perm >> 16,
812 .perm = perm
813 };
818 int error = is_delete ? -ENOENT : -ENOMEM; 814 int error = is_delete ? -ENOENT : -ENOMEM;
819 const u32 perm = 1 << type;
820 815
816 if (type == TOMOYO_TYPE_READ_WRITE)
817 e.perm |= tomoyo_rw_mask;
821 if (!domain) 818 if (!domain)
822 return -EINVAL; 819 return -EINVAL;
823 if (!tomoyo_is_correct_path(filename, 0, 0, 0)) 820 if (!tomoyo_is_correct_path(filename, 0, 0, 0))
824 return -EINVAL; 821 return -EINVAL;
825 saved_filename = tomoyo_get_name(filename); 822 e.filename = tomoyo_get_name(filename);
826 if (!saved_filename) 823 if (!e.filename)
827 return -ENOMEM; 824 return -ENOMEM;
828 if (!is_delete)
829 entry = kmalloc(sizeof(*entry), GFP_NOFS);
830 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 825 if (mutex_lock_interruptible(&tomoyo_policy_lock))
831 goto out; 826 goto out;
832 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 827 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
@@ -834,48 +829,42 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
834 container_of(ptr, struct tomoyo_path_acl, head); 829 container_of(ptr, struct tomoyo_path_acl, head);
835 if (ptr->type != TOMOYO_TYPE_PATH_ACL) 830 if (ptr->type != TOMOYO_TYPE_PATH_ACL)
836 continue; 831 continue;
837 if (acl->filename != saved_filename) 832 if (acl->filename != e.filename)
838 continue; 833 continue;
839 if (is_delete) { 834 if (is_delete) {
840 if (perm <= 0xFFFF) 835 if (perm <= 0xFFFF)
841 acl->perm &= ~perm; 836 acl->perm &= ~perm;
842 else 837 else
843 acl->perm_high &= ~(perm >> 16); 838 acl->perm_high &= ~(perm >> 16);
844 if ((acl->perm & rw_mask) != rw_mask) 839 if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask)
845 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); 840 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
846 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) 841 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
847 acl->perm &= ~rw_mask; 842 acl->perm &= ~tomoyo_rw_mask;
848 } else { 843 } else {
849 if (perm <= 0xFFFF) 844 if (perm <= 0xFFFF)
850 acl->perm |= perm; 845 acl->perm |= perm;
851 else 846 else
852 acl->perm_high |= (perm >> 16); 847 acl->perm_high |= (perm >> 16);
853 if ((acl->perm & rw_mask) == rw_mask) 848 if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask)
854 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; 849 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
855 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) 850 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
856 acl->perm |= rw_mask; 851 acl->perm |= tomoyo_rw_mask;
857 } 852 }
858 error = 0; 853 error = 0;
859 break; 854 break;
860 } 855 }
861 if (!is_delete && error && tomoyo_memory_ok(entry)) { 856 if (!is_delete && error) {
862 entry->head.type = TOMOYO_TYPE_PATH_ACL; 857 struct tomoyo_path_acl *entry =
863 if (perm <= 0xFFFF) 858 tomoyo_commit_ok(&e, sizeof(e));
864 entry->perm = perm; 859 if (entry) {
865 else 860 list_add_tail_rcu(&entry->head.list,
866 entry->perm_high = (perm >> 16); 861 &domain->acl_info_list);
867 if (perm == (1 << TOMOYO_TYPE_READ_WRITE)) 862 error = 0;
868 entry->perm |= rw_mask; 863 }
869 entry->filename = saved_filename;
870 saved_filename = NULL;
871 list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
872 entry = NULL;
873 error = 0;
874 } 864 }
875 mutex_unlock(&tomoyo_policy_lock); 865 mutex_unlock(&tomoyo_policy_lock);
876 out: 866 out:
877 kfree(entry); 867 tomoyo_put_name(e.filename);
878 tomoyo_put_name(saved_filename);
879 return error; 868 return error;
880} 869}
881 870
@@ -897,24 +886,23 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
897 struct tomoyo_domain_info *const domain, 886 struct tomoyo_domain_info *const domain,
898 const bool is_delete) 887 const bool is_delete)
899{ 888{
900 const struct tomoyo_path_info *saved_filename1; 889 const u8 perm = 1 << type;
901 const struct tomoyo_path_info *saved_filename2; 890 struct tomoyo_path2_acl e = {
891 .head.type = TOMOYO_TYPE_PATH2_ACL,
892 .perm = perm
893 };
902 struct tomoyo_acl_info *ptr; 894 struct tomoyo_acl_info *ptr;
903 struct tomoyo_path2_acl *entry = NULL;
904 int error = is_delete ? -ENOENT : -ENOMEM; 895 int error = is_delete ? -ENOENT : -ENOMEM;
905 const u8 perm = 1 << type;
906 896
907 if (!domain) 897 if (!domain)
908 return -EINVAL; 898 return -EINVAL;
909 if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || 899 if (!tomoyo_is_correct_path(filename1, 0, 0, 0) ||
910 !tomoyo_is_correct_path(filename2, 0, 0, 0)) 900 !tomoyo_is_correct_path(filename2, 0, 0, 0))
911 return -EINVAL; 901 return -EINVAL;
912 saved_filename1 = tomoyo_get_name(filename1); 902 e.filename1 = tomoyo_get_name(filename1);
913 saved_filename2 = tomoyo_get_name(filename2); 903 e.filename2 = tomoyo_get_name(filename2);
914 if (!saved_filename1 || !saved_filename2) 904 if (!e.filename1 || !e.filename2)
915 goto out; 905 goto out;
916 if (!is_delete)
917 entry = kmalloc(sizeof(*entry), GFP_NOFS);
918 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 906 if (mutex_lock_interruptible(&tomoyo_policy_lock))
919 goto out; 907 goto out;
920 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 908 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
@@ -922,8 +910,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
922 container_of(ptr, struct tomoyo_path2_acl, head); 910 container_of(ptr, struct tomoyo_path2_acl, head);
923 if (ptr->type != TOMOYO_TYPE_PATH2_ACL) 911 if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
924 continue; 912 continue;
925 if (acl->filename1 != saved_filename1 || 913 if (acl->filename1 != e.filename1 ||
926 acl->filename2 != saved_filename2) 914 acl->filename2 != e.filename2)
927 continue; 915 continue;
928 if (is_delete) 916 if (is_delete)
929 acl->perm &= ~perm; 917 acl->perm &= ~perm;
@@ -932,22 +920,19 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
932 error = 0; 920 error = 0;
933 break; 921 break;
934 } 922 }
935 if (!is_delete && error && tomoyo_memory_ok(entry)) { 923 if (!is_delete && error) {
936 entry->head.type = TOMOYO_TYPE_PATH2_ACL; 924 struct tomoyo_path2_acl *entry =
937 entry->perm = perm; 925 tomoyo_commit_ok(&e, sizeof(e));
938 entry->filename1 = saved_filename1; 926 if (entry) {
939 saved_filename1 = NULL; 927 list_add_tail_rcu(&entry->head.list,
940 entry->filename2 = saved_filename2; 928 &domain->acl_info_list);
941 saved_filename2 = NULL; 929 error = 0;
942 list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); 930 }
943 entry = NULL;
944 error = 0;
945 } 931 }
946 mutex_unlock(&tomoyo_policy_lock); 932 mutex_unlock(&tomoyo_policy_lock);
947 out: 933 out:
948 tomoyo_put_name(saved_filename1); 934 tomoyo_put_name(e.filename1);
949 tomoyo_put_name(saved_filename2); 935 tomoyo_put_name(e.filename2);
950 kfree(entry);
951 return error; 936 return error;
952} 937}
953 938
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 62062a68525a..d1b96f019621 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -223,6 +223,25 @@ bool tomoyo_memory_ok(void *ptr)
223} 223}
224 224
225/** 225/**
226 * tomoyo_commit_ok - Check memory quota.
227 *
228 * @data: Data to copy from.
229 * @size: Size in byte.
230 *
231 * Returns pointer to allocated memory on success, NULL otherwise.
232 */
233void *tomoyo_commit_ok(void *data, const unsigned int size)
234{
235 void *ptr = kzalloc(size, GFP_NOFS);
236 if (tomoyo_memory_ok(ptr)) {
237 memmove(ptr, data, size);
238 memset(data, 0, size);
239 return ptr;
240 }
241 return NULL;
242}
243
244/**
226 * tomoyo_memory_free - Free memory for elements. 245 * tomoyo_memory_free - Free memory for elements.
227 * 246 *
228 * @ptr: Pointer to allocated memory. 247 * @ptr: Pointer to allocated memory.