2 * security/tomoyo/domain.c
4 * Implementation of the Domain-Based Mandatory Access Control.
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
8 * Version: 2.2.0 2009/04/01
15 #include <linux/binfmts.h>
17 /* Variables definitions.*/
19 /* The initial domain. */
20 struct tomoyo_domain_info tomoyo_kernel_domain
;
23 * tomoyo_domain_list is used for holding list of domains.
24 * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
25 * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
27 * An entry is added by
29 * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
30 * /sys/kernel/security/tomoyo/domain_policy
34 * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
35 * /sys/kernel/security/tomoyo/domain_policy
37 * and all entries are retrieved by
39 * # cat /sys/kernel/security/tomoyo/domain_policy
41 * A domain is added by
43 * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
47 * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
49 * and all domains are retrieved by
51 * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
53 * Normally, a domainname is monotonically getting longer because a domainname
54 * which the process will belong to if an execve() operation succeeds is
55 * defined as a concatenation of "current domainname" + "pathname passed to
57 * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
60 LIST_HEAD(tomoyo_domain_list
);
63 * tomoyo_domain_initializer_entry is a structure which is used for holding
64 * "initialize_domain" and "no_initialize_domain" entries.
65 * It has following fields.
67 * (1) "list" which is linked to tomoyo_domain_initializer_list .
68 * (2) "domainname" which is "a domainname" or "the last component of a
69 * domainname". This field is NULL if "from" clause is not specified.
70 * (3) "program" which is a program's pathname.
71 * (4) "is_deleted" is a bool which is true if marked as deleted, false
73 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
75 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
76 * component of a domainname", false otherwise.
78 struct tomoyo_domain_initializer_entry
{
79 struct list_head list
;
80 const struct tomoyo_path_info
*domainname
; /* This may be NULL */
81 const struct tomoyo_path_info
*program
;
83 bool is_not
; /* True if this entry is "no_initialize_domain". */
84 /* True if the domainname is tomoyo_get_last_name(). */
89 * tomoyo_domain_keeper_entry is a structure which is used for holding
90 * "keep_domain" and "no_keep_domain" entries.
91 * It has following fields.
93 * (1) "list" which is linked to tomoyo_domain_keeper_list .
94 * (2) "domainname" which is "a domainname" or "the last component of a
96 * (3) "program" which is a program's pathname.
97 * This field is NULL if "from" clause is not specified.
98 * (4) "is_deleted" is a bool which is true if marked as deleted, false
100 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
102 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
103 * component of a domainname", false otherwise.
105 struct tomoyo_domain_keeper_entry
{
106 struct list_head list
;
107 const struct tomoyo_path_info
*domainname
;
108 const struct tomoyo_path_info
*program
; /* This may be NULL */
110 bool is_not
; /* True if this entry is "no_keep_domain". */
111 /* True if the domainname is tomoyo_get_last_name(). */
116 * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
117 * It has following fields.
119 * (1) "list" which is linked to tomoyo_alias_list .
120 * (2) "original_name" which is a dereferenced pathname.
121 * (3) "aliased_name" which is a symlink's pathname.
122 * (4) "is_deleted" is a bool which is true if marked as deleted, false
125 struct tomoyo_alias_entry
{
126 struct list_head list
;
127 const struct tomoyo_path_info
*original_name
;
128 const struct tomoyo_path_info
*aliased_name
;
133 * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
135 * @domain: Pointer to "struct tomoyo_domain_info".
136 * @is_delete: True if it is a delete request.
137 * @flags: Flags to set or clear.
141 void tomoyo_set_domain_flag(struct tomoyo_domain_info
*domain
,
142 const bool is_delete
, const u8 flags
)
144 /* We need to serialize because this is bitfield operation. */
145 static DEFINE_SPINLOCK(lock
);
148 domain
->flags
|= flags
;
150 domain
->flags
&= ~flags
;
155 * tomoyo_get_last_name - Get last component of a domainname.
157 * @domain: Pointer to "struct tomoyo_domain_info".
159 * Returns the last component of the domainname.
161 const char *tomoyo_get_last_name(const struct tomoyo_domain_info
*domain
)
163 const char *cp0
= domain
->domainname
->name
;
164 const char *cp1
= strrchr(cp0
, ' ');
172 * tomoyo_domain_initializer_list is used for holding list of programs which
173 * triggers reinitialization of domainname. Normally, a domainname is
174 * monotonically getting longer. But sometimes, we restart daemon programs.
175 * It would be convenient for us that "a daemon started upon system boot" and
176 * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO
177 * provides a way to shorten domainnames.
179 * An entry is added by
181 * # echo 'initialize_domain /usr/sbin/httpd' > \
182 * /sys/kernel/security/tomoyo/exception_policy
186 * # echo 'delete initialize_domain /usr/sbin/httpd' > \
187 * /sys/kernel/security/tomoyo/exception_policy
189 * and all entries are retrieved by
191 * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
193 * In the example above, /usr/sbin/httpd will belong to
194 * "<kernel> /usr/sbin/httpd" domain.
196 * You may specify a domainname using "from" keyword.
197 * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
198 * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd"
199 * domain to belong to "<kernel> /usr/sbin/httpd" domain.
201 * You may add "no_" prefix to "initialize_domain".
202 * "initialize_domain /usr/sbin/httpd" and
203 * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
204 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
205 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
207 static LIST_HEAD(tomoyo_domain_initializer_list
);
210 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
212 * @domainname: The name of domain. May be NULL.
213 * @program: The name of program.
214 * @is_not: True if it is "no_initialize_domain" entry.
215 * @is_delete: True if it is a delete request.
217 * Returns 0 on success, negative value otherwise.
219 * Caller holds tomoyo_read_lock().
221 static int tomoyo_update_domain_initializer_entry(const char *domainname
,
224 const bool is_delete
)
226 struct tomoyo_domain_initializer_entry
*new_entry
;
227 struct tomoyo_domain_initializer_entry
*ptr
;
228 const struct tomoyo_path_info
*saved_program
;
229 const struct tomoyo_path_info
*saved_domainname
= NULL
;
231 bool is_last_name
= false;
233 if (!tomoyo_is_correct_path(program
, 1, -1, -1, __func__
))
234 return -EINVAL
; /* No patterns allowed. */
236 if (!tomoyo_is_domain_def(domainname
) &&
237 tomoyo_is_correct_path(domainname
, 1, -1, -1, __func__
))
239 else if (!tomoyo_is_correct_domain(domainname
, __func__
))
241 saved_domainname
= tomoyo_save_name(domainname
);
242 if (!saved_domainname
)
245 saved_program
= tomoyo_save_name(program
);
248 new_entry
= kmalloc(sizeof(*new_entry
), GFP_KERNEL
);
249 mutex_lock(&tomoyo_policy_lock
);
250 list_for_each_entry_rcu(ptr
, &tomoyo_domain_initializer_list
, list
) {
251 if (ptr
->is_not
!= is_not
||
252 ptr
->domainname
!= saved_domainname
||
253 ptr
->program
!= saved_program
)
255 ptr
->is_deleted
= is_delete
;
263 if (!tomoyo_memory_ok(new_entry
))
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_rcu(&new_entry
->list
, &tomoyo_domain_initializer_list
);
273 mutex_unlock(&tomoyo_policy_lock
);
279 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
281 * @head: Pointer to "struct tomoyo_io_buffer".
283 * Returns true on success, false otherwise.
285 * Caller holds tomoyo_read_lock().
287 bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer
*head
)
289 struct list_head
*pos
;
292 list_for_each_cookie(pos
, head
->read_var2
,
293 &tomoyo_domain_initializer_list
) {
295 const char *from
= "";
296 const char *domain
= "";
297 struct tomoyo_domain_initializer_entry
*ptr
;
298 ptr
= list_entry(pos
, struct tomoyo_domain_initializer_entry
,
302 no
= ptr
->is_not
? "no_" : "";
303 if (ptr
->domainname
) {
305 domain
= ptr
->domainname
->name
;
307 done
= tomoyo_io_printf(head
,
308 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
309 "%s%s%s\n", no
, ptr
->program
->name
,
318 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
320 * @data: String to parse.
321 * @is_not: True if it is "no_initialize_domain" entry.
322 * @is_delete: True if it is a delete request.
324 * Returns 0 on success, negative value otherwise.
326 * Caller holds tomoyo_read_lock().
328 int tomoyo_write_domain_initializer_policy(char *data
, const bool is_not
,
329 const bool is_delete
)
331 char *cp
= strstr(data
, " from ");
335 return tomoyo_update_domain_initializer_entry(cp
+ 6, data
,
339 return tomoyo_update_domain_initializer_entry(NULL
, data
, is_not
,
344 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
346 * @domainname: The name of domain.
347 * @program: The name of program.
348 * @last_name: The last component of @domainname.
350 * Returns true if executing @program reinitializes domain transition,
353 * Caller holds tomoyo_read_lock().
355 static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info
*
357 const struct tomoyo_path_info
*program
,
358 const struct tomoyo_path_info
*
361 struct tomoyo_domain_initializer_entry
*ptr
;
364 list_for_each_entry_rcu(ptr
, &tomoyo_domain_initializer_list
, list
) {
367 if (ptr
->domainname
) {
368 if (!ptr
->is_last_name
) {
369 if (ptr
->domainname
!= domainname
)
372 if (tomoyo_pathcmp(ptr
->domainname
, last_name
))
376 if (tomoyo_pathcmp(ptr
->program
, program
))
388 * tomoyo_domain_keeper_list is used for holding list of domainnames which
389 * suppresses domain transition. Normally, a domainname is monotonically
390 * getting longer. But sometimes, we want to suppress domain transition.
391 * It would be convenient for us that programs executed from a login session
392 * belong to the same domain. Thus, TOMOYO provides a way to suppress domain
395 * An entry is added by
397 * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
398 * /sys/kernel/security/tomoyo/exception_policy
402 * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
403 * /sys/kernel/security/tomoyo/exception_policy
405 * and all entries are retrieved by
407 * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
409 * In the example above, any process which belongs to
410 * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
411 * unless explicitly specified by "initialize_domain" or "no_keep_domain".
413 * You may specify a program using "from" keyword.
414 * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
415 * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
416 * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
418 * You may add "no_" prefix to "keep_domain".
419 * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
420 * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
421 * cause "/usr/bin/passwd" to belong to
422 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
423 * explicitly specified by "initialize_domain".
425 static LIST_HEAD(tomoyo_domain_keeper_list
);
428 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
430 * @domainname: The name of domain.
431 * @program: The name of program. May be NULL.
432 * @is_not: True if it is "no_keep_domain" entry.
433 * @is_delete: True if it is a delete request.
435 * Returns 0 on success, negative value otherwise.
437 * Caller holds tomoyo_read_lock().
439 static int tomoyo_update_domain_keeper_entry(const char *domainname
,
442 const bool is_delete
)
444 struct tomoyo_domain_keeper_entry
*new_entry
;
445 struct tomoyo_domain_keeper_entry
*ptr
;
446 const struct tomoyo_path_info
*saved_domainname
;
447 const struct tomoyo_path_info
*saved_program
= NULL
;
449 bool is_last_name
= false;
451 if (!tomoyo_is_domain_def(domainname
) &&
452 tomoyo_is_correct_path(domainname
, 1, -1, -1, __func__
))
454 else if (!tomoyo_is_correct_domain(domainname
, __func__
))
457 if (!tomoyo_is_correct_path(program
, 1, -1, -1, __func__
))
459 saved_program
= tomoyo_save_name(program
);
463 saved_domainname
= tomoyo_save_name(domainname
);
464 if (!saved_domainname
)
466 new_entry
= kmalloc(sizeof(*new_entry
), GFP_KERNEL
);
467 mutex_lock(&tomoyo_policy_lock
);
468 list_for_each_entry_rcu(ptr
, &tomoyo_domain_keeper_list
, list
) {
469 if (ptr
->is_not
!= is_not
||
470 ptr
->domainname
!= saved_domainname
||
471 ptr
->program
!= saved_program
)
473 ptr
->is_deleted
= is_delete
;
481 if (!tomoyo_memory_ok(new_entry
))
483 new_entry
->domainname
= saved_domainname
;
484 new_entry
->program
= saved_program
;
485 new_entry
->is_not
= is_not
;
486 new_entry
->is_last_name
= is_last_name
;
487 list_add_tail_rcu(&new_entry
->list
, &tomoyo_domain_keeper_list
);
491 mutex_unlock(&tomoyo_policy_lock
);
497 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
499 * @data: String to parse.
500 * @is_not: True if it is "no_keep_domain" entry.
501 * @is_delete: True if it is a delete request.
503 * Caller holds tomoyo_read_lock().
505 int tomoyo_write_domain_keeper_policy(char *data
, const bool is_not
,
506 const bool is_delete
)
508 char *cp
= strstr(data
, " from ");
512 return tomoyo_update_domain_keeper_entry(cp
+ 6, data
, is_not
,
515 return tomoyo_update_domain_keeper_entry(data
, NULL
, is_not
, is_delete
);
519 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
521 * @head: Pointer to "struct tomoyo_io_buffer".
523 * Returns true on success, false otherwise.
525 * Caller holds tomoyo_read_lock().
527 bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer
*head
)
529 struct list_head
*pos
;
532 list_for_each_cookie(pos
, head
->read_var2
,
533 &tomoyo_domain_keeper_list
) {
534 struct tomoyo_domain_keeper_entry
*ptr
;
536 const char *from
= "";
537 const char *program
= "";
539 ptr
= list_entry(pos
, struct tomoyo_domain_keeper_entry
, list
);
542 no
= ptr
->is_not
? "no_" : "";
545 program
= ptr
->program
->name
;
547 done
= tomoyo_io_printf(head
,
548 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
549 "%s%s%s\n", no
, program
, from
,
550 ptr
->domainname
->name
);
558 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
560 * @domainname: The name of domain.
561 * @program: The name of program.
562 * @last_name: The last component of @domainname.
564 * Returns true if executing @program supresses domain transition,
567 * Caller holds tomoyo_read_lock().
569 static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info
*domainname
,
570 const struct tomoyo_path_info
*program
,
571 const struct tomoyo_path_info
*last_name
)
573 struct tomoyo_domain_keeper_entry
*ptr
;
576 list_for_each_entry_rcu(ptr
, &tomoyo_domain_keeper_list
, list
) {
579 if (!ptr
->is_last_name
) {
580 if (ptr
->domainname
!= domainname
)
583 if (tomoyo_pathcmp(ptr
->domainname
, last_name
))
586 if (ptr
->program
&& tomoyo_pathcmp(ptr
->program
, program
))
598 * tomoyo_alias_list is used for holding list of symlink's pathnames which are
599 * allowed to be passed to an execve() request. Normally, the domainname which
600 * the current process will belong to after execve() succeeds is calculated
601 * using dereferenced pathnames. But some programs behave differently depending
602 * on the name passed to argv[0]. For busybox, calculating domainname using
603 * dereferenced pathnames will cause all programs in the busybox to belong to
604 * the same domain. Thus, TOMOYO provides a way to allow use of symlink's
605 * pathname for checking execve()'s permission and calculating domainname which
606 * the current process will belong to after execve() succeeds.
608 * An entry is added by
610 * # echo 'alias /bin/busybox /bin/cat' > \
611 * /sys/kernel/security/tomoyo/exception_policy
615 * # echo 'delete alias /bin/busybox /bin/cat' > \
616 * /sys/kernel/security/tomoyo/exception_policy
618 * and all entries are retrieved by
620 * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
622 * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
623 * of /bin/cat is requested, permission is checked for /bin/cat rather than
624 * /bin/busybox and domainname which the current process will belong to after
625 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
627 static LIST_HEAD(tomoyo_alias_list
);
630 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
632 * @original_name: The original program's real name.
633 * @aliased_name: The symbolic program's symbolic link's name.
634 * @is_delete: True if it is a delete request.
636 * Returns 0 on success, negative value otherwise.
638 * Caller holds tomoyo_read_lock().
640 static int tomoyo_update_alias_entry(const char *original_name
,
641 const char *aliased_name
,
642 const bool is_delete
)
644 struct tomoyo_alias_entry
*new_entry
;
645 struct tomoyo_alias_entry
*ptr
;
646 const struct tomoyo_path_info
*saved_original_name
;
647 const struct tomoyo_path_info
*saved_aliased_name
;
650 if (!tomoyo_is_correct_path(original_name
, 1, -1, -1, __func__
) ||
651 !tomoyo_is_correct_path(aliased_name
, 1, -1, -1, __func__
))
652 return -EINVAL
; /* No patterns allowed. */
653 saved_original_name
= tomoyo_save_name(original_name
);
654 saved_aliased_name
= tomoyo_save_name(aliased_name
);
655 if (!saved_original_name
|| !saved_aliased_name
)
657 new_entry
= kmalloc(sizeof(*new_entry
), GFP_KERNEL
);
658 mutex_lock(&tomoyo_policy_lock
);
659 list_for_each_entry_rcu(ptr
, &tomoyo_alias_list
, list
) {
660 if (ptr
->original_name
!= saved_original_name
||
661 ptr
->aliased_name
!= saved_aliased_name
)
663 ptr
->is_deleted
= is_delete
;
671 if (!tomoyo_memory_ok(new_entry
))
673 new_entry
->original_name
= saved_original_name
;
674 new_entry
->aliased_name
= saved_aliased_name
;
675 list_add_tail_rcu(&new_entry
->list
, &tomoyo_alias_list
);
679 mutex_unlock(&tomoyo_policy_lock
);
685 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
687 * @head: Pointer to "struct tomoyo_io_buffer".
689 * Returns true on success, false otherwise.
691 * Caller holds tomoyo_read_lock().
693 bool tomoyo_read_alias_policy(struct tomoyo_io_buffer
*head
)
695 struct list_head
*pos
;
698 list_for_each_cookie(pos
, head
->read_var2
, &tomoyo_alias_list
) {
699 struct tomoyo_alias_entry
*ptr
;
701 ptr
= list_entry(pos
, struct tomoyo_alias_entry
, list
);
704 done
= tomoyo_io_printf(head
, TOMOYO_KEYWORD_ALIAS
"%s %s\n",
705 ptr
->original_name
->name
,
706 ptr
->aliased_name
->name
);
714 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
716 * @data: String to parse.
717 * @is_delete: True if it is a delete request.
719 * Returns 0 on success, negative value otherwise.
721 * Caller holds tomoyo_read_lock().
723 int tomoyo_write_alias_policy(char *data
, const bool is_delete
)
725 char *cp
= strchr(data
, ' ');
730 return tomoyo_update_alias_entry(data
, cp
, is_delete
);
734 * tomoyo_find_or_assign_new_domain - Create a domain.
736 * @domainname: The name of domain.
737 * @profile: Profile number to assign if the domain was newly created.
739 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
741 * Caller holds tomoyo_read_lock().
743 struct tomoyo_domain_info
*tomoyo_find_or_assign_new_domain(const char *
747 struct tomoyo_domain_info
*domain
;
748 const struct tomoyo_path_info
*saved_domainname
;
750 mutex_lock(&tomoyo_policy_lock
);
751 domain
= tomoyo_find_domain(domainname
);
754 if (!tomoyo_is_correct_domain(domainname
, __func__
))
756 saved_domainname
= tomoyo_save_name(domainname
);
757 if (!saved_domainname
)
759 domain
= kmalloc(sizeof(*domain
), GFP_KERNEL
);
760 if (tomoyo_memory_ok(domain
)) {
761 INIT_LIST_HEAD(&domain
->acl_info_list
);
762 domain
->domainname
= saved_domainname
;
763 domain
->profile
= profile
;
764 list_add_tail_rcu(&domain
->list
, &tomoyo_domain_list
);
771 mutex_unlock(&tomoyo_policy_lock
);
776 * tomoyo_find_next_domain - Find a domain.
778 * @bprm: Pointer to "struct linux_binprm".
780 * Returns 0 on success, negative value otherwise.
782 * Caller holds tomoyo_read_lock().
784 int tomoyo_find_next_domain(struct linux_binprm
*bprm
)
787 * This function assumes that the size of buffer returned by
788 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
790 struct tomoyo_page_buffer
*tmp
= tomoyo_alloc(sizeof(*tmp
));
791 struct tomoyo_domain_info
*old_domain
= tomoyo_domain();
792 struct tomoyo_domain_info
*domain
= NULL
;
793 const char *old_domain_name
= old_domain
->domainname
->name
;
794 const char *original_name
= bprm
->filename
;
795 char *new_domain_name
= NULL
;
796 char *real_program_name
= NULL
;
797 char *symlink_program_name
= NULL
;
798 const u8 mode
= tomoyo_check_flags(old_domain
, TOMOYO_MAC_FOR_FILE
);
799 const bool is_enforce
= (mode
== 3);
800 int retval
= -ENOMEM
;
801 struct tomoyo_path_info r
; /* real name */
802 struct tomoyo_path_info s
; /* symlink name */
803 struct tomoyo_path_info l
; /* last name */
804 static bool initialized
;
811 * Built-in initializers. This is needed because policies are
812 * not loaded until starting /sbin/init.
814 tomoyo_update_domain_initializer_entry(NULL
, "/sbin/hotplug",
816 tomoyo_update_domain_initializer_entry(NULL
, "/sbin/modprobe",
821 /* Get tomoyo_realpath of program. */
823 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
824 real_program_name
= tomoyo_realpath(original_name
);
825 if (!real_program_name
)
827 /* Get tomoyo_realpath of symbolic link. */
828 symlink_program_name
= tomoyo_realpath_nofollow(original_name
);
829 if (!symlink_program_name
)
832 r
.name
= real_program_name
;
833 tomoyo_fill_path_info(&r
);
834 s
.name
= symlink_program_name
;
835 tomoyo_fill_path_info(&s
);
836 l
.name
= tomoyo_get_last_name(old_domain
);
837 tomoyo_fill_path_info(&l
);
839 /* Check 'alias' directive. */
840 if (tomoyo_pathcmp(&r
, &s
)) {
841 struct tomoyo_alias_entry
*ptr
;
842 /* Is this program allowed to be called via symbolic links? */
843 list_for_each_entry_rcu(ptr
, &tomoyo_alias_list
, list
) {
844 if (ptr
->is_deleted
||
845 tomoyo_pathcmp(&r
, ptr
->original_name
) ||
846 tomoyo_pathcmp(&s
, ptr
->aliased_name
))
848 memset(real_program_name
, 0, TOMOYO_MAX_PATHNAME_LEN
);
849 strncpy(real_program_name
, ptr
->aliased_name
->name
,
850 TOMOYO_MAX_PATHNAME_LEN
- 1);
851 tomoyo_fill_path_info(&r
);
856 /* Check execute permission. */
857 retval
= tomoyo_check_exec_perm(old_domain
, &r
);
861 new_domain_name
= tmp
->buffer
;
862 if (tomoyo_is_domain_initializer(old_domain
->domainname
, &r
, &l
)) {
863 /* Transit to the child of tomoyo_kernel_domain domain. */
864 snprintf(new_domain_name
, TOMOYO_MAX_PATHNAME_LEN
+ 1,
865 TOMOYO_ROOT_NAME
" " "%s", real_program_name
);
866 } else if (old_domain
== &tomoyo_kernel_domain
&&
867 !tomoyo_policy_loaded
) {
869 * Needn't to transit from kernel domain before starting
870 * /sbin/init. But transit from kernel domain if executing
871 * initializers because they might start before /sbin/init.
874 } else if (tomoyo_is_domain_keeper(old_domain
->domainname
, &r
, &l
)) {
875 /* Keep current domain. */
878 /* Normal domain transition. */
879 snprintf(new_domain_name
, TOMOYO_MAX_PATHNAME_LEN
+ 1,
880 "%s %s", old_domain_name
, real_program_name
);
882 if (domain
|| strlen(new_domain_name
) >= TOMOYO_MAX_PATHNAME_LEN
)
884 domain
= tomoyo_find_domain(new_domain_name
);
889 domain
= tomoyo_find_or_assign_new_domain(new_domain_name
,
890 old_domain
->profile
);
894 printk(KERN_WARNING
"TOMOYO-ERROR: Domain '%s' not defined.\n",
899 tomoyo_set_domain_flag(old_domain
, false,
900 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED
);
904 bprm
->cred
->security
= domain
;
905 tomoyo_free(real_program_name
);
906 tomoyo_free(symlink_program_name
);