domain.c revision a230f9e7121cbcbfe23bd5a630abf6b53cece555
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
112void tomoyo_check_acl(struct tomoyo_request_info *r,
113		      bool (*check_entry) (const struct tomoyo_request_info *,
114					   const struct tomoyo_acl_info *))
115{
116	const struct tomoyo_domain_info *domain = r->domain;
117	struct tomoyo_acl_info *ptr;
118
119	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
120		if (ptr->is_deleted || ptr->type != r->param_type)
121			continue;
122		if (check_entry(r, ptr)) {
123			r->granted = true;
124			return;
125		}
126	}
127	r->granted = false;
128}
129
130/* The list for "struct tomoyo_domain_info". */
131LIST_HEAD(tomoyo_domain_list);
132
133struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY];
134struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP];
135
136/**
137 * tomoyo_get_last_name - Get last component of a domainname.
138 *
139 * @domain: Pointer to "struct tomoyo_domain_info".
140 *
141 * Returns the last component of the domainname.
142 */
143const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
144{
145	const char *cp0 = domain->domainname->name;
146	const char *cp1 = strrchr(cp0, ' ');
147
148	if (cp1)
149		return cp1 + 1;
150	return cp0;
151}
152
153static bool tomoyo_same_domain_initializer_entry(const struct tomoyo_acl_head *
154						 a,
155						 const struct tomoyo_acl_head *
156						 b)
157{
158	const struct tomoyo_domain_initializer_entry *p1 =
159		container_of(a, typeof(*p1), head);
160	const struct tomoyo_domain_initializer_entry *p2 =
161		container_of(b, typeof(*p2), head);
162	return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
163		&& p1->domainname == p2->domainname
164		&& p1->program == p2->program;
165}
166
167/**
168 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
169 *
170 * @domainname: The name of domain. May be NULL.
171 * @program:    The name of program.
172 * @is_not:     True if it is "no_initialize_domain" entry.
173 * @is_delete:  True if it is a delete request.
174 *
175 * Returns 0 on success, negative value otherwise.
176 *
177 * Caller holds tomoyo_read_lock().
178 */
179static int tomoyo_update_domain_initializer_entry(const char *domainname,
180						  const char *program,
181						  const bool is_not,
182						  const bool is_delete)
183{
184	struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
185	int error = is_delete ? -ENOENT : -ENOMEM;
186
187	if (!tomoyo_correct_path(program))
188		return -EINVAL;
189	if (domainname) {
190		if (!tomoyo_domain_def(domainname) &&
191		    tomoyo_correct_path(domainname))
192			e.is_last_name = true;
193		else if (!tomoyo_correct_domain(domainname))
194			return -EINVAL;
195		e.domainname = tomoyo_get_name(domainname);
196		if (!e.domainname)
197			goto out;
198	}
199	e.program = tomoyo_get_name(program);
200	if (!e.program)
201		goto out;
202	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
203				     &tomoyo_policy_list
204				     [TOMOYO_ID_DOMAIN_INITIALIZER],
205				     tomoyo_same_domain_initializer_entry);
206 out:
207	tomoyo_put_name(e.domainname);
208	tomoyo_put_name(e.program);
209	return error;
210}
211
212/**
213 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list.
214 *
215 * @head: Pointer to "struct tomoyo_io_buffer".
216 *
217 * Returns true on success, false otherwise.
218 *
219 * Caller holds tomoyo_read_lock().
220 */
221bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
222{
223	struct list_head *pos;
224	bool done = true;
225
226	list_for_each_cookie(pos, head->read_var2, &tomoyo_policy_list
227			     [TOMOYO_ID_DOMAIN_INITIALIZER]) {
228		const char *no;
229		const char *from = "";
230		const char *domain = "";
231		struct tomoyo_domain_initializer_entry *ptr;
232		ptr = list_entry(pos, struct tomoyo_domain_initializer_entry,
233				 head.list);
234		if (ptr->head.is_deleted)
235			continue;
236		no = ptr->is_not ? "no_" : "";
237		if (ptr->domainname) {
238			from = " from ";
239			domain = ptr->domainname->name;
240		}
241		done = tomoyo_io_printf(head,
242					"%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN
243					"%s%s%s\n", no, ptr->program->name,
244					from, domain);
245		if (!done)
246			break;
247	}
248	return done;
249}
250
251/**
252 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
253 *
254 * @data:      String to parse.
255 * @is_not:    True if it is "no_initialize_domain" entry.
256 * @is_delete: True if it is a delete request.
257 *
258 * Returns 0 on success, negative value otherwise.
259 *
260 * Caller holds tomoyo_read_lock().
261 */
262int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
263					   const bool is_delete)
264{
265	char *cp = strstr(data, " from ");
266
267	if (cp) {
268		*cp = '\0';
269		return tomoyo_update_domain_initializer_entry(cp + 6, data,
270							      is_not,
271							      is_delete);
272	}
273	return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
274						      is_delete);
275}
276
277/**
278 * tomoyo_domain_initializer - Check whether the given program causes domainname reinitialization.
279 *
280 * @domainname: The name of domain.
281 * @program:    The name of program.
282 * @last_name:  The last component of @domainname.
283 *
284 * Returns true if executing @program reinitializes domain transition,
285 * false otherwise.
286 *
287 * Caller holds tomoyo_read_lock().
288 */
289static bool tomoyo_domain_initializer(const struct tomoyo_path_info *
290					 domainname,
291					 const struct tomoyo_path_info *program,
292					 const struct tomoyo_path_info *
293					 last_name)
294{
295	struct tomoyo_domain_initializer_entry *ptr;
296	bool flag = false;
297
298	list_for_each_entry_rcu(ptr, &tomoyo_policy_list
299				[TOMOYO_ID_DOMAIN_INITIALIZER], head.list) {
300		if (ptr->head.is_deleted)
301			continue;
302		if (ptr->domainname) {
303			if (!ptr->is_last_name) {
304				if (ptr->domainname != domainname)
305					continue;
306			} else {
307				if (tomoyo_pathcmp(ptr->domainname, last_name))
308					continue;
309			}
310		}
311		if (tomoyo_pathcmp(ptr->program, program))
312			continue;
313		if (ptr->is_not) {
314			flag = false;
315			break;
316		}
317		flag = true;
318	}
319	return flag;
320}
321
322static bool tomoyo_same_domain_keeper_entry(const struct tomoyo_acl_head *a,
323					    const struct tomoyo_acl_head *b)
324{
325	const struct tomoyo_domain_keeper_entry *p1 =
326		container_of(a, typeof(*p1), head);
327	const struct tomoyo_domain_keeper_entry *p2 =
328		container_of(b, typeof(*p2), head);
329	return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
330		&& p1->domainname == p2->domainname
331		&& p1->program == p2->program;
332}
333
334/**
335 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
336 *
337 * @domainname: The name of domain.
338 * @program:    The name of program. May be NULL.
339 * @is_not:     True if it is "no_keep_domain" entry.
340 * @is_delete:  True if it is a delete request.
341 *
342 * Returns 0 on success, negative value otherwise.
343 *
344 * Caller holds tomoyo_read_lock().
345 */
346static int tomoyo_update_domain_keeper_entry(const char *domainname,
347					     const char *program,
348					     const bool is_not,
349					     const bool is_delete)
350{
351	struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
352	int error = is_delete ? -ENOENT : -ENOMEM;
353
354	if (!tomoyo_domain_def(domainname) &&
355	    tomoyo_correct_path(domainname))
356		e.is_last_name = true;
357	else if (!tomoyo_correct_domain(domainname))
358		return -EINVAL;
359	if (program) {
360		if (!tomoyo_correct_path(program))
361			return -EINVAL;
362		e.program = tomoyo_get_name(program);
363		if (!e.program)
364			goto out;
365	}
366	e.domainname = tomoyo_get_name(domainname);
367	if (!e.domainname)
368		goto out;
369	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
370				     &tomoyo_policy_list
371				     [TOMOYO_ID_DOMAIN_KEEPER],
372				     tomoyo_same_domain_keeper_entry);
373 out:
374	tomoyo_put_name(e.domainname);
375	tomoyo_put_name(e.program);
376	return error;
377}
378
379/**
380 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
381 *
382 * @data:      String to parse.
383 * @is_not:    True if it is "no_keep_domain" entry.
384 * @is_delete: True if it is a delete request.
385 *
386 * Caller holds tomoyo_read_lock().
387 */
388int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
389				      const bool is_delete)
390{
391	char *cp = strstr(data, " from ");
392
393	if (cp) {
394		*cp = '\0';
395		return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
396							 is_delete);
397	}
398	return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
399}
400
401/**
402 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list.
403 *
404 * @head: Pointer to "struct tomoyo_io_buffer".
405 *
406 * Returns true on success, false otherwise.
407 *
408 * Caller holds tomoyo_read_lock().
409 */
410bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
411{
412	struct list_head *pos;
413	bool done = true;
414
415	list_for_each_cookie(pos, head->read_var2,
416			     &tomoyo_policy_list[TOMOYO_ID_DOMAIN_KEEPER]) {
417		struct tomoyo_domain_keeper_entry *ptr;
418		const char *no;
419		const char *from = "";
420		const char *program = "";
421
422		ptr = list_entry(pos, struct tomoyo_domain_keeper_entry,
423				 head.list);
424		if (ptr->head.is_deleted)
425			continue;
426		no = ptr->is_not ? "no_" : "";
427		if (ptr->program) {
428			from = " from ";
429			program = ptr->program->name;
430		}
431		done = tomoyo_io_printf(head,
432					"%s" TOMOYO_KEYWORD_KEEP_DOMAIN
433					"%s%s%s\n", no, program, from,
434					ptr->domainname->name);
435		if (!done)
436			break;
437	}
438	return done;
439}
440
441/**
442 * tomoyo_domain_keeper - Check whether the given program causes domain transition suppression.
443 *
444 * @domainname: The name of domain.
445 * @program:    The name of program.
446 * @last_name:  The last component of @domainname.
447 *
448 * Returns true if executing @program supresses domain transition,
449 * false otherwise.
450 *
451 * Caller holds tomoyo_read_lock().
452 */
453static bool tomoyo_domain_keeper(const struct tomoyo_path_info *domainname,
454				    const struct tomoyo_path_info *program,
455				    const struct tomoyo_path_info *last_name)
456{
457	struct tomoyo_domain_keeper_entry *ptr;
458	bool flag = false;
459
460	list_for_each_entry_rcu(ptr,
461				&tomoyo_policy_list[TOMOYO_ID_DOMAIN_KEEPER],
462				head.list) {
463		if (ptr->head.is_deleted)
464			continue;
465		if (!ptr->is_last_name) {
466			if (ptr->domainname != domainname)
467				continue;
468		} else {
469			if (tomoyo_pathcmp(ptr->domainname, last_name))
470				continue;
471		}
472		if (ptr->program && tomoyo_pathcmp(ptr->program, program))
473			continue;
474		if (ptr->is_not) {
475			flag = false;
476			break;
477		}
478		flag = true;
479	}
480	return flag;
481}
482
483static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a,
484					 const struct tomoyo_acl_head *b)
485{
486	const struct tomoyo_aggregator_entry *p1 = container_of(a, typeof(*p1),
487								head);
488	const struct tomoyo_aggregator_entry *p2 = container_of(b, typeof(*p2),
489								head);
490	return p1->original_name == p2->original_name &&
491		p1->aggregated_name == p2->aggregated_name;
492}
493
494/**
495 * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list.
496 *
497 * @original_name:   The original program's name.
498 * @aggregated_name: The program name to use.
499 * @is_delete:       True if it is a delete request.
500 *
501 * Returns 0 on success, negative value otherwise.
502 *
503 * Caller holds tomoyo_read_lock().
504 */
505static int tomoyo_update_aggregator_entry(const char *original_name,
506					  const char *aggregated_name,
507					  const bool is_delete)
508{
509	struct tomoyo_aggregator_entry e = { };
510	int error = is_delete ? -ENOENT : -ENOMEM;
511
512	if (!tomoyo_correct_path(original_name) ||
513	    !tomoyo_correct_path(aggregated_name))
514		return -EINVAL;
515	e.original_name = tomoyo_get_name(original_name);
516	e.aggregated_name = tomoyo_get_name(aggregated_name);
517	if (!e.original_name || !e.aggregated_name ||
518	    e.aggregated_name->is_patterned) /* No patterns allowed. */
519		goto out;
520	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
521				     &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR],
522				     tomoyo_same_aggregator_entry);
523 out:
524	tomoyo_put_name(e.original_name);
525	tomoyo_put_name(e.aggregated_name);
526	return error;
527}
528
529/**
530 * tomoyo_read_aggregator_policy - Read "struct tomoyo_aggregator_entry" list.
531 *
532 * @head: Pointer to "struct tomoyo_io_buffer".
533 *
534 * Returns true on success, false otherwise.
535 *
536 * Caller holds tomoyo_read_lock().
537 */
538bool tomoyo_read_aggregator_policy(struct tomoyo_io_buffer *head)
539{
540	struct list_head *pos;
541	bool done = true;
542
543	list_for_each_cookie(pos, head->read_var2,
544			     &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR]) {
545		struct tomoyo_aggregator_entry *ptr;
546
547		ptr = list_entry(pos, struct tomoyo_aggregator_entry,
548				 head.list);
549		if (ptr->head.is_deleted)
550			continue;
551		done = tomoyo_io_printf(head, TOMOYO_KEYWORD_AGGREGATOR
552					"%s %s\n", ptr->original_name->name,
553					ptr->aggregated_name->name);
554		if (!done)
555			break;
556	}
557	return done;
558}
559
560/**
561 * tomoyo_write_aggregator_policy - Write "struct tomoyo_aggregator_entry" list.
562 *
563 * @data:      String to parse.
564 * @is_delete: True if it is a delete request.
565 *
566 * Returns 0 on success, negative value otherwise.
567 *
568 * Caller holds tomoyo_read_lock().
569 */
570int tomoyo_write_aggregator_policy(char *data, const bool is_delete)
571{
572	char *cp = strchr(data, ' ');
573
574	if (!cp)
575		return -EINVAL;
576	*cp++ = '\0';
577	return tomoyo_update_aggregator_entry(data, cp, is_delete);
578}
579
580static bool tomoyo_same_alias_entry(const struct tomoyo_acl_head *a,
581				    const struct tomoyo_acl_head *b)
582{
583	const struct tomoyo_alias_entry *p1 = container_of(a, typeof(*p1),
584							   head);
585	const struct tomoyo_alias_entry *p2 = container_of(b, typeof(*p2),
586							   head);
587	return p1->original_name == p2->original_name &&
588		p1->aliased_name == p2->aliased_name;
589}
590
591/**
592 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
593 *
594 * @original_name: The original program's real name.
595 * @aliased_name:  The symbolic program's symbolic link's name.
596 * @is_delete:     True if it is a delete request.
597 *
598 * Returns 0 on success, negative value otherwise.
599 *
600 * Caller holds tomoyo_read_lock().
601 */
602static int tomoyo_update_alias_entry(const char *original_name,
603				     const char *aliased_name,
604				     const bool is_delete)
605{
606	struct tomoyo_alias_entry e = { };
607	int error = is_delete ? -ENOENT : -ENOMEM;
608
609	if (!tomoyo_correct_path(original_name) ||
610	    !tomoyo_correct_path(aliased_name))
611		return -EINVAL;
612	e.original_name = tomoyo_get_name(original_name);
613	e.aliased_name = tomoyo_get_name(aliased_name);
614	if (!e.original_name || !e.aliased_name ||
615	    e.original_name->is_patterned || e.aliased_name->is_patterned)
616		goto out; /* No patterns allowed. */
617	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
618				     &tomoyo_policy_list[TOMOYO_ID_ALIAS],
619				     tomoyo_same_alias_entry);
620 out:
621	tomoyo_put_name(e.original_name);
622	tomoyo_put_name(e.aliased_name);
623	return error;
624}
625
626/**
627 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list.
628 *
629 * @head: Pointer to "struct tomoyo_io_buffer".
630 *
631 * Returns true on success, false otherwise.
632 *
633 * Caller holds tomoyo_read_lock().
634 */
635bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
636{
637	struct list_head *pos;
638	bool done = true;
639
640	list_for_each_cookie(pos, head->read_var2,
641			     &tomoyo_policy_list[TOMOYO_ID_ALIAS]) {
642		struct tomoyo_alias_entry *ptr;
643
644		ptr = list_entry(pos, struct tomoyo_alias_entry, head.list);
645		if (ptr->head.is_deleted)
646			continue;
647		done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n",
648					ptr->original_name->name,
649					ptr->aliased_name->name);
650		if (!done)
651			break;
652	}
653	return done;
654}
655
656/**
657 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list.
658 *
659 * @data:      String to parse.
660 * @is_delete: True if it is a delete request.
661 *
662 * Returns 0 on success, negative value otherwise.
663 *
664 * Caller holds tomoyo_read_lock().
665 */
666int tomoyo_write_alias_policy(char *data, const bool is_delete)
667{
668	char *cp = strchr(data, ' ');
669
670	if (!cp)
671		return -EINVAL;
672	*cp++ = '\0';
673	return tomoyo_update_alias_entry(data, cp, is_delete);
674}
675
676/**
677 * tomoyo_find_or_assign_new_domain - Create a domain.
678 *
679 * @domainname: The name of domain.
680 * @profile:    Profile number to assign if the domain was newly created.
681 *
682 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
683 *
684 * Caller holds tomoyo_read_lock().
685 */
686struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
687							    domainname,
688							    const u8 profile)
689{
690	struct tomoyo_domain_info *entry;
691	struct tomoyo_domain_info *domain = NULL;
692	const struct tomoyo_path_info *saved_domainname;
693	bool found = false;
694
695	if (!tomoyo_correct_domain(domainname))
696		return NULL;
697	saved_domainname = tomoyo_get_name(domainname);
698	if (!saved_domainname)
699		return NULL;
700	entry = kzalloc(sizeof(*entry), GFP_NOFS);
701	if (mutex_lock_interruptible(&tomoyo_policy_lock))
702		goto out;
703	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
704		if (domain->is_deleted ||
705		    tomoyo_pathcmp(saved_domainname, domain->domainname))
706			continue;
707		found = true;
708		break;
709	}
710	if (!found && tomoyo_memory_ok(entry)) {
711		INIT_LIST_HEAD(&entry->acl_info_list);
712		entry->domainname = saved_domainname;
713		saved_domainname = NULL;
714		entry->profile = profile;
715		list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
716		domain = entry;
717		entry = NULL;
718		found = true;
719	}
720	mutex_unlock(&tomoyo_policy_lock);
721 out:
722	tomoyo_put_name(saved_domainname);
723	kfree(entry);
724	return found ? domain : NULL;
725}
726
727/**
728 * tomoyo_find_next_domain - Find a domain.
729 *
730 * @bprm: Pointer to "struct linux_binprm".
731 *
732 * Returns 0 on success, negative value otherwise.
733 *
734 * Caller holds tomoyo_read_lock().
735 */
736int tomoyo_find_next_domain(struct linux_binprm *bprm)
737{
738	struct tomoyo_request_info r;
739	char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
740	struct tomoyo_domain_info *old_domain = tomoyo_domain();
741	struct tomoyo_domain_info *domain = NULL;
742	const char *old_domain_name = old_domain->domainname->name;
743	const char *original_name = bprm->filename;
744	u8 mode;
745	bool is_enforce;
746	int retval = -ENOMEM;
747	bool need_kfree = false;
748	struct tomoyo_path_info rn = { }; /* real name */
749	struct tomoyo_path_info sn = { }; /* symlink name */
750	struct tomoyo_path_info ln; /* last name */
751
752	ln.name = tomoyo_get_last_name(old_domain);
753	tomoyo_fill_path_info(&ln);
754	mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
755	is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
756	if (!tmp)
757		goto out;
758
759 retry:
760	if (need_kfree) {
761		kfree(rn.name);
762		need_kfree = false;
763	}
764	/* Get tomoyo_realpath of program. */
765	retval = -ENOENT;
766	rn.name = tomoyo_realpath(original_name);
767	if (!rn.name)
768		goto out;
769	tomoyo_fill_path_info(&rn);
770	need_kfree = true;
771
772	/* Get tomoyo_realpath of symbolic link. */
773	sn.name = tomoyo_realpath_nofollow(original_name);
774	if (!sn.name)
775		goto out;
776	tomoyo_fill_path_info(&sn);
777
778	/* Check 'alias' directive. */
779	if (tomoyo_pathcmp(&rn, &sn)) {
780		struct tomoyo_alias_entry *ptr;
781		/* Is this program allowed to be called via symbolic links? */
782		list_for_each_entry_rcu(ptr,
783					&tomoyo_policy_list[TOMOYO_ID_ALIAS],
784					head.list) {
785			if (ptr->head.is_deleted ||
786			    tomoyo_pathcmp(&rn, ptr->original_name) ||
787			    tomoyo_pathcmp(&sn, ptr->aliased_name))
788				continue;
789			kfree(rn.name);
790			need_kfree = false;
791			/* This is OK because it is read only. */
792			rn = *ptr->aliased_name;
793			break;
794		}
795	}
796
797	/* Check 'aggregator' directive. */
798	{
799		struct tomoyo_aggregator_entry *ptr;
800		list_for_each_entry_rcu(ptr, &tomoyo_policy_list
801					[TOMOYO_ID_AGGREGATOR], head.list) {
802			if (ptr->head.is_deleted ||
803			    !tomoyo_path_matches_pattern(&rn,
804							 ptr->original_name))
805				continue;
806			if (need_kfree)
807				kfree(rn.name);
808			need_kfree = false;
809			/* This is OK because it is read only. */
810			rn = *ptr->aggregated_name;
811			break;
812		}
813	}
814
815	/* Check execute permission. */
816	retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn);
817	if (retval == TOMOYO_RETRY_REQUEST)
818		goto retry;
819	if (retval < 0)
820		goto out;
821
822	if (tomoyo_domain_initializer(old_domain->domainname, &rn, &ln)) {
823		/* Transit to the child of tomoyo_kernel_domain domain. */
824		snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
825			 TOMOYO_ROOT_NAME " " "%s", rn.name);
826	} else if (old_domain == &tomoyo_kernel_domain &&
827		   !tomoyo_policy_loaded) {
828		/*
829		 * Needn't to transit from kernel domain before starting
830		 * /sbin/init. But transit from kernel domain if executing
831		 * initializers because they might start before /sbin/init.
832		 */
833		domain = old_domain;
834	} else if (tomoyo_domain_keeper(old_domain->domainname, &rn, &ln)) {
835		/* Keep current domain. */
836		domain = old_domain;
837	} else {
838		/* Normal domain transition. */
839		snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
840			 "%s %s", old_domain_name, rn.name);
841	}
842	if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
843		goto done;
844	domain = tomoyo_find_domain(tmp);
845	if (domain)
846		goto done;
847	if (is_enforce) {
848		int error = tomoyo_supervisor(&r, "# wants to create domain\n"
849					      "%s\n", tmp);
850		if (error == TOMOYO_RETRY_REQUEST)
851			goto retry;
852		if (error < 0)
853			goto done;
854	}
855	domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile);
856 done:
857	if (domain)
858		goto out;
859	printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
860	if (is_enforce)
861		retval = -EPERM;
862	else
863		old_domain->transition_failed = true;
864 out:
865	if (!domain)
866		domain = old_domain;
867	/* Update reference count on "struct tomoyo_domain_info". */
868	atomic_inc(&domain->users);
869	bprm->cred->security = domain;
870	if (need_kfree)
871		kfree(rn.name);
872	kfree(sn.name);
873	kfree(tmp);
874	return retval;
875}
876