diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-06-26 10:19:52 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-06-28 19:31:21 -0400 |
commit | bd03a3e4c9a9df0c6b007045fa7fc8889111a478 (patch) | |
tree | 9d78290c878e6466fe3e0bda7ee5989c0dc39e40 /security/tomoyo/domain.c | |
parent | 32997144fd9925fc4d506a16990a0c405f766526 (diff) |
TOMOYO: Add policy namespace support.
Mauras Olivier reported that it is difficult to use TOMOYO in LXC environments,
for TOMOYO cannot distinguish between environments outside the container and
environments inside the container since LXC environments are created using
pivot_root(). To address this problem, this patch introduces policy namespace.
Each policy namespace has its own set of domain policy, exception policy and
profiles, which are all independent of other namespaces. This independency
allows users to develop policy without worrying interference among namespaces.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo/domain.c')
-rw-r--r-- | security/tomoyo/domain.c | 360 |
1 files changed, 260 insertions, 100 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index af5f325e2f33..71acebc747c3 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -12,9 +12,6 @@ | |||
12 | 12 | ||
13 | /* Variables definitions.*/ | 13 | /* Variables definitions.*/ |
14 | 14 | ||
15 | /* The global ACL referred by "use_group" keyword. */ | ||
16 | struct list_head tomoyo_acl_group[TOMOYO_MAX_ACL_GROUPS]; | ||
17 | |||
18 | /* The initial domain. */ | 15 | /* The initial domain. */ |
19 | struct tomoyo_domain_info tomoyo_kernel_domain; | 16 | struct tomoyo_domain_info tomoyo_kernel_domain; |
20 | 17 | ||
@@ -158,7 +155,7 @@ retry: | |||
158 | } | 155 | } |
159 | if (!retried) { | 156 | if (!retried) { |
160 | retried = true; | 157 | retried = true; |
161 | list = &tomoyo_acl_group[domain->group]; | 158 | list = &domain->ns->acl_group[domain->group]; |
162 | goto retry; | 159 | goto retry; |
163 | } | 160 | } |
164 | r->granted = false; | 161 | r->granted = false; |
@@ -167,13 +164,10 @@ retry: | |||
167 | /* The list for "struct tomoyo_domain_info". */ | 164 | /* The list for "struct tomoyo_domain_info". */ |
168 | LIST_HEAD(tomoyo_domain_list); | 165 | LIST_HEAD(tomoyo_domain_list); |
169 | 166 | ||
170 | struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY]; | ||
171 | struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP]; | ||
172 | |||
173 | /** | 167 | /** |
174 | * tomoyo_last_word - Get last component of a domainname. | 168 | * tomoyo_last_word - Get last component of a domainname. |
175 | * | 169 | * |
176 | * @domainname: Domainname to check. | 170 | * @name: Domainname to check. |
177 | * | 171 | * |
178 | * Returns the last word of @domainname. | 172 | * Returns the last word of @domainname. |
179 | */ | 173 | */ |
@@ -247,7 +241,7 @@ int tomoyo_write_transition_control(struct tomoyo_acl_param *param, | |||
247 | if (!e.domainname) | 241 | if (!e.domainname) |
248 | goto out; | 242 | goto out; |
249 | } | 243 | } |
250 | param->list = &tomoyo_policy_list[TOMOYO_ID_TRANSITION_CONTROL]; | 244 | param->list = ¶m->ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; |
251 | error = tomoyo_update_policy(&e.head, sizeof(e), param, | 245 | error = tomoyo_update_policy(&e.head, sizeof(e), param, |
252 | tomoyo_same_transition_control); | 246 | tomoyo_same_transition_control); |
253 | out: | 247 | out: |
@@ -257,59 +251,88 @@ out: | |||
257 | } | 251 | } |
258 | 252 | ||
259 | /** | 253 | /** |
260 | * tomoyo_transition_type - Get domain transition type. | 254 | * tomoyo_scan_transition - Try to find specific domain transition type. |
261 | * | 255 | * |
262 | * @domainname: The name of domain. | 256 | * @list: Pointer to "struct list_head". |
263 | * @program: The name of program. | 257 | * @domainname: The name of current domain. |
258 | * @program: The name of requested program. | ||
259 | * @last_name: The last component of @domainname. | ||
260 | * @type: One of values in "enum tomoyo_transition_type". | ||
264 | * | 261 | * |
265 | * Returns TOMOYO_TRANSITION_CONTROL_INITIALIZE if executing @program | 262 | * Returns true if found one, false otherwise. |
266 | * reinitializes domain transition, TOMOYO_TRANSITION_CONTROL_KEEP if executing | ||
267 | * @program suppresses domain transition, others otherwise. | ||
268 | * | 263 | * |
269 | * Caller holds tomoyo_read_lock(). | 264 | * Caller holds tomoyo_read_lock(). |
270 | */ | 265 | */ |
271 | static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname, | 266 | static inline bool tomoyo_scan_transition |
272 | const struct tomoyo_path_info *program) | 267 | (const struct list_head *list, const struct tomoyo_path_info *domainname, |
268 | const struct tomoyo_path_info *program, const char *last_name, | ||
269 | const enum tomoyo_transition_type type) | ||
273 | { | 270 | { |
274 | const struct tomoyo_transition_control *ptr; | 271 | const struct tomoyo_transition_control *ptr; |
275 | const char *last_name = tomoyo_last_word(domainname->name); | 272 | list_for_each_entry_rcu(ptr, list, head.list) { |
276 | u8 type; | 273 | if (ptr->head.is_deleted || ptr->type != type) |
277 | for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) { | 274 | continue; |
278 | next: | 275 | if (ptr->domainname) { |
279 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list | 276 | if (!ptr->is_last_name) { |
280 | [TOMOYO_ID_TRANSITION_CONTROL], | 277 | if (ptr->domainname != domainname) |
281 | head.list) { | 278 | continue; |
282 | if (ptr->head.is_deleted || ptr->type != type) | 279 | } else { |
283 | continue; | ||
284 | if (ptr->domainname) { | ||
285 | if (!ptr->is_last_name) { | ||
286 | if (ptr->domainname != domainname) | ||
287 | continue; | ||
288 | } else { | ||
289 | /* | ||
290 | * Use direct strcmp() since this is | ||
291 | * unlikely used. | ||
292 | */ | ||
293 | if (strcmp(ptr->domainname->name, | ||
294 | last_name)) | ||
295 | continue; | ||
296 | } | ||
297 | } | ||
298 | if (ptr->program && | ||
299 | tomoyo_pathcmp(ptr->program, program)) | ||
300 | continue; | ||
301 | if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) { | ||
302 | /* | 280 | /* |
303 | * Do not check for initialize_domain if | 281 | * Use direct strcmp() since this is |
304 | * no_initialize_domain matched. | 282 | * unlikely used. |
305 | */ | 283 | */ |
306 | type = TOMOYO_TRANSITION_CONTROL_NO_KEEP; | 284 | if (strcmp(ptr->domainname->name, last_name)) |
307 | goto next; | 285 | continue; |
308 | } | 286 | } |
309 | goto done; | ||
310 | } | 287 | } |
288 | if (ptr->program && tomoyo_pathcmp(ptr->program, program)) | ||
289 | continue; | ||
290 | return true; | ||
291 | } | ||
292 | return false; | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * tomoyo_transition_type - Get domain transition type. | ||
297 | * | ||
298 | * @ns: Pointer to "struct tomoyo_policy_namespace". | ||
299 | * @domainname: The name of current domain. | ||
300 | * @program: The name of requested program. | ||
301 | * | ||
302 | * Returns TOMOYO_TRANSITION_CONTROL_TRANSIT if executing @program causes | ||
303 | * domain transition across namespaces, TOMOYO_TRANSITION_CONTROL_INITIALIZE if | ||
304 | * executing @program reinitializes domain transition within that namespace, | ||
305 | * TOMOYO_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname , | ||
306 | * others otherwise. | ||
307 | * | ||
308 | * Caller holds tomoyo_read_lock(). | ||
309 | */ | ||
310 | static enum tomoyo_transition_type tomoyo_transition_type | ||
311 | (const struct tomoyo_policy_namespace *ns, | ||
312 | const struct tomoyo_path_info *domainname, | ||
313 | const struct tomoyo_path_info *program) | ||
314 | { | ||
315 | const char *last_name = tomoyo_last_word(domainname->name); | ||
316 | enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET; | ||
317 | while (type < TOMOYO_MAX_TRANSITION_TYPE) { | ||
318 | const struct list_head * const list = | ||
319 | &ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; | ||
320 | if (!tomoyo_scan_transition(list, domainname, program, | ||
321 | last_name, type)) { | ||
322 | type++; | ||
323 | continue; | ||
324 | } | ||
325 | if (type != TOMOYO_TRANSITION_CONTROL_NO_RESET && | ||
326 | type != TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) | ||
327 | break; | ||
328 | /* | ||
329 | * Do not check for reset_domain if no_reset_domain matched. | ||
330 | * Do not check for initialize_domain if no_initialize_domain | ||
331 | * matched. | ||
332 | */ | ||
333 | type++; | ||
334 | type++; | ||
311 | } | 335 | } |
312 | done: | ||
313 | return type; | 336 | return type; |
314 | } | 337 | } |
315 | 338 | ||
@@ -355,7 +378,7 @@ int tomoyo_write_aggregator(struct tomoyo_acl_param *param) | |||
355 | if (!e.original_name || !e.aggregated_name || | 378 | if (!e.original_name || !e.aggregated_name || |
356 | e.aggregated_name->is_patterned) /* No patterns allowed. */ | 379 | e.aggregated_name->is_patterned) /* No patterns allowed. */ |
357 | goto out; | 380 | goto out; |
358 | param->list = &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR]; | 381 | param->list = ¶m->ns->policy_list[TOMOYO_ID_AGGREGATOR]; |
359 | error = tomoyo_update_policy(&e.head, sizeof(e), param, | 382 | error = tomoyo_update_policy(&e.head, sizeof(e), param, |
360 | tomoyo_same_aggregator); | 383 | tomoyo_same_aggregator); |
361 | out: | 384 | out: |
@@ -365,53 +388,171 @@ out: | |||
365 | } | 388 | } |
366 | 389 | ||
367 | /** | 390 | /** |
368 | * tomoyo_assign_domain - Create a domain. | 391 | * tomoyo_find_namespace - Find specified namespace. |
369 | * | 392 | * |
370 | * @domainname: The name of domain. | 393 | * @name: Name of namespace to find. |
371 | * @profile: Profile number to assign if the domain was newly created. | 394 | * @len: Length of @name. |
372 | * | 395 | * |
373 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. | 396 | * Returns pointer to "struct tomoyo_policy_namespace" if found, |
397 | * NULL otherwise. | ||
374 | * | 398 | * |
375 | * Caller holds tomoyo_read_lock(). | 399 | * Caller holds tomoyo_read_lock(). |
376 | */ | 400 | */ |
377 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | 401 | static struct tomoyo_policy_namespace *tomoyo_find_namespace |
378 | const u8 profile) | 402 | (const char *name, const unsigned int len) |
379 | { | 403 | { |
380 | struct tomoyo_domain_info *entry; | 404 | struct tomoyo_policy_namespace *ns; |
381 | struct tomoyo_domain_info *domain = NULL; | 405 | list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { |
382 | const struct tomoyo_path_info *saved_domainname; | 406 | if (strncmp(name, ns->name, len) || |
383 | bool found = false; | 407 | (name[len] && name[len] != ' ')) |
408 | continue; | ||
409 | return ns; | ||
410 | } | ||
411 | return NULL; | ||
412 | } | ||
384 | 413 | ||
385 | if (!tomoyo_correct_domain(domainname)) | 414 | /** |
415 | * tomoyo_assign_namespace - Create a new namespace. | ||
416 | * | ||
417 | * @domainname: Name of namespace to create. | ||
418 | * | ||
419 | * Returns pointer to "struct tomoyo_policy_namespace" on success, | ||
420 | * NULL otherwise. | ||
421 | * | ||
422 | * Caller holds tomoyo_read_lock(). | ||
423 | */ | ||
424 | struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) | ||
425 | { | ||
426 | struct tomoyo_policy_namespace *ptr; | ||
427 | struct tomoyo_policy_namespace *entry; | ||
428 | const char *cp = domainname; | ||
429 | unsigned int len = 0; | ||
430 | while (*cp && *cp++ != ' ') | ||
431 | len++; | ||
432 | ptr = tomoyo_find_namespace(domainname, len); | ||
433 | if (ptr) | ||
434 | return ptr; | ||
435 | if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname)) | ||
386 | return NULL; | 436 | return NULL; |
387 | saved_domainname = tomoyo_get_name(domainname); | 437 | entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS); |
388 | if (!saved_domainname) | 438 | if (!entry) |
389 | return NULL; | 439 | return NULL; |
390 | entry = kzalloc(sizeof(*entry), GFP_NOFS); | ||
391 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 440 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
392 | goto out; | 441 | goto out; |
393 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | 442 | ptr = tomoyo_find_namespace(domainname, len); |
394 | if (domain->is_deleted || | 443 | if (!ptr && tomoyo_memory_ok(entry)) { |
395 | tomoyo_pathcmp(saved_domainname, domain->domainname)) | 444 | char *name = (char *) (entry + 1); |
396 | continue; | 445 | ptr = entry; |
397 | found = true; | 446 | memmove(name, domainname, len); |
398 | break; | 447 | name[len] = '\0'; |
399 | } | 448 | entry->name = name; |
400 | if (!found && tomoyo_memory_ok(entry)) { | 449 | tomoyo_init_policy_namespace(entry); |
401 | INIT_LIST_HEAD(&entry->acl_info_list); | ||
402 | entry->domainname = saved_domainname; | ||
403 | saved_domainname = NULL; | ||
404 | entry->profile = profile; | ||
405 | list_add_tail_rcu(&entry->list, &tomoyo_domain_list); | ||
406 | domain = entry; | ||
407 | entry = NULL; | 450 | entry = NULL; |
408 | found = true; | ||
409 | } | 451 | } |
410 | mutex_unlock(&tomoyo_policy_lock); | 452 | mutex_unlock(&tomoyo_policy_lock); |
411 | out: | 453 | out: |
412 | tomoyo_put_name(saved_domainname); | ||
413 | kfree(entry); | 454 | kfree(entry); |
414 | return found ? domain : NULL; | 455 | return ptr; |
456 | } | ||
457 | |||
458 | /** | ||
459 | * tomoyo_namespace_jump - Check for namespace jump. | ||
460 | * | ||
461 | * @domainname: Name of domain. | ||
462 | * | ||
463 | * Returns true if namespace differs, false otherwise. | ||
464 | */ | ||
465 | static bool tomoyo_namespace_jump(const char *domainname) | ||
466 | { | ||
467 | const char *namespace = tomoyo_current_namespace()->name; | ||
468 | const int len = strlen(namespace); | ||
469 | return strncmp(domainname, namespace, len) || | ||
470 | (domainname[len] && domainname[len] != ' '); | ||
471 | } | ||
472 | |||
473 | /** | ||
474 | * tomoyo_assign_domain - Create a domain or a namespace. | ||
475 | * | ||
476 | * @domainname: The name of domain. | ||
477 | * @transit: True if transit to domain found or created. | ||
478 | * | ||
479 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. | ||
480 | * | ||
481 | * Caller holds tomoyo_read_lock(). | ||
482 | */ | ||
483 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | ||
484 | const bool transit) | ||
485 | { | ||
486 | struct tomoyo_domain_info e = { }; | ||
487 | struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname); | ||
488 | bool created = false; | ||
489 | if (entry) { | ||
490 | if (transit) { | ||
491 | /* | ||
492 | * Since namespace is created at runtime, profiles may | ||
493 | * not be created by the moment the process transits to | ||
494 | * that domain. Do not perform domain transition if | ||
495 | * profile for that domain is not yet created. | ||
496 | */ | ||
497 | if (!entry->ns->profile_ptr[entry->profile]) | ||
498 | return NULL; | ||
499 | } | ||
500 | return entry; | ||
501 | } | ||
502 | /* Requested domain does not exist. */ | ||
503 | /* Don't create requested domain if domainname is invalid. */ | ||
504 | if (strlen(domainname) >= TOMOYO_EXEC_TMPSIZE - 10 || | ||
505 | !tomoyo_correct_domain(domainname)) | ||
506 | return NULL; | ||
507 | /* | ||
508 | * Since definition of profiles and acl_groups may differ across | ||
509 | * namespaces, do not inherit "use_profile" and "use_group" settings | ||
510 | * by automatically creating requested domain upon domain transition. | ||
511 | */ | ||
512 | if (transit && tomoyo_namespace_jump(domainname)) | ||
513 | return NULL; | ||
514 | e.ns = tomoyo_assign_namespace(domainname); | ||
515 | if (!e.ns) | ||
516 | return NULL; | ||
517 | /* | ||
518 | * "use_profile" and "use_group" settings for automatically created | ||
519 | * domains are inherited from current domain. These are 0 for manually | ||
520 | * created domains. | ||
521 | */ | ||
522 | if (transit) { | ||
523 | const struct tomoyo_domain_info *domain = tomoyo_domain(); | ||
524 | e.profile = domain->profile; | ||
525 | e.group = domain->group; | ||
526 | } | ||
527 | e.domainname = tomoyo_get_name(domainname); | ||
528 | if (!e.domainname) | ||
529 | return NULL; | ||
530 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
531 | goto out; | ||
532 | entry = tomoyo_find_domain(domainname); | ||
533 | if (!entry) { | ||
534 | entry = tomoyo_commit_ok(&e, sizeof(e)); | ||
535 | if (entry) { | ||
536 | INIT_LIST_HEAD(&entry->acl_info_list); | ||
537 | list_add_tail_rcu(&entry->list, &tomoyo_domain_list); | ||
538 | created = true; | ||
539 | } | ||
540 | } | ||
541 | mutex_unlock(&tomoyo_policy_lock); | ||
542 | out: | ||
543 | tomoyo_put_name(e.domainname); | ||
544 | if (entry && transit) { | ||
545 | if (created) { | ||
546 | struct tomoyo_request_info r; | ||
547 | tomoyo_init_request_info(&r, entry, | ||
548 | TOMOYO_MAC_FILE_EXECUTE); | ||
549 | r.granted = false; | ||
550 | tomoyo_write_log(&r, "use_profile %u\n", | ||
551 | entry->profile); | ||
552 | tomoyo_write_log(&r, "use_group %u\n", entry->group); | ||
553 | } | ||
554 | } | ||
555 | return entry; | ||
415 | } | 556 | } |
416 | 557 | ||
417 | /** | 558 | /** |
@@ -434,6 +575,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
434 | bool is_enforce; | 575 | bool is_enforce; |
435 | int retval = -ENOMEM; | 576 | int retval = -ENOMEM; |
436 | bool need_kfree = false; | 577 | bool need_kfree = false; |
578 | bool reject_on_transition_failure = false; | ||
437 | struct tomoyo_path_info rn = { }; /* real name */ | 579 | struct tomoyo_path_info rn = { }; /* real name */ |
438 | 580 | ||
439 | mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); | 581 | mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); |
@@ -457,8 +599,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
457 | /* Check 'aggregator' directive. */ | 599 | /* Check 'aggregator' directive. */ |
458 | { | 600 | { |
459 | struct tomoyo_aggregator *ptr; | 601 | struct tomoyo_aggregator *ptr; |
460 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list | 602 | struct list_head *list = |
461 | [TOMOYO_ID_AGGREGATOR], head.list) { | 603 | &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; |
604 | /* Check 'aggregator' directive. */ | ||
605 | list_for_each_entry_rcu(ptr, list, head.list) { | ||
462 | if (ptr->head.is_deleted || | 606 | if (ptr->head.is_deleted || |
463 | !tomoyo_path_matches_pattern(&rn, | 607 | !tomoyo_path_matches_pattern(&rn, |
464 | ptr->original_name)) | 608 | ptr->original_name)) |
@@ -492,11 +636,21 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
492 | } | 636 | } |
493 | 637 | ||
494 | /* Calculate domain to transit to. */ | 638 | /* Calculate domain to transit to. */ |
495 | switch (tomoyo_transition_type(old_domain->domainname, &rn)) { | 639 | switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, |
640 | &rn)) { | ||
641 | case TOMOYO_TRANSITION_CONTROL_RESET: | ||
642 | /* Transit to the root of specified namespace. */ | ||
643 | snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name); | ||
644 | /* | ||
645 | * Make do_execve() fail if domain transition across namespaces | ||
646 | * has failed. | ||
647 | */ | ||
648 | reject_on_transition_failure = true; | ||
649 | break; | ||
496 | case TOMOYO_TRANSITION_CONTROL_INITIALIZE: | 650 | case TOMOYO_TRANSITION_CONTROL_INITIALIZE: |
497 | /* Transit to the child of tomoyo_kernel_domain domain. */ | 651 | /* Transit to the child of current namespace's root. */ |
498 | snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " " | 652 | snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", |
499 | "%s", rn.name); | 653 | old_domain->ns->name, rn.name); |
500 | break; | 654 | break; |
501 | case TOMOYO_TRANSITION_CONTROL_KEEP: | 655 | case TOMOYO_TRANSITION_CONTROL_KEEP: |
502 | /* Keep current domain. */ | 656 | /* Keep current domain. */ |
@@ -519,19 +673,25 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
519 | } | 673 | } |
520 | break; | 674 | break; |
521 | } | 675 | } |
522 | if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10) | ||
523 | goto done; | ||
524 | domain = tomoyo_find_domain(tmp); | ||
525 | if (!domain) | 676 | if (!domain) |
526 | domain = tomoyo_assign_domain(tmp, old_domain->profile); | 677 | domain = tomoyo_assign_domain(tmp, true); |
527 | done: | ||
528 | if (domain) | 678 | if (domain) |
529 | goto out; | 679 | retval = 0; |
530 | printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp); | 680 | else if (reject_on_transition_failure) { |
531 | if (is_enforce) | 681 | printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", tmp); |
532 | retval = -EPERM; | 682 | retval = -ENOMEM; |
533 | else | 683 | } else if (r.mode == TOMOYO_CONFIG_ENFORCING) |
534 | old_domain->transition_failed = true; | 684 | retval = -ENOMEM; |
685 | else { | ||
686 | retval = 0; | ||
687 | if (!old_domain->transition_failed) { | ||
688 | old_domain->transition_failed = true; | ||
689 | r.granted = false; | ||
690 | tomoyo_write_log(&r, "%s", "transition_failed\n"); | ||
691 | printk(KERN_WARNING | ||
692 | "ERROR: Domain '%s' not defined.\n", tmp); | ||
693 | } | ||
694 | } | ||
535 | out: | 695 | out: |
536 | if (!domain) | 696 | if (!domain) |
537 | domain = old_domain; | 697 | domain = old_domain; |