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