aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/domain.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/domain.c')
-rw-r--r--security/tomoyo/domain.c391
1 files changed, 148 insertions, 243 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index fcf52accce2b..66caaa1b842a 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -10,8 +10,6 @@
10 */ 10 */
11 11
12#include "common.h" 12#include "common.h"
13#include "tomoyo.h"
14#include "realpath.h"
15#include <linux/binfmts.h> 13#include <linux/binfmts.h>
16 14
17/* Variables definitions.*/ 15/* Variables definitions.*/
@@ -58,99 +56,6 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
58 * exceptions. 56 * exceptions.
59 */ 57 */
60LIST_HEAD(tomoyo_domain_list); 58LIST_HEAD(tomoyo_domain_list);
61DECLARE_RWSEM(tomoyo_domain_list_lock);
62
63/*
64 * tomoyo_domain_initializer_entry is a structure which is used for holding
65 * "initialize_domain" and "no_initialize_domain" entries.
66 * It has following fields.
67 *
68 * (1) "list" which is linked to tomoyo_domain_initializer_list .
69 * (2) "domainname" which is "a domainname" or "the last component of a
70 * domainname". This field is NULL if "from" clause is not specified.
71 * (3) "program" which is a program's pathname.
72 * (4) "is_deleted" is a bool which is true if marked as deleted, false
73 * otherwise.
74 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
75 * otherwise.
76 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
77 * component of a domainname", false otherwise.
78 */
79struct tomoyo_domain_initializer_entry {
80 struct list_head list;
81 const struct tomoyo_path_info *domainname; /* This may be NULL */
82 const struct tomoyo_path_info *program;
83 bool is_deleted;
84 bool is_not; /* True if this entry is "no_initialize_domain". */
85 /* True if the domainname is tomoyo_get_last_name(). */
86 bool is_last_name;
87};
88
89/*
90 * tomoyo_domain_keeper_entry is a structure which is used for holding
91 * "keep_domain" and "no_keep_domain" entries.
92 * It has following fields.
93 *
94 * (1) "list" which is linked to tomoyo_domain_keeper_list .
95 * (2) "domainname" which is "a domainname" or "the last component of a
96 * domainname".
97 * (3) "program" which is a program's pathname.
98 * This field is NULL if "from" clause is not specified.
99 * (4) "is_deleted" is a bool which is true if marked as deleted, false
100 * otherwise.
101 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
102 * otherwise.
103 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
104 * component of a domainname", false otherwise.
105 */
106struct tomoyo_domain_keeper_entry {
107 struct list_head list;
108 const struct tomoyo_path_info *domainname;
109 const struct tomoyo_path_info *program; /* This may be NULL */
110 bool is_deleted;
111 bool is_not; /* True if this entry is "no_keep_domain". */
112 /* True if the domainname is tomoyo_get_last_name(). */
113 bool is_last_name;
114};
115
116/*
117 * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
118 * It has following fields.
119 *
120 * (1) "list" which is linked to tomoyo_alias_list .
121 * (2) "original_name" which is a dereferenced pathname.
122 * (3) "aliased_name" which is a symlink's pathname.
123 * (4) "is_deleted" is a bool which is true if marked as deleted, false
124 * otherwise.
125 */
126struct tomoyo_alias_entry {
127 struct list_head list;
128 const struct tomoyo_path_info *original_name;
129 const struct tomoyo_path_info *aliased_name;
130 bool is_deleted;
131};
132
133/**
134 * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
135 *
136 * @domain: Pointer to "struct tomoyo_domain_info".
137 * @is_delete: True if it is a delete request.
138 * @flags: Flags to set or clear.
139 *
140 * Returns nothing.
141 */
142void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
143 const bool is_delete, const u8 flags)
144{
145 /* We need to serialize because this is bitfield operation. */
146 static DEFINE_SPINLOCK(lock);
147 spin_lock(&lock);
148 if (!is_delete)
149 domain->flags |= flags;
150 else
151 domain->flags &= ~flags;
152 spin_unlock(&lock);
153}
154 59
155/** 60/**
156 * tomoyo_get_last_name - Get last component of a domainname. 61 * tomoyo_get_last_name - Get last component of a domainname.
@@ -205,8 +110,7 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
205 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain 110 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
206 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain. 111 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
207 */ 112 */
208static LIST_HEAD(tomoyo_domain_initializer_list); 113LIST_HEAD(tomoyo_domain_initializer_list);
209static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
210 114
211/** 115/**
212 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. 116 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
@@ -217,59 +121,65 @@ static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
217 * @is_delete: True if it is a delete request. 121 * @is_delete: True if it is a delete request.
218 * 122 *
219 * Returns 0 on success, negative value otherwise. 123 * Returns 0 on success, negative value otherwise.
124 *
125 * Caller holds tomoyo_read_lock().
220 */ 126 */
221static int tomoyo_update_domain_initializer_entry(const char *domainname, 127static int tomoyo_update_domain_initializer_entry(const char *domainname,
222 const char *program, 128 const char *program,
223 const bool is_not, 129 const bool is_not,
224 const bool is_delete) 130 const bool is_delete)
225{ 131{
226 struct tomoyo_domain_initializer_entry *new_entry; 132 struct tomoyo_domain_initializer_entry *entry = NULL;
227 struct tomoyo_domain_initializer_entry *ptr; 133 struct tomoyo_domain_initializer_entry *ptr;
228 const struct tomoyo_path_info *saved_program; 134 const struct tomoyo_path_info *saved_program = NULL;
229 const struct tomoyo_path_info *saved_domainname = NULL; 135 const struct tomoyo_path_info *saved_domainname = NULL;
230 int error = -ENOMEM; 136 int error = is_delete ? -ENOENT : -ENOMEM;
231 bool is_last_name = false; 137 bool is_last_name = false;
232 138
233 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) 139 if (!tomoyo_is_correct_path(program, 1, -1, -1))
234 return -EINVAL; /* No patterns allowed. */ 140 return -EINVAL; /* No patterns allowed. */
235 if (domainname) { 141 if (domainname) {
236 if (!tomoyo_is_domain_def(domainname) && 142 if (!tomoyo_is_domain_def(domainname) &&
237 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) 143 tomoyo_is_correct_path(domainname, 1, -1, -1))
238 is_last_name = true; 144 is_last_name = true;
239 else if (!tomoyo_is_correct_domain(domainname, __func__)) 145 else if (!tomoyo_is_correct_domain(domainname))
240 return -EINVAL; 146 return -EINVAL;
241 saved_domainname = tomoyo_save_name(domainname); 147 saved_domainname = tomoyo_get_name(domainname);
242 if (!saved_domainname) 148 if (!saved_domainname)
243 return -ENOMEM; 149 goto out;
244 } 150 }
245 saved_program = tomoyo_save_name(program); 151 saved_program = tomoyo_get_name(program);
246 if (!saved_program) 152 if (!saved_program)
247 return -ENOMEM; 153 goto out;
248 down_write(&tomoyo_domain_initializer_list_lock); 154 if (!is_delete)
249 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { 155 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
156 mutex_lock(&tomoyo_policy_lock);
157 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
250 if (ptr->is_not != is_not || 158 if (ptr->is_not != is_not ||
251 ptr->domainname != saved_domainname || 159 ptr->domainname != saved_domainname ||
252 ptr->program != saved_program) 160 ptr->program != saved_program)
253 continue; 161 continue;
254 ptr->is_deleted = is_delete; 162 ptr->is_deleted = is_delete;
255 error = 0; 163 error = 0;
256 goto out; 164 break;
257 } 165 }
258 if (is_delete) { 166 if (!is_delete && error && tomoyo_memory_ok(entry)) {
259 error = -ENOENT; 167 entry->domainname = saved_domainname;
260 goto out; 168 saved_domainname = NULL;
169 entry->program = saved_program;
170 saved_program = NULL;
171 entry->is_not = is_not;
172 entry->is_last_name = is_last_name;
173 list_add_tail_rcu(&entry->list,
174 &tomoyo_domain_initializer_list);
175 entry = NULL;
176 error = 0;
261 } 177 }
262 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 178 mutex_unlock(&tomoyo_policy_lock);
263 if (!new_entry)
264 goto out;
265 new_entry->domainname = saved_domainname;
266 new_entry->program = saved_program;
267 new_entry->is_not = is_not;
268 new_entry->is_last_name = is_last_name;
269 list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
270 error = 0;
271 out: 179 out:
272 up_write(&tomoyo_domain_initializer_list_lock); 180 tomoyo_put_name(saved_domainname);
181 tomoyo_put_name(saved_program);
182 kfree(entry);
273 return error; 183 return error;
274} 184}
275 185
@@ -279,13 +189,14 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
279 * @head: Pointer to "struct tomoyo_io_buffer". 189 * @head: Pointer to "struct tomoyo_io_buffer".
280 * 190 *
281 * Returns true on success, false otherwise. 191 * Returns true on success, false otherwise.
192 *
193 * Caller holds tomoyo_read_lock().
282 */ 194 */
283bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 195bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
284{ 196{
285 struct list_head *pos; 197 struct list_head *pos;
286 bool done = true; 198 bool done = true;
287 199
288 down_read(&tomoyo_domain_initializer_list_lock);
289 list_for_each_cookie(pos, head->read_var2, 200 list_for_each_cookie(pos, head->read_var2,
290 &tomoyo_domain_initializer_list) { 201 &tomoyo_domain_initializer_list) {
291 const char *no; 202 const char *no;
@@ -308,7 +219,6 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
308 if (!done) 219 if (!done)
309 break; 220 break;
310 } 221 }
311 up_read(&tomoyo_domain_initializer_list_lock);
312 return done; 222 return done;
313} 223}
314 224
@@ -320,6 +230,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
320 * @is_delete: True if it is a delete request. 230 * @is_delete: True if it is a delete request.
321 * 231 *
322 * Returns 0 on success, negative value otherwise. 232 * Returns 0 on success, negative value otherwise.
233 *
234 * Caller holds tomoyo_read_lock().
323 */ 235 */
324int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 236int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
325 const bool is_delete) 237 const bool is_delete)
@@ -345,6 +257,8 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
345 * 257 *
346 * Returns true if executing @program reinitializes domain transition, 258 * Returns true if executing @program reinitializes domain transition,
347 * false otherwise. 259 * false otherwise.
260 *
261 * Caller holds tomoyo_read_lock().
348 */ 262 */
349static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 263static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
350 domainname, 264 domainname,
@@ -355,8 +269,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
355 struct tomoyo_domain_initializer_entry *ptr; 269 struct tomoyo_domain_initializer_entry *ptr;
356 bool flag = false; 270 bool flag = false;
357 271
358 down_read(&tomoyo_domain_initializer_list_lock); 272 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
359 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
360 if (ptr->is_deleted) 273 if (ptr->is_deleted)
361 continue; 274 continue;
362 if (ptr->domainname) { 275 if (ptr->domainname) {
@@ -376,7 +289,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
376 } 289 }
377 flag = true; 290 flag = true;
378 } 291 }
379 up_read(&tomoyo_domain_initializer_list_lock);
380 return flag; 292 return flag;
381} 293}
382 294
@@ -418,8 +330,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
418 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless 330 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
419 * explicitly specified by "initialize_domain". 331 * explicitly specified by "initialize_domain".
420 */ 332 */
421static LIST_HEAD(tomoyo_domain_keeper_list); 333LIST_HEAD(tomoyo_domain_keeper_list);
422static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
423 334
424/** 335/**
425 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 336 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
@@ -430,59 +341,64 @@ static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
430 * @is_delete: True if it is a delete request. 341 * @is_delete: True if it is a delete request.
431 * 342 *
432 * Returns 0 on success, negative value otherwise. 343 * Returns 0 on success, negative value otherwise.
344 *
345 * Caller holds tomoyo_read_lock().
433 */ 346 */
434static int tomoyo_update_domain_keeper_entry(const char *domainname, 347static int tomoyo_update_domain_keeper_entry(const char *domainname,
435 const char *program, 348 const char *program,
436 const bool is_not, 349 const bool is_not,
437 const bool is_delete) 350 const bool is_delete)
438{ 351{
439 struct tomoyo_domain_keeper_entry *new_entry; 352 struct tomoyo_domain_keeper_entry *entry = NULL;
440 struct tomoyo_domain_keeper_entry *ptr; 353 struct tomoyo_domain_keeper_entry *ptr;
441 const struct tomoyo_path_info *saved_domainname; 354 const struct tomoyo_path_info *saved_domainname = NULL;
442 const struct tomoyo_path_info *saved_program = NULL; 355 const struct tomoyo_path_info *saved_program = NULL;
443 int error = -ENOMEM; 356 int error = is_delete ? -ENOENT : -ENOMEM;
444 bool is_last_name = false; 357 bool is_last_name = false;
445 358
446 if (!tomoyo_is_domain_def(domainname) && 359 if (!tomoyo_is_domain_def(domainname) &&
447 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) 360 tomoyo_is_correct_path(domainname, 1, -1, -1))
448 is_last_name = true; 361 is_last_name = true;
449 else if (!tomoyo_is_correct_domain(domainname, __func__)) 362 else if (!tomoyo_is_correct_domain(domainname))
450 return -EINVAL; 363 return -EINVAL;
451 if (program) { 364 if (program) {
452 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) 365 if (!tomoyo_is_correct_path(program, 1, -1, -1))
453 return -EINVAL; 366 return -EINVAL;
454 saved_program = tomoyo_save_name(program); 367 saved_program = tomoyo_get_name(program);
455 if (!saved_program) 368 if (!saved_program)
456 return -ENOMEM; 369 goto out;
457 } 370 }
458 saved_domainname = tomoyo_save_name(domainname); 371 saved_domainname = tomoyo_get_name(domainname);
459 if (!saved_domainname) 372 if (!saved_domainname)
460 return -ENOMEM; 373 goto out;
461 down_write(&tomoyo_domain_keeper_list_lock); 374 if (!is_delete)
462 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { 375 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
376 mutex_lock(&tomoyo_policy_lock);
377 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
463 if (ptr->is_not != is_not || 378 if (ptr->is_not != is_not ||
464 ptr->domainname != saved_domainname || 379 ptr->domainname != saved_domainname ||
465 ptr->program != saved_program) 380 ptr->program != saved_program)
466 continue; 381 continue;
467 ptr->is_deleted = is_delete; 382 ptr->is_deleted = is_delete;
468 error = 0; 383 error = 0;
469 goto out; 384 break;
470 } 385 }
471 if (is_delete) { 386 if (!is_delete && error && tomoyo_memory_ok(entry)) {
472 error = -ENOENT; 387 entry->domainname = saved_domainname;
473 goto out; 388 saved_domainname = NULL;
389 entry->program = saved_program;
390 saved_program = NULL;
391 entry->is_not = is_not;
392 entry->is_last_name = is_last_name;
393 list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list);
394 entry = NULL;
395 error = 0;
474 } 396 }
475 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 397 mutex_unlock(&tomoyo_policy_lock);
476 if (!new_entry)
477 goto out;
478 new_entry->domainname = saved_domainname;
479 new_entry->program = saved_program;
480 new_entry->is_not = is_not;
481 new_entry->is_last_name = is_last_name;
482 list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
483 error = 0;
484 out: 398 out:
485 up_write(&tomoyo_domain_keeper_list_lock); 399 tomoyo_put_name(saved_domainname);
400 tomoyo_put_name(saved_program);
401 kfree(entry);
486 return error; 402 return error;
487} 403}
488 404
@@ -493,6 +409,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
493 * @is_not: True if it is "no_keep_domain" entry. 409 * @is_not: True if it is "no_keep_domain" entry.
494 * @is_delete: True if it is a delete request. 410 * @is_delete: True if it is a delete request.
495 * 411 *
412 * Caller holds tomoyo_read_lock().
496 */ 413 */
497int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 414int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
498 const bool is_delete) 415 const bool is_delete)
@@ -513,13 +430,14 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
513 * @head: Pointer to "struct tomoyo_io_buffer". 430 * @head: Pointer to "struct tomoyo_io_buffer".
514 * 431 *
515 * Returns true on success, false otherwise. 432 * Returns true on success, false otherwise.
433 *
434 * Caller holds tomoyo_read_lock().
516 */ 435 */
517bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 436bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
518{ 437{
519 struct list_head *pos; 438 struct list_head *pos;
520 bool done = true; 439 bool done = true;
521 440
522 down_read(&tomoyo_domain_keeper_list_lock);
523 list_for_each_cookie(pos, head->read_var2, 441 list_for_each_cookie(pos, head->read_var2,
524 &tomoyo_domain_keeper_list) { 442 &tomoyo_domain_keeper_list) {
525 struct tomoyo_domain_keeper_entry *ptr; 443 struct tomoyo_domain_keeper_entry *ptr;
@@ -542,7 +460,6 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
542 if (!done) 460 if (!done)
543 break; 461 break;
544 } 462 }
545 up_read(&tomoyo_domain_keeper_list_lock);
546 return done; 463 return done;
547} 464}
548 465
@@ -555,6 +472,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
555 * 472 *
556 * Returns true if executing @program supresses domain transition, 473 * Returns true if executing @program supresses domain transition,
557 * false otherwise. 474 * false otherwise.
475 *
476 * Caller holds tomoyo_read_lock().
558 */ 477 */
559static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 478static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
560 const struct tomoyo_path_info *program, 479 const struct tomoyo_path_info *program,
@@ -563,8 +482,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
563 struct tomoyo_domain_keeper_entry *ptr; 482 struct tomoyo_domain_keeper_entry *ptr;
564 bool flag = false; 483 bool flag = false;
565 484
566 down_read(&tomoyo_domain_keeper_list_lock); 485 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
567 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
568 if (ptr->is_deleted) 486 if (ptr->is_deleted)
569 continue; 487 continue;
570 if (!ptr->is_last_name) { 488 if (!ptr->is_last_name) {
@@ -582,7 +500,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
582 } 500 }
583 flag = true; 501 flag = true;
584 } 502 }
585 up_read(&tomoyo_domain_keeper_list_lock);
586 return flag; 503 return flag;
587} 504}
588 505
@@ -616,8 +533,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
616 * /bin/busybox and domainname which the current process will belong to after 533 * /bin/busybox and domainname which the current process will belong to after
617 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . 534 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
618 */ 535 */
619static LIST_HEAD(tomoyo_alias_list); 536LIST_HEAD(tomoyo_alias_list);
620static DECLARE_RWSEM(tomoyo_alias_list_lock);
621 537
622/** 538/**
623 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 539 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
@@ -627,46 +543,51 @@ static DECLARE_RWSEM(tomoyo_alias_list_lock);
627 * @is_delete: True if it is a delete request. 543 * @is_delete: True if it is a delete request.
628 * 544 *
629 * Returns 0 on success, negative value otherwise. 545 * Returns 0 on success, negative value otherwise.
546 *
547 * Caller holds tomoyo_read_lock().
630 */ 548 */
631static int tomoyo_update_alias_entry(const char *original_name, 549static int tomoyo_update_alias_entry(const char *original_name,
632 const char *aliased_name, 550 const char *aliased_name,
633 const bool is_delete) 551 const bool is_delete)
634{ 552{
635 struct tomoyo_alias_entry *new_entry; 553 struct tomoyo_alias_entry *entry = NULL;
636 struct tomoyo_alias_entry *ptr; 554 struct tomoyo_alias_entry *ptr;
637 const struct tomoyo_path_info *saved_original_name; 555 const struct tomoyo_path_info *saved_original_name;
638 const struct tomoyo_path_info *saved_aliased_name; 556 const struct tomoyo_path_info *saved_aliased_name;
639 int error = -ENOMEM; 557 int error = is_delete ? -ENOENT : -ENOMEM;
640 558
641 if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || 559 if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
642 !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) 560 !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
643 return -EINVAL; /* No patterns allowed. */ 561 return -EINVAL; /* No patterns allowed. */
644 saved_original_name = tomoyo_save_name(original_name); 562 saved_original_name = tomoyo_get_name(original_name);
645 saved_aliased_name = tomoyo_save_name(aliased_name); 563 saved_aliased_name = tomoyo_get_name(aliased_name);
646 if (!saved_original_name || !saved_aliased_name) 564 if (!saved_original_name || !saved_aliased_name)
647 return -ENOMEM; 565 goto out;
648 down_write(&tomoyo_alias_list_lock); 566 if (!is_delete)
649 list_for_each_entry(ptr, &tomoyo_alias_list, list) { 567 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
568 mutex_lock(&tomoyo_policy_lock);
569 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
650 if (ptr->original_name != saved_original_name || 570 if (ptr->original_name != saved_original_name ||
651 ptr->aliased_name != saved_aliased_name) 571 ptr->aliased_name != saved_aliased_name)
652 continue; 572 continue;
653 ptr->is_deleted = is_delete; 573 ptr->is_deleted = is_delete;
654 error = 0; 574 error = 0;
655 goto out; 575 break;
656 } 576 }
657 if (is_delete) { 577 if (!is_delete && error && tomoyo_memory_ok(entry)) {
658 error = -ENOENT; 578 entry->original_name = saved_original_name;
659 goto out; 579 saved_original_name = NULL;
580 entry->aliased_name = saved_aliased_name;
581 saved_aliased_name = NULL;
582 list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
583 entry = NULL;
584 error = 0;
660 } 585 }
661 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 586 mutex_unlock(&tomoyo_policy_lock);
662 if (!new_entry)
663 goto out;
664 new_entry->original_name = saved_original_name;
665 new_entry->aliased_name = saved_aliased_name;
666 list_add_tail(&new_entry->list, &tomoyo_alias_list);
667 error = 0;
668 out: 587 out:
669 up_write(&tomoyo_alias_list_lock); 588 tomoyo_put_name(saved_original_name);
589 tomoyo_put_name(saved_aliased_name);
590 kfree(entry);
670 return error; 591 return error;
671} 592}
672 593
@@ -676,13 +597,14 @@ static int tomoyo_update_alias_entry(const char *original_name,
676 * @head: Pointer to "struct tomoyo_io_buffer". 597 * @head: Pointer to "struct tomoyo_io_buffer".
677 * 598 *
678 * Returns true on success, false otherwise. 599 * Returns true on success, false otherwise.
600 *
601 * Caller holds tomoyo_read_lock().
679 */ 602 */
680bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 603bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
681{ 604{
682 struct list_head *pos; 605 struct list_head *pos;
683 bool done = true; 606 bool done = true;
684 607
685 down_read(&tomoyo_alias_list_lock);
686 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { 608 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
687 struct tomoyo_alias_entry *ptr; 609 struct tomoyo_alias_entry *ptr;
688 610
@@ -695,7 +617,6 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
695 if (!done) 617 if (!done)
696 break; 618 break;
697 } 619 }
698 up_read(&tomoyo_alias_list_lock);
699 return done; 620 return done;
700} 621}
701 622
@@ -706,6 +627,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
706 * @is_delete: True if it is a delete request. 627 * @is_delete: True if it is a delete request.
707 * 628 *
708 * Returns 0 on success, negative value otherwise. 629 * Returns 0 on success, negative value otherwise.
630 *
631 * Caller holds tomoyo_read_lock().
709 */ 632 */
710int tomoyo_write_alias_policy(char *data, const bool is_delete) 633int tomoyo_write_alias_policy(char *data, const bool is_delete)
711{ 634{
@@ -724,63 +647,46 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete)
724 * @profile: Profile number to assign if the domain was newly created. 647 * @profile: Profile number to assign if the domain was newly created.
725 * 648 *
726 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 649 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
650 *
651 * Caller holds tomoyo_read_lock().
727 */ 652 */
728struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 653struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
729 domainname, 654 domainname,
730 const u8 profile) 655 const u8 profile)
731{ 656{
732 struct tomoyo_domain_info *domain = NULL; 657 struct tomoyo_domain_info *entry;
658 struct tomoyo_domain_info *domain;
733 const struct tomoyo_path_info *saved_domainname; 659 const struct tomoyo_path_info *saved_domainname;
660 bool found = false;
734 661
735 down_write(&tomoyo_domain_list_lock); 662 if (!tomoyo_is_correct_domain(domainname))
736 domain = tomoyo_find_domain(domainname); 663 return NULL;
737 if (domain) 664 saved_domainname = tomoyo_get_name(domainname);
738 goto out;
739 if (!tomoyo_is_correct_domain(domainname, __func__))
740 goto out;
741 saved_domainname = tomoyo_save_name(domainname);
742 if (!saved_domainname) 665 if (!saved_domainname)
743 goto out; 666 return NULL;
744 /* Can I reuse memory of deleted domain? */ 667 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
745 list_for_each_entry(domain, &tomoyo_domain_list, list) { 668 mutex_lock(&tomoyo_policy_lock);
746 struct task_struct *p; 669 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
747 struct tomoyo_acl_info *ptr; 670 if (domain->is_deleted ||
748 bool flag; 671 tomoyo_pathcmp(saved_domainname, domain->domainname))
749 if (!domain->is_deleted ||
750 domain->domainname != saved_domainname)
751 continue; 672 continue;
752 flag = false; 673 found = true;
753 read_lock(&tasklist_lock); 674 break;
754 for_each_process(p) {
755 if (tomoyo_real_domain(p) != domain)
756 continue;
757 flag = true;
758 break;
759 }
760 read_unlock(&tasklist_lock);
761 if (flag)
762 continue;
763 list_for_each_entry(ptr, &domain->acl_info_list, list) {
764 ptr->type |= TOMOYO_ACL_DELETED;
765 }
766 tomoyo_set_domain_flag(domain, true, domain->flags);
767 domain->profile = profile;
768 domain->quota_warned = false;
769 mb(); /* Avoid out-of-order execution. */
770 domain->is_deleted = false;
771 goto out;
772 } 675 }
773 /* No memory reusable. Create using new memory. */ 676 if (!found && tomoyo_memory_ok(entry)) {
774 domain = tomoyo_alloc_element(sizeof(*domain)); 677 INIT_LIST_HEAD(&entry->acl_info_list);
775 if (domain) { 678 entry->domainname = saved_domainname;
776 INIT_LIST_HEAD(&domain->acl_info_list); 679 saved_domainname = NULL;
777 domain->domainname = saved_domainname; 680 entry->profile = profile;
778 domain->profile = profile; 681 list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
779 list_add_tail(&domain->list, &tomoyo_domain_list); 682 domain = entry;
683 entry = NULL;
684 found = true;
780 } 685 }
781 out: 686 mutex_unlock(&tomoyo_policy_lock);
782 up_write(&tomoyo_domain_list_lock); 687 tomoyo_put_name(saved_domainname);
783 return domain; 688 kfree(entry);
689 return found ? domain : NULL;
784} 690}
785 691
786/** 692/**
@@ -789,6 +695,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
789 * @bprm: Pointer to "struct linux_binprm". 695 * @bprm: Pointer to "struct linux_binprm".
790 * 696 *
791 * Returns 0 on success, negative value otherwise. 697 * Returns 0 on success, negative value otherwise.
698 *
699 * Caller holds tomoyo_read_lock().
792 */ 700 */
793int tomoyo_find_next_domain(struct linux_binprm *bprm) 701int tomoyo_find_next_domain(struct linux_binprm *bprm)
794{ 702{
@@ -796,7 +704,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
796 * This function assumes that the size of buffer returned by 704 * This function assumes that the size of buffer returned by
797 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. 705 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
798 */ 706 */
799 struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp)); 707 struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
800 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 708 struct tomoyo_domain_info *old_domain = tomoyo_domain();
801 struct tomoyo_domain_info *domain = NULL; 709 struct tomoyo_domain_info *domain = NULL;
802 const char *old_domain_name = old_domain->domainname->name; 710 const char *old_domain_name = old_domain->domainname->name;
@@ -849,8 +757,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
849 if (tomoyo_pathcmp(&r, &s)) { 757 if (tomoyo_pathcmp(&r, &s)) {
850 struct tomoyo_alias_entry *ptr; 758 struct tomoyo_alias_entry *ptr;
851 /* Is this program allowed to be called via symbolic links? */ 759 /* Is this program allowed to be called via symbolic links? */
852 down_read(&tomoyo_alias_list_lock); 760 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
853 list_for_each_entry(ptr, &tomoyo_alias_list, list) {
854 if (ptr->is_deleted || 761 if (ptr->is_deleted ||
855 tomoyo_pathcmp(&r, ptr->original_name) || 762 tomoyo_pathcmp(&r, ptr->original_name) ||
856 tomoyo_pathcmp(&s, ptr->aliased_name)) 763 tomoyo_pathcmp(&s, ptr->aliased_name))
@@ -861,7 +768,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
861 tomoyo_fill_path_info(&r); 768 tomoyo_fill_path_info(&r);
862 break; 769 break;
863 } 770 }
864 up_read(&tomoyo_alias_list_lock);
865 } 771 }
866 772
867 /* Check execute permission. */ 773 /* Check execute permission. */
@@ -892,9 +798,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
892 } 798 }
893 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 799 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
894 goto done; 800 goto done;
895 down_read(&tomoyo_domain_list_lock);
896 domain = tomoyo_find_domain(new_domain_name); 801 domain = tomoyo_find_domain(new_domain_name);
897 up_read(&tomoyo_domain_list_lock);
898 if (domain) 802 if (domain)
899 goto done; 803 goto done;
900 if (is_enforce) 804 if (is_enforce)
@@ -909,14 +813,15 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
909 if (is_enforce) 813 if (is_enforce)
910 retval = -EPERM; 814 retval = -EPERM;
911 else 815 else
912 tomoyo_set_domain_flag(old_domain, false, 816 old_domain->transition_failed = true;
913 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
914 out: 817 out:
915 if (!domain) 818 if (!domain)
916 domain = old_domain; 819 domain = old_domain;
820 /* Update reference count on "struct tomoyo_domain_info". */
821 atomic_inc(&domain->users);
917 bprm->cred->security = domain; 822 bprm->cred->security = domain;
918 tomoyo_free(real_program_name); 823 kfree(real_program_name);
919 tomoyo_free(symlink_program_name); 824 kfree(symlink_program_name);
920 tomoyo_free(tmp); 825 kfree(tmp);
921 return retval; 826 return retval;
922} 827}