domain.c revision a8f7640963ada66c412314c3559c11ff6946c1a5
1/*
2 * security/tomoyo/domain.c
3 *
4 * Copyright (C) 2005-2011  NTT DATA CORPORATION
5 */
6
7#include "common.h"
8#include <linux/binfmts.h>
9#include <linux/slab.h>
10
11/* Variables definitions.*/
12
13/* The initial domain. */
14struct tomoyo_domain_info tomoyo_kernel_domain;
15
16/**
17 * tomoyo_update_policy - Update an entry for exception policy.
18 *
19 * @new_entry:       Pointer to "struct tomoyo_acl_info".
20 * @size:            Size of @new_entry in bytes.
21 * @param:           Pointer to "struct tomoyo_acl_param".
22 * @check_duplicate: Callback function to find duplicated entry.
23 *
24 * Returns 0 on success, negative value otherwise.
25 *
26 * Caller holds tomoyo_read_lock().
27 */
28int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
29			 struct tomoyo_acl_param *param,
30			 bool (*check_duplicate) (const struct tomoyo_acl_head
31						  *,
32						  const struct tomoyo_acl_head
33						  *))
34{
35	int error = param->is_delete ? -ENOENT : -ENOMEM;
36	struct tomoyo_acl_head *entry;
37	struct list_head *list = param->list;
38
39	if (mutex_lock_interruptible(&tomoyo_policy_lock))
40		return -ENOMEM;
41	list_for_each_entry_rcu(entry, list, list) {
42		if (!check_duplicate(entry, new_entry))
43			continue;
44		entry->is_deleted = param->is_delete;
45		error = 0;
46		break;
47	}
48	if (error && !param->is_delete) {
49		entry = tomoyo_commit_ok(new_entry, size);
50		if (entry) {
51			list_add_tail_rcu(&entry->list, list);
52			error = 0;
53		}
54	}
55	mutex_unlock(&tomoyo_policy_lock);
56	return error;
57}
58
59/**
60 * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry.
61 *
62 * @a: Pointer to "struct tomoyo_acl_info".
63 * @b: Pointer to "struct tomoyo_acl_info".
64 *
65 * Returns true if @a == @b, false otherwise.
66 */
67static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
68					const struct tomoyo_acl_info *b)
69{
70	return a->type == b->type && a->cond == b->cond;
71}
72
73/**
74 * tomoyo_update_domain - Update an entry for domain policy.
75 *
76 * @new_entry:       Pointer to "struct tomoyo_acl_info".
77 * @size:            Size of @new_entry in bytes.
78 * @param:           Pointer to "struct tomoyo_acl_param".
79 * @check_duplicate: Callback function to find duplicated entry.
80 * @merge_duplicate: Callback function to merge duplicated entry.
81 *
82 * Returns 0 on success, negative value otherwise.
83 *
84 * Caller holds tomoyo_read_lock().
85 */
86int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
87			 struct tomoyo_acl_param *param,
88			 bool (*check_duplicate) (const struct tomoyo_acl_info
89						  *,
90						  const struct tomoyo_acl_info
91						  *),
92			 bool (*merge_duplicate) (struct tomoyo_acl_info *,
93						  struct tomoyo_acl_info *,
94						  const bool))
95{
96	const bool is_delete = param->is_delete;
97	int error = is_delete ? -ENOENT : -ENOMEM;
98	struct tomoyo_acl_info *entry;
99	struct list_head * const list = param->list;
100
101	if (param->data[0]) {
102		new_entry->cond = tomoyo_get_condition(param);
103		if (!new_entry->cond)
104			return -EINVAL;
105	}
106	if (mutex_lock_interruptible(&tomoyo_policy_lock))
107		goto out;
108	list_for_each_entry_rcu(entry, list, list) {
109		if (!tomoyo_same_acl_head(entry, new_entry) ||
110		    !check_duplicate(entry, new_entry))
111			continue;
112		if (merge_duplicate)
113			entry->is_deleted = merge_duplicate(entry, new_entry,
114							    is_delete);
115		else
116			entry->is_deleted = is_delete;
117		error = 0;
118		break;
119	}
120	if (error && !is_delete) {
121		entry = tomoyo_commit_ok(new_entry, size);
122		if (entry) {
123			list_add_tail_rcu(&entry->list, list);
124			error = 0;
125		}
126	}
127	mutex_unlock(&tomoyo_policy_lock);
128out:
129	tomoyo_put_condition(new_entry->cond);
130	return error;
131}
132
133/**
134 * tomoyo_check_acl - Do permission check.
135 *
136 * @r:           Pointer to "struct tomoyo_request_info".
137 * @check_entry: Callback function to check type specific parameters.
138 *
139 * Returns 0 on success, negative value otherwise.
140 *
141 * Caller holds tomoyo_read_lock().
142 */
143void tomoyo_check_acl(struct tomoyo_request_info *r,
144		      bool (*check_entry) (struct tomoyo_request_info *,
145					   const struct tomoyo_acl_info *))
146{
147	const struct tomoyo_domain_info *domain = r->domain;
148	struct tomoyo_acl_info *ptr;
149	bool retried = false;
150	const struct list_head *list = &domain->acl_info_list;
151
152retry:
153	list_for_each_entry_rcu(ptr, list, list) {
154		if (ptr->is_deleted || ptr->type != r->param_type)
155			continue;
156		if (!check_entry(r, ptr))
157			continue;
158		if (!tomoyo_condition(r, ptr->cond))
159			continue;
160		r->matched_acl = ptr;
161		r->granted = true;
162		return;
163	}
164	if (!retried) {
165		retried = true;
166		list = &domain->ns->acl_group[domain->group];
167		goto retry;
168	}
169	r->granted = false;
170}
171
172/* The list for "struct tomoyo_domain_info". */
173LIST_HEAD(tomoyo_domain_list);
174
175/**
176 * tomoyo_last_word - Get last component of a domainname.
177 *
178 * @name: Domainname to check.
179 *
180 * Returns the last word of @domainname.
181 */
182static const char *tomoyo_last_word(const char *name)
183{
184	const char *cp = strrchr(name, ' ');
185	if (cp)
186		return cp + 1;
187	return name;
188}
189
190/**
191 * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry.
192 *
193 * @a: Pointer to "struct tomoyo_acl_head".
194 * @b: Pointer to "struct tomoyo_acl_head".
195 *
196 * Returns true if @a == @b, false otherwise.
197 */
198static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
199					   const struct tomoyo_acl_head *b)
200{
201	const struct tomoyo_transition_control *p1 = container_of(a,
202								  typeof(*p1),
203								  head);
204	const struct tomoyo_transition_control *p2 = container_of(b,
205								  typeof(*p2),
206								  head);
207	return p1->type == p2->type && p1->is_last_name == p2->is_last_name
208		&& p1->domainname == p2->domainname
209		&& p1->program == p2->program;
210}
211
212/**
213 * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
214 *
215 * @param: Pointer to "struct tomoyo_acl_param".
216 * @type:  Type of this entry.
217 *
218 * Returns 0 on success, negative value otherwise.
219 */
220int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
221				    const u8 type)
222{
223	struct tomoyo_transition_control e = { .type = type };
224	int error = param->is_delete ? -ENOENT : -ENOMEM;
225	char *program = param->data;
226	char *domainname = strstr(program, " from ");
227	if (domainname) {
228		*domainname = '\0';
229		domainname += 6;
230	} else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
231		   type == TOMOYO_TRANSITION_CONTROL_KEEP) {
232		domainname = program;
233		program = NULL;
234	}
235	if (program && strcmp(program, "any")) {
236		if (!tomoyo_correct_path(program))
237			return -EINVAL;
238		e.program = tomoyo_get_name(program);
239		if (!e.program)
240			goto out;
241	}
242	if (domainname && strcmp(domainname, "any")) {
243		if (!tomoyo_correct_domain(domainname)) {
244			if (!tomoyo_correct_path(domainname))
245				goto out;
246			e.is_last_name = true;
247		}
248		e.domainname = tomoyo_get_name(domainname);
249		if (!e.domainname)
250			goto out;
251	}
252	param->list = &param->ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL];
253	error = tomoyo_update_policy(&e.head, sizeof(e), param,
254				     tomoyo_same_transition_control);
255out:
256	tomoyo_put_name(e.domainname);
257	tomoyo_put_name(e.program);
258	return error;
259}
260
261/**
262 * tomoyo_scan_transition - Try to find specific domain transition type.
263 *
264 * @list:       Pointer to "struct list_head".
265 * @domainname: The name of current domain.
266 * @program:    The name of requested program.
267 * @last_name:  The last component of @domainname.
268 * @type:       One of values in "enum tomoyo_transition_type".
269 *
270 * Returns true if found one, false otherwise.
271 *
272 * Caller holds tomoyo_read_lock().
273 */
274static inline bool tomoyo_scan_transition
275(const struct list_head *list, const struct tomoyo_path_info *domainname,
276 const struct tomoyo_path_info *program, const char *last_name,
277 const enum tomoyo_transition_type type)
278{
279	const struct tomoyo_transition_control *ptr;
280	list_for_each_entry_rcu(ptr, list, head.list) {
281		if (ptr->head.is_deleted || ptr->type != type)
282			continue;
283		if (ptr->domainname) {
284			if (!ptr->is_last_name) {
285				if (ptr->domainname != domainname)
286					continue;
287			} else {
288				/*
289				 * Use direct strcmp() since this is
290				 * unlikely used.
291				 */
292				if (strcmp(ptr->domainname->name, last_name))
293					continue;
294			}
295		}
296		if (ptr->program && tomoyo_pathcmp(ptr->program, program))
297			continue;
298		return true;
299	}
300	return false;
301}
302
303/**
304 * tomoyo_transition_type - Get domain transition type.
305 *
306 * @ns:         Pointer to "struct tomoyo_policy_namespace".
307 * @domainname: The name of current domain.
308 * @program:    The name of requested program.
309 *
310 * Returns TOMOYO_TRANSITION_CONTROL_TRANSIT if executing @program causes
311 * domain transition across namespaces, TOMOYO_TRANSITION_CONTROL_INITIALIZE if
312 * executing @program reinitializes domain transition within that namespace,
313 * TOMOYO_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname ,
314 * others otherwise.
315 *
316 * Caller holds tomoyo_read_lock().
317 */
318static enum tomoyo_transition_type tomoyo_transition_type
319(const struct tomoyo_policy_namespace *ns,
320 const struct tomoyo_path_info *domainname,
321 const struct tomoyo_path_info *program)
322{
323	const char *last_name = tomoyo_last_word(domainname->name);
324	enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET;
325	while (type < TOMOYO_MAX_TRANSITION_TYPE) {
326		const struct list_head * const list =
327			&ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL];
328		if (!tomoyo_scan_transition(list, domainname, program,
329					    last_name, type)) {
330			type++;
331			continue;
332		}
333		if (type != TOMOYO_TRANSITION_CONTROL_NO_RESET &&
334		    type != TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE)
335			break;
336		/*
337		 * Do not check for reset_domain if no_reset_domain matched.
338		 * Do not check for initialize_domain if no_initialize_domain
339		 * matched.
340		 */
341		type++;
342		type++;
343	}
344	return type;
345}
346
347/**
348 * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry.
349 *
350 * @a: Pointer to "struct tomoyo_acl_head".
351 * @b: Pointer to "struct tomoyo_acl_head".
352 *
353 * Returns true if @a == @b, false otherwise.
354 */
355static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
356				   const struct tomoyo_acl_head *b)
357{
358	const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1),
359							  head);
360	const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2),
361							  head);
362	return p1->original_name == p2->original_name &&
363		p1->aggregated_name == p2->aggregated_name;
364}
365
366/**
367 * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
368 *
369 * @param: Pointer to "struct tomoyo_acl_param".
370 *
371 * Returns 0 on success, negative value otherwise.
372 *
373 * Caller holds tomoyo_read_lock().
374 */
375int tomoyo_write_aggregator(struct tomoyo_acl_param *param)
376{
377	struct tomoyo_aggregator e = { };
378	int error = param->is_delete ? -ENOENT : -ENOMEM;
379	const char *original_name = tomoyo_read_token(param);
380	const char *aggregated_name = tomoyo_read_token(param);
381	if (!tomoyo_correct_word(original_name) ||
382	    !tomoyo_correct_path(aggregated_name))
383		return -EINVAL;
384	e.original_name = tomoyo_get_name(original_name);
385	e.aggregated_name = tomoyo_get_name(aggregated_name);
386	if (!e.original_name || !e.aggregated_name ||
387	    e.aggregated_name->is_patterned) /* No patterns allowed. */
388		goto out;
389	param->list = &param->ns->policy_list[TOMOYO_ID_AGGREGATOR];
390	error = tomoyo_update_policy(&e.head, sizeof(e), param,
391				     tomoyo_same_aggregator);
392out:
393	tomoyo_put_name(e.original_name);
394	tomoyo_put_name(e.aggregated_name);
395	return error;
396}
397
398/**
399 * tomoyo_find_namespace - Find specified namespace.
400 *
401 * @name: Name of namespace to find.
402 * @len:  Length of @name.
403 *
404 * Returns pointer to "struct tomoyo_policy_namespace" if found,
405 * NULL otherwise.
406 *
407 * Caller holds tomoyo_read_lock().
408 */
409static struct tomoyo_policy_namespace *tomoyo_find_namespace
410(const char *name, const unsigned int len)
411{
412	struct tomoyo_policy_namespace *ns;
413	list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
414		if (strncmp(name, ns->name, len) ||
415		    (name[len] && name[len] != ' '))
416			continue;
417		return ns;
418	}
419	return NULL;
420}
421
422/**
423 * tomoyo_assign_namespace - Create a new namespace.
424 *
425 * @domainname: Name of namespace to create.
426 *
427 * Returns pointer to "struct tomoyo_policy_namespace" on success,
428 * NULL otherwise.
429 *
430 * Caller holds tomoyo_read_lock().
431 */
432struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname)
433{
434	struct tomoyo_policy_namespace *ptr;
435	struct tomoyo_policy_namespace *entry;
436	const char *cp = domainname;
437	unsigned int len = 0;
438	while (*cp && *cp++ != ' ')
439		len++;
440	ptr = tomoyo_find_namespace(domainname, len);
441	if (ptr)
442		return ptr;
443	if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname))
444		return NULL;
445	entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS);
446	if (!entry)
447		return NULL;
448	if (mutex_lock_interruptible(&tomoyo_policy_lock))
449		goto out;
450	ptr = tomoyo_find_namespace(domainname, len);
451	if (!ptr && tomoyo_memory_ok(entry)) {
452		char *name = (char *) (entry + 1);
453		ptr = entry;
454		memmove(name, domainname, len);
455		name[len] = '\0';
456		entry->name = name;
457		tomoyo_init_policy_namespace(entry);
458		entry = NULL;
459	}
460	mutex_unlock(&tomoyo_policy_lock);
461out:
462	kfree(entry);
463	return ptr;
464}
465
466/**
467 * tomoyo_namespace_jump - Check for namespace jump.
468 *
469 * @domainname: Name of domain.
470 *
471 * Returns true if namespace differs, false otherwise.
472 */
473static bool tomoyo_namespace_jump(const char *domainname)
474{
475	const char *namespace = tomoyo_current_namespace()->name;
476	const int len = strlen(namespace);
477	return strncmp(domainname, namespace, len) ||
478		(domainname[len] && domainname[len] != ' ');
479}
480
481/**
482 * tomoyo_assign_domain - Create a domain or a namespace.
483 *
484 * @domainname: The name of domain.
485 * @transit:    True if transit to domain found or created.
486 *
487 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
488 *
489 * Caller holds tomoyo_read_lock().
490 */
491struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
492						const bool transit)
493{
494	struct tomoyo_domain_info e = { };
495	struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname);
496	bool created = false;
497	if (entry) {
498		if (transit) {
499			/*
500			 * Since namespace is created at runtime, profiles may
501			 * not be created by the moment the process transits to
502			 * that domain. Do not perform domain transition if
503			 * profile for that domain is not yet created.
504			 */
505			if (!entry->ns->profile_ptr[entry->profile])
506				return NULL;
507		}
508		return entry;
509	}
510	/* Requested domain does not exist. */
511	/* Don't create requested domain if domainname is invalid. */
512	if (strlen(domainname) >= TOMOYO_EXEC_TMPSIZE - 10 ||
513	    !tomoyo_correct_domain(domainname))
514		return NULL;
515	/*
516	 * Since definition of profiles and acl_groups may differ across
517	 * namespaces, do not inherit "use_profile" and "use_group" settings
518	 * by automatically creating requested domain upon domain transition.
519	 */
520	if (transit && tomoyo_namespace_jump(domainname))
521		return NULL;
522	e.ns = tomoyo_assign_namespace(domainname);
523	if (!e.ns)
524		return NULL;
525	/*
526	 * "use_profile" and "use_group" settings for automatically created
527	 * domains are inherited from current domain. These are 0 for manually
528	 * created domains.
529	 */
530	if (transit) {
531		const struct tomoyo_domain_info *domain = tomoyo_domain();
532		e.profile = domain->profile;
533		e.group = domain->group;
534	}
535	e.domainname = tomoyo_get_name(domainname);
536	if (!e.domainname)
537		return NULL;
538	if (mutex_lock_interruptible(&tomoyo_policy_lock))
539		goto out;
540	entry = tomoyo_find_domain(domainname);
541	if (!entry) {
542		entry = tomoyo_commit_ok(&e, sizeof(e));
543		if (entry) {
544			INIT_LIST_HEAD(&entry->acl_info_list);
545			list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
546			created = true;
547		}
548	}
549	mutex_unlock(&tomoyo_policy_lock);
550out:
551	tomoyo_put_name(e.domainname);
552	if (entry && transit) {
553		if (created) {
554			struct tomoyo_request_info r;
555			tomoyo_init_request_info(&r, entry,
556						 TOMOYO_MAC_FILE_EXECUTE);
557			r.granted = false;
558			tomoyo_write_log(&r, "use_profile %u\n",
559					 entry->profile);
560			tomoyo_write_log(&r, "use_group %u\n", entry->group);
561		}
562	}
563	return entry;
564}
565
566/**
567 * tomoyo_environ - Check permission for environment variable names.
568 *
569 * @ee: Pointer to "struct tomoyo_execve".
570 *
571 * Returns 0 on success, negative value otherwise.
572 */
573static int tomoyo_environ(struct tomoyo_execve *ee)
574{
575	struct tomoyo_request_info *r = &ee->r;
576	struct linux_binprm *bprm = ee->bprm;
577	/* env_page.data is allocated by tomoyo_dump_page(). */
578	struct tomoyo_page_dump env_page = { };
579	char *arg_ptr; /* Size is TOMOYO_EXEC_TMPSIZE bytes */
580	int arg_len = 0;
581	unsigned long pos = bprm->p;
582	int offset = pos % PAGE_SIZE;
583	int argv_count = bprm->argc;
584	int envp_count = bprm->envc;
585	int error = -ENOMEM;
586
587	ee->r.type = TOMOYO_MAC_ENVIRON;
588	ee->r.profile = r->domain->profile;
589	ee->r.mode = tomoyo_get_mode(r->domain->ns, ee->r.profile,
590				     TOMOYO_MAC_ENVIRON);
591	if (!r->mode || !envp_count)
592		return 0;
593	arg_ptr = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
594	if (!arg_ptr)
595		goto out;
596	while (error == -ENOMEM) {
597		if (!tomoyo_dump_page(bprm, pos, &env_page))
598			goto out;
599		pos += PAGE_SIZE - offset;
600		/* Read. */
601		while (argv_count && offset < PAGE_SIZE) {
602			if (!env_page.data[offset++])
603				argv_count--;
604		}
605		if (argv_count) {
606			offset = 0;
607			continue;
608		}
609		while (offset < PAGE_SIZE) {
610			const unsigned char c = env_page.data[offset++];
611
612			if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
613				if (c == '=') {
614					arg_ptr[arg_len++] = '\0';
615				} else if (c == '\\') {
616					arg_ptr[arg_len++] = '\\';
617					arg_ptr[arg_len++] = '\\';
618				} else if (c > ' ' && c < 127) {
619					arg_ptr[arg_len++] = c;
620				} else {
621					arg_ptr[arg_len++] = '\\';
622					arg_ptr[arg_len++] = (c >> 6) + '0';
623					arg_ptr[arg_len++]
624						= ((c >> 3) & 7) + '0';
625					arg_ptr[arg_len++] = (c & 7) + '0';
626				}
627			} else {
628				arg_ptr[arg_len] = '\0';
629			}
630			if (c)
631				continue;
632			if (tomoyo_env_perm(r, arg_ptr)) {
633				error = -EPERM;
634				break;
635			}
636			if (!--envp_count) {
637				error = 0;
638				break;
639			}
640			arg_len = 0;
641		}
642		offset = 0;
643	}
644out:
645	if (r->mode != TOMOYO_CONFIG_ENFORCING)
646		error = 0;
647	kfree(env_page.data);
648	kfree(arg_ptr);
649	return error;
650}
651
652/**
653 * tomoyo_find_next_domain - Find a domain.
654 *
655 * @bprm: Pointer to "struct linux_binprm".
656 *
657 * Returns 0 on success, negative value otherwise.
658 *
659 * Caller holds tomoyo_read_lock().
660 */
661int tomoyo_find_next_domain(struct linux_binprm *bprm)
662{
663	struct tomoyo_domain_info *old_domain = tomoyo_domain();
664	struct tomoyo_domain_info *domain = NULL;
665	const char *original_name = bprm->filename;
666	int retval = -ENOMEM;
667	bool reject_on_transition_failure = false;
668	const struct tomoyo_path_info *candidate;
669	struct tomoyo_path_info exename;
670	struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS);
671
672	if (!ee)
673		return -ENOMEM;
674	ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
675	if (!ee->tmp) {
676		kfree(ee);
677		return -ENOMEM;
678	}
679	/* ee->dump->data is allocated by tomoyo_dump_page(). */
680	tomoyo_init_request_info(&ee->r, NULL, TOMOYO_MAC_FILE_EXECUTE);
681	ee->r.ee = ee;
682	ee->bprm = bprm;
683	ee->r.obj = &ee->obj;
684	ee->obj.path1 = bprm->file->f_path;
685	/* Get symlink's pathname of program. */
686	retval = -ENOENT;
687	exename.name = tomoyo_realpath_nofollow(original_name);
688	if (!exename.name)
689		goto out;
690	tomoyo_fill_path_info(&exename);
691retry:
692	/* Check 'aggregator' directive. */
693	{
694		struct tomoyo_aggregator *ptr;
695		struct list_head *list =
696			&old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR];
697		/* Check 'aggregator' directive. */
698		candidate = &exename;
699		list_for_each_entry_rcu(ptr, list, head.list) {
700			if (ptr->head.is_deleted ||
701			    !tomoyo_path_matches_pattern(&exename,
702							 ptr->original_name))
703				continue;
704			candidate = ptr->aggregated_name;
705			break;
706		}
707	}
708
709	/* Check execute permission. */
710	retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE,
711					candidate);
712	if (retval == TOMOYO_RETRY_REQUEST)
713		goto retry;
714	if (retval < 0)
715		goto out;
716	/*
717	 * To be able to specify domainnames with wildcards, use the
718	 * pathname specified in the policy (which may contain
719	 * wildcard) rather than the pathname passed to execve()
720	 * (which never contains wildcard).
721	 */
722	if (ee->r.param.path.matched_path)
723		candidate = ee->r.param.path.matched_path;
724
725	/* Calculate domain to transit to. */
726	switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname,
727				       candidate)) {
728	case TOMOYO_TRANSITION_CONTROL_RESET:
729		/* Transit to the root of specified namespace. */
730		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>",
731			 candidate->name);
732		/*
733		 * Make do_execve() fail if domain transition across namespaces
734		 * has failed.
735		 */
736		reject_on_transition_failure = true;
737		break;
738	case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
739		/* Transit to the child of current namespace's root. */
740		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
741			 old_domain->ns->name, candidate->name);
742		break;
743	case TOMOYO_TRANSITION_CONTROL_KEEP:
744		/* Keep current domain. */
745		domain = old_domain;
746		break;
747	default:
748		if (old_domain == &tomoyo_kernel_domain &&
749		    !tomoyo_policy_loaded) {
750			/*
751			 * Needn't to transit from kernel domain before
752			 * starting /sbin/init. But transit from kernel domain
753			 * if executing initializers because they might start
754			 * before /sbin/init.
755			 */
756			domain = old_domain;
757			break;
758		}
759		/* Normal domain transition. */
760		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
761			 old_domain->domainname->name, candidate->name);
762		break;
763	}
764	if (!domain)
765		domain = tomoyo_assign_domain(ee->tmp, true);
766	if (domain)
767		retval = 0;
768	else if (reject_on_transition_failure) {
769		printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n",
770		       ee->tmp);
771		retval = -ENOMEM;
772	} else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING)
773		retval = -ENOMEM;
774	else {
775		retval = 0;
776		if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) {
777			old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true;
778			ee->r.granted = false;
779			tomoyo_write_log(&ee->r, "%s", tomoyo_dif
780					 [TOMOYO_DIF_TRANSITION_FAILED]);
781			printk(KERN_WARNING
782			       "ERROR: Domain '%s' not defined.\n", ee->tmp);
783		}
784	}
785 out:
786	if (!domain)
787		domain = old_domain;
788	/* Update reference count on "struct tomoyo_domain_info". */
789	atomic_inc(&domain->users);
790	bprm->cred->security = domain;
791	kfree(exename.name);
792	if (!retval) {
793		ee->r.domain = domain;
794		retval = tomoyo_environ(ee);
795	}
796	kfree(ee->tmp);
797	kfree(ee->dump.data);
798	kfree(ee);
799	return retval;
800}
801
802/**
803 * tomoyo_dump_page - Dump a page to buffer.
804 *
805 * @bprm: Pointer to "struct linux_binprm".
806 * @pos:  Location to dump.
807 * @dump: Poiner to "struct tomoyo_page_dump".
808 *
809 * Returns true on success, false otherwise.
810 */
811bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
812		      struct tomoyo_page_dump *dump)
813{
814	struct page *page;
815
816	/* dump->data is released by tomoyo_find_next_domain(). */
817	if (!dump->data) {
818		dump->data = kzalloc(PAGE_SIZE, GFP_NOFS);
819		if (!dump->data)
820			return false;
821	}
822	/* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
823#ifdef CONFIG_MMU
824	if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
825		return false;
826#else
827	page = bprm->page[pos / PAGE_SIZE];
828#endif
829	if (page != dump->page) {
830		const unsigned int offset = pos % PAGE_SIZE;
831		/*
832		 * Maybe kmap()/kunmap() should be used here.
833		 * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
834		 * So do I.
835		 */
836		char *kaddr = kmap_atomic(page, KM_USER0);
837
838		dump->page = page;
839		memcpy(dump->data + offset, kaddr + offset,
840		       PAGE_SIZE - offset);
841		kunmap_atomic(kaddr, KM_USER0);
842	}
843	/* Same with put_arg_page(page) in fs/exec.c */
844#ifdef CONFIG_MMU
845	put_page(page);
846#endif
847	return true;
848}
849