xref: /linux/security/tomoyo/condition.c (revision cdd38c5f1ce4398ec58fec95904b75824daab7b5)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
22066a361STetsuo Handa /*
32066a361STetsuo Handa  * security/tomoyo/condition.c
42066a361STetsuo Handa  *
52066a361STetsuo Handa  * Copyright (C) 2005-2011  NTT DATA CORPORATION
62066a361STetsuo Handa  */
72066a361STetsuo Handa 
82066a361STetsuo Handa #include "common.h"
92066a361STetsuo Handa #include <linux/slab.h>
102066a361STetsuo Handa 
112066a361STetsuo Handa /* List of "struct tomoyo_condition". */
122066a361STetsuo Handa LIST_HEAD(tomoyo_condition_list);
132066a361STetsuo Handa 
142066a361STetsuo Handa /**
155b636857STetsuo Handa  * tomoyo_argv - Check argv[] in "struct linux_binbrm".
165b636857STetsuo Handa  *
175b636857STetsuo Handa  * @index:   Index number of @arg_ptr.
185b636857STetsuo Handa  * @arg_ptr: Contents of argv[@index].
195b636857STetsuo Handa  * @argc:    Length of @argv.
205b636857STetsuo Handa  * @argv:    Pointer to "struct tomoyo_argv".
215b636857STetsuo Handa  * @checked: Set to true if @argv[@index] was found.
225b636857STetsuo Handa  *
235b636857STetsuo Handa  * Returns true on success, false otherwise.
245b636857STetsuo Handa  */
tomoyo_argv(const unsigned int index,const char * arg_ptr,const int argc,const struct tomoyo_argv * argv,u8 * checked)255b636857STetsuo Handa static bool tomoyo_argv(const unsigned int index, const char *arg_ptr,
265b636857STetsuo Handa 			const int argc, const struct tomoyo_argv *argv,
275b636857STetsuo Handa 			u8 *checked)
285b636857STetsuo Handa {
295b636857STetsuo Handa 	int i;
305b636857STetsuo Handa 	struct tomoyo_path_info arg;
31cdcf6723STetsuo Handa 
325b636857STetsuo Handa 	arg.name = arg_ptr;
335b636857STetsuo Handa 	for (i = 0; i < argc; argv++, checked++, i++) {
345b636857STetsuo Handa 		bool result;
35cdcf6723STetsuo Handa 
365b636857STetsuo Handa 		if (index != argv->index)
375b636857STetsuo Handa 			continue;
385b636857STetsuo Handa 		*checked = 1;
395b636857STetsuo Handa 		tomoyo_fill_path_info(&arg);
405b636857STetsuo Handa 		result = tomoyo_path_matches_pattern(&arg, argv->value);
415b636857STetsuo Handa 		if (argv->is_not)
425b636857STetsuo Handa 			result = !result;
435b636857STetsuo Handa 		if (!result)
445b636857STetsuo Handa 			return false;
455b636857STetsuo Handa 	}
465b636857STetsuo Handa 	return true;
475b636857STetsuo Handa }
485b636857STetsuo Handa 
495b636857STetsuo Handa /**
505b636857STetsuo Handa  * tomoyo_envp - Check envp[] in "struct linux_binbrm".
515b636857STetsuo Handa  *
525b636857STetsuo Handa  * @env_name:  The name of environment variable.
535b636857STetsuo Handa  * @env_value: The value of environment variable.
545b636857STetsuo Handa  * @envc:      Length of @envp.
555b636857STetsuo Handa  * @envp:      Pointer to "struct tomoyo_envp".
565b636857STetsuo Handa  * @checked:   Set to true if @envp[@env_name] was found.
575b636857STetsuo Handa  *
585b636857STetsuo Handa  * Returns true on success, false otherwise.
595b636857STetsuo Handa  */
tomoyo_envp(const char * env_name,const char * env_value,const int envc,const struct tomoyo_envp * envp,u8 * checked)605b636857STetsuo Handa static bool tomoyo_envp(const char *env_name, const char *env_value,
615b636857STetsuo Handa 			const int envc, const struct tomoyo_envp *envp,
625b636857STetsuo Handa 			u8 *checked)
635b636857STetsuo Handa {
645b636857STetsuo Handa 	int i;
655b636857STetsuo Handa 	struct tomoyo_path_info name;
665b636857STetsuo Handa 	struct tomoyo_path_info value;
67cdcf6723STetsuo Handa 
685b636857STetsuo Handa 	name.name = env_name;
695b636857STetsuo Handa 	tomoyo_fill_path_info(&name);
705b636857STetsuo Handa 	value.name = env_value;
715b636857STetsuo Handa 	tomoyo_fill_path_info(&value);
725b636857STetsuo Handa 	for (i = 0; i < envc; envp++, checked++, i++) {
735b636857STetsuo Handa 		bool result;
74cdcf6723STetsuo Handa 
755b636857STetsuo Handa 		if (!tomoyo_path_matches_pattern(&name, envp->name))
765b636857STetsuo Handa 			continue;
775b636857STetsuo Handa 		*checked = 1;
785b636857STetsuo Handa 		if (envp->value) {
795b636857STetsuo Handa 			result = tomoyo_path_matches_pattern(&value,
805b636857STetsuo Handa 							     envp->value);
815b636857STetsuo Handa 			if (envp->is_not)
825b636857STetsuo Handa 				result = !result;
835b636857STetsuo Handa 		} else {
845b636857STetsuo Handa 			result = true;
855b636857STetsuo Handa 			if (!envp->is_not)
865b636857STetsuo Handa 				result = !result;
875b636857STetsuo Handa 		}
885b636857STetsuo Handa 		if (!result)
895b636857STetsuo Handa 			return false;
905b636857STetsuo Handa 	}
915b636857STetsuo Handa 	return true;
925b636857STetsuo Handa }
935b636857STetsuo Handa 
945b636857STetsuo Handa /**
955b636857STetsuo Handa  * tomoyo_scan_bprm - Scan "struct linux_binprm".
965b636857STetsuo Handa  *
975b636857STetsuo Handa  * @ee:   Pointer to "struct tomoyo_execve".
985b636857STetsuo Handa  * @argc: Length of @argc.
995b636857STetsuo Handa  * @argv: Pointer to "struct tomoyo_argv".
1005b636857STetsuo Handa  * @envc: Length of @envp.
101*15269fb1STetsuo Handa  * @envp: Pointer to "struct tomoyo_envp".
1025b636857STetsuo Handa  *
1035b636857STetsuo Handa  * Returns true on success, false otherwise.
1045b636857STetsuo Handa  */
tomoyo_scan_bprm(struct tomoyo_execve * ee,const u16 argc,const struct tomoyo_argv * argv,const u16 envc,const struct tomoyo_envp * envp)1055b636857STetsuo Handa static bool tomoyo_scan_bprm(struct tomoyo_execve *ee,
1065b636857STetsuo Handa 			     const u16 argc, const struct tomoyo_argv *argv,
1075b636857STetsuo Handa 			     const u16 envc, const struct tomoyo_envp *envp)
1085b636857STetsuo Handa {
1095b636857STetsuo Handa 	struct linux_binprm *bprm = ee->bprm;
1105b636857STetsuo Handa 	struct tomoyo_page_dump *dump = &ee->dump;
1115b636857STetsuo Handa 	char *arg_ptr = ee->tmp;
1125b636857STetsuo Handa 	int arg_len = 0;
1135b636857STetsuo Handa 	unsigned long pos = bprm->p;
1145b636857STetsuo Handa 	int offset = pos % PAGE_SIZE;
1155b636857STetsuo Handa 	int argv_count = bprm->argc;
1165b636857STetsuo Handa 	int envp_count = bprm->envc;
1175b636857STetsuo Handa 	bool result = true;
1185b636857STetsuo Handa 	u8 local_checked[32];
1195b636857STetsuo Handa 	u8 *checked;
120cdcf6723STetsuo Handa 
1215b636857STetsuo Handa 	if (argc + envc <= sizeof(local_checked)) {
1225b636857STetsuo Handa 		checked = local_checked;
1235b636857STetsuo Handa 		memset(local_checked, 0, sizeof(local_checked));
1245b636857STetsuo Handa 	} else {
1255b636857STetsuo Handa 		checked = kzalloc(argc + envc, GFP_NOFS);
1265b636857STetsuo Handa 		if (!checked)
1275b636857STetsuo Handa 			return false;
1285b636857STetsuo Handa 	}
1295b636857STetsuo Handa 	while (argv_count || envp_count) {
1305b636857STetsuo Handa 		if (!tomoyo_dump_page(bprm, pos, dump)) {
1315b636857STetsuo Handa 			result = false;
1325b636857STetsuo Handa 			goto out;
1335b636857STetsuo Handa 		}
1345b636857STetsuo Handa 		pos += PAGE_SIZE - offset;
1355b636857STetsuo Handa 		while (offset < PAGE_SIZE) {
1365b636857STetsuo Handa 			/* Read. */
1375b636857STetsuo Handa 			const char *kaddr = dump->data;
1385b636857STetsuo Handa 			const unsigned char c = kaddr[offset++];
139cdcf6723STetsuo Handa 
1405b636857STetsuo Handa 			if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
1415b636857STetsuo Handa 				if (c == '\\') {
1425b636857STetsuo Handa 					arg_ptr[arg_len++] = '\\';
1435b636857STetsuo Handa 					arg_ptr[arg_len++] = '\\';
1445b636857STetsuo Handa 				} else if (c > ' ' && c < 127) {
1455b636857STetsuo Handa 					arg_ptr[arg_len++] = c;
1465b636857STetsuo Handa 				} else {
1475b636857STetsuo Handa 					arg_ptr[arg_len++] = '\\';
1485b636857STetsuo Handa 					arg_ptr[arg_len++] = (c >> 6) + '0';
1495b636857STetsuo Handa 					arg_ptr[arg_len++] =
1505b636857STetsuo Handa 						((c >> 3) & 7) + '0';
1515b636857STetsuo Handa 					arg_ptr[arg_len++] = (c & 7) + '0';
1525b636857STetsuo Handa 				}
1535b636857STetsuo Handa 			} else {
1545b636857STetsuo Handa 				arg_ptr[arg_len] = '\0';
1555b636857STetsuo Handa 			}
1565b636857STetsuo Handa 			if (c)
1575b636857STetsuo Handa 				continue;
1585b636857STetsuo Handa 			/* Check. */
1595b636857STetsuo Handa 			if (argv_count) {
1605b636857STetsuo Handa 				if (!tomoyo_argv(bprm->argc - argv_count,
1615b636857STetsuo Handa 						 arg_ptr, argc, argv,
1625b636857STetsuo Handa 						 checked)) {
1635b636857STetsuo Handa 					result = false;
1645b636857STetsuo Handa 					break;
1655b636857STetsuo Handa 				}
1665b636857STetsuo Handa 				argv_count--;
1675b636857STetsuo Handa 			} else if (envp_count) {
1685b636857STetsuo Handa 				char *cp = strchr(arg_ptr, '=');
169cdcf6723STetsuo Handa 
1705b636857STetsuo Handa 				if (cp) {
1715b636857STetsuo Handa 					*cp = '\0';
1725b636857STetsuo Handa 					if (!tomoyo_envp(arg_ptr, cp + 1,
1735b636857STetsuo Handa 							 envc, envp,
1745b636857STetsuo Handa 							 checked + argc)) {
1755b636857STetsuo Handa 						result = false;
1765b636857STetsuo Handa 						break;
1775b636857STetsuo Handa 					}
1785b636857STetsuo Handa 				}
1795b636857STetsuo Handa 				envp_count--;
1805b636857STetsuo Handa 			} else {
1815b636857STetsuo Handa 				break;
1825b636857STetsuo Handa 			}
1835b636857STetsuo Handa 			arg_len = 0;
1845b636857STetsuo Handa 		}
1855b636857STetsuo Handa 		offset = 0;
1865b636857STetsuo Handa 		if (!result)
1875b636857STetsuo Handa 			break;
1885b636857STetsuo Handa 	}
1895b636857STetsuo Handa out:
1905b636857STetsuo Handa 	if (result) {
1915b636857STetsuo Handa 		int i;
192cdcf6723STetsuo Handa 
1935b636857STetsuo Handa 		/* Check not-yet-checked entries. */
1945b636857STetsuo Handa 		for (i = 0; i < argc; i++) {
1955b636857STetsuo Handa 			if (checked[i])
1965b636857STetsuo Handa 				continue;
1975b636857STetsuo Handa 			/*
1985b636857STetsuo Handa 			 * Return true only if all unchecked indexes in
1995b636857STetsuo Handa 			 * bprm->argv[] are not matched.
2005b636857STetsuo Handa 			 */
2015b636857STetsuo Handa 			if (argv[i].is_not)
2025b636857STetsuo Handa 				continue;
2035b636857STetsuo Handa 			result = false;
2045b636857STetsuo Handa 			break;
2055b636857STetsuo Handa 		}
2065b636857STetsuo Handa 		for (i = 0; i < envc; envp++, i++) {
2075b636857STetsuo Handa 			if (checked[argc + i])
2085b636857STetsuo Handa 				continue;
2095b636857STetsuo Handa 			/*
2105b636857STetsuo Handa 			 * Return true only if all unchecked environ variables
2115b636857STetsuo Handa 			 * in bprm->envp[] are either undefined or not matched.
2125b636857STetsuo Handa 			 */
2135b636857STetsuo Handa 			if ((!envp->value && !envp->is_not) ||
2145b636857STetsuo Handa 			    (envp->value && envp->is_not))
2155b636857STetsuo Handa 				continue;
2165b636857STetsuo Handa 			result = false;
2175b636857STetsuo Handa 			break;
2185b636857STetsuo Handa 		}
2195b636857STetsuo Handa 	}
2205b636857STetsuo Handa 	if (checked != local_checked)
2215b636857STetsuo Handa 		kfree(checked);
2225b636857STetsuo Handa 	return result;
2235b636857STetsuo Handa }
2245b636857STetsuo Handa 
2255b636857STetsuo Handa /**
2262ca9bf45STetsuo Handa  * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition".
2272ca9bf45STetsuo Handa  *
2282ca9bf45STetsuo Handa  * @file:  Pointer to "struct file".
2292ca9bf45STetsuo Handa  * @ptr:   Pointer to "struct tomoyo_name_union".
2302ca9bf45STetsuo Handa  * @match: True if "exec.realpath=", false if "exec.realpath!=".
2312ca9bf45STetsuo Handa  *
2322ca9bf45STetsuo Handa  * Returns true on success, false otherwise.
2332ca9bf45STetsuo Handa  */
tomoyo_scan_exec_realpath(struct file * file,const struct tomoyo_name_union * ptr,const bool match)2342ca9bf45STetsuo Handa static bool tomoyo_scan_exec_realpath(struct file *file,
2352ca9bf45STetsuo Handa 				      const struct tomoyo_name_union *ptr,
2362ca9bf45STetsuo Handa 				      const bool match)
2372ca9bf45STetsuo Handa {
2382ca9bf45STetsuo Handa 	bool result;
2392ca9bf45STetsuo Handa 	struct tomoyo_path_info exe;
240cdcf6723STetsuo Handa 
2412ca9bf45STetsuo Handa 	if (!file)
2422ca9bf45STetsuo Handa 		return false;
2432ca9bf45STetsuo Handa 	exe.name = tomoyo_realpath_from_path(&file->f_path);
2442ca9bf45STetsuo Handa 	if (!exe.name)
2452ca9bf45STetsuo Handa 		return false;
2462ca9bf45STetsuo Handa 	tomoyo_fill_path_info(&exe);
2472ca9bf45STetsuo Handa 	result = tomoyo_compare_name_union(&exe, ptr);
2482ca9bf45STetsuo Handa 	kfree(exe.name);
2492ca9bf45STetsuo Handa 	return result == match;
2502ca9bf45STetsuo Handa }
2512ca9bf45STetsuo Handa 
2522ca9bf45STetsuo Handa /**
2532ca9bf45STetsuo Handa  * tomoyo_get_dqword - tomoyo_get_name() for a quoted string.
2542ca9bf45STetsuo Handa  *
2552ca9bf45STetsuo Handa  * @start: String to save.
2562ca9bf45STetsuo Handa  *
2572ca9bf45STetsuo Handa  * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
2582ca9bf45STetsuo Handa  */
tomoyo_get_dqword(char * start)2592ca9bf45STetsuo Handa static const struct tomoyo_path_info *tomoyo_get_dqword(char *start)
2602ca9bf45STetsuo Handa {
2612ca9bf45STetsuo Handa 	char *cp = start + strlen(start) - 1;
262cdcf6723STetsuo Handa 
2632ca9bf45STetsuo Handa 	if (cp == start || *start++ != '"' || *cp != '"')
2642ca9bf45STetsuo Handa 		return NULL;
2652ca9bf45STetsuo Handa 	*cp = '\0';
2662ca9bf45STetsuo Handa 	if (*start && !tomoyo_correct_word(start))
2672ca9bf45STetsuo Handa 		return NULL;
2682ca9bf45STetsuo Handa 	return tomoyo_get_name(start);
2692ca9bf45STetsuo Handa }
2702ca9bf45STetsuo Handa 
2712ca9bf45STetsuo Handa /**
2722ca9bf45STetsuo Handa  * tomoyo_parse_name_union_quoted - Parse a quoted word.
2732ca9bf45STetsuo Handa  *
2742ca9bf45STetsuo Handa  * @param: Pointer to "struct tomoyo_acl_param".
2752ca9bf45STetsuo Handa  * @ptr:   Pointer to "struct tomoyo_name_union".
2762ca9bf45STetsuo Handa  *
2772ca9bf45STetsuo Handa  * Returns true on success, false otherwise.
2782ca9bf45STetsuo Handa  */
tomoyo_parse_name_union_quoted(struct tomoyo_acl_param * param,struct tomoyo_name_union * ptr)2792ca9bf45STetsuo Handa static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param,
2802ca9bf45STetsuo Handa 					   struct tomoyo_name_union *ptr)
2812ca9bf45STetsuo Handa {
2822ca9bf45STetsuo Handa 	char *filename = param->data;
283cdcf6723STetsuo Handa 
2842ca9bf45STetsuo Handa 	if (*filename == '@')
2852ca9bf45STetsuo Handa 		return tomoyo_parse_name_union(param, ptr);
2862ca9bf45STetsuo Handa 	ptr->filename = tomoyo_get_dqword(filename);
2872ca9bf45STetsuo Handa 	return ptr->filename != NULL;
2882ca9bf45STetsuo Handa }
2892ca9bf45STetsuo Handa 
2902ca9bf45STetsuo Handa /**
2915b636857STetsuo Handa  * tomoyo_parse_argv - Parse an argv[] condition part.
2925b636857STetsuo Handa  *
2935b636857STetsuo Handa  * @left:  Lefthand value.
2945b636857STetsuo Handa  * @right: Righthand value.
2955b636857STetsuo Handa  * @argv:  Pointer to "struct tomoyo_argv".
2965b636857STetsuo Handa  *
2975b636857STetsuo Handa  * Returns true on success, false otherwise.
2985b636857STetsuo Handa  */
tomoyo_parse_argv(char * left,char * right,struct tomoyo_argv * argv)2995b636857STetsuo Handa static bool tomoyo_parse_argv(char *left, char *right,
3005b636857STetsuo Handa 			      struct tomoyo_argv *argv)
3015b636857STetsuo Handa {
3025b636857STetsuo Handa 	if (tomoyo_parse_ulong(&argv->index, &left) !=
3035b636857STetsuo Handa 	    TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left)
3045b636857STetsuo Handa 		return false;
3055b636857STetsuo Handa 	argv->value = tomoyo_get_dqword(right);
3065b636857STetsuo Handa 	return argv->value != NULL;
3075b636857STetsuo Handa }
3085b636857STetsuo Handa 
3095b636857STetsuo Handa /**
3105b636857STetsuo Handa  * tomoyo_parse_envp - Parse an envp[] condition part.
3115b636857STetsuo Handa  *
3125b636857STetsuo Handa  * @left:  Lefthand value.
3135b636857STetsuo Handa  * @right: Righthand value.
3145b636857STetsuo Handa  * @envp:  Pointer to "struct tomoyo_envp".
3155b636857STetsuo Handa  *
3165b636857STetsuo Handa  * Returns true on success, false otherwise.
3175b636857STetsuo Handa  */
tomoyo_parse_envp(char * left,char * right,struct tomoyo_envp * envp)3185b636857STetsuo Handa static bool tomoyo_parse_envp(char *left, char *right,
3195b636857STetsuo Handa 			      struct tomoyo_envp *envp)
3205b636857STetsuo Handa {
3215b636857STetsuo Handa 	const struct tomoyo_path_info *name;
3225b636857STetsuo Handa 	const struct tomoyo_path_info *value;
3235b636857STetsuo Handa 	char *cp = left + strlen(left) - 1;
324cdcf6723STetsuo Handa 
3255b636857STetsuo Handa 	if (*cp-- != ']' || *cp != '"')
3265b636857STetsuo Handa 		goto out;
3275b636857STetsuo Handa 	*cp = '\0';
3285b636857STetsuo Handa 	if (!tomoyo_correct_word(left))
3295b636857STetsuo Handa 		goto out;
3305b636857STetsuo Handa 	name = tomoyo_get_name(left);
3315b636857STetsuo Handa 	if (!name)
3325b636857STetsuo Handa 		goto out;
3335b636857STetsuo Handa 	if (!strcmp(right, "NULL")) {
3345b636857STetsuo Handa 		value = NULL;
3355b636857STetsuo Handa 	} else {
3365b636857STetsuo Handa 		value = tomoyo_get_dqword(right);
3375b636857STetsuo Handa 		if (!value) {
3385b636857STetsuo Handa 			tomoyo_put_name(name);
3395b636857STetsuo Handa 			goto out;
3405b636857STetsuo Handa 		}
3415b636857STetsuo Handa 	}
3425b636857STetsuo Handa 	envp->name = name;
3435b636857STetsuo Handa 	envp->value = value;
3445b636857STetsuo Handa 	return true;
3455b636857STetsuo Handa out:
3465b636857STetsuo Handa 	return false;
3475b636857STetsuo Handa }
3485b636857STetsuo Handa 
3495b636857STetsuo Handa /**
3502066a361STetsuo Handa  * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
3512066a361STetsuo Handa  *
3522066a361STetsuo Handa  * @a: Pointer to "struct tomoyo_condition".
3532066a361STetsuo Handa  * @b: Pointer to "struct tomoyo_condition".
3542066a361STetsuo Handa  *
3552066a361STetsuo Handa  * Returns true if @a == @b, false otherwise.
3562066a361STetsuo Handa  */
tomoyo_same_condition(const struct tomoyo_condition * a,const struct tomoyo_condition * b)3572066a361STetsuo Handa static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
3582066a361STetsuo Handa 					 const struct tomoyo_condition *b)
3592066a361STetsuo Handa {
3602066a361STetsuo Handa 	return a->size == b->size && a->condc == b->condc &&
3612066a361STetsuo Handa 		a->numbers_count == b->numbers_count &&
3622ca9bf45STetsuo Handa 		a->names_count == b->names_count &&
3635b636857STetsuo Handa 		a->argc == b->argc && a->envc == b->envc &&
3646bce98edSTetsuo Handa 		a->grant_log == b->grant_log && a->transit == b->transit &&
3652066a361STetsuo Handa 		!memcmp(a + 1, b + 1, a->size - sizeof(*a));
3662066a361STetsuo Handa }
3672066a361STetsuo Handa 
3682066a361STetsuo Handa /**
3692066a361STetsuo Handa  * tomoyo_condition_type - Get condition type.
3702066a361STetsuo Handa  *
3712066a361STetsuo Handa  * @word: Keyword string.
3722066a361STetsuo Handa  *
3732066a361STetsuo Handa  * Returns one of values in "enum tomoyo_conditions_index" on success,
3742066a361STetsuo Handa  * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
3752066a361STetsuo Handa  */
tomoyo_condition_type(const char * word)3762066a361STetsuo Handa static u8 tomoyo_condition_type(const char *word)
3772066a361STetsuo Handa {
3782066a361STetsuo Handa 	u8 i;
379cdcf6723STetsuo Handa 
3802066a361STetsuo Handa 	for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
3812066a361STetsuo Handa 		if (!strcmp(word, tomoyo_condition_keyword[i]))
3822066a361STetsuo Handa 			break;
3832066a361STetsuo Handa 	}
3842066a361STetsuo Handa 	return i;
3852066a361STetsuo Handa }
3862066a361STetsuo Handa 
3872066a361STetsuo Handa /* Define this to enable debug mode. */
3882066a361STetsuo Handa /* #define DEBUG_CONDITION */
3892066a361STetsuo Handa 
3902066a361STetsuo Handa #ifdef DEBUG_CONDITION
3912066a361STetsuo Handa #define dprintk printk
3922066a361STetsuo Handa #else
3932066a361STetsuo Handa #define dprintk(...) do { } while (0)
3942066a361STetsuo Handa #endif
3952066a361STetsuo Handa 
3962066a361STetsuo Handa /**
3972066a361STetsuo Handa  * tomoyo_commit_condition - Commit "struct tomoyo_condition".
3982066a361STetsuo Handa  *
3992066a361STetsuo Handa  * @entry: Pointer to "struct tomoyo_condition".
4002066a361STetsuo Handa  *
4012066a361STetsuo Handa  * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
4022066a361STetsuo Handa  *
4032066a361STetsuo Handa  * This function merges duplicated entries. This function returns NULL if
4042066a361STetsuo Handa  * @entry is not duplicated but memory quota for policy has exceeded.
4052066a361STetsuo Handa  */
tomoyo_commit_condition(struct tomoyo_condition * entry)4062066a361STetsuo Handa static struct tomoyo_condition *tomoyo_commit_condition
4072066a361STetsuo Handa (struct tomoyo_condition *entry)
4082066a361STetsuo Handa {
4092066a361STetsuo Handa 	struct tomoyo_condition *ptr;
4102066a361STetsuo Handa 	bool found = false;
411cdcf6723STetsuo Handa 
4122066a361STetsuo Handa 	if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
4132066a361STetsuo Handa 		dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
4142066a361STetsuo Handa 		ptr = NULL;
4152066a361STetsuo Handa 		found = true;
4162066a361STetsuo Handa 		goto out;
4172066a361STetsuo Handa 	}
418f9732ea1STetsuo Handa 	list_for_each_entry(ptr, &tomoyo_condition_list, head.list) {
419f9732ea1STetsuo Handa 		if (!tomoyo_same_condition(ptr, entry) ||
420f9732ea1STetsuo Handa 		    atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
4212066a361STetsuo Handa 			continue;
4222066a361STetsuo Handa 		/* Same entry found. Share this entry. */
4232066a361STetsuo Handa 		atomic_inc(&ptr->head.users);
4242066a361STetsuo Handa 		found = true;
4252066a361STetsuo Handa 		break;
4262066a361STetsuo Handa 	}
4272066a361STetsuo Handa 	if (!found) {
4282066a361STetsuo Handa 		if (tomoyo_memory_ok(entry)) {
4292066a361STetsuo Handa 			atomic_set(&entry->head.users, 1);
430f9732ea1STetsuo Handa 			list_add(&entry->head.list, &tomoyo_condition_list);
4312066a361STetsuo Handa 		} else {
4322066a361STetsuo Handa 			found = true;
4332066a361STetsuo Handa 			ptr = NULL;
4342066a361STetsuo Handa 		}
4352066a361STetsuo Handa 	}
4362066a361STetsuo Handa 	mutex_unlock(&tomoyo_policy_lock);
4372066a361STetsuo Handa out:
4382066a361STetsuo Handa 	if (found) {
4392066a361STetsuo Handa 		tomoyo_del_condition(&entry->head.list);
4402066a361STetsuo Handa 		kfree(entry);
4412066a361STetsuo Handa 		entry = ptr;
4422066a361STetsuo Handa 	}
4432066a361STetsuo Handa 	return entry;
4442066a361STetsuo Handa }
4452066a361STetsuo Handa 
4462066a361STetsuo Handa /**
4476bce98edSTetsuo Handa  * tomoyo_get_transit_preference - Parse domain transition preference for execve().
4486bce98edSTetsuo Handa  *
4496bce98edSTetsuo Handa  * @param: Pointer to "struct tomoyo_acl_param".
4506bce98edSTetsuo Handa  * @e:     Pointer to "struct tomoyo_condition".
4516bce98edSTetsuo Handa  *
4526bce98edSTetsuo Handa  * Returns the condition string part.
4536bce98edSTetsuo Handa  */
tomoyo_get_transit_preference(struct tomoyo_acl_param * param,struct tomoyo_condition * e)4546bce98edSTetsuo Handa static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param,
4556bce98edSTetsuo Handa 					   struct tomoyo_condition *e)
4566bce98edSTetsuo Handa {
4576bce98edSTetsuo Handa 	char * const pos = param->data;
4586bce98edSTetsuo Handa 	bool flag;
459cdcf6723STetsuo Handa 
4606bce98edSTetsuo Handa 	if (*pos == '<') {
4616bce98edSTetsuo Handa 		e->transit = tomoyo_get_domainname(param);
4626bce98edSTetsuo Handa 		goto done;
4636bce98edSTetsuo Handa 	}
4646bce98edSTetsuo Handa 	{
4656bce98edSTetsuo Handa 		char *cp = strchr(pos, ' ');
466cdcf6723STetsuo Handa 
4676bce98edSTetsuo Handa 		if (cp)
4686bce98edSTetsuo Handa 			*cp = '\0';
4696bce98edSTetsuo Handa 		flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") ||
4706bce98edSTetsuo Handa 			!strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
4716bce98edSTetsuo Handa 			!strcmp(pos, "child") || !strcmp(pos, "parent");
4726bce98edSTetsuo Handa 		if (cp)
4736bce98edSTetsuo Handa 			*cp = ' ';
4746bce98edSTetsuo Handa 	}
4756bce98edSTetsuo Handa 	if (!flag)
4766bce98edSTetsuo Handa 		return pos;
4776bce98edSTetsuo Handa 	e->transit = tomoyo_get_name(tomoyo_read_token(param));
4786bce98edSTetsuo Handa done:
4796bce98edSTetsuo Handa 	if (e->transit)
4806bce98edSTetsuo Handa 		return param->data;
4816bce98edSTetsuo Handa 	/*
4826bce98edSTetsuo Handa 	 * Return a bad read-only condition string that will let
4836bce98edSTetsuo Handa 	 * tomoyo_get_condition() return NULL.
4846bce98edSTetsuo Handa 	 */
4856bce98edSTetsuo Handa 	return "/";
4866bce98edSTetsuo Handa }
4876bce98edSTetsuo Handa 
4886bce98edSTetsuo Handa /**
4892066a361STetsuo Handa  * tomoyo_get_condition - Parse condition part.
4902066a361STetsuo Handa  *
4912066a361STetsuo Handa  * @param: Pointer to "struct tomoyo_acl_param".
4922066a361STetsuo Handa  *
4932066a361STetsuo Handa  * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
4942066a361STetsuo Handa  */
tomoyo_get_condition(struct tomoyo_acl_param * param)4952066a361STetsuo Handa struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
4962066a361STetsuo Handa {
4972066a361STetsuo Handa 	struct tomoyo_condition *entry = NULL;
4982066a361STetsuo Handa 	struct tomoyo_condition_element *condp = NULL;
4992066a361STetsuo Handa 	struct tomoyo_number_union *numbers_p = NULL;
5002ca9bf45STetsuo Handa 	struct tomoyo_name_union *names_p = NULL;
5015b636857STetsuo Handa 	struct tomoyo_argv *argv = NULL;
5025b636857STetsuo Handa 	struct tomoyo_envp *envp = NULL;
5032066a361STetsuo Handa 	struct tomoyo_condition e = { };
5046bce98edSTetsuo Handa 	char * const start_of_string =
5056bce98edSTetsuo Handa 		tomoyo_get_transit_preference(param, &e);
5062066a361STetsuo Handa 	char * const end_of_string = start_of_string + strlen(start_of_string);
5072066a361STetsuo Handa 	char *pos;
508cdcf6723STetsuo Handa 
5092066a361STetsuo Handa rerun:
5102066a361STetsuo Handa 	pos = start_of_string;
5112066a361STetsuo Handa 	while (1) {
5122066a361STetsuo Handa 		u8 left = -1;
5132066a361STetsuo Handa 		u8 right = -1;
5142066a361STetsuo Handa 		char *left_word = pos;
5152066a361STetsuo Handa 		char *cp;
5162066a361STetsuo Handa 		char *right_word;
5172066a361STetsuo Handa 		bool is_not;
518cdcf6723STetsuo Handa 
5192066a361STetsuo Handa 		if (!*left_word)
5202066a361STetsuo Handa 			break;
5212066a361STetsuo Handa 		/*
5222066a361STetsuo Handa 		 * Since left-hand condition does not allow use of "path_group"
5232066a361STetsuo Handa 		 * or "number_group" and environment variable's names do not
5242066a361STetsuo Handa 		 * accept '=', it is guaranteed that the original line consists
5252066a361STetsuo Handa 		 * of one or more repetition of $left$operator$right blocks
5262066a361STetsuo Handa 		 * where "$left is free from '=' and ' '" and "$operator is
5272066a361STetsuo Handa 		 * either '=' or '!='" and "$right is free from ' '".
5282066a361STetsuo Handa 		 * Therefore, we can reconstruct the original line at the end
5292066a361STetsuo Handa 		 * of dry run even if we overwrite $operator with '\0'.
5302066a361STetsuo Handa 		 */
5312066a361STetsuo Handa 		cp = strchr(pos, ' ');
5322066a361STetsuo Handa 		if (cp) {
5332066a361STetsuo Handa 			*cp = '\0'; /* Will restore later. */
5342066a361STetsuo Handa 			pos = cp + 1;
5352066a361STetsuo Handa 		} else {
5362066a361STetsuo Handa 			pos = "";
5372066a361STetsuo Handa 		}
5382066a361STetsuo Handa 		right_word = strchr(left_word, '=');
5392066a361STetsuo Handa 		if (!right_word || right_word == left_word)
5402066a361STetsuo Handa 			goto out;
5412066a361STetsuo Handa 		is_not = *(right_word - 1) == '!';
5422066a361STetsuo Handa 		if (is_not)
5432066a361STetsuo Handa 			*(right_word++ - 1) = '\0'; /* Will restore later. */
5442066a361STetsuo Handa 		else if (*(right_word + 1) != '=')
5452066a361STetsuo Handa 			*right_word++ = '\0'; /* Will restore later. */
5462066a361STetsuo Handa 		else
5472066a361STetsuo Handa 			goto out;
5482066a361STetsuo Handa 		dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
5492066a361STetsuo Handa 			is_not ? "!" : "", right_word);
5501f067a68STetsuo Handa 		if (!strcmp(left_word, "grant_log")) {
5511f067a68STetsuo Handa 			if (entry) {
5521f067a68STetsuo Handa 				if (is_not ||
5531f067a68STetsuo Handa 				    entry->grant_log != TOMOYO_GRANTLOG_AUTO)
5541f067a68STetsuo Handa 					goto out;
5551f067a68STetsuo Handa 				else if (!strcmp(right_word, "yes"))
5561f067a68STetsuo Handa 					entry->grant_log = TOMOYO_GRANTLOG_YES;
5571f067a68STetsuo Handa 				else if (!strcmp(right_word, "no"))
5581f067a68STetsuo Handa 					entry->grant_log = TOMOYO_GRANTLOG_NO;
5591f067a68STetsuo Handa 				else
5601f067a68STetsuo Handa 					goto out;
5611f067a68STetsuo Handa 			}
5621f067a68STetsuo Handa 			continue;
5631f067a68STetsuo Handa 		}
5645b636857STetsuo Handa 		if (!strncmp(left_word, "exec.argv[", 10)) {
5655b636857STetsuo Handa 			if (!argv) {
5665b636857STetsuo Handa 				e.argc++;
5675b636857STetsuo Handa 				e.condc++;
5685b636857STetsuo Handa 			} else {
5695b636857STetsuo Handa 				e.argc--;
5705b636857STetsuo Handa 				e.condc--;
5715b636857STetsuo Handa 				left = TOMOYO_ARGV_ENTRY;
5725b636857STetsuo Handa 				argv->is_not = is_not;
5735b636857STetsuo Handa 				if (!tomoyo_parse_argv(left_word + 10,
5745b636857STetsuo Handa 						       right_word, argv++))
5755b636857STetsuo Handa 					goto out;
5765b636857STetsuo Handa 			}
5775b636857STetsuo Handa 			goto store_value;
5785b636857STetsuo Handa 		}
5795b636857STetsuo Handa 		if (!strncmp(left_word, "exec.envp[\"", 11)) {
5805b636857STetsuo Handa 			if (!envp) {
5815b636857STetsuo Handa 				e.envc++;
5825b636857STetsuo Handa 				e.condc++;
5835b636857STetsuo Handa 			} else {
5845b636857STetsuo Handa 				e.envc--;
5855b636857STetsuo Handa 				e.condc--;
5865b636857STetsuo Handa 				left = TOMOYO_ENVP_ENTRY;
5875b636857STetsuo Handa 				envp->is_not = is_not;
5885b636857STetsuo Handa 				if (!tomoyo_parse_envp(left_word + 11,
5895b636857STetsuo Handa 						       right_word, envp++))
5905b636857STetsuo Handa 					goto out;
5915b636857STetsuo Handa 			}
5925b636857STetsuo Handa 			goto store_value;
5935b636857STetsuo Handa 		}
5942066a361STetsuo Handa 		left = tomoyo_condition_type(left_word);
5952066a361STetsuo Handa 		dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
5962066a361STetsuo Handa 			left);
5972066a361STetsuo Handa 		if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
5982066a361STetsuo Handa 			if (!numbers_p) {
5992066a361STetsuo Handa 				e.numbers_count++;
6002066a361STetsuo Handa 			} else {
6012066a361STetsuo Handa 				e.numbers_count--;
6022066a361STetsuo Handa 				left = TOMOYO_NUMBER_UNION;
6032066a361STetsuo Handa 				param->data = left_word;
6042066a361STetsuo Handa 				if (*left_word == '@' ||
6052066a361STetsuo Handa 				    !tomoyo_parse_number_union(param,
6062066a361STetsuo Handa 							       numbers_p++))
6072066a361STetsuo Handa 					goto out;
6082066a361STetsuo Handa 			}
6092066a361STetsuo Handa 		}
6102066a361STetsuo Handa 		if (!condp)
6112066a361STetsuo Handa 			e.condc++;
6122066a361STetsuo Handa 		else
6132066a361STetsuo Handa 			e.condc--;
6142ca9bf45STetsuo Handa 		if (left == TOMOYO_EXEC_REALPATH ||
6152ca9bf45STetsuo Handa 		    left == TOMOYO_SYMLINK_TARGET) {
6162ca9bf45STetsuo Handa 			if (!names_p) {
6172ca9bf45STetsuo Handa 				e.names_count++;
6182ca9bf45STetsuo Handa 			} else {
6192ca9bf45STetsuo Handa 				e.names_count--;
6202ca9bf45STetsuo Handa 				right = TOMOYO_NAME_UNION;
6212ca9bf45STetsuo Handa 				param->data = right_word;
6222ca9bf45STetsuo Handa 				if (!tomoyo_parse_name_union_quoted(param,
6232ca9bf45STetsuo Handa 								    names_p++))
6242ca9bf45STetsuo Handa 					goto out;
6252ca9bf45STetsuo Handa 			}
6262ca9bf45STetsuo Handa 			goto store_value;
6272ca9bf45STetsuo Handa 		}
6282066a361STetsuo Handa 		right = tomoyo_condition_type(right_word);
6292066a361STetsuo Handa 		if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
6302066a361STetsuo Handa 			if (!numbers_p) {
6312066a361STetsuo Handa 				e.numbers_count++;
6322066a361STetsuo Handa 			} else {
6332066a361STetsuo Handa 				e.numbers_count--;
6342066a361STetsuo Handa 				right = TOMOYO_NUMBER_UNION;
6352066a361STetsuo Handa 				param->data = right_word;
6362066a361STetsuo Handa 				if (!tomoyo_parse_number_union(param,
6372066a361STetsuo Handa 							       numbers_p++))
6382066a361STetsuo Handa 					goto out;
6392066a361STetsuo Handa 			}
6402066a361STetsuo Handa 		}
6412ca9bf45STetsuo Handa store_value:
6422066a361STetsuo Handa 		if (!condp) {
643cdcf6723STetsuo Handa 			dprintk(KERN_WARNING "%u: dry_run left=%u right=%u match=%u\n",
644cdcf6723STetsuo Handa 				__LINE__, left, right, !is_not);
6452066a361STetsuo Handa 			continue;
6462066a361STetsuo Handa 		}
6472066a361STetsuo Handa 		condp->left = left;
6482066a361STetsuo Handa 		condp->right = right;
6492066a361STetsuo Handa 		condp->equals = !is_not;
6502066a361STetsuo Handa 		dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
6512066a361STetsuo Handa 			__LINE__, condp->left, condp->right,
6522066a361STetsuo Handa 			condp->equals);
6532066a361STetsuo Handa 		condp++;
6542066a361STetsuo Handa 	}
6555b636857STetsuo Handa 	dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
6565b636857STetsuo Handa 		__LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
6575b636857STetsuo Handa 		e.envc);
6582066a361STetsuo Handa 	if (entry) {
6595b636857STetsuo Handa 		BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
6605b636857STetsuo Handa 		       e.condc);
6612066a361STetsuo Handa 		return tomoyo_commit_condition(entry);
6622066a361STetsuo Handa 	}
6632066a361STetsuo Handa 	e.size = sizeof(*entry)
6642066a361STetsuo Handa 		+ e.condc * sizeof(struct tomoyo_condition_element)
6652ca9bf45STetsuo Handa 		+ e.numbers_count * sizeof(struct tomoyo_number_union)
6665b636857STetsuo Handa 		+ e.names_count * sizeof(struct tomoyo_name_union)
6675b636857STetsuo Handa 		+ e.argc * sizeof(struct tomoyo_argv)
6685b636857STetsuo Handa 		+ e.envc * sizeof(struct tomoyo_envp);
6692066a361STetsuo Handa 	entry = kzalloc(e.size, GFP_NOFS);
6702066a361STetsuo Handa 	if (!entry)
6716bce98edSTetsuo Handa 		goto out2;
6722066a361STetsuo Handa 	*entry = e;
6736bce98edSTetsuo Handa 	e.transit = NULL;
6742066a361STetsuo Handa 	condp = (struct tomoyo_condition_element *) (entry + 1);
6752066a361STetsuo Handa 	numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
6762ca9bf45STetsuo Handa 	names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
6775b636857STetsuo Handa 	argv = (struct tomoyo_argv *) (names_p + e.names_count);
6785b636857STetsuo Handa 	envp = (struct tomoyo_envp *) (argv + e.argc);
6792066a361STetsuo Handa 	{
6802066a361STetsuo Handa 		bool flag = false;
681cdcf6723STetsuo Handa 
6822066a361STetsuo Handa 		for (pos = start_of_string; pos < end_of_string; pos++) {
6832066a361STetsuo Handa 			if (*pos)
6842066a361STetsuo Handa 				continue;
6852066a361STetsuo Handa 			if (flag) /* Restore " ". */
6862066a361STetsuo Handa 				*pos = ' ';
6872066a361STetsuo Handa 			else if (*(pos + 1) == '=') /* Restore "!=". */
6882066a361STetsuo Handa 				*pos = '!';
6892066a361STetsuo Handa 			else /* Restore "=". */
6902066a361STetsuo Handa 				*pos = '=';
6912066a361STetsuo Handa 			flag = !flag;
6922066a361STetsuo Handa 		}
6932066a361STetsuo Handa 	}
6942066a361STetsuo Handa 	goto rerun;
6952066a361STetsuo Handa out:
6962066a361STetsuo Handa 	dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
6972066a361STetsuo Handa 	if (entry) {
6982066a361STetsuo Handa 		tomoyo_del_condition(&entry->head.list);
6992066a361STetsuo Handa 		kfree(entry);
7002066a361STetsuo Handa 	}
7016bce98edSTetsuo Handa out2:
7026bce98edSTetsuo Handa 	tomoyo_put_name(e.transit);
7032066a361STetsuo Handa 	return NULL;
7042066a361STetsuo Handa }
7052066a361STetsuo Handa 
7062066a361STetsuo Handa /**
7078761afd4STetsuo Handa  * tomoyo_get_attributes - Revalidate "struct inode".
7088761afd4STetsuo Handa  *
7098761afd4STetsuo Handa  * @obj: Pointer to "struct tomoyo_obj_info".
7108761afd4STetsuo Handa  *
7118761afd4STetsuo Handa  * Returns nothing.
7128761afd4STetsuo Handa  */
tomoyo_get_attributes(struct tomoyo_obj_info * obj)7138761afd4STetsuo Handa void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
7148761afd4STetsuo Handa {
7158761afd4STetsuo Handa 	u8 i;
7168761afd4STetsuo Handa 	struct dentry *dentry = NULL;
7178761afd4STetsuo Handa 
7188761afd4STetsuo Handa 	for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
7198761afd4STetsuo Handa 		struct inode *inode;
720cdcf6723STetsuo Handa 
7218761afd4STetsuo Handa 		switch (i) {
7228761afd4STetsuo Handa 		case TOMOYO_PATH1:
7238761afd4STetsuo Handa 			dentry = obj->path1.dentry;
7248761afd4STetsuo Handa 			if (!dentry)
7258761afd4STetsuo Handa 				continue;
7268761afd4STetsuo Handa 			break;
7278761afd4STetsuo Handa 		case TOMOYO_PATH2:
7288761afd4STetsuo Handa 			dentry = obj->path2.dentry;
7298761afd4STetsuo Handa 			if (!dentry)
7308761afd4STetsuo Handa 				continue;
7318761afd4STetsuo Handa 			break;
7328761afd4STetsuo Handa 		default:
7338761afd4STetsuo Handa 			if (!dentry)
7348761afd4STetsuo Handa 				continue;
7358761afd4STetsuo Handa 			dentry = dget_parent(dentry);
7368761afd4STetsuo Handa 			break;
7378761afd4STetsuo Handa 		}
738c6f493d6SDavid Howells 		inode = d_backing_inode(dentry);
7398761afd4STetsuo Handa 		if (inode) {
7408761afd4STetsuo Handa 			struct tomoyo_mini_stat *stat = &obj->stat[i];
741cdcf6723STetsuo Handa 
7428761afd4STetsuo Handa 			stat->uid  = inode->i_uid;
7438761afd4STetsuo Handa 			stat->gid  = inode->i_gid;
7448761afd4STetsuo Handa 			stat->ino  = inode->i_ino;
7458761afd4STetsuo Handa 			stat->mode = inode->i_mode;
7468761afd4STetsuo Handa 			stat->dev  = inode->i_sb->s_dev;
7478761afd4STetsuo Handa 			stat->rdev = inode->i_rdev;
7488761afd4STetsuo Handa 			obj->stat_valid[i] = true;
7498761afd4STetsuo Handa 		}
750cdcf6723STetsuo Handa 		if (i & 1) /* TOMOYO_PATH1_PARENT or TOMOYO_PATH2_PARENT */
7518761afd4STetsuo Handa 			dput(dentry);
7528761afd4STetsuo Handa 	}
7538761afd4STetsuo Handa }
7548761afd4STetsuo Handa 
7558761afd4STetsuo Handa /**
7562066a361STetsuo Handa  * tomoyo_condition - Check condition part.
7572066a361STetsuo Handa  *
7582066a361STetsuo Handa  * @r:    Pointer to "struct tomoyo_request_info".
7592066a361STetsuo Handa  * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
7602066a361STetsuo Handa  *
7612066a361STetsuo Handa  * Returns true on success, false otherwise.
7622066a361STetsuo Handa  *
7632066a361STetsuo Handa  * Caller holds tomoyo_read_lock().
7642066a361STetsuo Handa  */
tomoyo_condition(struct tomoyo_request_info * r,const struct tomoyo_condition * cond)7652066a361STetsuo Handa bool tomoyo_condition(struct tomoyo_request_info *r,
7662066a361STetsuo Handa 		      const struct tomoyo_condition *cond)
7672066a361STetsuo Handa {
7682066a361STetsuo Handa 	u32 i;
7692066a361STetsuo Handa 	unsigned long min_v[2] = { 0, 0 };
7702066a361STetsuo Handa 	unsigned long max_v[2] = { 0, 0 };
7712066a361STetsuo Handa 	const struct tomoyo_condition_element *condp;
7722066a361STetsuo Handa 	const struct tomoyo_number_union *numbers_p;
7732ca9bf45STetsuo Handa 	const struct tomoyo_name_union *names_p;
7745b636857STetsuo Handa 	const struct tomoyo_argv *argv;
7755b636857STetsuo Handa 	const struct tomoyo_envp *envp;
7768761afd4STetsuo Handa 	struct tomoyo_obj_info *obj;
7772066a361STetsuo Handa 	u16 condc;
7785b636857STetsuo Handa 	u16 argc;
7795b636857STetsuo Handa 	u16 envc;
7805b636857STetsuo Handa 	struct linux_binprm *bprm = NULL;
781cdcf6723STetsuo Handa 
7822066a361STetsuo Handa 	if (!cond)
7832066a361STetsuo Handa 		return true;
7842066a361STetsuo Handa 	condc = cond->condc;
7855b636857STetsuo Handa 	argc = cond->argc;
7865b636857STetsuo Handa 	envc = cond->envc;
7878761afd4STetsuo Handa 	obj = r->obj;
7885b636857STetsuo Handa 	if (r->ee)
7895b636857STetsuo Handa 		bprm = r->ee->bprm;
7905b636857STetsuo Handa 	if (!bprm && (argc || envc))
7915b636857STetsuo Handa 		return false;
7922066a361STetsuo Handa 	condp = (struct tomoyo_condition_element *) (cond + 1);
7932066a361STetsuo Handa 	numbers_p = (const struct tomoyo_number_union *) (condp + condc);
7942ca9bf45STetsuo Handa 	names_p = (const struct tomoyo_name_union *)
7952ca9bf45STetsuo Handa 		(numbers_p + cond->numbers_count);
7965b636857STetsuo Handa 	argv = (const struct tomoyo_argv *) (names_p + cond->names_count);
7975b636857STetsuo Handa 	envp = (const struct tomoyo_envp *) (argv + argc);
7982066a361STetsuo Handa 	for (i = 0; i < condc; i++) {
7992066a361STetsuo Handa 		const bool match = condp->equals;
8002066a361STetsuo Handa 		const u8 left = condp->left;
8012066a361STetsuo Handa 		const u8 right = condp->right;
8028761afd4STetsuo Handa 		bool is_bitop[2] = { false, false };
8032066a361STetsuo Handa 		u8 j;
804cdcf6723STetsuo Handa 
8052066a361STetsuo Handa 		condp++;
8065b636857STetsuo Handa 		/* Check argv[] and envp[] later. */
8075b636857STetsuo Handa 		if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
8085b636857STetsuo Handa 			continue;
8092ca9bf45STetsuo Handa 		/* Check string expressions. */
8102ca9bf45STetsuo Handa 		if (right == TOMOYO_NAME_UNION) {
8112ca9bf45STetsuo Handa 			const struct tomoyo_name_union *ptr = names_p++;
8122ca9bf45STetsuo Handa 			struct tomoyo_path_info *symlink;
8132ca9bf45STetsuo Handa 			struct tomoyo_execve *ee;
8142ca9bf45STetsuo Handa 			struct file *file;
815cdcf6723STetsuo Handa 
816cdcf6723STetsuo Handa 			switch (left) {
8172ca9bf45STetsuo Handa 			case TOMOYO_SYMLINK_TARGET:
8182ca9bf45STetsuo Handa 				symlink = obj ? obj->symlink_target : NULL;
8192ca9bf45STetsuo Handa 				if (!symlink ||
8202ca9bf45STetsuo Handa 				    !tomoyo_compare_name_union(symlink, ptr)
8212ca9bf45STetsuo Handa 				    == match)
8222ca9bf45STetsuo Handa 					goto out;
8232ca9bf45STetsuo Handa 				break;
8242ca9bf45STetsuo Handa 			case TOMOYO_EXEC_REALPATH:
8252ca9bf45STetsuo Handa 				ee = r->ee;
8262ca9bf45STetsuo Handa 				file = ee ? ee->bprm->file : NULL;
8272ca9bf45STetsuo Handa 				if (!tomoyo_scan_exec_realpath(file, ptr,
8282ca9bf45STetsuo Handa 							       match))
8292ca9bf45STetsuo Handa 					goto out;
8302ca9bf45STetsuo Handa 				break;
8312ca9bf45STetsuo Handa 			}
8322ca9bf45STetsuo Handa 			continue;
8332ca9bf45STetsuo Handa 		}
8342066a361STetsuo Handa 		/* Check numeric or bit-op expressions. */
8352066a361STetsuo Handa 		for (j = 0; j < 2; j++) {
8362066a361STetsuo Handa 			const u8 index = j ? right : left;
8372066a361STetsuo Handa 			unsigned long value = 0;
838cdcf6723STetsuo Handa 
8392066a361STetsuo Handa 			switch (index) {
8402066a361STetsuo Handa 			case TOMOYO_TASK_UID:
841609fcd1bSEric W. Biederman 				value = from_kuid(&init_user_ns, current_uid());
8422066a361STetsuo Handa 				break;
8432066a361STetsuo Handa 			case TOMOYO_TASK_EUID:
844609fcd1bSEric W. Biederman 				value = from_kuid(&init_user_ns, current_euid());
8452066a361STetsuo Handa 				break;
8462066a361STetsuo Handa 			case TOMOYO_TASK_SUID:
847609fcd1bSEric W. Biederman 				value = from_kuid(&init_user_ns, current_suid());
8482066a361STetsuo Handa 				break;
8492066a361STetsuo Handa 			case TOMOYO_TASK_FSUID:
850609fcd1bSEric W. Biederman 				value = from_kuid(&init_user_ns, current_fsuid());
8512066a361STetsuo Handa 				break;
8522066a361STetsuo Handa 			case TOMOYO_TASK_GID:
853609fcd1bSEric W. Biederman 				value = from_kgid(&init_user_ns, current_gid());
8542066a361STetsuo Handa 				break;
8552066a361STetsuo Handa 			case TOMOYO_TASK_EGID:
856609fcd1bSEric W. Biederman 				value = from_kgid(&init_user_ns, current_egid());
8572066a361STetsuo Handa 				break;
8582066a361STetsuo Handa 			case TOMOYO_TASK_SGID:
859609fcd1bSEric W. Biederman 				value = from_kgid(&init_user_ns, current_sgid());
8602066a361STetsuo Handa 				break;
8612066a361STetsuo Handa 			case TOMOYO_TASK_FSGID:
862609fcd1bSEric W. Biederman 				value = from_kgid(&init_user_ns, current_fsgid());
8632066a361STetsuo Handa 				break;
8642066a361STetsuo Handa 			case TOMOYO_TASK_PID:
8652066a361STetsuo Handa 				value = tomoyo_sys_getpid();
8662066a361STetsuo Handa 				break;
8672066a361STetsuo Handa 			case TOMOYO_TASK_PPID:
8682066a361STetsuo Handa 				value = tomoyo_sys_getppid();
8692066a361STetsuo Handa 				break;
8708761afd4STetsuo Handa 			case TOMOYO_TYPE_IS_SOCKET:
8718761afd4STetsuo Handa 				value = S_IFSOCK;
8728761afd4STetsuo Handa 				break;
8738761afd4STetsuo Handa 			case TOMOYO_TYPE_IS_SYMLINK:
8748761afd4STetsuo Handa 				value = S_IFLNK;
8758761afd4STetsuo Handa 				break;
8768761afd4STetsuo Handa 			case TOMOYO_TYPE_IS_FILE:
8778761afd4STetsuo Handa 				value = S_IFREG;
8788761afd4STetsuo Handa 				break;
8798761afd4STetsuo Handa 			case TOMOYO_TYPE_IS_BLOCK_DEV:
8808761afd4STetsuo Handa 				value = S_IFBLK;
8818761afd4STetsuo Handa 				break;
8828761afd4STetsuo Handa 			case TOMOYO_TYPE_IS_DIRECTORY:
8838761afd4STetsuo Handa 				value = S_IFDIR;
8848761afd4STetsuo Handa 				break;
8858761afd4STetsuo Handa 			case TOMOYO_TYPE_IS_CHAR_DEV:
8868761afd4STetsuo Handa 				value = S_IFCHR;
8878761afd4STetsuo Handa 				break;
8888761afd4STetsuo Handa 			case TOMOYO_TYPE_IS_FIFO:
8898761afd4STetsuo Handa 				value = S_IFIFO;
8908761afd4STetsuo Handa 				break;
8918761afd4STetsuo Handa 			case TOMOYO_MODE_SETUID:
8928761afd4STetsuo Handa 				value = S_ISUID;
8938761afd4STetsuo Handa 				break;
8948761afd4STetsuo Handa 			case TOMOYO_MODE_SETGID:
8958761afd4STetsuo Handa 				value = S_ISGID;
8968761afd4STetsuo Handa 				break;
8978761afd4STetsuo Handa 			case TOMOYO_MODE_STICKY:
8988761afd4STetsuo Handa 				value = S_ISVTX;
8998761afd4STetsuo Handa 				break;
9008761afd4STetsuo Handa 			case TOMOYO_MODE_OWNER_READ:
901cdcf6723STetsuo Handa 				value = 0400;
9028761afd4STetsuo Handa 				break;
9038761afd4STetsuo Handa 			case TOMOYO_MODE_OWNER_WRITE:
904cdcf6723STetsuo Handa 				value = 0200;
9058761afd4STetsuo Handa 				break;
9068761afd4STetsuo Handa 			case TOMOYO_MODE_OWNER_EXECUTE:
907cdcf6723STetsuo Handa 				value = 0100;
9088761afd4STetsuo Handa 				break;
9098761afd4STetsuo Handa 			case TOMOYO_MODE_GROUP_READ:
910cdcf6723STetsuo Handa 				value = 0040;
9118761afd4STetsuo Handa 				break;
9128761afd4STetsuo Handa 			case TOMOYO_MODE_GROUP_WRITE:
913cdcf6723STetsuo Handa 				value = 0020;
9148761afd4STetsuo Handa 				break;
9158761afd4STetsuo Handa 			case TOMOYO_MODE_GROUP_EXECUTE:
916cdcf6723STetsuo Handa 				value = 0010;
9178761afd4STetsuo Handa 				break;
9188761afd4STetsuo Handa 			case TOMOYO_MODE_OTHERS_READ:
919cdcf6723STetsuo Handa 				value = 0004;
9208761afd4STetsuo Handa 				break;
9218761afd4STetsuo Handa 			case TOMOYO_MODE_OTHERS_WRITE:
922cdcf6723STetsuo Handa 				value = 0002;
9238761afd4STetsuo Handa 				break;
9248761afd4STetsuo Handa 			case TOMOYO_MODE_OTHERS_EXECUTE:
925cdcf6723STetsuo Handa 				value = 0001;
9268761afd4STetsuo Handa 				break;
9275b636857STetsuo Handa 			case TOMOYO_EXEC_ARGC:
9285b636857STetsuo Handa 				if (!bprm)
9295b636857STetsuo Handa 					goto out;
9305b636857STetsuo Handa 				value = bprm->argc;
9315b636857STetsuo Handa 				break;
9325b636857STetsuo Handa 			case TOMOYO_EXEC_ENVC:
9335b636857STetsuo Handa 				if (!bprm)
9345b636857STetsuo Handa 					goto out;
9355b636857STetsuo Handa 				value = bprm->envc;
9365b636857STetsuo Handa 				break;
9372066a361STetsuo Handa 			case TOMOYO_NUMBER_UNION:
9382066a361STetsuo Handa 				/* Fetch values later. */
9392066a361STetsuo Handa 				break;
9402066a361STetsuo Handa 			default:
9418761afd4STetsuo Handa 				if (!obj)
9428761afd4STetsuo Handa 					goto out;
9438761afd4STetsuo Handa 				if (!obj->validate_done) {
9448761afd4STetsuo Handa 					tomoyo_get_attributes(obj);
9458761afd4STetsuo Handa 					obj->validate_done = true;
9468761afd4STetsuo Handa 				}
9478761afd4STetsuo Handa 				{
9488761afd4STetsuo Handa 					u8 stat_index;
9498761afd4STetsuo Handa 					struct tomoyo_mini_stat *stat;
950cdcf6723STetsuo Handa 
9518761afd4STetsuo Handa 					switch (index) {
9528761afd4STetsuo Handa 					case TOMOYO_PATH1_UID:
9538761afd4STetsuo Handa 					case TOMOYO_PATH1_GID:
9548761afd4STetsuo Handa 					case TOMOYO_PATH1_INO:
9558761afd4STetsuo Handa 					case TOMOYO_PATH1_MAJOR:
9568761afd4STetsuo Handa 					case TOMOYO_PATH1_MINOR:
9578761afd4STetsuo Handa 					case TOMOYO_PATH1_TYPE:
9588761afd4STetsuo Handa 					case TOMOYO_PATH1_DEV_MAJOR:
9598761afd4STetsuo Handa 					case TOMOYO_PATH1_DEV_MINOR:
9608761afd4STetsuo Handa 					case TOMOYO_PATH1_PERM:
9618761afd4STetsuo Handa 						stat_index = TOMOYO_PATH1;
9628761afd4STetsuo Handa 						break;
9638761afd4STetsuo Handa 					case TOMOYO_PATH2_UID:
9648761afd4STetsuo Handa 					case TOMOYO_PATH2_GID:
9658761afd4STetsuo Handa 					case TOMOYO_PATH2_INO:
9668761afd4STetsuo Handa 					case TOMOYO_PATH2_MAJOR:
9678761afd4STetsuo Handa 					case TOMOYO_PATH2_MINOR:
9688761afd4STetsuo Handa 					case TOMOYO_PATH2_TYPE:
9698761afd4STetsuo Handa 					case TOMOYO_PATH2_DEV_MAJOR:
9708761afd4STetsuo Handa 					case TOMOYO_PATH2_DEV_MINOR:
9718761afd4STetsuo Handa 					case TOMOYO_PATH2_PERM:
9728761afd4STetsuo Handa 						stat_index = TOMOYO_PATH2;
9738761afd4STetsuo Handa 						break;
9748761afd4STetsuo Handa 					case TOMOYO_PATH1_PARENT_UID:
9758761afd4STetsuo Handa 					case TOMOYO_PATH1_PARENT_GID:
9768761afd4STetsuo Handa 					case TOMOYO_PATH1_PARENT_INO:
9778761afd4STetsuo Handa 					case TOMOYO_PATH1_PARENT_PERM:
9788761afd4STetsuo Handa 						stat_index =
9798761afd4STetsuo Handa 							TOMOYO_PATH1_PARENT;
9808761afd4STetsuo Handa 						break;
9818761afd4STetsuo Handa 					case TOMOYO_PATH2_PARENT_UID:
9828761afd4STetsuo Handa 					case TOMOYO_PATH2_PARENT_GID:
9838761afd4STetsuo Handa 					case TOMOYO_PATH2_PARENT_INO:
9848761afd4STetsuo Handa 					case TOMOYO_PATH2_PARENT_PERM:
9858761afd4STetsuo Handa 						stat_index =
9868761afd4STetsuo Handa 							TOMOYO_PATH2_PARENT;
9878761afd4STetsuo Handa 						break;
9888761afd4STetsuo Handa 					default:
9898761afd4STetsuo Handa 						goto out;
9908761afd4STetsuo Handa 					}
9918761afd4STetsuo Handa 					if (!obj->stat_valid[stat_index])
9928761afd4STetsuo Handa 						goto out;
9938761afd4STetsuo Handa 					stat = &obj->stat[stat_index];
9948761afd4STetsuo Handa 					switch (index) {
9958761afd4STetsuo Handa 					case TOMOYO_PATH1_UID:
9968761afd4STetsuo Handa 					case TOMOYO_PATH2_UID:
9978761afd4STetsuo Handa 					case TOMOYO_PATH1_PARENT_UID:
9988761afd4STetsuo Handa 					case TOMOYO_PATH2_PARENT_UID:
999609fcd1bSEric W. Biederman 						value = from_kuid(&init_user_ns, stat->uid);
10008761afd4STetsuo Handa 						break;
10018761afd4STetsuo Handa 					case TOMOYO_PATH1_GID:
10028761afd4STetsuo Handa 					case TOMOYO_PATH2_GID:
10038761afd4STetsuo Handa 					case TOMOYO_PATH1_PARENT_GID:
10048761afd4STetsuo Handa 					case TOMOYO_PATH2_PARENT_GID:
1005609fcd1bSEric W. Biederman 						value = from_kgid(&init_user_ns, stat->gid);
10068761afd4STetsuo Handa 						break;
10078761afd4STetsuo Handa 					case TOMOYO_PATH1_INO:
10088761afd4STetsuo Handa 					case TOMOYO_PATH2_INO:
10098761afd4STetsuo Handa 					case TOMOYO_PATH1_PARENT_INO:
10108761afd4STetsuo Handa 					case TOMOYO_PATH2_PARENT_INO:
10118761afd4STetsuo Handa 						value = stat->ino;
10128761afd4STetsuo Handa 						break;
10138761afd4STetsuo Handa 					case TOMOYO_PATH1_MAJOR:
10148761afd4STetsuo Handa 					case TOMOYO_PATH2_MAJOR:
10158761afd4STetsuo Handa 						value = MAJOR(stat->dev);
10168761afd4STetsuo Handa 						break;
10178761afd4STetsuo Handa 					case TOMOYO_PATH1_MINOR:
10188761afd4STetsuo Handa 					case TOMOYO_PATH2_MINOR:
10198761afd4STetsuo Handa 						value = MINOR(stat->dev);
10208761afd4STetsuo Handa 						break;
10218761afd4STetsuo Handa 					case TOMOYO_PATH1_TYPE:
10228761afd4STetsuo Handa 					case TOMOYO_PATH2_TYPE:
10238761afd4STetsuo Handa 						value = stat->mode & S_IFMT;
10248761afd4STetsuo Handa 						break;
10258761afd4STetsuo Handa 					case TOMOYO_PATH1_DEV_MAJOR:
10268761afd4STetsuo Handa 					case TOMOYO_PATH2_DEV_MAJOR:
10278761afd4STetsuo Handa 						value = MAJOR(stat->rdev);
10288761afd4STetsuo Handa 						break;
10298761afd4STetsuo Handa 					case TOMOYO_PATH1_DEV_MINOR:
10308761afd4STetsuo Handa 					case TOMOYO_PATH2_DEV_MINOR:
10318761afd4STetsuo Handa 						value = MINOR(stat->rdev);
10328761afd4STetsuo Handa 						break;
10338761afd4STetsuo Handa 					case TOMOYO_PATH1_PERM:
10348761afd4STetsuo Handa 					case TOMOYO_PATH2_PERM:
10358761afd4STetsuo Handa 					case TOMOYO_PATH1_PARENT_PERM:
10368761afd4STetsuo Handa 					case TOMOYO_PATH2_PARENT_PERM:
10378761afd4STetsuo Handa 						value = stat->mode & S_IALLUGO;
10388761afd4STetsuo Handa 						break;
10398761afd4STetsuo Handa 					}
10408761afd4STetsuo Handa 				}
10412066a361STetsuo Handa 				break;
10422066a361STetsuo Handa 			}
10432066a361STetsuo Handa 			max_v[j] = value;
10442066a361STetsuo Handa 			min_v[j] = value;
10458761afd4STetsuo Handa 			switch (index) {
10468761afd4STetsuo Handa 			case TOMOYO_MODE_SETUID:
10478761afd4STetsuo Handa 			case TOMOYO_MODE_SETGID:
10488761afd4STetsuo Handa 			case TOMOYO_MODE_STICKY:
10498761afd4STetsuo Handa 			case TOMOYO_MODE_OWNER_READ:
10508761afd4STetsuo Handa 			case TOMOYO_MODE_OWNER_WRITE:
10518761afd4STetsuo Handa 			case TOMOYO_MODE_OWNER_EXECUTE:
10528761afd4STetsuo Handa 			case TOMOYO_MODE_GROUP_READ:
10538761afd4STetsuo Handa 			case TOMOYO_MODE_GROUP_WRITE:
10548761afd4STetsuo Handa 			case TOMOYO_MODE_GROUP_EXECUTE:
10558761afd4STetsuo Handa 			case TOMOYO_MODE_OTHERS_READ:
10568761afd4STetsuo Handa 			case TOMOYO_MODE_OTHERS_WRITE:
10578761afd4STetsuo Handa 			case TOMOYO_MODE_OTHERS_EXECUTE:
10588761afd4STetsuo Handa 				is_bitop[j] = true;
10598761afd4STetsuo Handa 			}
10602066a361STetsuo Handa 		}
10612066a361STetsuo Handa 		if (left == TOMOYO_NUMBER_UNION) {
10622066a361STetsuo Handa 			/* Fetch values now. */
10632066a361STetsuo Handa 			const struct tomoyo_number_union *ptr = numbers_p++;
1064cdcf6723STetsuo Handa 
10652066a361STetsuo Handa 			min_v[0] = ptr->values[0];
10662066a361STetsuo Handa 			max_v[0] = ptr->values[1];
10672066a361STetsuo Handa 		}
10682066a361STetsuo Handa 		if (right == TOMOYO_NUMBER_UNION) {
10692066a361STetsuo Handa 			/* Fetch values now. */
10702066a361STetsuo Handa 			const struct tomoyo_number_union *ptr = numbers_p++;
1071cdcf6723STetsuo Handa 
10722066a361STetsuo Handa 			if (ptr->group) {
10732066a361STetsuo Handa 				if (tomoyo_number_matches_group(min_v[0],
10742066a361STetsuo Handa 								max_v[0],
10752066a361STetsuo Handa 								ptr->group)
10762066a361STetsuo Handa 				    == match)
10772066a361STetsuo Handa 					continue;
10782066a361STetsuo Handa 			} else {
10792066a361STetsuo Handa 				if ((min_v[0] <= ptr->values[1] &&
10802066a361STetsuo Handa 				     max_v[0] >= ptr->values[0]) == match)
10812066a361STetsuo Handa 					continue;
10822066a361STetsuo Handa 			}
10832066a361STetsuo Handa 			goto out;
10842066a361STetsuo Handa 		}
10858761afd4STetsuo Handa 		/*
10868761afd4STetsuo Handa 		 * Bit operation is valid only when counterpart value
10878761afd4STetsuo Handa 		 * represents permission.
10888761afd4STetsuo Handa 		 */
10898761afd4STetsuo Handa 		if (is_bitop[0] && is_bitop[1]) {
10908761afd4STetsuo Handa 			goto out;
10918761afd4STetsuo Handa 		} else if (is_bitop[0]) {
10928761afd4STetsuo Handa 			switch (right) {
10938761afd4STetsuo Handa 			case TOMOYO_PATH1_PERM:
10948761afd4STetsuo Handa 			case TOMOYO_PATH1_PARENT_PERM:
10958761afd4STetsuo Handa 			case TOMOYO_PATH2_PERM:
10968761afd4STetsuo Handa 			case TOMOYO_PATH2_PARENT_PERM:
10978761afd4STetsuo Handa 				if (!(max_v[0] & max_v[1]) == !match)
10988761afd4STetsuo Handa 					continue;
10998761afd4STetsuo Handa 			}
11008761afd4STetsuo Handa 			goto out;
11018761afd4STetsuo Handa 		} else if (is_bitop[1]) {
11028761afd4STetsuo Handa 			switch (left) {
11038761afd4STetsuo Handa 			case TOMOYO_PATH1_PERM:
11048761afd4STetsuo Handa 			case TOMOYO_PATH1_PARENT_PERM:
11058761afd4STetsuo Handa 			case TOMOYO_PATH2_PERM:
11068761afd4STetsuo Handa 			case TOMOYO_PATH2_PARENT_PERM:
11078761afd4STetsuo Handa 				if (!(max_v[0] & max_v[1]) == !match)
11088761afd4STetsuo Handa 					continue;
11098761afd4STetsuo Handa 			}
11108761afd4STetsuo Handa 			goto out;
11118761afd4STetsuo Handa 		}
11122066a361STetsuo Handa 		/* Normal value range comparison. */
11132066a361STetsuo Handa 		if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
11142066a361STetsuo Handa 			continue;
11152066a361STetsuo Handa out:
11162066a361STetsuo Handa 		return false;
11172066a361STetsuo Handa 	}
11185b636857STetsuo Handa 	/* Check argv[] and envp[] now. */
11195b636857STetsuo Handa 	if (r->ee && (argc || envc))
11205b636857STetsuo Handa 		return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp);
11212066a361STetsuo Handa 	return true;
11222066a361STetsuo Handa }
1123