cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

condition.c (27759B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * security/tomoyo/condition.c
      4 *
      5 * Copyright (C) 2005-2011  NTT DATA CORPORATION
      6 */
      7
      8#include "common.h"
      9#include <linux/slab.h>
     10
     11/* List of "struct tomoyo_condition". */
     12LIST_HEAD(tomoyo_condition_list);
     13
     14/**
     15 * tomoyo_argv - Check argv[] in "struct linux_binbrm".
     16 *
     17 * @index:   Index number of @arg_ptr.
     18 * @arg_ptr: Contents of argv[@index].
     19 * @argc:    Length of @argv.
     20 * @argv:    Pointer to "struct tomoyo_argv".
     21 * @checked: Set to true if @argv[@index] was found.
     22 *
     23 * Returns true on success, false otherwise.
     24 */
     25static bool tomoyo_argv(const unsigned int index, const char *arg_ptr,
     26			const int argc, const struct tomoyo_argv *argv,
     27			u8 *checked)
     28{
     29	int i;
     30	struct tomoyo_path_info arg;
     31
     32	arg.name = arg_ptr;
     33	for (i = 0; i < argc; argv++, checked++, i++) {
     34		bool result;
     35
     36		if (index != argv->index)
     37			continue;
     38		*checked = 1;
     39		tomoyo_fill_path_info(&arg);
     40		result = tomoyo_path_matches_pattern(&arg, argv->value);
     41		if (argv->is_not)
     42			result = !result;
     43		if (!result)
     44			return false;
     45	}
     46	return true;
     47}
     48
     49/**
     50 * tomoyo_envp - Check envp[] in "struct linux_binbrm".
     51 *
     52 * @env_name:  The name of environment variable.
     53 * @env_value: The value of environment variable.
     54 * @envc:      Length of @envp.
     55 * @envp:      Pointer to "struct tomoyo_envp".
     56 * @checked:   Set to true if @envp[@env_name] was found.
     57 *
     58 * Returns true on success, false otherwise.
     59 */
     60static bool tomoyo_envp(const char *env_name, const char *env_value,
     61			const int envc, const struct tomoyo_envp *envp,
     62			u8 *checked)
     63{
     64	int i;
     65	struct tomoyo_path_info name;
     66	struct tomoyo_path_info value;
     67
     68	name.name = env_name;
     69	tomoyo_fill_path_info(&name);
     70	value.name = env_value;
     71	tomoyo_fill_path_info(&value);
     72	for (i = 0; i < envc; envp++, checked++, i++) {
     73		bool result;
     74
     75		if (!tomoyo_path_matches_pattern(&name, envp->name))
     76			continue;
     77		*checked = 1;
     78		if (envp->value) {
     79			result = tomoyo_path_matches_pattern(&value,
     80							     envp->value);
     81			if (envp->is_not)
     82				result = !result;
     83		} else {
     84			result = true;
     85			if (!envp->is_not)
     86				result = !result;
     87		}
     88		if (!result)
     89			return false;
     90	}
     91	return true;
     92}
     93
     94/**
     95 * tomoyo_scan_bprm - Scan "struct linux_binprm".
     96 *
     97 * @ee:   Pointer to "struct tomoyo_execve".
     98 * @argc: Length of @argc.
     99 * @argv: Pointer to "struct tomoyo_argv".
    100 * @envc: Length of @envp.
    101 * @envp: Pointer to "struct tomoyo_envp".
    102 *
    103 * Returns true on success, false otherwise.
    104 */
    105static bool tomoyo_scan_bprm(struct tomoyo_execve *ee,
    106			     const u16 argc, const struct tomoyo_argv *argv,
    107			     const u16 envc, const struct tomoyo_envp *envp)
    108{
    109	struct linux_binprm *bprm = ee->bprm;
    110	struct tomoyo_page_dump *dump = &ee->dump;
    111	char *arg_ptr = ee->tmp;
    112	int arg_len = 0;
    113	unsigned long pos = bprm->p;
    114	int offset = pos % PAGE_SIZE;
    115	int argv_count = bprm->argc;
    116	int envp_count = bprm->envc;
    117	bool result = true;
    118	u8 local_checked[32];
    119	u8 *checked;
    120
    121	if (argc + envc <= sizeof(local_checked)) {
    122		checked = local_checked;
    123		memset(local_checked, 0, sizeof(local_checked));
    124	} else {
    125		checked = kzalloc(argc + envc, GFP_NOFS);
    126		if (!checked)
    127			return false;
    128	}
    129	while (argv_count || envp_count) {
    130		if (!tomoyo_dump_page(bprm, pos, dump)) {
    131			result = false;
    132			goto out;
    133		}
    134		pos += PAGE_SIZE - offset;
    135		while (offset < PAGE_SIZE) {
    136			/* Read. */
    137			const char *kaddr = dump->data;
    138			const unsigned char c = kaddr[offset++];
    139
    140			if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
    141				if (c == '\\') {
    142					arg_ptr[arg_len++] = '\\';
    143					arg_ptr[arg_len++] = '\\';
    144				} else if (c > ' ' && c < 127) {
    145					arg_ptr[arg_len++] = c;
    146				} else {
    147					arg_ptr[arg_len++] = '\\';
    148					arg_ptr[arg_len++] = (c >> 6) + '0';
    149					arg_ptr[arg_len++] =
    150						((c >> 3) & 7) + '0';
    151					arg_ptr[arg_len++] = (c & 7) + '0';
    152				}
    153			} else {
    154				arg_ptr[arg_len] = '\0';
    155			}
    156			if (c)
    157				continue;
    158			/* Check. */
    159			if (argv_count) {
    160				if (!tomoyo_argv(bprm->argc - argv_count,
    161						 arg_ptr, argc, argv,
    162						 checked)) {
    163					result = false;
    164					break;
    165				}
    166				argv_count--;
    167			} else if (envp_count) {
    168				char *cp = strchr(arg_ptr, '=');
    169
    170				if (cp) {
    171					*cp = '\0';
    172					if (!tomoyo_envp(arg_ptr, cp + 1,
    173							 envc, envp,
    174							 checked + argc)) {
    175						result = false;
    176						break;
    177					}
    178				}
    179				envp_count--;
    180			} else {
    181				break;
    182			}
    183			arg_len = 0;
    184		}
    185		offset = 0;
    186		if (!result)
    187			break;
    188	}
    189out:
    190	if (result) {
    191		int i;
    192
    193		/* Check not-yet-checked entries. */
    194		for (i = 0; i < argc; i++) {
    195			if (checked[i])
    196				continue;
    197			/*
    198			 * Return true only if all unchecked indexes in
    199			 * bprm->argv[] are not matched.
    200			 */
    201			if (argv[i].is_not)
    202				continue;
    203			result = false;
    204			break;
    205		}
    206		for (i = 0; i < envc; envp++, i++) {
    207			if (checked[argc + i])
    208				continue;
    209			/*
    210			 * Return true only if all unchecked environ variables
    211			 * in bprm->envp[] are either undefined or not matched.
    212			 */
    213			if ((!envp->value && !envp->is_not) ||
    214			    (envp->value && envp->is_not))
    215				continue;
    216			result = false;
    217			break;
    218		}
    219	}
    220	if (checked != local_checked)
    221		kfree(checked);
    222	return result;
    223}
    224
    225/**
    226 * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition".
    227 *
    228 * @file:  Pointer to "struct file".
    229 * @ptr:   Pointer to "struct tomoyo_name_union".
    230 * @match: True if "exec.realpath=", false if "exec.realpath!=".
    231 *
    232 * Returns true on success, false otherwise.
    233 */
    234static bool tomoyo_scan_exec_realpath(struct file *file,
    235				      const struct tomoyo_name_union *ptr,
    236				      const bool match)
    237{
    238	bool result;
    239	struct tomoyo_path_info exe;
    240
    241	if (!file)
    242		return false;
    243	exe.name = tomoyo_realpath_from_path(&file->f_path);
    244	if (!exe.name)
    245		return false;
    246	tomoyo_fill_path_info(&exe);
    247	result = tomoyo_compare_name_union(&exe, ptr);
    248	kfree(exe.name);
    249	return result == match;
    250}
    251
    252/**
    253 * tomoyo_get_dqword - tomoyo_get_name() for a quoted string.
    254 *
    255 * @start: String to save.
    256 *
    257 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
    258 */
    259static const struct tomoyo_path_info *tomoyo_get_dqword(char *start)
    260{
    261	char *cp = start + strlen(start) - 1;
    262
    263	if (cp == start || *start++ != '"' || *cp != '"')
    264		return NULL;
    265	*cp = '\0';
    266	if (*start && !tomoyo_correct_word(start))
    267		return NULL;
    268	return tomoyo_get_name(start);
    269}
    270
    271/**
    272 * tomoyo_parse_name_union_quoted - Parse a quoted word.
    273 *
    274 * @param: Pointer to "struct tomoyo_acl_param".
    275 * @ptr:   Pointer to "struct tomoyo_name_union".
    276 *
    277 * Returns true on success, false otherwise.
    278 */
    279static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param,
    280					   struct tomoyo_name_union *ptr)
    281{
    282	char *filename = param->data;
    283
    284	if (*filename == '@')
    285		return tomoyo_parse_name_union(param, ptr);
    286	ptr->filename = tomoyo_get_dqword(filename);
    287	return ptr->filename != NULL;
    288}
    289
    290/**
    291 * tomoyo_parse_argv - Parse an argv[] condition part.
    292 *
    293 * @left:  Lefthand value.
    294 * @right: Righthand value.
    295 * @argv:  Pointer to "struct tomoyo_argv".
    296 *
    297 * Returns true on success, false otherwise.
    298 */
    299static bool tomoyo_parse_argv(char *left, char *right,
    300			      struct tomoyo_argv *argv)
    301{
    302	if (tomoyo_parse_ulong(&argv->index, &left) !=
    303	    TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left)
    304		return false;
    305	argv->value = tomoyo_get_dqword(right);
    306	return argv->value != NULL;
    307}
    308
    309/**
    310 * tomoyo_parse_envp - Parse an envp[] condition part.
    311 *
    312 * @left:  Lefthand value.
    313 * @right: Righthand value.
    314 * @envp:  Pointer to "struct tomoyo_envp".
    315 *
    316 * Returns true on success, false otherwise.
    317 */
    318static bool tomoyo_parse_envp(char *left, char *right,
    319			      struct tomoyo_envp *envp)
    320{
    321	const struct tomoyo_path_info *name;
    322	const struct tomoyo_path_info *value;
    323	char *cp = left + strlen(left) - 1;
    324
    325	if (*cp-- != ']' || *cp != '"')
    326		goto out;
    327	*cp = '\0';
    328	if (!tomoyo_correct_word(left))
    329		goto out;
    330	name = tomoyo_get_name(left);
    331	if (!name)
    332		goto out;
    333	if (!strcmp(right, "NULL")) {
    334		value = NULL;
    335	} else {
    336		value = tomoyo_get_dqword(right);
    337		if (!value) {
    338			tomoyo_put_name(name);
    339			goto out;
    340		}
    341	}
    342	envp->name = name;
    343	envp->value = value;
    344	return true;
    345out:
    346	return false;
    347}
    348
    349/**
    350 * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry.
    351 *
    352 * @a: Pointer to "struct tomoyo_condition".
    353 * @b: Pointer to "struct tomoyo_condition".
    354 *
    355 * Returns true if @a == @b, false otherwise.
    356 */
    357static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
    358					 const struct tomoyo_condition *b)
    359{
    360	return a->size == b->size && a->condc == b->condc &&
    361		a->numbers_count == b->numbers_count &&
    362		a->names_count == b->names_count &&
    363		a->argc == b->argc && a->envc == b->envc &&
    364		a->grant_log == b->grant_log && a->transit == b->transit &&
    365		!memcmp(a + 1, b + 1, a->size - sizeof(*a));
    366}
    367
    368/**
    369 * tomoyo_condition_type - Get condition type.
    370 *
    371 * @word: Keyword string.
    372 *
    373 * Returns one of values in "enum tomoyo_conditions_index" on success,
    374 * TOMOYO_MAX_CONDITION_KEYWORD otherwise.
    375 */
    376static u8 tomoyo_condition_type(const char *word)
    377{
    378	u8 i;
    379
    380	for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) {
    381		if (!strcmp(word, tomoyo_condition_keyword[i]))
    382			break;
    383	}
    384	return i;
    385}
    386
    387/* Define this to enable debug mode. */
    388/* #define DEBUG_CONDITION */
    389
    390#ifdef DEBUG_CONDITION
    391#define dprintk printk
    392#else
    393#define dprintk(...) do { } while (0)
    394#endif
    395
    396/**
    397 * tomoyo_commit_condition - Commit "struct tomoyo_condition".
    398 *
    399 * @entry: Pointer to "struct tomoyo_condition".
    400 *
    401 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
    402 *
    403 * This function merges duplicated entries. This function returns NULL if
    404 * @entry is not duplicated but memory quota for policy has exceeded.
    405 */
    406static struct tomoyo_condition *tomoyo_commit_condition
    407(struct tomoyo_condition *entry)
    408{
    409	struct tomoyo_condition *ptr;
    410	bool found = false;
    411
    412	if (mutex_lock_interruptible(&tomoyo_policy_lock)) {
    413		dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
    414		ptr = NULL;
    415		found = true;
    416		goto out;
    417	}
    418	list_for_each_entry(ptr, &tomoyo_condition_list, head.list) {
    419		if (!tomoyo_same_condition(ptr, entry) ||
    420		    atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
    421			continue;
    422		/* Same entry found. Share this entry. */
    423		atomic_inc(&ptr->head.users);
    424		found = true;
    425		break;
    426	}
    427	if (!found) {
    428		if (tomoyo_memory_ok(entry)) {
    429			atomic_set(&entry->head.users, 1);
    430			list_add(&entry->head.list, &tomoyo_condition_list);
    431		} else {
    432			found = true;
    433			ptr = NULL;
    434		}
    435	}
    436	mutex_unlock(&tomoyo_policy_lock);
    437out:
    438	if (found) {
    439		tomoyo_del_condition(&entry->head.list);
    440		kfree(entry);
    441		entry = ptr;
    442	}
    443	return entry;
    444}
    445
    446/**
    447 * tomoyo_get_transit_preference - Parse domain transition preference for execve().
    448 *
    449 * @param: Pointer to "struct tomoyo_acl_param".
    450 * @e:     Pointer to "struct tomoyo_condition".
    451 *
    452 * Returns the condition string part.
    453 */
    454static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param,
    455					   struct tomoyo_condition *e)
    456{
    457	char * const pos = param->data;
    458	bool flag;
    459
    460	if (*pos == '<') {
    461		e->transit = tomoyo_get_domainname(param);
    462		goto done;
    463	}
    464	{
    465		char *cp = strchr(pos, ' ');
    466
    467		if (cp)
    468			*cp = '\0';
    469		flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") ||
    470			!strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
    471			!strcmp(pos, "child") || !strcmp(pos, "parent");
    472		if (cp)
    473			*cp = ' ';
    474	}
    475	if (!flag)
    476		return pos;
    477	e->transit = tomoyo_get_name(tomoyo_read_token(param));
    478done:
    479	if (e->transit)
    480		return param->data;
    481	/*
    482	 * Return a bad read-only condition string that will let
    483	 * tomoyo_get_condition() return NULL.
    484	 */
    485	return "/";
    486}
    487
    488/**
    489 * tomoyo_get_condition - Parse condition part.
    490 *
    491 * @param: Pointer to "struct tomoyo_acl_param".
    492 *
    493 * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
    494 */
    495struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
    496{
    497	struct tomoyo_condition *entry = NULL;
    498	struct tomoyo_condition_element *condp = NULL;
    499	struct tomoyo_number_union *numbers_p = NULL;
    500	struct tomoyo_name_union *names_p = NULL;
    501	struct tomoyo_argv *argv = NULL;
    502	struct tomoyo_envp *envp = NULL;
    503	struct tomoyo_condition e = { };
    504	char * const start_of_string =
    505		tomoyo_get_transit_preference(param, &e);
    506	char * const end_of_string = start_of_string + strlen(start_of_string);
    507	char *pos;
    508
    509rerun:
    510	pos = start_of_string;
    511	while (1) {
    512		u8 left = -1;
    513		u8 right = -1;
    514		char *left_word = pos;
    515		char *cp;
    516		char *right_word;
    517		bool is_not;
    518
    519		if (!*left_word)
    520			break;
    521		/*
    522		 * Since left-hand condition does not allow use of "path_group"
    523		 * or "number_group" and environment variable's names do not
    524		 * accept '=', it is guaranteed that the original line consists
    525		 * of one or more repetition of $left$operator$right blocks
    526		 * where "$left is free from '=' and ' '" and "$operator is
    527		 * either '=' or '!='" and "$right is free from ' '".
    528		 * Therefore, we can reconstruct the original line at the end
    529		 * of dry run even if we overwrite $operator with '\0'.
    530		 */
    531		cp = strchr(pos, ' ');
    532		if (cp) {
    533			*cp = '\0'; /* Will restore later. */
    534			pos = cp + 1;
    535		} else {
    536			pos = "";
    537		}
    538		right_word = strchr(left_word, '=');
    539		if (!right_word || right_word == left_word)
    540			goto out;
    541		is_not = *(right_word - 1) == '!';
    542		if (is_not)
    543			*(right_word++ - 1) = '\0'; /* Will restore later. */
    544		else if (*(right_word + 1) != '=')
    545			*right_word++ = '\0'; /* Will restore later. */
    546		else
    547			goto out;
    548		dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
    549			is_not ? "!" : "", right_word);
    550		if (!strcmp(left_word, "grant_log")) {
    551			if (entry) {
    552				if (is_not ||
    553				    entry->grant_log != TOMOYO_GRANTLOG_AUTO)
    554					goto out;
    555				else if (!strcmp(right_word, "yes"))
    556					entry->grant_log = TOMOYO_GRANTLOG_YES;
    557				else if (!strcmp(right_word, "no"))
    558					entry->grant_log = TOMOYO_GRANTLOG_NO;
    559				else
    560					goto out;
    561			}
    562			continue;
    563		}
    564		if (!strncmp(left_word, "exec.argv[", 10)) {
    565			if (!argv) {
    566				e.argc++;
    567				e.condc++;
    568			} else {
    569				e.argc--;
    570				e.condc--;
    571				left = TOMOYO_ARGV_ENTRY;
    572				argv->is_not = is_not;
    573				if (!tomoyo_parse_argv(left_word + 10,
    574						       right_word, argv++))
    575					goto out;
    576			}
    577			goto store_value;
    578		}
    579		if (!strncmp(left_word, "exec.envp[\"", 11)) {
    580			if (!envp) {
    581				e.envc++;
    582				e.condc++;
    583			} else {
    584				e.envc--;
    585				e.condc--;
    586				left = TOMOYO_ENVP_ENTRY;
    587				envp->is_not = is_not;
    588				if (!tomoyo_parse_envp(left_word + 11,
    589						       right_word, envp++))
    590					goto out;
    591			}
    592			goto store_value;
    593		}
    594		left = tomoyo_condition_type(left_word);
    595		dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
    596			left);
    597		if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
    598			if (!numbers_p) {
    599				e.numbers_count++;
    600			} else {
    601				e.numbers_count--;
    602				left = TOMOYO_NUMBER_UNION;
    603				param->data = left_word;
    604				if (*left_word == '@' ||
    605				    !tomoyo_parse_number_union(param,
    606							       numbers_p++))
    607					goto out;
    608			}
    609		}
    610		if (!condp)
    611			e.condc++;
    612		else
    613			e.condc--;
    614		if (left == TOMOYO_EXEC_REALPATH ||
    615		    left == TOMOYO_SYMLINK_TARGET) {
    616			if (!names_p) {
    617				e.names_count++;
    618			} else {
    619				e.names_count--;
    620				right = TOMOYO_NAME_UNION;
    621				param->data = right_word;
    622				if (!tomoyo_parse_name_union_quoted(param,
    623								    names_p++))
    624					goto out;
    625			}
    626			goto store_value;
    627		}
    628		right = tomoyo_condition_type(right_word);
    629		if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
    630			if (!numbers_p) {
    631				e.numbers_count++;
    632			} else {
    633				e.numbers_count--;
    634				right = TOMOYO_NUMBER_UNION;
    635				param->data = right_word;
    636				if (!tomoyo_parse_number_union(param,
    637							       numbers_p++))
    638					goto out;
    639			}
    640		}
    641store_value:
    642		if (!condp) {
    643			dprintk(KERN_WARNING "%u: dry_run left=%u right=%u match=%u\n",
    644				__LINE__, left, right, !is_not);
    645			continue;
    646		}
    647		condp->left = left;
    648		condp->right = right;
    649		condp->equals = !is_not;
    650		dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
    651			__LINE__, condp->left, condp->right,
    652			condp->equals);
    653		condp++;
    654	}
    655	dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
    656		__LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
    657		e.envc);
    658	if (entry) {
    659		BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
    660		       e.condc);
    661		return tomoyo_commit_condition(entry);
    662	}
    663	e.size = sizeof(*entry)
    664		+ e.condc * sizeof(struct tomoyo_condition_element)
    665		+ e.numbers_count * sizeof(struct tomoyo_number_union)
    666		+ e.names_count * sizeof(struct tomoyo_name_union)
    667		+ e.argc * sizeof(struct tomoyo_argv)
    668		+ e.envc * sizeof(struct tomoyo_envp);
    669	entry = kzalloc(e.size, GFP_NOFS);
    670	if (!entry)
    671		goto out2;
    672	*entry = e;
    673	e.transit = NULL;
    674	condp = (struct tomoyo_condition_element *) (entry + 1);
    675	numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
    676	names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
    677	argv = (struct tomoyo_argv *) (names_p + e.names_count);
    678	envp = (struct tomoyo_envp *) (argv + e.argc);
    679	{
    680		bool flag = false;
    681
    682		for (pos = start_of_string; pos < end_of_string; pos++) {
    683			if (*pos)
    684				continue;
    685			if (flag) /* Restore " ". */
    686				*pos = ' ';
    687			else if (*(pos + 1) == '=') /* Restore "!=". */
    688				*pos = '!';
    689			else /* Restore "=". */
    690				*pos = '=';
    691			flag = !flag;
    692		}
    693	}
    694	goto rerun;
    695out:
    696	dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
    697	if (entry) {
    698		tomoyo_del_condition(&entry->head.list);
    699		kfree(entry);
    700	}
    701out2:
    702	tomoyo_put_name(e.transit);
    703	return NULL;
    704}
    705
    706/**
    707 * tomoyo_get_attributes - Revalidate "struct inode".
    708 *
    709 * @obj: Pointer to "struct tomoyo_obj_info".
    710 *
    711 * Returns nothing.
    712 */
    713void tomoyo_get_attributes(struct tomoyo_obj_info *obj)
    714{
    715	u8 i;
    716	struct dentry *dentry = NULL;
    717
    718	for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
    719		struct inode *inode;
    720
    721		switch (i) {
    722		case TOMOYO_PATH1:
    723			dentry = obj->path1.dentry;
    724			if (!dentry)
    725				continue;
    726			break;
    727		case TOMOYO_PATH2:
    728			dentry = obj->path2.dentry;
    729			if (!dentry)
    730				continue;
    731			break;
    732		default:
    733			if (!dentry)
    734				continue;
    735			dentry = dget_parent(dentry);
    736			break;
    737		}
    738		inode = d_backing_inode(dentry);
    739		if (inode) {
    740			struct tomoyo_mini_stat *stat = &obj->stat[i];
    741
    742			stat->uid  = inode->i_uid;
    743			stat->gid  = inode->i_gid;
    744			stat->ino  = inode->i_ino;
    745			stat->mode = inode->i_mode;
    746			stat->dev  = inode->i_sb->s_dev;
    747			stat->rdev = inode->i_rdev;
    748			obj->stat_valid[i] = true;
    749		}
    750		if (i & 1) /* TOMOYO_PATH1_PARENT or TOMOYO_PATH2_PARENT */
    751			dput(dentry);
    752	}
    753}
    754
    755/**
    756 * tomoyo_condition - Check condition part.
    757 *
    758 * @r:    Pointer to "struct tomoyo_request_info".
    759 * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
    760 *
    761 * Returns true on success, false otherwise.
    762 *
    763 * Caller holds tomoyo_read_lock().
    764 */
    765bool tomoyo_condition(struct tomoyo_request_info *r,
    766		      const struct tomoyo_condition *cond)
    767{
    768	u32 i;
    769	unsigned long min_v[2] = { 0, 0 };
    770	unsigned long max_v[2] = { 0, 0 };
    771	const struct tomoyo_condition_element *condp;
    772	const struct tomoyo_number_union *numbers_p;
    773	const struct tomoyo_name_union *names_p;
    774	const struct tomoyo_argv *argv;
    775	const struct tomoyo_envp *envp;
    776	struct tomoyo_obj_info *obj;
    777	u16 condc;
    778	u16 argc;
    779	u16 envc;
    780	struct linux_binprm *bprm = NULL;
    781
    782	if (!cond)
    783		return true;
    784	condc = cond->condc;
    785	argc = cond->argc;
    786	envc = cond->envc;
    787	obj = r->obj;
    788	if (r->ee)
    789		bprm = r->ee->bprm;
    790	if (!bprm && (argc || envc))
    791		return false;
    792	condp = (struct tomoyo_condition_element *) (cond + 1);
    793	numbers_p = (const struct tomoyo_number_union *) (condp + condc);
    794	names_p = (const struct tomoyo_name_union *)
    795		(numbers_p + cond->numbers_count);
    796	argv = (const struct tomoyo_argv *) (names_p + cond->names_count);
    797	envp = (const struct tomoyo_envp *) (argv + argc);
    798	for (i = 0; i < condc; i++) {
    799		const bool match = condp->equals;
    800		const u8 left = condp->left;
    801		const u8 right = condp->right;
    802		bool is_bitop[2] = { false, false };
    803		u8 j;
    804
    805		condp++;
    806		/* Check argv[] and envp[] later. */
    807		if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY)
    808			continue;
    809		/* Check string expressions. */
    810		if (right == TOMOYO_NAME_UNION) {
    811			const struct tomoyo_name_union *ptr = names_p++;
    812			struct tomoyo_path_info *symlink;
    813			struct tomoyo_execve *ee;
    814			struct file *file;
    815
    816			switch (left) {
    817			case TOMOYO_SYMLINK_TARGET:
    818				symlink = obj ? obj->symlink_target : NULL;
    819				if (!symlink ||
    820				    !tomoyo_compare_name_union(symlink, ptr)
    821				    == match)
    822					goto out;
    823				break;
    824			case TOMOYO_EXEC_REALPATH:
    825				ee = r->ee;
    826				file = ee ? ee->bprm->file : NULL;
    827				if (!tomoyo_scan_exec_realpath(file, ptr,
    828							       match))
    829					goto out;
    830				break;
    831			}
    832			continue;
    833		}
    834		/* Check numeric or bit-op expressions. */
    835		for (j = 0; j < 2; j++) {
    836			const u8 index = j ? right : left;
    837			unsigned long value = 0;
    838
    839			switch (index) {
    840			case TOMOYO_TASK_UID:
    841				value = from_kuid(&init_user_ns, current_uid());
    842				break;
    843			case TOMOYO_TASK_EUID:
    844				value = from_kuid(&init_user_ns, current_euid());
    845				break;
    846			case TOMOYO_TASK_SUID:
    847				value = from_kuid(&init_user_ns, current_suid());
    848				break;
    849			case TOMOYO_TASK_FSUID:
    850				value = from_kuid(&init_user_ns, current_fsuid());
    851				break;
    852			case TOMOYO_TASK_GID:
    853				value = from_kgid(&init_user_ns, current_gid());
    854				break;
    855			case TOMOYO_TASK_EGID:
    856				value = from_kgid(&init_user_ns, current_egid());
    857				break;
    858			case TOMOYO_TASK_SGID:
    859				value = from_kgid(&init_user_ns, current_sgid());
    860				break;
    861			case TOMOYO_TASK_FSGID:
    862				value = from_kgid(&init_user_ns, current_fsgid());
    863				break;
    864			case TOMOYO_TASK_PID:
    865				value = tomoyo_sys_getpid();
    866				break;
    867			case TOMOYO_TASK_PPID:
    868				value = tomoyo_sys_getppid();
    869				break;
    870			case TOMOYO_TYPE_IS_SOCKET:
    871				value = S_IFSOCK;
    872				break;
    873			case TOMOYO_TYPE_IS_SYMLINK:
    874				value = S_IFLNK;
    875				break;
    876			case TOMOYO_TYPE_IS_FILE:
    877				value = S_IFREG;
    878				break;
    879			case TOMOYO_TYPE_IS_BLOCK_DEV:
    880				value = S_IFBLK;
    881				break;
    882			case TOMOYO_TYPE_IS_DIRECTORY:
    883				value = S_IFDIR;
    884				break;
    885			case TOMOYO_TYPE_IS_CHAR_DEV:
    886				value = S_IFCHR;
    887				break;
    888			case TOMOYO_TYPE_IS_FIFO:
    889				value = S_IFIFO;
    890				break;
    891			case TOMOYO_MODE_SETUID:
    892				value = S_ISUID;
    893				break;
    894			case TOMOYO_MODE_SETGID:
    895				value = S_ISGID;
    896				break;
    897			case TOMOYO_MODE_STICKY:
    898				value = S_ISVTX;
    899				break;
    900			case TOMOYO_MODE_OWNER_READ:
    901				value = 0400;
    902				break;
    903			case TOMOYO_MODE_OWNER_WRITE:
    904				value = 0200;
    905				break;
    906			case TOMOYO_MODE_OWNER_EXECUTE:
    907				value = 0100;
    908				break;
    909			case TOMOYO_MODE_GROUP_READ:
    910				value = 0040;
    911				break;
    912			case TOMOYO_MODE_GROUP_WRITE:
    913				value = 0020;
    914				break;
    915			case TOMOYO_MODE_GROUP_EXECUTE:
    916				value = 0010;
    917				break;
    918			case TOMOYO_MODE_OTHERS_READ:
    919				value = 0004;
    920				break;
    921			case TOMOYO_MODE_OTHERS_WRITE:
    922				value = 0002;
    923				break;
    924			case TOMOYO_MODE_OTHERS_EXECUTE:
    925				value = 0001;
    926				break;
    927			case TOMOYO_EXEC_ARGC:
    928				if (!bprm)
    929					goto out;
    930				value = bprm->argc;
    931				break;
    932			case TOMOYO_EXEC_ENVC:
    933				if (!bprm)
    934					goto out;
    935				value = bprm->envc;
    936				break;
    937			case TOMOYO_NUMBER_UNION:
    938				/* Fetch values later. */
    939				break;
    940			default:
    941				if (!obj)
    942					goto out;
    943				if (!obj->validate_done) {
    944					tomoyo_get_attributes(obj);
    945					obj->validate_done = true;
    946				}
    947				{
    948					u8 stat_index;
    949					struct tomoyo_mini_stat *stat;
    950
    951					switch (index) {
    952					case TOMOYO_PATH1_UID:
    953					case TOMOYO_PATH1_GID:
    954					case TOMOYO_PATH1_INO:
    955					case TOMOYO_PATH1_MAJOR:
    956					case TOMOYO_PATH1_MINOR:
    957					case TOMOYO_PATH1_TYPE:
    958					case TOMOYO_PATH1_DEV_MAJOR:
    959					case TOMOYO_PATH1_DEV_MINOR:
    960					case TOMOYO_PATH1_PERM:
    961						stat_index = TOMOYO_PATH1;
    962						break;
    963					case TOMOYO_PATH2_UID:
    964					case TOMOYO_PATH2_GID:
    965					case TOMOYO_PATH2_INO:
    966					case TOMOYO_PATH2_MAJOR:
    967					case TOMOYO_PATH2_MINOR:
    968					case TOMOYO_PATH2_TYPE:
    969					case TOMOYO_PATH2_DEV_MAJOR:
    970					case TOMOYO_PATH2_DEV_MINOR:
    971					case TOMOYO_PATH2_PERM:
    972						stat_index = TOMOYO_PATH2;
    973						break;
    974					case TOMOYO_PATH1_PARENT_UID:
    975					case TOMOYO_PATH1_PARENT_GID:
    976					case TOMOYO_PATH1_PARENT_INO:
    977					case TOMOYO_PATH1_PARENT_PERM:
    978						stat_index =
    979							TOMOYO_PATH1_PARENT;
    980						break;
    981					case TOMOYO_PATH2_PARENT_UID:
    982					case TOMOYO_PATH2_PARENT_GID:
    983					case TOMOYO_PATH2_PARENT_INO:
    984					case TOMOYO_PATH2_PARENT_PERM:
    985						stat_index =
    986							TOMOYO_PATH2_PARENT;
    987						break;
    988					default:
    989						goto out;
    990					}
    991					if (!obj->stat_valid[stat_index])
    992						goto out;
    993					stat = &obj->stat[stat_index];
    994					switch (index) {
    995					case TOMOYO_PATH1_UID:
    996					case TOMOYO_PATH2_UID:
    997					case TOMOYO_PATH1_PARENT_UID:
    998					case TOMOYO_PATH2_PARENT_UID:
    999						value = from_kuid(&init_user_ns, stat->uid);
   1000						break;
   1001					case TOMOYO_PATH1_GID:
   1002					case TOMOYO_PATH2_GID:
   1003					case TOMOYO_PATH1_PARENT_GID:
   1004					case TOMOYO_PATH2_PARENT_GID:
   1005						value = from_kgid(&init_user_ns, stat->gid);
   1006						break;
   1007					case TOMOYO_PATH1_INO:
   1008					case TOMOYO_PATH2_INO:
   1009					case TOMOYO_PATH1_PARENT_INO:
   1010					case TOMOYO_PATH2_PARENT_INO:
   1011						value = stat->ino;
   1012						break;
   1013					case TOMOYO_PATH1_MAJOR:
   1014					case TOMOYO_PATH2_MAJOR:
   1015						value = MAJOR(stat->dev);
   1016						break;
   1017					case TOMOYO_PATH1_MINOR:
   1018					case TOMOYO_PATH2_MINOR:
   1019						value = MINOR(stat->dev);
   1020						break;
   1021					case TOMOYO_PATH1_TYPE:
   1022					case TOMOYO_PATH2_TYPE:
   1023						value = stat->mode & S_IFMT;
   1024						break;
   1025					case TOMOYO_PATH1_DEV_MAJOR:
   1026					case TOMOYO_PATH2_DEV_MAJOR:
   1027						value = MAJOR(stat->rdev);
   1028						break;
   1029					case TOMOYO_PATH1_DEV_MINOR:
   1030					case TOMOYO_PATH2_DEV_MINOR:
   1031						value = MINOR(stat->rdev);
   1032						break;
   1033					case TOMOYO_PATH1_PERM:
   1034					case TOMOYO_PATH2_PERM:
   1035					case TOMOYO_PATH1_PARENT_PERM:
   1036					case TOMOYO_PATH2_PARENT_PERM:
   1037						value = stat->mode & S_IALLUGO;
   1038						break;
   1039					}
   1040				}
   1041				break;
   1042			}
   1043			max_v[j] = value;
   1044			min_v[j] = value;
   1045			switch (index) {
   1046			case TOMOYO_MODE_SETUID:
   1047			case TOMOYO_MODE_SETGID:
   1048			case TOMOYO_MODE_STICKY:
   1049			case TOMOYO_MODE_OWNER_READ:
   1050			case TOMOYO_MODE_OWNER_WRITE:
   1051			case TOMOYO_MODE_OWNER_EXECUTE:
   1052			case TOMOYO_MODE_GROUP_READ:
   1053			case TOMOYO_MODE_GROUP_WRITE:
   1054			case TOMOYO_MODE_GROUP_EXECUTE:
   1055			case TOMOYO_MODE_OTHERS_READ:
   1056			case TOMOYO_MODE_OTHERS_WRITE:
   1057			case TOMOYO_MODE_OTHERS_EXECUTE:
   1058				is_bitop[j] = true;
   1059			}
   1060		}
   1061		if (left == TOMOYO_NUMBER_UNION) {
   1062			/* Fetch values now. */
   1063			const struct tomoyo_number_union *ptr = numbers_p++;
   1064
   1065			min_v[0] = ptr->values[0];
   1066			max_v[0] = ptr->values[1];
   1067		}
   1068		if (right == TOMOYO_NUMBER_UNION) {
   1069			/* Fetch values now. */
   1070			const struct tomoyo_number_union *ptr = numbers_p++;
   1071
   1072			if (ptr->group) {
   1073				if (tomoyo_number_matches_group(min_v[0],
   1074								max_v[0],
   1075								ptr->group)
   1076				    == match)
   1077					continue;
   1078			} else {
   1079				if ((min_v[0] <= ptr->values[1] &&
   1080				     max_v[0] >= ptr->values[0]) == match)
   1081					continue;
   1082			}
   1083			goto out;
   1084		}
   1085		/*
   1086		 * Bit operation is valid only when counterpart value
   1087		 * represents permission.
   1088		 */
   1089		if (is_bitop[0] && is_bitop[1]) {
   1090			goto out;
   1091		} else if (is_bitop[0]) {
   1092			switch (right) {
   1093			case TOMOYO_PATH1_PERM:
   1094			case TOMOYO_PATH1_PARENT_PERM:
   1095			case TOMOYO_PATH2_PERM:
   1096			case TOMOYO_PATH2_PARENT_PERM:
   1097				if (!(max_v[0] & max_v[1]) == !match)
   1098					continue;
   1099			}
   1100			goto out;
   1101		} else if (is_bitop[1]) {
   1102			switch (left) {
   1103			case TOMOYO_PATH1_PERM:
   1104			case TOMOYO_PATH1_PARENT_PERM:
   1105			case TOMOYO_PATH2_PERM:
   1106			case TOMOYO_PATH2_PARENT_PERM:
   1107				if (!(max_v[0] & max_v[1]) == !match)
   1108					continue;
   1109			}
   1110			goto out;
   1111		}
   1112		/* Normal value range comparison. */
   1113		if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
   1114			continue;
   1115out:
   1116		return false;
   1117	}
   1118	/* Check argv[] and envp[] now. */
   1119	if (r->ee && (argc || envc))
   1120		return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp);
   1121	return true;
   1122}