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;
22 /* The list for "struct tomoyo_domain_info". */
23 LIST_HEAD(tomoyo_domain_list);
24 DECLARE_RWSEM(tomoyo_domain_list_lock);
26 /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */
27 struct tomoyo_domain_initializer_entry {
28 struct list_head list;
29 const struct tomoyo_path_info *domainname; /* This may be NULL */
30 const struct tomoyo_path_info *program;
32 bool is_not; /* True if this entry is "no_initialize_domain". */
33 /* True if the domainname is tomoyo_get_last_name(). */
37 /* Structure for "keep_domain" and "no_keep_domain" keyword. */
38 struct tomoyo_domain_keeper_entry {
39 struct list_head list;
40 const struct tomoyo_path_info *domainname;
41 const struct tomoyo_path_info *program; /* This may be NULL */
43 bool is_not; /* True if this entry is "no_keep_domain". */
44 /* True if the domainname is tomoyo_get_last_name(). */
48 /* Structure for "alias" keyword. */
49 struct tomoyo_alias_entry {
50 struct list_head list;
51 const struct tomoyo_path_info *original_name;
52 const struct tomoyo_path_info *aliased_name;
57 * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
59 * @domain: Pointer to "struct tomoyo_domain_info".
60 * @is_delete: True if it is a delete request.
61 * @flags: Flags to set or clear.
65 void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
66 const bool is_delete, const u8 flags)
68 /* We need to serialize because this is bitfield operation. */
69 static DEFINE_SPINLOCK(lock);
72 domain->flags |= flags;
74 domain->flags &= ~flags;
79 * tomoyo_get_last_name - Get last component of a domainname.
81 * @domain: Pointer to "struct tomoyo_domain_info".
83 * Returns the last component of the domainname.
85 const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
87 const char *cp0 = domain->domainname->name;
88 const char *cp1 = strrchr(cp0, ' ');
95 /* The list for "struct tomoyo_domain_initializer_entry". */
96 static LIST_HEAD(tomoyo_domain_initializer_list);
97 static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
100 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
102 * @domainname: The name of domain. May be NULL.
103 * @program: The name of program.
104 * @is_not: True if it is "no_initialize_domain" entry.
105 * @is_delete: True if it is a delete request.
107 * Returns 0 on success, negative value otherwise.
109 static int tomoyo_update_domain_initializer_entry(const char *domainname,
112 const bool is_delete)
114 struct tomoyo_domain_initializer_entry *new_entry;
115 struct tomoyo_domain_initializer_entry *ptr;
116 const struct tomoyo_path_info *saved_program;
117 const struct tomoyo_path_info *saved_domainname = NULL;
119 bool is_last_name = false;
121 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
122 return -EINVAL; /* No patterns allowed. */
124 if (!tomoyo_is_domain_def(domainname) &&
125 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
127 else if (!tomoyo_is_correct_domain(domainname, __func__))
129 saved_domainname = tomoyo_save_name(domainname);
130 if (!saved_domainname)
133 saved_program = tomoyo_save_name(program);
136 down_write(&tomoyo_domain_initializer_list_lock);
137 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
138 if (ptr->is_not != is_not ||
139 ptr->domainname != saved_domainname ||
140 ptr->program != saved_program)
142 ptr->is_deleted = is_delete;
150 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
153 new_entry->domainname = saved_domainname;
154 new_entry->program = saved_program;
155 new_entry->is_not = is_not;
156 new_entry->is_last_name = is_last_name;
157 list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
160 up_write(&tomoyo_domain_initializer_list_lock);
165 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
167 * @head: Pointer to "struct tomoyo_io_buffer".
169 * Returns true on success, false otherwise.
171 bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
173 struct list_head *pos;
176 down_read(&tomoyo_domain_initializer_list_lock);
177 list_for_each_cookie(pos, head->read_var2,
178 &tomoyo_domain_initializer_list) {
180 const char *from = "";
181 const char *domain = "";
182 struct tomoyo_domain_initializer_entry *ptr;
183 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
187 no = ptr->is_not ? "no_" : "";
188 if (ptr->domainname) {
190 domain = ptr->domainname->name;
192 if (!tomoyo_io_printf(head,
193 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
194 "%s%s%s\n", no, ptr->program->name, from,
200 up_read(&tomoyo_domain_initializer_list_lock);
205 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
207 * @data: String to parse.
208 * @is_not: True if it is "no_initialize_domain" entry.
209 * @is_delete: True if it is a delete request.
211 * Returns 0 on success, negative value otherwise.
213 int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
214 const bool is_delete)
216 char *cp = strstr(data, " from ");
220 return tomoyo_update_domain_initializer_entry(cp + 6, data,
224 return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
229 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
231 * @domainname: The name of domain.
232 * @program: The name of program.
233 * @last_name: The last component of @domainname.
235 * Returns true if executing @program reinitializes domain transition,
238 static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
240 const struct tomoyo_path_info *program,
241 const struct tomoyo_path_info *
244 struct tomoyo_domain_initializer_entry *ptr;
247 down_read(&tomoyo_domain_initializer_list_lock);
248 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
251 if (ptr->domainname) {
252 if (!ptr->is_last_name) {
253 if (ptr->domainname != domainname)
256 if (tomoyo_pathcmp(ptr->domainname, last_name))
260 if (tomoyo_pathcmp(ptr->program, program))
268 up_read(&tomoyo_domain_initializer_list_lock);
272 /* The list for "struct tomoyo_domain_keeper_entry". */
273 static LIST_HEAD(tomoyo_domain_keeper_list);
274 static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
277 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
279 * @domainname: The name of domain.
280 * @program: The name of program. May be NULL.
281 * @is_not: True if it is "no_keep_domain" entry.
282 * @is_delete: True if it is a delete request.
284 * Returns 0 on success, negative value otherwise.
286 static int tomoyo_update_domain_keeper_entry(const char *domainname,
289 const bool is_delete)
291 struct tomoyo_domain_keeper_entry *new_entry;
292 struct tomoyo_domain_keeper_entry *ptr;
293 const struct tomoyo_path_info *saved_domainname;
294 const struct tomoyo_path_info *saved_program = NULL;
296 bool is_last_name = false;
298 if (!tomoyo_is_domain_def(domainname) &&
299 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__))
301 else if (!tomoyo_is_correct_domain(domainname, __func__))
304 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
306 saved_program = tomoyo_save_name(program);
310 saved_domainname = tomoyo_save_name(domainname);
311 if (!saved_domainname)
313 down_write(&tomoyo_domain_keeper_list_lock);
314 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
315 if (ptr->is_not != is_not ||
316 ptr->domainname != saved_domainname ||
317 ptr->program != saved_program)
319 ptr->is_deleted = is_delete;
327 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
330 new_entry->domainname = saved_domainname;
331 new_entry->program = saved_program;
332 new_entry->is_not = is_not;
333 new_entry->is_last_name = is_last_name;
334 list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
337 up_write(&tomoyo_domain_keeper_list_lock);
342 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
344 * @data: String to parse.
345 * @is_not: True if it is "no_keep_domain" entry.
346 * @is_delete: True if it is a delete request.
349 int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
350 const bool is_delete)
352 char *cp = strstr(data, " from ");
356 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
359 return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
363 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
365 * @head: Pointer to "struct tomoyo_io_buffer".
367 * Returns true on success, false otherwise.
369 bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
371 struct list_head *pos;
374 down_read(&tomoyo_domain_keeper_list_lock);
375 list_for_each_cookie(pos, head->read_var2,
376 &tomoyo_domain_keeper_list) {
377 struct tomoyo_domain_keeper_entry *ptr;
379 const char *from = "";
380 const char *program = "";
382 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
385 no = ptr->is_not ? "no_" : "";
388 program = ptr->program->name;
390 if (!tomoyo_io_printf(head,
391 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN
392 "%s%s%s\n", no, program, from,
393 ptr->domainname->name)) {
398 up_read(&tomoyo_domain_keeper_list_lock);
403 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
405 * @domainname: The name of domain.
406 * @program: The name of program.
407 * @last_name: The last component of @domainname.
409 * Returns true if executing @program supresses domain transition,
412 static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
413 const struct tomoyo_path_info *program,
414 const struct tomoyo_path_info *last_name)
416 struct tomoyo_domain_keeper_entry *ptr;
419 down_read(&tomoyo_domain_keeper_list_lock);
420 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
423 if (!ptr->is_last_name) {
424 if (ptr->domainname != domainname)
427 if (tomoyo_pathcmp(ptr->domainname, last_name))
430 if (ptr->program && tomoyo_pathcmp(ptr->program, program))
438 up_read(&tomoyo_domain_keeper_list_lock);
442 /* The list for "struct tomoyo_alias_entry". */
443 static LIST_HEAD(tomoyo_alias_list);
444 static DECLARE_RWSEM(tomoyo_alias_list_lock);
447 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
449 * @original_name: The original program's real name.
450 * @aliased_name: The symbolic program's symbolic link's name.
451 * @is_delete: True if it is a delete request.
453 * Returns 0 on success, negative value otherwise.
455 static int tomoyo_update_alias_entry(const char *original_name,
456 const char *aliased_name,
457 const bool is_delete)
459 struct tomoyo_alias_entry *new_entry;
460 struct tomoyo_alias_entry *ptr;
461 const struct tomoyo_path_info *saved_original_name;
462 const struct tomoyo_path_info *saved_aliased_name;
465 if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
466 !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
467 return -EINVAL; /* No patterns allowed. */
468 saved_original_name = tomoyo_save_name(original_name);
469 saved_aliased_name = tomoyo_save_name(aliased_name);
470 if (!saved_original_name || !saved_aliased_name)
472 down_write(&tomoyo_alias_list_lock);
473 list_for_each_entry(ptr, &tomoyo_alias_list, list) {
474 if (ptr->original_name != saved_original_name ||
475 ptr->aliased_name != saved_aliased_name)
477 ptr->is_deleted = is_delete;
485 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
488 new_entry->original_name = saved_original_name;
489 new_entry->aliased_name = saved_aliased_name;
490 list_add_tail(&new_entry->list, &tomoyo_alias_list);
493 up_write(&tomoyo_alias_list_lock);
498 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
500 * @head: Pointer to "struct tomoyo_io_buffer".
502 * Returns true on success, false otherwise.
504 bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
506 struct list_head *pos;
509 down_read(&tomoyo_alias_list_lock);
510 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
511 struct tomoyo_alias_entry *ptr;
513 ptr = list_entry(pos, struct tomoyo_alias_entry, list);
516 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
517 ptr->original_name->name,
518 ptr->aliased_name->name)) {
523 up_read(&tomoyo_alias_list_lock);
528 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
530 * @data: String to parse.
531 * @is_delete: True if it is a delete request.
533 * Returns 0 on success, negative value otherwise.
535 int tomoyo_write_alias_policy(char *data, const bool is_delete)
537 char *cp = strchr(data, ' ');
542 return tomoyo_update_alias_entry(data, cp, is_delete);
545 /* Domain create/delete handler. */
548 * tomoyo_delete_domain - Delete a domain.
550 * @domainname: The name of domain.
554 int tomoyo_delete_domain(char *domainname)
556 struct tomoyo_domain_info *domain;
557 struct tomoyo_path_info name;
559 name.name = domainname;
560 tomoyo_fill_path_info(&name);
561 down_write(&tomoyo_domain_list_lock);
562 /* Is there an active domain? */
563 list_for_each_entry(domain, &tomoyo_domain_list, list) {
564 /* Never delete tomoyo_kernel_domain */
565 if (domain == &tomoyo_kernel_domain)
567 if (domain->is_deleted ||
568 tomoyo_pathcmp(domain->domainname, &name))
570 domain->is_deleted = true;
573 up_write(&tomoyo_domain_list_lock);
578 * tomoyo_find_or_assign_new_domain - Create a domain.
580 * @domainname: The name of domain.
581 * @profile: Profile number to assign if the domain was newly created.
583 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
585 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
589 struct tomoyo_domain_info *domain = NULL;
590 const struct tomoyo_path_info *saved_domainname;
592 down_write(&tomoyo_domain_list_lock);
593 domain = tomoyo_find_domain(domainname);
596 if (!tomoyo_is_correct_domain(domainname, __func__))
598 saved_domainname = tomoyo_save_name(domainname);
599 if (!saved_domainname)
601 /* Can I reuse memory of deleted domain? */
602 list_for_each_entry(domain, &tomoyo_domain_list, list) {
603 struct task_struct *p;
604 struct tomoyo_acl_info *ptr;
606 if (!domain->is_deleted ||
607 domain->domainname != saved_domainname)
610 read_lock(&tasklist_lock);
611 for_each_process(p) {
612 if (tomoyo_real_domain(p) != domain)
617 read_unlock(&tasklist_lock);
620 list_for_each_entry(ptr, &domain->acl_info_list, list) {
621 ptr->type |= TOMOYO_ACL_DELETED;
623 tomoyo_set_domain_flag(domain, true, domain->flags);
624 domain->profile = profile;
625 domain->quota_warned = false;
626 mb(); /* Avoid out-of-order execution. */
627 domain->is_deleted = false;
630 /* No memory reusable. Create using new memory. */
631 domain = tomoyo_alloc_element(sizeof(*domain));
633 INIT_LIST_HEAD(&domain->acl_info_list);
634 domain->domainname = saved_domainname;
635 domain->profile = profile;
636 list_add_tail(&domain->list, &tomoyo_domain_list);
639 up_write(&tomoyo_domain_list_lock);
644 * tomoyo_find_next_domain - Find a domain.
646 * @bprm: Pointer to "struct linux_binprm".
647 * @next_domain: Pointer to pointer to "struct tomoyo_domain_info".
649 * Returns 0 on success, negative value otherwise.
651 int tomoyo_find_next_domain(struct linux_binprm *bprm,
652 struct tomoyo_domain_info **next_domain)
655 * This function assumes that the size of buffer returned by
656 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
658 struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp));
659 struct tomoyo_domain_info *old_domain = tomoyo_domain();
660 struct tomoyo_domain_info *domain = NULL;
661 const char *old_domain_name = old_domain->domainname->name;
662 const char *original_name = bprm->filename;
663 char *new_domain_name = NULL;
664 char *real_program_name = NULL;
665 char *symlink_program_name = NULL;
666 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
667 const bool is_enforce = (mode == 3);
668 int retval = -ENOMEM;
669 struct tomoyo_path_info r; /* real name */
670 struct tomoyo_path_info s; /* symlink name */
671 struct tomoyo_path_info l; /* last name */
672 static bool initialized;
679 * Built-in initializers. This is needed because policies are
680 * not loaded until starting /sbin/init.
682 tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
684 tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
689 /* Get tomoyo_realpath of program. */
691 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
692 real_program_name = tomoyo_realpath(original_name);
693 if (!real_program_name)
695 /* Get tomoyo_realpath of symbolic link. */
696 symlink_program_name = tomoyo_realpath_nofollow(original_name);
697 if (!symlink_program_name)
700 r.name = real_program_name;
701 tomoyo_fill_path_info(&r);
702 s.name = symlink_program_name;
703 tomoyo_fill_path_info(&s);
704 l.name = tomoyo_get_last_name(old_domain);
705 tomoyo_fill_path_info(&l);
707 /* Check 'alias' directive. */
708 if (tomoyo_pathcmp(&r, &s)) {
709 struct tomoyo_alias_entry *ptr;
710 /* Is this program allowed to be called via symbolic links? */
711 down_read(&tomoyo_alias_list_lock);
712 list_for_each_entry(ptr, &tomoyo_alias_list, list) {
713 if (ptr->is_deleted ||
714 tomoyo_pathcmp(&r, ptr->original_name) ||
715 tomoyo_pathcmp(&s, ptr->aliased_name))
717 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
718 strncpy(real_program_name, ptr->aliased_name->name,
719 TOMOYO_MAX_PATHNAME_LEN - 1);
720 tomoyo_fill_path_info(&r);
723 up_read(&tomoyo_alias_list_lock);
726 /* Check execute permission. */
727 retval = tomoyo_check_exec_perm(old_domain, &r, tmp);
731 new_domain_name = tmp->buffer;
732 if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
733 /* Transit to the child of tomoyo_kernel_domain domain. */
734 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
735 TOMOYO_ROOT_NAME " " "%s", real_program_name);
736 } else if (old_domain == &tomoyo_kernel_domain &&
737 !tomoyo_policy_loaded) {
739 * Needn't to transit from kernel domain before starting
740 * /sbin/init. But transit from kernel domain if executing
741 * initializers because they might start before /sbin/init.
744 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
745 /* Keep current domain. */
748 /* Normal domain transition. */
749 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
750 "%s %s", old_domain_name, real_program_name);
752 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
754 down_read(&tomoyo_domain_list_lock);
755 domain = tomoyo_find_domain(new_domain_name);
756 up_read(&tomoyo_domain_list_lock);
761 domain = tomoyo_find_or_assign_new_domain(new_domain_name,
762 old_domain->profile);
766 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
771 tomoyo_set_domain_flag(old_domain, false,
772 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
774 tomoyo_free(real_program_name);
775 tomoyo_free(symlink_program_name);
776 *next_domain = domain ? domain : old_domain;