domain.c revision 05336dee9f5a23c042e5938b42f996dd35e31ee6
1/*
2 * security/tomoyo/domain.c
3 *
4 * Domain transition functions for TOMOYO.
5 *
6 * Copyright (C) 2005-2010  NTT DATA CORPORATION
7 */
8
9#include "common.h"
10#include <linux/binfmts.h>
11#include <linux/slab.h>
12
13/* Variables definitions.*/
14
15/* The initial domain. */
16struct tomoyo_domain_info tomoyo_kernel_domain;
17
18/**
19 * tomoyo_update_policy - Update an entry for exception policy.
20 *
21 * @new_entry:       Pointer to "struct tomoyo_acl_info".
22 * @size:            Size of @new_entry in bytes.
23 * @is_delete:       True if it is a delete request.
24 * @list:            Pointer to "struct list_head".
25 * @check_duplicate: Callback function to find duplicated entry.
26 *
27 * Returns 0 on success, negative value otherwise.
28 *
29 * Caller holds tomoyo_read_lock().
30 */
31int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
32			 bool is_delete, struct list_head *list,
33			 bool (*check_duplicate) (const struct tomoyo_acl_head
34						  *,
35						  const struct tomoyo_acl_head
36						  *))
37{
38	int error = is_delete ? -ENOENT : -ENOMEM;
39	struct tomoyo_acl_head *entry;
40
41	if (mutex_lock_interruptible(&tomoyo_policy_lock))
42		return -ENOMEM;
43	list_for_each_entry_rcu(entry, list, list) {
44		if (!check_duplicate(entry, new_entry))
45			continue;
46		entry->is_deleted = is_delete;
47		error = 0;
48		break;
49	}
50	if (error && !is_delete) {
51		entry = tomoyo_commit_ok(new_entry, size);
52		if (entry) {
53			list_add_tail_rcu(&entry->list, list);
54			error = 0;
55		}
56	}
57	mutex_unlock(&tomoyo_policy_lock);
58	return error;
59}
60
61/**
62 * tomoyo_update_domain - Update an entry for domain policy.
63 *
64 * @new_entry:       Pointer to "struct tomoyo_acl_info".
65 * @size:            Size of @new_entry in bytes.
66 * @is_delete:       True if it is a delete request.
67 * @domain:          Pointer to "struct tomoyo_domain_info".
68 * @check_duplicate: Callback function to find duplicated entry.
69 * @merge_duplicate: Callback function to merge duplicated entry.
70 *
71 * Returns 0 on success, negative value otherwise.
72 *
73 * Caller holds tomoyo_read_lock().
74 */
75int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
76			 bool is_delete, struct tomoyo_domain_info *domain,
77			 bool (*check_duplicate) (const struct tomoyo_acl_info
78						  *,
79						  const struct tomoyo_acl_info
80						  *),
81			 bool (*merge_duplicate) (struct tomoyo_acl_info *,
82						  struct tomoyo_acl_info *,
83						  const bool))
84{
85	int error = is_delete ? -ENOENT : -ENOMEM;
86	struct tomoyo_acl_info *entry;
87
88	if (mutex_lock_interruptible(&tomoyo_policy_lock))
89		return error;
90	list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
91		if (!check_duplicate(entry, new_entry))
92			continue;
93		if (merge_duplicate)
94			entry->is_deleted = merge_duplicate(entry, new_entry,
95							    is_delete);
96		else
97			entry->is_deleted = is_delete;
98		error = 0;
99		break;
100	}
101	if (error && !is_delete) {
102		entry = tomoyo_commit_ok(new_entry, size);
103		if (entry) {
104			list_add_tail_rcu(&entry->list, &domain->acl_info_list);
105			error = 0;
106		}
107	}
108	mutex_unlock(&tomoyo_policy_lock);
109	return error;
110}
111
112/*
113 * tomoyo_domain_list is used for holding list of domains.
114 * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
115 * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
116 *
117 * An entry is added by
118 *
119 * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \
120 *                                  /sys/kernel/security/tomoyo/domain_policy
121 *
122 * and is deleted by
123 *
124 * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \
125 *                                  /sys/kernel/security/tomoyo/domain_policy
126 *
127 * and all entries are retrieved by
128 *
129 * # cat /sys/kernel/security/tomoyo/domain_policy
130 *
131 * A domain is added by
132 *
133 * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy
134 *
135 * and is deleted by
136 *
137 * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy
138 *
139 * and all domains are retrieved by
140 *
141 * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy
142 *
143 * Normally, a domainname is monotonically getting longer because a domainname
144 * which the process will belong to if an execve() operation succeeds is
145 * defined as a concatenation of "current domainname" + "pathname passed to
146 * execve()".
147 * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for
148 * exceptions.
149 */
150LIST_HEAD(tomoyo_domain_list);
151
152/**
153 * tomoyo_get_last_name - Get last component of a domainname.
154 *
155 * @domain: Pointer to "struct tomoyo_domain_info".
156 *
157 * Returns the last component of the domainname.
158 */
159const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
160{
161	const char *cp0 = domain->domainname->name;
162	const char *cp1 = strrchr(cp0, ' ');
163
164	if (cp1)
165		return cp1 + 1;
166	return cp0;
167}
168
169/*
170 * tomoyo_domain_initializer_list is used for holding list of programs which
171 * triggers reinitialization of domainname. Normally, a domainname is
172 * monotonically getting longer. But sometimes, we restart daemon programs.
173 * It would be convenient for us that "a daemon started upon system boot" and
174 * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO
175 * provides a way to shorten domainnames.
176 *
177 * An entry is added by
178 *
179 * # echo 'initialize_domain /usr/sbin/httpd' > \
180 *                               /sys/kernel/security/tomoyo/exception_policy
181 *
182 * and is deleted by
183 *
184 * # echo 'delete initialize_domain /usr/sbin/httpd' > \
185 *                               /sys/kernel/security/tomoyo/exception_policy
186 *
187 * and all entries are retrieved by
188 *
189 * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy
190 *
191 * In the example above, /usr/sbin/httpd will belong to
192 * "<kernel> /usr/sbin/httpd" domain.
193 *
194 * You may specify a domainname using "from" keyword.
195 * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
196 * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd"
197 * domain to belong to "<kernel> /usr/sbin/httpd" domain.
198 *
199 * You may add "no_" prefix to "initialize_domain".
200 * "initialize_domain /usr/sbin/httpd" and
201 * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd"
202 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
203 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
204 */
205LIST_HEAD(tomoyo_domain_initializer_list);
206
207static bool tomoyo_same_domain_initializer_entry(const struct tomoyo_acl_head *
208						 a,
209						 const struct tomoyo_acl_head *
210						 b)
211{
212	const struct tomoyo_domain_initializer_entry *p1 =
213		container_of(a, typeof(*p1), head);
214	const struct tomoyo_domain_initializer_entry *p2 =
215		container_of(b, typeof(*p2), head);
216	return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
217		&& p1->domainname == p2->domainname
218		&& p1->program == p2->program;
219}
220
221/**
222 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
223 *
224 * @domainname: The name of domain. May be NULL.
225 * @program:    The name of program.
226 * @is_not:     True if it is "no_initialize_domain" entry.
227 * @is_delete:  True if it is a delete request.
228 *
229 * Returns 0 on success, negative value otherwise.
230 *
231 * Caller holds tomoyo_read_lock().
232 */
233static int tomoyo_update_domain_initializer_entry(const char *domainname,
234						  const char *program,
235						  const bool is_not,
236						  const bool is_delete)
237{
238	struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
239	int error = is_delete ? -ENOENT : -ENOMEM;
240
241	if (!tomoyo_is_correct_path(program))
242		return -EINVAL;
243	if (domainname) {
244		if (!tomoyo_is_domain_def(domainname) &&
245		    tomoyo_is_correct_path(domainname))
246			e.is_last_name = true;
247		else if (!tomoyo_is_correct_domain(domainname))
248			return -EINVAL;
249		e.domainname = tomoyo_get_name(domainname);
250		if (!e.domainname)
251			goto out;
252	}
253	e.program = tomoyo_get_name(program);
254	if (!e.program)
255		goto out;
256	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
257				     &tomoyo_domain_initializer_list,
258				     tomoyo_same_domain_initializer_entry);
259 out:
260	tomoyo_put_name(e.domainname);
261	tomoyo_put_name(e.program);
262	return error;
263}
264
265/**
266 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
267 *
268 * @head: Pointer to "struct tomoyo_io_buffer".
269 *
270 * Returns true on success, false otherwise.
271 *
272 * Caller holds tomoyo_read_lock().
273 */
274bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
275{
276	struct list_head *pos;
277	bool done = true;
278
279	list_for_each_cookie(pos, head->read_var2,
280			     &tomoyo_domain_initializer_list) {
281		const char *no;
282		const char *from = "";
283		const char *domain = "";
284		struct tomoyo_domain_initializer_entry *ptr;
285		ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
286				 head.list);
287		if (ptr->head.is_deleted)
288			continue;
289		no = ptr->is_not ? "no_" : "";
290		if (ptr->domainname) {
291			from = " from ";
292			domain = ptr->domainname->name;
293		}
294		done = tomoyo_io_printf(head,
295					"%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
296					"%s%s%s\n", no, ptr->program->name,
297					from, domain);
298		if (!done)
299			break;
300	}
301	return done;
302}
303
304/**
305 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
306 *
307 * @data:      String to parse.
308 * @is_not:    True if it is "no_initialize_domain" entry.
309 * @is_delete: True if it is a delete request.
310 *
311 * Returns 0 on success, negative value otherwise.
312 *
313 * Caller holds tomoyo_read_lock().
314 */
315int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
316					   const bool is_delete)
317{
318	char *cp = strstr(data, " from ");
319
320	if (cp) {
321		*cp = '\0';
322		return tomoyo_update_domain_initializer_entry(cp + 6, data,
323							      is_not,
324							      is_delete);
325	}
326	return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
327						      is_delete);
328}
329
330/**
331 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization.
332 *
333 * @domainname: The name of domain.
334 * @program:    The name of program.
335 * @last_name:  The last component of @domainname.
336 *
337 * Returns true if executing @program reinitializes domain transition,
338 * false otherwise.
339 *
340 * Caller holds tomoyo_read_lock().
341 */
342static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
343					 domainname,
344					 const struct tomoyo_path_info *program,
345					 const struct tomoyo_path_info *
346					 last_name)
347{
348	struct tomoyo_domain_initializer_entry *ptr;
349	bool flag = false;
350
351	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list,
352				head.list) {
353		if (ptr->head.is_deleted)
354			continue;
355		if (ptr->domainname) {
356			if (!ptr->is_last_name) {
357				if (ptr->domainname != domainname)
358					continue;
359			} else {
360				if (tomoyo_pathcmp(ptr->domainname, last_name))
361					continue;
362			}
363		}
364		if (tomoyo_pathcmp(ptr->program, program))
365			continue;
366		if (ptr->is_not) {
367			flag = false;
368			break;
369		}
370		flag = true;
371	}
372	return flag;
373}
374
375/*
376 * tomoyo_domain_keeper_list is used for holding list of domainnames which
377 * suppresses domain transition. Normally, a domainname is monotonically
378 * getting longer. But sometimes, we want to suppress domain transition.
379 * It would be convenient for us that programs executed from a login session
380 * belong to the same domain. Thus, TOMOYO provides a way to suppress domain
381 * transition.
382 *
383 * An entry is added by
384 *
385 * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
386 *                              /sys/kernel/security/tomoyo/exception_policy
387 *
388 * and is deleted by
389 *
390 * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \
391 *                              /sys/kernel/security/tomoyo/exception_policy
392 *
393 * and all entries are retrieved by
394 *
395 * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy
396 *
397 * In the example above, any process which belongs to
398 * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain,
399 * unless explicitly specified by "initialize_domain" or "no_keep_domain".
400 *
401 * You may specify a program using "from" keyword.
402 * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash"
403 * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash"
404 * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain.
405 *
406 * You may add "no_" prefix to "keep_domain".
407 * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and
408 * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will
409 * cause "/usr/bin/passwd" to belong to
410 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
411 * explicitly specified by "initialize_domain".
412 */
413LIST_HEAD(tomoyo_domain_keeper_list);
414
415static bool tomoyo_same_domain_keeper_entry(const struct tomoyo_acl_head *a,
416					    const struct tomoyo_acl_head *b)
417{
418	const struct tomoyo_domain_keeper_entry *p1 =
419		container_of(a, typeof(*p1), head);
420	const struct tomoyo_domain_keeper_entry *p2 =
421		container_of(b, typeof(*p2), head);
422	return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
423		&& p1->domainname == p2->domainname
424		&& p1->program == p2->program;
425}
426
427/**
428 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
429 *
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.
434 *
435 * Returns 0 on success, negative value otherwise.
436 *
437 * Caller holds tomoyo_read_lock().
438 */
439static int tomoyo_update_domain_keeper_entry(const char *domainname,
440					     const char *program,
441					     const bool is_not,
442					     const bool is_delete)
443{
444	struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
445	int error = is_delete ? -ENOENT : -ENOMEM;
446
447	if (!tomoyo_is_domain_def(domainname) &&
448	    tomoyo_is_correct_path(domainname))
449		e.is_last_name = true;
450	else if (!tomoyo_is_correct_domain(domainname))
451		return -EINVAL;
452	if (program) {
453		if (!tomoyo_is_correct_path(program))
454			return -EINVAL;
455		e.program = tomoyo_get_name(program);
456		if (!e.program)
457			goto out;
458	}
459	e.domainname = tomoyo_get_name(domainname);
460	if (!e.domainname)
461		goto out;
462	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
463				     &tomoyo_domain_keeper_list,
464				     tomoyo_same_domain_keeper_entry);
465 out:
466	tomoyo_put_name(e.domainname);
467	tomoyo_put_name(e.program);
468	return error;
469}
470
471/**
472 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
473 *
474 * @data:      String to parse.
475 * @is_not:    True if it is "no_keep_domain" entry.
476 * @is_delete: True if it is a delete request.
477 *
478 * Caller holds tomoyo_read_lock().
479 */
480int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
481				      const bool is_delete)
482{
483	char *cp = strstr(data, " from ");
484
485	if (cp) {
486		*cp = '\0';
487		return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
488							 is_delete);
489	}
490	return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
491}
492
493/**
494 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
495 *
496 * @head: Pointer to "struct tomoyo_io_buffer".
497 *
498 * Returns true on success, false otherwise.
499 *
500 * Caller holds tomoyo_read_lock().
501 */
502bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
503{
504	struct list_head *pos;
505	bool done = true;
506
507	list_for_each_cookie(pos, head->read_var2,
508			     &tomoyo_domain_keeper_list) {
509		struct tomoyo_domain_keeper_entry *ptr;
510		const char *no;
511		const char *from = "";
512		const char *program = "";
513
514		ptr = list_entry(pos, struct tomoyo_domain_keeper_entry,
515				 head.list);
516		if (ptr->head.is_deleted)
517			continue;
518		no = ptr->is_not ? "no_" : "";
519		if (ptr->program) {
520			from = " from ";
521			program = ptr->program->name;
522		}
523		done = tomoyo_io_printf(head,
524					"%s" TOMOYO_KEYWORD_KEEP_DOMAIN
525					"%s%s%s\n", no, program, from,
526					ptr->domainname->name);
527		if (!done)
528			break;
529	}
530	return done;
531}
532
533/**
534 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression.
535 *
536 * @domainname: The name of domain.
537 * @program:    The name of program.
538 * @last_name:  The last component of @domainname.
539 *
540 * Returns true if executing @program supresses domain transition,
541 * false otherwise.
542 *
543 * Caller holds tomoyo_read_lock().
544 */
545static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
546				    const struct tomoyo_path_info *program,
547				    const struct tomoyo_path_info *last_name)
548{
549	struct tomoyo_domain_keeper_entry *ptr;
550	bool flag = false;
551
552	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, head.list) {
553		if (ptr->head.is_deleted)
554			continue;
555		if (!ptr->is_last_name) {
556			if (ptr->domainname != domainname)
557				continue;
558		} else {
559			if (tomoyo_pathcmp(ptr->domainname, last_name))
560				continue;
561		}
562		if (ptr->program && tomoyo_pathcmp(ptr->program, program))
563			continue;
564		if (ptr->is_not) {
565			flag = false;
566			break;
567		}
568		flag = true;
569	}
570	return flag;
571}
572
573/*
574 * tomoyo_aggregator_list is used for holding list of rewrite table for
575 * execve() request. Some programs provides similar functionality. This keyword
576 * allows users to aggregate such programs.
577 *
578 * Entries are added by
579 *
580 * # echo 'aggregator /usr/bin/vi /./editor' > \
581 *                            /sys/kernel/security/tomoyo/exception_policy
582 * # echo 'aggregator /usr/bin/emacs /./editor' > \
583 *                            /sys/kernel/security/tomoyo/exception_policy
584 *
585 * and are deleted by
586 *
587 * # echo 'delete aggregator /usr/bin/vi /./editor' > \
588 *                            /sys/kernel/security/tomoyo/exception_policy
589 * # echo 'delete aggregator /usr/bin/emacs /./editor' > \
590 *                            /sys/kernel/security/tomoyo/exception_policy
591 *
592 * and all entries are retrieved by
593 *
594 * # grep ^aggregator /sys/kernel/security/tomoyo/exception_policy
595 *
596 * In the example above, if /usr/bin/vi or /usr/bin/emacs are executed,
597 * permission is checked for /./editor and domainname which the current process
598 * will belong to after execve() succeeds is calculated using /./editor .
599 */
600LIST_HEAD(tomoyo_aggregator_list);
601
602static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a,
603					 const struct tomoyo_acl_head *b)
604{
605	const struct tomoyo_aggregator_entry *p1 = container_of(a, typeof(*p1),
606								head);
607	const struct tomoyo_aggregator_entry *p2 = container_of(b, typeof(*p2),
608								head);
609	return p1->original_name == p2->original_name &&
610		p1->aggregated_name == p2->aggregated_name;
611}
612
613/**
614 * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list.
615 *
616 * @original_name:   The original program's name.
617 * @aggregated_name: The program name to use.
618 * @is_delete:       True if it is a delete request.
619 *
620 * Returns 0 on success, negative value otherwise.
621 *
622 * Caller holds tomoyo_read_lock().
623 */
624static int tomoyo_update_aggregator_entry(const char *original_name,
625					  const char *aggregated_name,
626					  const bool is_delete)
627{
628	struct tomoyo_aggregator_entry e = { };
629	int error = is_delete ? -ENOENT : -ENOMEM;
630
631	if (!tomoyo_is_correct_path(original_name) ||
632	    !tomoyo_is_correct_path(aggregated_name))
633		return -EINVAL;
634	e.original_name = tomoyo_get_name(original_name);
635	e.aggregated_name = tomoyo_get_name(aggregated_name);
636	if (!e.original_name || !e.aggregated_name ||
637	    e.aggregated_name->is_patterned) /* No patterns allowed. */
638		goto out;
639	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
640				     &tomoyo_aggregator_list,
641				     tomoyo_same_aggregator_entry);
642 out:
643	tomoyo_put_name(e.original_name);
644	tomoyo_put_name(e.aggregated_name);
645	return error;
646}
647
648/**
649 * tomoyo_read_aggregator_policy - Read "struct tomoyo_aggregator_entry" list.
650 *
651 * @head: Pointer to "struct tomoyo_io_buffer".
652 *
653 * Returns true on success, false otherwise.
654 *
655 * Caller holds tomoyo_read_lock().
656 */
657bool tomoyo_read_aggregator_policy(struct tomoyo_io_buffer *head)
658{
659	struct list_head *pos;
660	bool done = true;
661
662	list_for_each_cookie(pos, head->read_var2, &tomoyo_aggregator_list) {
663		struct tomoyo_aggregator_entry *ptr;
664
665		ptr = list_entry(pos, struct tomoyo_aggregator_entry,
666				 head.list);
667		if (ptr->head.is_deleted)
668			continue;
669		done = tomoyo_io_printf(head, TOMOYO_KEYWORD_AGGREGATOR
670					"%s %s\n", ptr->original_name->name,
671					ptr->aggregated_name->name);
672		if (!done)
673			break;
674	}
675	return done;
676}
677
678/**
679 * tomoyo_write_aggregator_policy - Write "struct tomoyo_aggregator_entry" list.
680 *
681 * @data:      String to parse.
682 * @is_delete: True if it is a delete request.
683 *
684 * Returns 0 on success, negative value otherwise.
685 *
686 * Caller holds tomoyo_read_lock().
687 */
688int tomoyo_write_aggregator_policy(char *data, const bool is_delete)
689{
690	char *cp = strchr(data, ' ');
691
692	if (!cp)
693		return -EINVAL;
694	*cp++ = '\0';
695	return tomoyo_update_aggregator_entry(data, cp, is_delete);
696}
697
698/*
699 * tomoyo_alias_list is used for holding list of symlink's pathnames which are
700 * allowed to be passed to an execve() request. Normally, the domainname which
701 * the current process will belong to after execve() succeeds is calculated
702 * using dereferenced pathnames. But some programs behave differently depending
703 * on the name passed to argv[0]. For busybox, calculating domainname using
704 * dereferenced pathnames will cause all programs in the busybox to belong to
705 * the same domain. Thus, TOMOYO provides a way to allow use of symlink's
706 * pathname for checking execve()'s permission and calculating domainname which
707 * the current process will belong to after execve() succeeds.
708 *
709 * An entry is added by
710 *
711 * # echo 'alias /bin/busybox /bin/cat' > \
712 *                            /sys/kernel/security/tomoyo/exception_policy
713 *
714 * and is deleted by
715 *
716 * # echo 'delete alias /bin/busybox /bin/cat' > \
717 *                            /sys/kernel/security/tomoyo/exception_policy
718 *
719 * and all entries are retrieved by
720 *
721 * # grep ^alias /sys/kernel/security/tomoyo/exception_policy
722 *
723 * In the example above, if /bin/cat is a symlink to /bin/busybox and execution
724 * of /bin/cat is requested, permission is checked for /bin/cat rather than
725 * /bin/busybox and domainname which the current process will belong to after
726 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
727 */
728LIST_HEAD(tomoyo_alias_list);
729
730static bool tomoyo_same_alias_entry(const struct tomoyo_acl_head *a,
731				    const struct tomoyo_acl_head *b)
732{
733	const struct tomoyo_alias_entry *p1 = container_of(a, typeof(*p1),
734							   head);
735	const struct tomoyo_alias_entry *p2 = container_of(b, typeof(*p2),
736							   head);
737	return p1->original_name == p2->original_name &&
738		p1->aliased_name == p2->aliased_name;
739}
740
741/**
742 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
743 *
744 * @original_name: The original program's real name.
745 * @aliased_name:  The symbolic program's symbolic link's name.
746 * @is_delete:     True if it is a delete request.
747 *
748 * Returns 0 on success, negative value otherwise.
749 *
750 * Caller holds tomoyo_read_lock().
751 */
752static int tomoyo_update_alias_entry(const char *original_name,
753				     const char *aliased_name,
754				     const bool is_delete)
755{
756	struct tomoyo_alias_entry e = { };
757	int error = is_delete ? -ENOENT : -ENOMEM;
758
759	if (!tomoyo_is_correct_path(original_name) ||
760	    !tomoyo_is_correct_path(aliased_name))
761		return -EINVAL;
762	e.original_name = tomoyo_get_name(original_name);
763	e.aliased_name = tomoyo_get_name(aliased_name);
764	if (!e.original_name || !e.aliased_name ||
765	    e.original_name->is_patterned || e.aliased_name->is_patterned)
766		goto out; /* No patterns allowed. */
767	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
768				     &tomoyo_alias_list,
769				     tomoyo_same_alias_entry);
770 out:
771	tomoyo_put_name(e.original_name);
772	tomoyo_put_name(e.aliased_name);
773	return error;
774}
775
776/**
777 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
778 *
779 * @head: Pointer to "struct tomoyo_io_buffer".
780 *
781 * Returns true on success, false otherwise.
782 *
783 * Caller holds tomoyo_read_lock().
784 */
785bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
786{
787	struct list_head *pos;
788	bool done = true;
789
790	list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
791		struct tomoyo_alias_entry *ptr;
792
793		ptr = list_entry(pos, struct tomoyo_alias_entry, head.list);
794		if (ptr->head.is_deleted)
795			continue;
796		done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
797					ptr->original_name->name,
798					ptr->aliased_name->name);
799		if (!done)
800			break;
801	}
802	return done;
803}
804
805/**
806 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
807 *
808 * @data:      String to parse.
809 * @is_delete: True if it is a delete request.
810 *
811 * Returns 0 on success, negative value otherwise.
812 *
813 * Caller holds tomoyo_read_lock().
814 */
815int tomoyo_write_alias_policy(char *data, const bool is_delete)
816{
817	char *cp = strchr(data, ' ');
818
819	if (!cp)
820		return -EINVAL;
821	*cp++ = '\0';
822	return tomoyo_update_alias_entry(data, cp, is_delete);
823}
824
825/**
826 * tomoyo_find_or_assign_new_domain - Create a domain.
827 *
828 * @domainname: The name of domain.
829 * @profile:    Profile number to assign if the domain was newly created.
830 *
831 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
832 *
833 * Caller holds tomoyo_read_lock().
834 */
835struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
836							    domainname,
837							    const u8 profile)
838{
839	struct tomoyo_domain_info *entry;
840	struct tomoyo_domain_info *domain = NULL;
841	const struct tomoyo_path_info *saved_domainname;
842	bool found = false;
843
844	if (!tomoyo_is_correct_domain(domainname))
845		return NULL;
846	saved_domainname = tomoyo_get_name(domainname);
847	if (!saved_domainname)
848		return NULL;
849	entry = kzalloc(sizeof(*entry), GFP_NOFS);
850	if (mutex_lock_interruptible(&tomoyo_policy_lock))
851		goto out;
852	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
853		if (domain->is_deleted ||
854		    tomoyo_pathcmp(saved_domainname, domain->domainname))
855			continue;
856		found = true;
857		break;
858	}
859	if (!found && tomoyo_memory_ok(entry)) {
860		INIT_LIST_HEAD(&entry->acl_info_list);
861		entry->domainname = saved_domainname;
862		saved_domainname = NULL;
863		entry->profile = profile;
864		list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
865		domain = entry;
866		entry = NULL;
867		found = true;
868	}
869	mutex_unlock(&tomoyo_policy_lock);
870 out:
871	tomoyo_put_name(saved_domainname);
872	kfree(entry);
873	return found ? domain : NULL;
874}
875
876/**
877 * tomoyo_find_next_domain - Find a domain.
878 *
879 * @bprm: Pointer to "struct linux_binprm".
880 *
881 * Returns 0 on success, negative value otherwise.
882 *
883 * Caller holds tomoyo_read_lock().
884 */
885int tomoyo_find_next_domain(struct linux_binprm *bprm)
886{
887	struct tomoyo_request_info r;
888	char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
889	struct tomoyo_domain_info *old_domain = tomoyo_domain();
890	struct tomoyo_domain_info *domain = NULL;
891	const char *old_domain_name = old_domain->domainname->name;
892	const char *original_name = bprm->filename;
893	u8 mode;
894	bool is_enforce;
895	int retval = -ENOMEM;
896	bool need_kfree = false;
897	struct tomoyo_path_info rn = { }; /* real name */
898	struct tomoyo_path_info sn = { }; /* symlink name */
899	struct tomoyo_path_info ln; /* last name */
900
901	ln.name = tomoyo_get_last_name(old_domain);
902	tomoyo_fill_path_info(&ln);
903	mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
904	is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
905	if (!tmp)
906		goto out;
907
908 retry:
909	if (need_kfree) {
910		kfree(rn.name);
911		need_kfree = false;
912	}
913	/* Get tomoyo_realpath of program. */
914	retval = -ENOENT;
915	rn.name = tomoyo_realpath(original_name);
916	if (!rn.name)
917		goto out;
918	tomoyo_fill_path_info(&rn);
919	need_kfree = true;
920
921	/* Get tomoyo_realpath of symbolic link. */
922	sn.name = tomoyo_realpath_nofollow(original_name);
923	if (!sn.name)
924		goto out;
925	tomoyo_fill_path_info(&sn);
926
927	/* Check 'alias' directive. */
928	if (tomoyo_pathcmp(&rn, &sn)) {
929		struct tomoyo_alias_entry *ptr;
930		/* Is this program allowed to be called via symbolic links? */
931		list_for_each_entry_rcu(ptr, &tomoyo_alias_list, head.list) {
932			if (ptr->head.is_deleted ||
933			    tomoyo_pathcmp(&rn, ptr->original_name) ||
934			    tomoyo_pathcmp(&sn, ptr->aliased_name))
935				continue;
936			kfree(rn.name);
937			need_kfree = false;
938			/* This is OK because it is read only. */
939			rn = *ptr->aliased_name;
940			break;
941		}
942	}
943
944	/* Check 'aggregator' directive. */
945	{
946		struct tomoyo_aggregator_entry *ptr;
947		list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list,
948					head.list) {
949			if (ptr->head.is_deleted ||
950			    !tomoyo_path_matches_pattern(&rn,
951							 ptr->original_name))
952				continue;
953			if (need_kfree)
954				kfree(rn.name);
955			need_kfree = false;
956			/* This is OK because it is read only. */
957			rn = *ptr->aggregated_name;
958			break;
959		}
960	}
961
962	/* Check execute permission. */
963	retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn);
964	if (retval == TOMOYO_RETRY_REQUEST)
965		goto retry;
966	if (retval < 0)
967		goto out;
968
969	if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) {
970		/* Transit to the child of tomoyo_kernel_domain domain. */
971		snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
972			 TOMOYO_ROOT_NAME " " "%s", rn.name);
973	} else if (old_domain == &tomoyo_kernel_domain &&
974		   !tomoyo_policy_loaded) {
975		/*
976		 * Needn't to transit from kernel domain before starting
977		 * /sbin/init. But transit from kernel domain if executing
978		 * initializers because they might start before /sbin/init.
979		 */
980		domain = old_domain;
981	} else if (tomoyo_is_domain_keeper(old_domain->domainname, &rn, &ln)) {
982		/* Keep current domain. */
983		domain = old_domain;
984	} else {
985		/* Normal domain transition. */
986		snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
987			 "%s %s", old_domain_name, rn.name);
988	}
989	if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
990		goto done;
991	domain = tomoyo_find_domain(tmp);
992	if (domain)
993		goto done;
994	if (is_enforce) {
995		int error = tomoyo_supervisor(&r, "# wants to create domain\n"
996					      "%s\n", tmp);
997		if (error == TOMOYO_RETRY_REQUEST)
998			goto retry;
999		if (error < 0)
1000			goto done;
1001	}
1002	domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile);
1003 done:
1004	if (domain)
1005		goto out;
1006	printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
1007	if (is_enforce)
1008		retval = -EPERM;
1009	else
1010		old_domain->transition_failed = true;
1011 out:
1012	if (!domain)
1013		domain = old_domain;
1014	/* Update reference count on "struct tomoyo_domain_info". */
1015	atomic_inc(&domain->users);
1016	bprm->cred->security = domain;
1017	if (need_kfree)
1018		kfree(rn.name);
1019	kfree(sn.name);
1020	kfree(tmp);
1021	return retval;
1022}
1023