xref: /linux/security/tomoyo/domain.c (revision b3b77c8caef1750ebeea1054e39e358550ea9f55)
1 /*
2  * security/tomoyo/domain.c
3  *
4  * Implementation of the Domain-Based Mandatory Access Control.
5  *
6  * Copyright (C) 2005-2009  NTT DATA CORPORATION
7  *
8  * Version: 2.2.0   2009/04/01
9  *
10  */
11 
12 #include "common.h"
13 #include <linux/binfmts.h>
14 #include <linux/slab.h>
15 
16 /* Variables definitions.*/
17 
18 /* The initial domain. */
19 struct tomoyo_domain_info tomoyo_kernel_domain;
20 
21 /*
22  * tomoyo_domain_list is used for holding list of domains.
23  * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
24  * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
25  *
26  * An entry is added by
27  *
28  * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
29  *                                  /sys/kernel/security/tomoyo/domain_policy
30  *
31  * and is deleted by
32  *
33  * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
34  *                                  /sys/kernel/security/tomoyo/domain_policy
35  *
36  * and all entries are retrieved by
37  *
38  * # cat /sys/kernel/security/tomoyo/domain_policy
39  *
40  * A domain is added by
41  *
42  * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
43  *
44  * and is deleted by
45  *
46  * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
47  *
48  * and all domains are retrieved by
49  *
50  * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
51  *
52  * Normally, a domainname is monotonically getting longer because a domainname
53  * which the process will belong to if an execve() operation succeeds is
54  * defined as a concatenation of "current domainname" + "pathname passed to
55  * execve()".
56  * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
57  * exceptions.
58  */
59 LIST_HEAD(tomoyo_domain_list);
60 
61 /**
62  * tomoyo_get_last_name - Get last component of a domainname.
63  *
64  * @domain: Pointer to "struct tomoyo_domain_info".
65  *
66  * Returns the last component of the domainname.
67  */
68 const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
69 {
70 	const char *cp0 = domain->domainname->name;
71 	const char *cp1 = strrchr(cp0, ' ');
72 
73 	if (cp1)
74 		return cp1 + 1;
75 	return cp0;
76 }
77 
78 /*
79  * tomoyo_domain_initializer_list is used for holding list of programs which
80  * triggers reinitialization of domainname. Normally, a domainname is
81  * monotonically getting longer. But sometimes, we restart daemon programs.
82  * It would be convenient for us that "a daemon started upon system boot" and
83  * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO
84  * provides a way to shorten domainnames.
85  *
86  * An entry is added by
87  *
88  * # echo 'initialize_domain /usr/sbin/httpd' > \
89  *                               /sys/kernel/security/tomoyo/exception_policy
90  *
91  * and is deleted by
92  *
93  * # echo 'delete initialize_domain /usr/sbin/httpd' > \
94  *                               /sys/kernel/security/tomoyo/exception_policy
95  *
96  * and all entries are retrieved by
97  *
98  * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
99  *
100  * In the example above, /usr/sbin/httpd will belong to
101  * "<kernel> /usr/sbin/httpd" domain.
102  *
103  * You may specify a domainname using "from" keyword.
104  * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
105  * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd"
106  * domain to belong to "<kernel> /usr/sbin/httpd" domain.
107  *
108  * You may add "no_" prefix to "initialize_domain".
109  * "initialize_domain /usr/sbin/httpd" and
110  * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
111  * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
112  * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
113  */
114 LIST_HEAD(tomoyo_domain_initializer_list);
115 
116 /**
117  * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
118  *
119  * @domainname: The name of domain. May be NULL.
120  * @program:    The name of program.
121  * @is_not:     True if it is "no_initialize_domain" entry.
122  * @is_delete:  True if it is a delete request.
123  *
124  * Returns 0 on success, negative value otherwise.
125  *
126  * Caller holds tomoyo_read_lock().
127  */
128 static int tomoyo_update_domain_initializer_entry(const char *domainname,
129 						  const char *program,
130 						  const bool is_not,
131 						  const bool is_delete)
132 {
133 	struct tomoyo_domain_initializer_entry *ptr;
134 	struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
135 	int error = is_delete ? -ENOENT : -ENOMEM;
136 
137 	if (!tomoyo_is_correct_path(program, 1, -1, -1))
138 		return -EINVAL; /* No patterns allowed. */
139 	if (domainname) {
140 		if (!tomoyo_is_domain_def(domainname) &&
141 		    tomoyo_is_correct_path(domainname, 1, -1, -1))
142 			e.is_last_name = true;
143 		else if (!tomoyo_is_correct_domain(domainname))
144 			return -EINVAL;
145 		e.domainname = tomoyo_get_name(domainname);
146 		if (!e.domainname)
147 			goto out;
148 	}
149 	e.program = tomoyo_get_name(program);
150 	if (!e.program)
151 		goto out;
152 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
153 		goto out;
154 	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
155 		if (!tomoyo_is_same_domain_initializer_entry(ptr, &e))
156 			continue;
157 		ptr->is_deleted = is_delete;
158 		error = 0;
159 		break;
160 	}
161 	if (!is_delete && error) {
162 		struct tomoyo_domain_initializer_entry *entry =
163 			tomoyo_commit_ok(&e, sizeof(e));
164 		if (entry) {
165 			list_add_tail_rcu(&entry->list,
166 					  &tomoyo_domain_initializer_list);
167 			error = 0;
168 		}
169 	}
170 	mutex_unlock(&tomoyo_policy_lock);
171  out:
172 	tomoyo_put_name(e.domainname);
173 	tomoyo_put_name(e.program);
174 	return error;
175 }
176 
177 /**
178  * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
179  *
180  * @head: Pointer to "struct tomoyo_io_buffer".
181  *
182  * Returns true on success, false otherwise.
183  *
184  * Caller holds tomoyo_read_lock().
185  */
186 bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
187 {
188 	struct list_head *pos;
189 	bool done = true;
190 
191 	list_for_each_cookie(pos, head->read_var2,
192 			     &tomoyo_domain_initializer_list) {
193 		const char *no;
194 		const char *from = "";
195 		const char *domain = "";
196 		struct tomoyo_domain_initializer_entry *ptr;
197 		ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
198 				  list);
199 		if (ptr->is_deleted)
200 			continue;
201 		no = ptr->is_not ? "no_" : "";
202 		if (ptr->domainname) {
203 			from = " from ";
204 			domain = ptr->domainname->name;
205 		}
206 		done = tomoyo_io_printf(head,
207 					"%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
208 					"%s%s%s\n", no, ptr->program->name,
209 					from, domain);
210 		if (!done)
211 			break;
212 	}
213 	return done;
214 }
215 
216 /**
217  * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
218  *
219  * @data:      String to parse.
220  * @is_not:    True if it is "no_initialize_domain" entry.
221  * @is_delete: True if it is a delete request.
222  *
223  * Returns 0 on success, negative value otherwise.
224  *
225  * Caller holds tomoyo_read_lock().
226  */
227 int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
228 					   const bool is_delete)
229 {
230 	char *cp = strstr(data, " from ");
231 
232 	if (cp) {
233 		*cp = '\0';
234 		return tomoyo_update_domain_initializer_entry(cp + 6, data,
235 							      is_not,
236 							      is_delete);
237 	}
238 	return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
239 						      is_delete);
240 }
241 
242 /**
243  * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
244  *
245  * @domainname: The name of domain.
246  * @program:    The name of program.
247  * @last_name:  The last component of @domainname.
248  *
249  * Returns true if executing @program reinitializes domain transition,
250  * false otherwise.
251  *
252  * Caller holds tomoyo_read_lock().
253  */
254 static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
255 					 domainname,
256 					 const struct tomoyo_path_info *program,
257 					 const struct tomoyo_path_info *
258 					 last_name)
259 {
260 	struct tomoyo_domain_initializer_entry *ptr;
261 	bool flag = false;
262 
263 	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
264 		if (ptr->is_deleted)
265 			continue;
266 		if (ptr->domainname) {
267 			if (!ptr->is_last_name) {
268 				if (ptr->domainname != domainname)
269 					continue;
270 			} else {
271 				if (tomoyo_pathcmp(ptr->domainname, last_name))
272 					continue;
273 			}
274 		}
275 		if (tomoyo_pathcmp(ptr->program, program))
276 			continue;
277 		if (ptr->is_not) {
278 			flag = false;
279 			break;
280 		}
281 		flag = true;
282 	}
283 	return flag;
284 }
285 
286 /*
287  * tomoyo_domain_keeper_list is used for holding list of domainnames which
288  * suppresses domain transition. Normally, a domainname is monotonically
289  * getting longer. But sometimes, we want to suppress domain transition.
290  * It would be convenient for us that programs executed from a login session
291  * belong to the same domain. Thus, TOMOYO provides a way to suppress domain
292  * transition.
293  *
294  * An entry is added by
295  *
296  * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
297  *                              /sys/kernel/security/tomoyo/exception_policy
298  *
299  * and is deleted by
300  *
301  * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
302  *                              /sys/kernel/security/tomoyo/exception_policy
303  *
304  * and all entries are retrieved by
305  *
306  * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
307  *
308  * In the example above, any process which belongs to
309  * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
310  * unless explicitly specified by "initialize_domain" or "no_keep_domain".
311  *
312  * You may specify a program using "from" keyword.
313  * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
314  * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
315  * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
316  *
317  * You may add "no_" prefix to "keep_domain".
318  * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
319  * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
320  * cause "/usr/bin/passwd" to belong to
321  * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
322  * explicitly specified by "initialize_domain".
323  */
324 LIST_HEAD(tomoyo_domain_keeper_list);
325 
326 /**
327  * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
328  *
329  * @domainname: The name of domain.
330  * @program:    The name of program. May be NULL.
331  * @is_not:     True if it is "no_keep_domain" entry.
332  * @is_delete:  True if it is a delete request.
333  *
334  * Returns 0 on success, negative value otherwise.
335  *
336  * Caller holds tomoyo_read_lock().
337  */
338 static int tomoyo_update_domain_keeper_entry(const char *domainname,
339 					     const char *program,
340 					     const bool is_not,
341 					     const bool is_delete)
342 {
343 	struct tomoyo_domain_keeper_entry *ptr;
344 	struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
345 	int error = is_delete ? -ENOENT : -ENOMEM;
346 
347 	if (!tomoyo_is_domain_def(domainname) &&
348 	    tomoyo_is_correct_path(domainname, 1, -1, -1))
349 		e.is_last_name = true;
350 	else if (!tomoyo_is_correct_domain(domainname))
351 		return -EINVAL;
352 	if (program) {
353 		if (!tomoyo_is_correct_path(program, 1, -1, -1))
354 			return -EINVAL;
355 		e.program = tomoyo_get_name(program);
356 		if (!e.program)
357 			goto out;
358 	}
359 	e.domainname = tomoyo_get_name(domainname);
360 	if (!e.domainname)
361 		goto out;
362 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
363 		goto out;
364 	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
365 		if (!tomoyo_is_same_domain_keeper_entry(ptr, &e))
366 			continue;
367 		ptr->is_deleted = is_delete;
368 		error = 0;
369 		break;
370 	}
371 	if (!is_delete && error) {
372 		struct tomoyo_domain_keeper_entry *entry =
373 			tomoyo_commit_ok(&e, sizeof(e));
374 		if (entry) {
375 			list_add_tail_rcu(&entry->list,
376 					  &tomoyo_domain_keeper_list);
377 			error = 0;
378 		}
379 	}
380 	mutex_unlock(&tomoyo_policy_lock);
381  out:
382 	tomoyo_put_name(e.domainname);
383 	tomoyo_put_name(e.program);
384 	return error;
385 }
386 
387 /**
388  * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
389  *
390  * @data:      String to parse.
391  * @is_not:    True if it is "no_keep_domain" entry.
392  * @is_delete: True if it is a delete request.
393  *
394  * Caller holds tomoyo_read_lock().
395  */
396 int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
397 				      const bool is_delete)
398 {
399 	char *cp = strstr(data, " from ");
400 
401 	if (cp) {
402 		*cp = '\0';
403 		return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
404 							 is_delete);
405 	}
406 	return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
407 }
408 
409 /**
410  * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
411  *
412  * @head: Pointer to "struct tomoyo_io_buffer".
413  *
414  * Returns true on success, false otherwise.
415  *
416  * Caller holds tomoyo_read_lock().
417  */
418 bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
419 {
420 	struct list_head *pos;
421 	bool done = true;
422 
423 	list_for_each_cookie(pos, head->read_var2,
424 			     &tomoyo_domain_keeper_list) {
425 		struct tomoyo_domain_keeper_entry *ptr;
426 		const char *no;
427 		const char *from = "";
428 		const char *program = "";
429 
430 		ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list);
431 		if (ptr->is_deleted)
432 			continue;
433 		no = ptr->is_not ? "no_" : "";
434 		if (ptr->program) {
435 			from = " from ";
436 			program = ptr->program->name;
437 		}
438 		done = tomoyo_io_printf(head,
439 					"%s" TOMOYO_KEYWORD_KEEP_DOMAIN
440 					"%s%s%s\n", no, program, from,
441 					ptr->domainname->name);
442 		if (!done)
443 			break;
444 	}
445 	return done;
446 }
447 
448 /**
449  * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
450  *
451  * @domainname: The name of domain.
452  * @program:    The name of program.
453  * @last_name:  The last component of @domainname.
454  *
455  * Returns true if executing @program supresses domain transition,
456  * false otherwise.
457  *
458  * Caller holds tomoyo_read_lock().
459  */
460 static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
461 				    const struct tomoyo_path_info *program,
462 				    const struct tomoyo_path_info *last_name)
463 {
464 	struct tomoyo_domain_keeper_entry *ptr;
465 	bool flag = false;
466 
467 	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
468 		if (ptr->is_deleted)
469 			continue;
470 		if (!ptr->is_last_name) {
471 			if (ptr->domainname != domainname)
472 				continue;
473 		} else {
474 			if (tomoyo_pathcmp(ptr->domainname, last_name))
475 				continue;
476 		}
477 		if (ptr->program && tomoyo_pathcmp(ptr->program, program))
478 			continue;
479 		if (ptr->is_not) {
480 			flag = false;
481 			break;
482 		}
483 		flag = true;
484 	}
485 	return flag;
486 }
487 
488 /*
489  * tomoyo_alias_list is used for holding list of symlink's pathnames which are
490  * allowed to be passed to an execve() request. Normally, the domainname which
491  * the current process will belong to after execve() succeeds is calculated
492  * using dereferenced pathnames. But some programs behave differently depending
493  * on the name passed to argv[0]. For busybox, calculating domainname using
494  * dereferenced pathnames will cause all programs in the busybox to belong to
495  * the same domain. Thus, TOMOYO provides a way to allow use of symlink's
496  * pathname for checking execve()'s permission and calculating domainname which
497  * the current process will belong to after execve() succeeds.
498  *
499  * An entry is added by
500  *
501  * # echo 'alias /bin/busybox /bin/cat' > \
502  *                            /sys/kernel/security/tomoyo/exception_policy
503  *
504  * and is deleted by
505  *
506  * # echo 'delete alias /bin/busybox /bin/cat' > \
507  *                            /sys/kernel/security/tomoyo/exception_policy
508  *
509  * and all entries are retrieved by
510  *
511  * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
512  *
513  * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
514  * of /bin/cat is requested, permission is checked for /bin/cat rather than
515  * /bin/busybox and domainname which the current process will belong to after
516  * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
517  */
518 LIST_HEAD(tomoyo_alias_list);
519 
520 /**
521  * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
522  *
523  * @original_name: The original program's real name.
524  * @aliased_name:  The symbolic program's symbolic link's name.
525  * @is_delete:     True if it is a delete request.
526  *
527  * Returns 0 on success, negative value otherwise.
528  *
529  * Caller holds tomoyo_read_lock().
530  */
531 static int tomoyo_update_alias_entry(const char *original_name,
532 				     const char *aliased_name,
533 				     const bool is_delete)
534 {
535 	struct tomoyo_alias_entry *ptr;
536 	struct tomoyo_alias_entry e = { };
537 	int error = is_delete ? -ENOENT : -ENOMEM;
538 
539 	if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
540 	    !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
541 		return -EINVAL; /* No patterns allowed. */
542 	e.original_name = tomoyo_get_name(original_name);
543 	e.aliased_name = tomoyo_get_name(aliased_name);
544 	if (!e.original_name || !e.aliased_name)
545 		goto out;
546 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
547 		goto out;
548 	list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
549 		if (!tomoyo_is_same_alias_entry(ptr, &e))
550 			continue;
551 		ptr->is_deleted = is_delete;
552 		error = 0;
553 		break;
554 	}
555 	if (!is_delete && error) {
556 		struct tomoyo_alias_entry *entry =
557 			tomoyo_commit_ok(&e, sizeof(e));
558 		if (entry) {
559 			list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
560 			error = 0;
561 		}
562 	}
563 	mutex_unlock(&tomoyo_policy_lock);
564  out:
565 	tomoyo_put_name(e.original_name);
566 	tomoyo_put_name(e.aliased_name);
567 	return error;
568 }
569 
570 /**
571  * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
572  *
573  * @head: Pointer to "struct tomoyo_io_buffer".
574  *
575  * Returns true on success, false otherwise.
576  *
577  * Caller holds tomoyo_read_lock().
578  */
579 bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
580 {
581 	struct list_head *pos;
582 	bool done = true;
583 
584 	list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
585 		struct tomoyo_alias_entry *ptr;
586 
587 		ptr = list_entry(pos, struct tomoyo_alias_entry, list);
588 		if (ptr->is_deleted)
589 			continue;
590 		done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
591 					ptr->original_name->name,
592 					ptr->aliased_name->name);
593 		if (!done)
594 			break;
595 	}
596 	return done;
597 }
598 
599 /**
600  * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
601  *
602  * @data:      String to parse.
603  * @is_delete: True if it is a delete request.
604  *
605  * Returns 0 on success, negative value otherwise.
606  *
607  * Caller holds tomoyo_read_lock().
608  */
609 int tomoyo_write_alias_policy(char *data, const bool is_delete)
610 {
611 	char *cp = strchr(data, ' ');
612 
613 	if (!cp)
614 		return -EINVAL;
615 	*cp++ = '\0';
616 	return tomoyo_update_alias_entry(data, cp, is_delete);
617 }
618 
619 /**
620  * tomoyo_find_or_assign_new_domain - Create a domain.
621  *
622  * @domainname: The name of domain.
623  * @profile:    Profile number to assign if the domain was newly created.
624  *
625  * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
626  *
627  * Caller holds tomoyo_read_lock().
628  */
629 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
630 							    domainname,
631 							    const u8 profile)
632 {
633 	struct tomoyo_domain_info *entry;
634 	struct tomoyo_domain_info *domain = NULL;
635 	const struct tomoyo_path_info *saved_domainname;
636 	bool found = false;
637 
638 	if (!tomoyo_is_correct_domain(domainname))
639 		return NULL;
640 	saved_domainname = tomoyo_get_name(domainname);
641 	if (!saved_domainname)
642 		return NULL;
643 	entry = kzalloc(sizeof(*entry), GFP_NOFS);
644 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
645 		goto out;
646 	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
647 		if (domain->is_deleted ||
648 		    tomoyo_pathcmp(saved_domainname, domain->domainname))
649 			continue;
650 		found = true;
651 		break;
652 	}
653 	if (!found && tomoyo_memory_ok(entry)) {
654 		INIT_LIST_HEAD(&entry->acl_info_list);
655 		entry->domainname = saved_domainname;
656 		saved_domainname = NULL;
657 		entry->profile = profile;
658 		list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
659 		domain = entry;
660 		entry = NULL;
661 		found = true;
662 	}
663 	mutex_unlock(&tomoyo_policy_lock);
664  out:
665 	tomoyo_put_name(saved_domainname);
666 	kfree(entry);
667 	return found ? domain : NULL;
668 }
669 
670 /**
671  * tomoyo_find_next_domain - Find a domain.
672  *
673  * @bprm: Pointer to "struct linux_binprm".
674  *
675  * Returns 0 on success, negative value otherwise.
676  *
677  * Caller holds tomoyo_read_lock().
678  */
679 int tomoyo_find_next_domain(struct linux_binprm *bprm)
680 {
681 	/*
682 	 * This function assumes that the size of buffer returned by
683 	 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
684 	 */
685 	struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_NOFS);
686 	struct tomoyo_domain_info *old_domain = tomoyo_domain();
687 	struct tomoyo_domain_info *domain = NULL;
688 	const char *old_domain_name = old_domain->domainname->name;
689 	const char *original_name = bprm->filename;
690 	char *new_domain_name = NULL;
691 	char *real_program_name = NULL;
692 	char *symlink_program_name = NULL;
693 	const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
694 	const bool is_enforce = (mode == 3);
695 	int retval = -ENOMEM;
696 	struct tomoyo_path_info r; /* real name */
697 	struct tomoyo_path_info s; /* symlink name */
698 	struct tomoyo_path_info l; /* last name */
699 	static bool initialized;
700 
701 	if (!tmp)
702 		goto out;
703 
704 	if (!initialized) {
705 		/*
706 		 * Built-in initializers. This is needed because policies are
707 		 * not loaded until starting /sbin/init.
708 		 */
709 		tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug",
710 						       false, false);
711 		tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe",
712 						       false, false);
713 		initialized = true;
714 	}
715 
716 	/* Get tomoyo_realpath of program. */
717 	retval = -ENOENT;
718 	/* I hope tomoyo_realpath() won't fail with -ENOMEM. */
719 	real_program_name = tomoyo_realpath(original_name);
720 	if (!real_program_name)
721 		goto out;
722 	/* Get tomoyo_realpath of symbolic link. */
723 	symlink_program_name = tomoyo_realpath_nofollow(original_name);
724 	if (!symlink_program_name)
725 		goto out;
726 
727 	r.name = real_program_name;
728 	tomoyo_fill_path_info(&r);
729 	s.name = symlink_program_name;
730 	tomoyo_fill_path_info(&s);
731 	l.name = tomoyo_get_last_name(old_domain);
732 	tomoyo_fill_path_info(&l);
733 
734 	/* Check 'alias' directive. */
735 	if (tomoyo_pathcmp(&r, &s)) {
736 		struct tomoyo_alias_entry *ptr;
737 		/* Is this program allowed to be called via symbolic links? */
738 		list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
739 			if (ptr->is_deleted ||
740 			    tomoyo_pathcmp(&r, ptr->original_name) ||
741 			    tomoyo_pathcmp(&s, ptr->aliased_name))
742 				continue;
743 			memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
744 			strncpy(real_program_name, ptr->aliased_name->name,
745 				TOMOYO_MAX_PATHNAME_LEN - 1);
746 			tomoyo_fill_path_info(&r);
747 			break;
748 		}
749 	}
750 
751 	/* Check execute permission. */
752 	retval = tomoyo_check_exec_perm(old_domain, &r);
753 	if (retval < 0)
754 		goto out;
755 
756 	new_domain_name = tmp->buffer;
757 	if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
758 		/* Transit to the child of tomoyo_kernel_domain domain. */
759 		snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
760 			 TOMOYO_ROOT_NAME " " "%s", real_program_name);
761 	} else if (old_domain == &tomoyo_kernel_domain &&
762 		   !tomoyo_policy_loaded) {
763 		/*
764 		 * Needn't to transit from kernel domain before starting
765 		 * /sbin/init. But transit from kernel domain if executing
766 		 * initializers because they might start before /sbin/init.
767 		 */
768 		domain = old_domain;
769 	} else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
770 		/* Keep current domain. */
771 		domain = old_domain;
772 	} else {
773 		/* Normal domain transition. */
774 		snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
775 			 "%s %s", old_domain_name, real_program_name);
776 	}
777 	if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
778 		goto done;
779 	domain = tomoyo_find_domain(new_domain_name);
780 	if (domain)
781 		goto done;
782 	if (is_enforce)
783 		goto done;
784 	domain = tomoyo_find_or_assign_new_domain(new_domain_name,
785 						  old_domain->profile);
786  done:
787 	if (domain)
788 		goto out;
789 	printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
790 	       new_domain_name);
791 	if (is_enforce)
792 		retval = -EPERM;
793 	else
794 		old_domain->transition_failed = true;
795  out:
796 	if (!domain)
797 		domain = old_domain;
798 	/* Update reference count on "struct tomoyo_domain_info". */
799 	atomic_inc(&domain->users);
800 	bprm->cred->security = domain;
801 	kfree(real_program_name);
802 	kfree(symlink_program_name);
803 	kfree(tmp);
804 	return retval;
805 }
806