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.c219
1 files changed, 27 insertions, 192 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 1a122974240f..3575b0e7c7fd 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -127,46 +127,12 @@ void tomoyo_check_acl(struct tomoyo_request_info *r,
127 r->granted = false; 127 r->granted = false;
128} 128}
129 129
130/* 130/* The list for "struct tomoyo_domain_info". */
131 * tomoyo_domain_list is used for holding list of domains.
132 * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
133 * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
134 *
135 * An entry is added by
136 *
137 * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
138 * /sys/kernel/security/tomoyo/domain_policy
139 *
140 * and is deleted by
141 *
142 * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
143 * /sys/kernel/security/tomoyo/domain_policy
144 *
145 * and all entries are retrieved by
146 *
147 * # cat /sys/kernel/security/tomoyo/domain_policy
148 *
149 * A domain is added by
150 *
151 * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
152 *
153 * and is deleted by
154 *
155 * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
156 *
157 * and all domains are retrieved by
158 *
159 * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
160 *
161 * Normally, a domainname is monotonically getting longer because a domainname
162 * which the process will belong to if an execve() operation succeeds is
163 * defined as a concatenation of "current domainname" + "pathname passed to
164 * execve()".
165 * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
166 * exceptions.
167 */
168LIST_HEAD(tomoyo_domain_list); 131LIST_HEAD(tomoyo_domain_list);
169 132
133struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
134struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
135
170/** 136/**
171 * tomoyo_get_last_name - Get last component of a domainname. 137 * tomoyo_get_last_name - Get last component of a domainname.
172 * 138 *
@@ -184,44 +150,6 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
184 return cp0; 150 return cp0;
185} 151}
186 152
187/*
188 * tomoyo_domain_initializer_list is used for holding list of programs which
189 * triggers reinitialization of domainname. Normally, a domainname is
190 * monotonically getting longer. But sometimes, we restart daemon programs.
191 * It would be convenient for us that "a daemon started upon system boot" and
192 * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO
193 * provides a way to shorten domainnames.
194 *
195 * An entry is added by
196 *
197 * # echo 'initialize_domain /usr/sbin/httpd' > \
198 * /sys/kernel/security/tomoyo/exception_policy
199 *
200 * and is deleted by
201 *
202 * # echo 'delete initialize_domain /usr/sbin/httpd' > \
203 * /sys/kernel/security/tomoyo/exception_policy
204 *
205 * and all entries are retrieved by
206 *
207 * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
208 *
209 * In the example above, /usr/sbin/httpd will belong to
210 * "<kernel> /usr/sbin/httpd" domain.
211 *
212 * You may specify a domainname using "from" keyword.
213 * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
214 * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd"
215 * domain to belong to "<kernel> /usr/sbin/httpd" domain.
216 *
217 * You may add "no_" prefix to "initialize_domain".
218 * "initialize_domain /usr/sbin/httpd" and
219 * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
220 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
221 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
222 */
223LIST_HEAD(tomoyo_domain_initializer_list);
224
225static bool tomoyo_same_domain_initializer_entry(const struct tomoyo_acl_head * 153static bool tomoyo_same_domain_initializer_entry(const struct tomoyo_acl_head *
226 a, 154 a,
227 const struct tomoyo_acl_head * 155 const struct tomoyo_acl_head *
@@ -272,7 +200,8 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
272 if (!e.program) 200 if (!e.program)
273 goto out; 201 goto out;
274 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 202 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
275 &tomoyo_domain_initializer_list, 203 &tomoyo_policy_list
204 [TOMOYO_ID_DOMAIN_INITIALIZER],
276 tomoyo_same_domain_initializer_entry); 205 tomoyo_same_domain_initializer_entry);
277 out: 206 out:
278 tomoyo_put_name(e.domainname); 207 tomoyo_put_name(e.domainname);
@@ -294,8 +223,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
294 struct list_head *pos; 223 struct list_head *pos;
295 bool done = true; 224 bool done = true;
296 225
297 list_for_each_cookie(pos, head->read_var2, 226 list_for_each_cookie(pos, head->read_var2, &tomoyo_policy_list
298 &tomoyo_domain_initializer_list) { 227 [TOMOYO_ID_DOMAIN_INITIALIZER]) {
299 const char *no; 228 const char *no;
300 const char *from = ""; 229 const char *from = "";
301 const char *domain = ""; 230 const char *domain = "";
@@ -366,8 +295,8 @@ static bool tomoyo_domain_initializer(const struct tomoyo_path_info *
366 struct tomoyo_domain_initializer_entry *ptr; 295 struct tomoyo_domain_initializer_entry *ptr;
367 bool flag = false; 296 bool flag = false;
368 297
369 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, 298 list_for_each_entry_rcu(ptr, &tomoyo_policy_list
370 head.list) { 299 [TOMOYO_ID_DOMAIN_INITIALIZER], head.list) {
371 if (ptr->head.is_deleted) 300 if (ptr->head.is_deleted)
372 continue; 301 continue;
373 if (ptr->domainname) { 302 if (ptr->domainname) {
@@ -390,46 +319,6 @@ static bool tomoyo_domain_initializer(const struct tomoyo_path_info *
390 return flag; 319 return flag;
391} 320}
392 321
393/*
394 * tomoyo_domain_keeper_list is used for holding list of domainnames which
395 * suppresses domain transition. Normally, a domainname is monotonically
396 * getting longer. But sometimes, we want to suppress domain transition.
397 * It would be convenient for us that programs executed from a login session
398 * belong to the same domain. Thus, TOMOYO provides a way to suppress domain
399 * transition.
400 *
401 * An entry is added by
402 *
403 * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
404 * /sys/kernel/security/tomoyo/exception_policy
405 *
406 * and is deleted by
407 *
408 * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
409 * /sys/kernel/security/tomoyo/exception_policy
410 *
411 * and all entries are retrieved by
412 *
413 * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
414 *
415 * In the example above, any process which belongs to
416 * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
417 * unless explicitly specified by "initialize_domain" or "no_keep_domain".
418 *
419 * You may specify a program using "from" keyword.
420 * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
421 * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
422 * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
423 *
424 * You may add "no_" prefix to "keep_domain".
425 * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
426 * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
427 * cause "/usr/bin/passwd" to belong to
428 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
429 * explicitly specified by "initialize_domain".
430 */
431LIST_HEAD(tomoyo_domain_keeper_list);
432
433static bool tomoyo_same_domain_keeper_entry(const struct tomoyo_acl_head *a, 322static bool tomoyo_same_domain_keeper_entry(const struct tomoyo_acl_head *a,
434 const struct tomoyo_acl_head *b) 323 const struct tomoyo_acl_head *b)
435{ 324{
@@ -478,7 +367,8 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
478 if (!e.domainname) 367 if (!e.domainname)
479 goto out; 368 goto out;
480 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 369 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
481 &tomoyo_domain_keeper_list, 370 &tomoyo_policy_list
371 [TOMOYO_ID_DOMAIN_KEEPER],
482 tomoyo_same_domain_keeper_entry); 372 tomoyo_same_domain_keeper_entry);
483 out: 373 out:
484 tomoyo_put_name(e.domainname); 374 tomoyo_put_name(e.domainname);
@@ -523,7 +413,7 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
523 bool done = true; 413 bool done = true;
524 414
525 list_for_each_cookie(pos, head->read_var2, 415 list_for_each_cookie(pos, head->read_var2,
526 &tomoyo_domain_keeper_list) { 416 &tomoyo_policy_list[TOMOYO_ID_DOMAIN_KEEPER]) {
527 struct tomoyo_domain_keeper_entry *ptr; 417 struct tomoyo_domain_keeper_entry *ptr;
528 const char *no; 418 const char *no;
529 const char *from = ""; 419 const char *from = "";
@@ -567,7 +457,9 @@ static bool tomoyo_domain_keeper(const struct tomoyo_path_info *domainname,
567 struct tomoyo_domain_keeper_entry *ptr; 457 struct tomoyo_domain_keeper_entry *ptr;
568 bool flag = false; 458 bool flag = false;
569 459
570 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, head.list) { 460 list_for_each_entry_rcu(ptr,
461 &tomoyo_policy_list[TOMOYO_ID_DOMAIN_KEEPER],
462 head.list) {
571 if (ptr->head.is_deleted) 463 if (ptr->head.is_deleted)
572 continue; 464 continue;
573 if (!ptr->is_last_name) { 465 if (!ptr->is_last_name) {
@@ -588,35 +480,6 @@ static bool tomoyo_domain_keeper(const struct tomoyo_path_info *domainname,
588 return flag; 480 return flag;
589} 481}
590 482
591/*
592 * tomoyo_aggregator_list is used for holding list of rewrite table for
593 * execve() request. Some programs provides similar functionality. This keyword
594 * allows users to aggregate such programs.
595 *
596 * Entries are added by
597 *
598 * # echo 'aggregator /usr/bin/vi /./editor' > \
599 * /sys/kernel/security/tomoyo/exception_policy
600 * # echo 'aggregator /usr/bin/emacs /./editor' > \
601 * /sys/kernel/security/tomoyo/exception_policy
602 *
603 * and are deleted by
604 *
605 * # echo 'delete aggregator /usr/bin/vi /./editor' > \
606 * /sys/kernel/security/tomoyo/exception_policy
607 * # echo 'delete aggregator /usr/bin/emacs /./editor' > \
608 * /sys/kernel/security/tomoyo/exception_policy
609 *
610 * and all entries are retrieved by
611 *
612 * # grep ^aggregator /sys/kernel/security/tomoyo/exception_policy
613 *
614 * In the example above, if /usr/bin/vi or /usr/bin/emacs are executed,
615 * permission is checked for /./editor and domainname which the current process
616 * will belong to after execve() succeeds is calculated using /./editor .
617 */
618LIST_HEAD(tomoyo_aggregator_list);
619
620static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a, 483static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a,
621 const struct tomoyo_acl_head *b) 484 const struct tomoyo_acl_head *b)
622{ 485{
@@ -655,7 +518,7 @@ static int tomoyo_update_aggregator_entry(const char *original_name,
655 e.aggregated_name->is_patterned) /* No patterns allowed. */ 518 e.aggregated_name->is_patterned) /* No patterns allowed. */
656 goto out; 519 goto out;
657 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 520 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
658 &tomoyo_aggregator_list, 521 &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR],
659 tomoyo_same_aggregator_entry); 522 tomoyo_same_aggregator_entry);
660 out: 523 out:
661 tomoyo_put_name(e.original_name); 524 tomoyo_put_name(e.original_name);
@@ -677,7 +540,8 @@ bool tomoyo_read_aggregator_policy(struct tomoyo_io_buffer *head)
677 struct list_head *pos; 540 struct list_head *pos;
678 bool done = true; 541 bool done = true;
679 542
680 list_for_each_cookie(pos, head->read_var2, &tomoyo_aggregator_list) { 543 list_for_each_cookie(pos, head->read_var2,
544 &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR]) {
681 struct tomoyo_aggregator_entry *ptr; 545 struct tomoyo_aggregator_entry *ptr;
682 546
683 ptr = list_entry(pos, struct tomoyo_aggregator_entry, 547 ptr = list_entry(pos, struct tomoyo_aggregator_entry,
@@ -713,38 +577,6 @@ int tomoyo_write_aggregator_policy(char *data, const bool is_delete)
713 return tomoyo_update_aggregator_entry(data, cp, is_delete); 577 return tomoyo_update_aggregator_entry(data, cp, is_delete);
714} 578}
715 579
716/*
717 * tomoyo_alias_list is used for holding list of symlink's pathnames which are
718 * allowed to be passed to an execve() request. Normally, the domainname which
719 * the current process will belong to after execve() succeeds is calculated
720 * using dereferenced pathnames. But some programs behave differently depending
721 * on the name passed to argv[0]. For busybox, calculating domainname using
722 * dereferenced pathnames will cause all programs in the busybox to belong to
723 * the same domain. Thus, TOMOYO provides a way to allow use of symlink's
724 * pathname for checking execve()'s permission and calculating domainname which
725 * the current process will belong to after execve() succeeds.
726 *
727 * An entry is added by
728 *
729 * # echo 'alias /bin/busybox /bin/cat' > \
730 * /sys/kernel/security/tomoyo/exception_policy
731 *
732 * and is deleted by
733 *
734 * # echo 'delete alias /bin/busybox /bin/cat' > \
735 * /sys/kernel/security/tomoyo/exception_policy
736 *
737 * and all entries are retrieved by
738 *
739 * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
740 *
741 * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
742 * of /bin/cat is requested, permission is checked for /bin/cat rather than
743 * /bin/busybox and domainname which the current process will belong to after
744 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
745 */
746LIST_HEAD(tomoyo_alias_list);
747
748static bool tomoyo_same_alias_entry(const struct tomoyo_acl_head *a, 580static bool tomoyo_same_alias_entry(const struct tomoyo_acl_head *a,
749 const struct tomoyo_acl_head *b) 581 const struct tomoyo_acl_head *b)
750{ 582{
@@ -783,7 +615,7 @@ static int tomoyo_update_alias_entry(const char *original_name,
783 e.original_name->is_patterned || e.aliased_name->is_patterned) 615 e.original_name->is_patterned || e.aliased_name->is_patterned)
784 goto out; /* No patterns allowed. */ 616 goto out; /* No patterns allowed. */
785 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 617 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
786 &tomoyo_alias_list, 618 &tomoyo_policy_list[TOMOYO_ID_ALIAS],
787 tomoyo_same_alias_entry); 619 tomoyo_same_alias_entry);
788 out: 620 out:
789 tomoyo_put_name(e.original_name); 621 tomoyo_put_name(e.original_name);
@@ -805,7 +637,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
805 struct list_head *pos; 637 struct list_head *pos;
806 bool done = true; 638 bool done = true;
807 639
808 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { 640 list_for_each_cookie(pos, head->read_var2,
641 &tomoyo_policy_list[TOMOYO_ID_ALIAS]) {
809 struct tomoyo_alias_entry *ptr; 642 struct tomoyo_alias_entry *ptr;
810 643
811 ptr = list_entry(pos, struct tomoyo_alias_entry, head.list); 644 ptr = list_entry(pos, struct tomoyo_alias_entry, head.list);
@@ -946,7 +779,9 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
946 if (tomoyo_pathcmp(&rn, &sn)) { 779 if (tomoyo_pathcmp(&rn, &sn)) {
947 struct tomoyo_alias_entry *ptr; 780 struct tomoyo_alias_entry *ptr;
948 /* Is this program allowed to be called via symbolic links? */ 781 /* Is this program allowed to be called via symbolic links? */
949 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, head.list) { 782 list_for_each_entry_rcu(ptr,
783 &tomoyo_policy_list[TOMOYO_ID_ALIAS],
784 head.list) {
950 if (ptr->head.is_deleted || 785 if (ptr->head.is_deleted ||
951 tomoyo_pathcmp(&rn, ptr->original_name) || 786 tomoyo_pathcmp(&rn, ptr->original_name) ||
952 tomoyo_pathcmp(&sn, ptr->aliased_name)) 787 tomoyo_pathcmp(&sn, ptr->aliased_name))
@@ -962,8 +797,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
962 /* Check 'aggregator' directive. */ 797 /* Check 'aggregator' directive. */
963 { 798 {
964 struct tomoyo_aggregator_entry *ptr; 799 struct tomoyo_aggregator_entry *ptr;
965 list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, 800 list_for_each_entry_rcu(ptr, &tomoyo_policy_list
966 head.list) { 801 [TOMOYO_ID_AGGREGATOR], head.list) {
967 if (ptr->head.is_deleted || 802 if (ptr->head.is_deleted ||
968 !tomoyo_path_matches_pattern(&rn, 803 !tomoyo_path_matches_pattern(&rn,
969 ptr->original_name)) 804 ptr->original_name))