1255e72915d4cbddceb435e13d81601755714e9fSE Android/* Authors: Karl MacMillan <kmacmillan@tresys.com>
2255e72915d4cbddceb435e13d81601755714e9fSE Android *          Frank Mayer <mayerf@tresys.com>
3255e72915d4cbddceb435e13d81601755714e9fSE Android *          David Caplan <dac@tresys.com>
4255e72915d4cbddceb435e13d81601755714e9fSE Android *
5255e72915d4cbddceb435e13d81601755714e9fSE Android * Copyright (C) 2003 - 2005 Tresys Technology, LLC
6255e72915d4cbddceb435e13d81601755714e9fSE Android *
7255e72915d4cbddceb435e13d81601755714e9fSE Android *  This library is free software; you can redistribute it and/or
8255e72915d4cbddceb435e13d81601755714e9fSE Android *  modify it under the terms of the GNU Lesser General Public
9255e72915d4cbddceb435e13d81601755714e9fSE Android *  License as published by the Free Software Foundation; either
10255e72915d4cbddceb435e13d81601755714e9fSE Android *  version 2.1 of the License, or (at your option) any later version.
11255e72915d4cbddceb435e13d81601755714e9fSE Android *
12255e72915d4cbddceb435e13d81601755714e9fSE Android *  This library is distributed in the hope that it will be useful,
13255e72915d4cbddceb435e13d81601755714e9fSE Android *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14255e72915d4cbddceb435e13d81601755714e9fSE Android *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15255e72915d4cbddceb435e13d81601755714e9fSE Android *  Lesser General Public License for more details.
16255e72915d4cbddceb435e13d81601755714e9fSE Android *
17255e72915d4cbddceb435e13d81601755714e9fSE Android *  You should have received a copy of the GNU Lesser General Public
18255e72915d4cbddceb435e13d81601755714e9fSE Android *  License along with this library; if not, write to the Free Software
19255e72915d4cbddceb435e13d81601755714e9fSE Android *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20255e72915d4cbddceb435e13d81601755714e9fSE Android */
21255e72915d4cbddceb435e13d81601755714e9fSE Android
22255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h>
23255e72915d4cbddceb435e13d81601755714e9fSE Android
24255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/flask_types.h>
25255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/conditional.h>
26255e72915d4cbddceb435e13d81601755714e9fSE Android
27255e72915d4cbddceb435e13d81601755714e9fSE Android#include "private.h"
28255e72915d4cbddceb435e13d81601755714e9fSE Android
29255e72915d4cbddceb435e13d81601755714e9fSE Android/* move all type rules to top of t/f lists to help kernel on evaluation */
30255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic void cond_optimize(cond_av_list_t ** l)
31255e72915d4cbddceb435e13d81601755714e9fSE Android{
32255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *top, *p, *cur;
33255e72915d4cbddceb435e13d81601755714e9fSE Android
34255e72915d4cbddceb435e13d81601755714e9fSE Android	top = p = cur = *l;
35255e72915d4cbddceb435e13d81601755714e9fSE Android
36255e72915d4cbddceb435e13d81601755714e9fSE Android	while (cur) {
37255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((cur->node->key.specified & AVTAB_TYPE) && (top != cur)) {
38255e72915d4cbddceb435e13d81601755714e9fSE Android			p->next = cur->next;
39255e72915d4cbddceb435e13d81601755714e9fSE Android			cur->next = top;
40255e72915d4cbddceb435e13d81601755714e9fSE Android			top = cur;
41255e72915d4cbddceb435e13d81601755714e9fSE Android			cur = p->next;
42255e72915d4cbddceb435e13d81601755714e9fSE Android		} else {
43255e72915d4cbddceb435e13d81601755714e9fSE Android			p = cur;
44255e72915d4cbddceb435e13d81601755714e9fSE Android			cur = cur->next;
45255e72915d4cbddceb435e13d81601755714e9fSE Android		}
46255e72915d4cbddceb435e13d81601755714e9fSE Android	}
47255e72915d4cbddceb435e13d81601755714e9fSE Android	*l = top;
48255e72915d4cbddceb435e13d81601755714e9fSE Android}
49255e72915d4cbddceb435e13d81601755714e9fSE Android
50255e72915d4cbddceb435e13d81601755714e9fSE Android/* reorder t/f lists for kernel */
51255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_optimize_lists(cond_list_t * cl)
52255e72915d4cbddceb435e13d81601755714e9fSE Android{
53255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_list_t *n;
54255e72915d4cbddceb435e13d81601755714e9fSE Android
55255e72915d4cbddceb435e13d81601755714e9fSE Android	for (n = cl; n != NULL; n = n->next) {
56255e72915d4cbddceb435e13d81601755714e9fSE Android		cond_optimize(&n->true_list);
57255e72915d4cbddceb435e13d81601755714e9fSE Android		cond_optimize(&n->false_list);
58255e72915d4cbddceb435e13d81601755714e9fSE Android	}
59255e72915d4cbddceb435e13d81601755714e9fSE Android}
60255e72915d4cbddceb435e13d81601755714e9fSE Android
61255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int bool_present(unsigned int target, unsigned int bools[],
62255e72915d4cbddceb435e13d81601755714e9fSE Android			unsigned int num_bools)
63255e72915d4cbddceb435e13d81601755714e9fSE Android{
64255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i = 0;
65255e72915d4cbddceb435e13d81601755714e9fSE Android	int ret = 1;
66255e72915d4cbddceb435e13d81601755714e9fSE Android
67255e72915d4cbddceb435e13d81601755714e9fSE Android	if (num_bools > COND_MAX_BOOLS) {
68255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
69255e72915d4cbddceb435e13d81601755714e9fSE Android	}
70255e72915d4cbddceb435e13d81601755714e9fSE Android	while (i < num_bools && target != bools[i])
71255e72915d4cbddceb435e13d81601755714e9fSE Android		i++;
72255e72915d4cbddceb435e13d81601755714e9fSE Android	if (i == num_bools)
73255e72915d4cbddceb435e13d81601755714e9fSE Android		ret = 0;	/* got to end w/o match */
74255e72915d4cbddceb435e13d81601755714e9fSE Android	return ret;
75255e72915d4cbddceb435e13d81601755714e9fSE Android}
76255e72915d4cbddceb435e13d81601755714e9fSE Android
77255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int same_bools(cond_node_t * a, cond_node_t * b)
78255e72915d4cbddceb435e13d81601755714e9fSE Android{
79255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i, x;
80255e72915d4cbddceb435e13d81601755714e9fSE Android
81255e72915d4cbddceb435e13d81601755714e9fSE Android	x = a->nbools;
82255e72915d4cbddceb435e13d81601755714e9fSE Android
83255e72915d4cbddceb435e13d81601755714e9fSE Android	/* same number of bools? */
84255e72915d4cbddceb435e13d81601755714e9fSE Android	if (x != b->nbools)
85255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
86255e72915d4cbddceb435e13d81601755714e9fSE Android
87255e72915d4cbddceb435e13d81601755714e9fSE Android	/* make sure all the bools in a are also in b */
88255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < x; i++)
89255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!bool_present(a->bool_ids[i], b->bool_ids, x))
90255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
91255e72915d4cbddceb435e13d81601755714e9fSE Android	return 1;
92255e72915d4cbddceb435e13d81601755714e9fSE Android}
93255e72915d4cbddceb435e13d81601755714e9fSE Android
94255e72915d4cbddceb435e13d81601755714e9fSE Android/*
95255e72915d4cbddceb435e13d81601755714e9fSE Android * Determine if two conditional expressions are equal.
96255e72915d4cbddceb435e13d81601755714e9fSE Android */
97255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_expr_equal(cond_node_t * a, cond_node_t * b)
98255e72915d4cbddceb435e13d81601755714e9fSE Android{
99255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_expr_t *cur_a, *cur_b;
100255e72915d4cbddceb435e13d81601755714e9fSE Android
101255e72915d4cbddceb435e13d81601755714e9fSE Android	if (a == NULL || b == NULL)
102255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
103255e72915d4cbddceb435e13d81601755714e9fSE Android
104255e72915d4cbddceb435e13d81601755714e9fSE Android	if (a->nbools != b->nbools)
105255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
106255e72915d4cbddceb435e13d81601755714e9fSE Android
107255e72915d4cbddceb435e13d81601755714e9fSE Android	/* if exprs have <= COND_MAX_BOOLS we can check the precompute values
108255e72915d4cbddceb435e13d81601755714e9fSE Android	 * for the expressions.
109255e72915d4cbddceb435e13d81601755714e9fSE Android	 */
110255e72915d4cbddceb435e13d81601755714e9fSE Android	if (a->nbools <= COND_MAX_BOOLS && b->nbools <= COND_MAX_BOOLS) {
111255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!same_bools(a, b))
112255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
113255e72915d4cbddceb435e13d81601755714e9fSE Android		return (a->expr_pre_comp == b->expr_pre_comp);
114255e72915d4cbddceb435e13d81601755714e9fSE Android	}
115255e72915d4cbddceb435e13d81601755714e9fSE Android
116255e72915d4cbddceb435e13d81601755714e9fSE Android	/* for long expressions we check for exactly the same expression */
117255e72915d4cbddceb435e13d81601755714e9fSE Android	cur_a = a->expr;
118255e72915d4cbddceb435e13d81601755714e9fSE Android	cur_b = b->expr;
119255e72915d4cbddceb435e13d81601755714e9fSE Android	while (1) {
120255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cur_a == NULL && cur_b == NULL)
121255e72915d4cbddceb435e13d81601755714e9fSE Android			return 1;
122255e72915d4cbddceb435e13d81601755714e9fSE Android		else if (cur_a == NULL || cur_b == NULL)
123255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
124255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cur_a->expr_type != cur_b->expr_type)
125255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
126255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cur_a->expr_type == COND_BOOL) {
127255e72915d4cbddceb435e13d81601755714e9fSE Android			if (cur_a->bool != cur_b->bool)
128255e72915d4cbddceb435e13d81601755714e9fSE Android				return 0;
129255e72915d4cbddceb435e13d81601755714e9fSE Android		}
130255e72915d4cbddceb435e13d81601755714e9fSE Android		cur_a = cur_a->next;
131255e72915d4cbddceb435e13d81601755714e9fSE Android		cur_b = cur_b->next;
132255e72915d4cbddceb435e13d81601755714e9fSE Android	}
133255e72915d4cbddceb435e13d81601755714e9fSE Android	return 1;
134255e72915d4cbddceb435e13d81601755714e9fSE Android}
135255e72915d4cbddceb435e13d81601755714e9fSE Android
136255e72915d4cbddceb435e13d81601755714e9fSE Android/* Create a new conditional node, optionally copying
137255e72915d4cbddceb435e13d81601755714e9fSE Android * the conditional expression from an existing node.
138255e72915d4cbddceb435e13d81601755714e9fSE Android * If node is NULL then a new node will be created
139255e72915d4cbddceb435e13d81601755714e9fSE Android * with no conditional expression.
140255e72915d4cbddceb435e13d81601755714e9fSE Android */
141255e72915d4cbddceb435e13d81601755714e9fSE Androidcond_node_t *cond_node_create(policydb_t * p, cond_node_t * node)
142255e72915d4cbddceb435e13d81601755714e9fSE Android{
143255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_node_t *new_node;
144255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i;
145255e72915d4cbddceb435e13d81601755714e9fSE Android
146255e72915d4cbddceb435e13d81601755714e9fSE Android	new_node = (cond_node_t *)malloc(sizeof(cond_node_t));
147255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!new_node) {
148255e72915d4cbddceb435e13d81601755714e9fSE Android		return NULL;
149255e72915d4cbddceb435e13d81601755714e9fSE Android	}
150255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(new_node, 0, sizeof(cond_node_t));
151255e72915d4cbddceb435e13d81601755714e9fSE Android
152255e72915d4cbddceb435e13d81601755714e9fSE Android	if (node) {
153255e72915d4cbddceb435e13d81601755714e9fSE Android		new_node->expr = cond_copy_expr(node->expr);
154255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!new_node->expr) {
155255e72915d4cbddceb435e13d81601755714e9fSE Android			free(new_node);
156255e72915d4cbddceb435e13d81601755714e9fSE Android			return NULL;
157255e72915d4cbddceb435e13d81601755714e9fSE Android		}
158255e72915d4cbddceb435e13d81601755714e9fSE Android		new_node->cur_state = cond_evaluate_expr(p, new_node->expr);
159255e72915d4cbddceb435e13d81601755714e9fSE Android		new_node->nbools = node->nbools;
160255e72915d4cbddceb435e13d81601755714e9fSE Android		for (i = 0; i < min(node->nbools, COND_MAX_BOOLS); i++)
161255e72915d4cbddceb435e13d81601755714e9fSE Android			new_node->bool_ids[i] = node->bool_ids[i];
162255e72915d4cbddceb435e13d81601755714e9fSE Android		new_node->expr_pre_comp = node->expr_pre_comp;
163fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley		new_node->flags = node->flags;
164255e72915d4cbddceb435e13d81601755714e9fSE Android	}
165255e72915d4cbddceb435e13d81601755714e9fSE Android
166255e72915d4cbddceb435e13d81601755714e9fSE Android	return new_node;
167255e72915d4cbddceb435e13d81601755714e9fSE Android}
168255e72915d4cbddceb435e13d81601755714e9fSE Android
169255e72915d4cbddceb435e13d81601755714e9fSE Android/* Find a conditional (the needle) within a list of existing ones (the
170255e72915d4cbddceb435e13d81601755714e9fSE Android * haystack) that has a matching expression.  If found, return a
171255e72915d4cbddceb435e13d81601755714e9fSE Android * pointer to the existing node, setting 'was_created' to 0.
172255e72915d4cbddceb435e13d81601755714e9fSE Android * Otherwise create a new one and return it, setting 'was_created' to
173255e72915d4cbddceb435e13d81601755714e9fSE Android * 1. */
174255e72915d4cbddceb435e13d81601755714e9fSE Androidcond_node_t *cond_node_find(policydb_t * p,
175255e72915d4cbddceb435e13d81601755714e9fSE Android			    cond_node_t * needle, cond_node_t * haystack,
176255e72915d4cbddceb435e13d81601755714e9fSE Android			    int *was_created)
177255e72915d4cbddceb435e13d81601755714e9fSE Android{
178255e72915d4cbddceb435e13d81601755714e9fSE Android	while (haystack) {
179255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cond_expr_equal(needle, haystack)) {
180255e72915d4cbddceb435e13d81601755714e9fSE Android			*was_created = 0;
181255e72915d4cbddceb435e13d81601755714e9fSE Android			return haystack;
182255e72915d4cbddceb435e13d81601755714e9fSE Android		}
183255e72915d4cbddceb435e13d81601755714e9fSE Android		haystack = haystack->next;
184255e72915d4cbddceb435e13d81601755714e9fSE Android	}
185255e72915d4cbddceb435e13d81601755714e9fSE Android	*was_created = 1;
186255e72915d4cbddceb435e13d81601755714e9fSE Android
187255e72915d4cbddceb435e13d81601755714e9fSE Android	return cond_node_create(p, needle);
188255e72915d4cbddceb435e13d81601755714e9fSE Android}
189255e72915d4cbddceb435e13d81601755714e9fSE Android
190255e72915d4cbddceb435e13d81601755714e9fSE Android/* return either a pre-existing matching node or create a new node */
191255e72915d4cbddceb435e13d81601755714e9fSE Androidcond_node_t *cond_node_search(policydb_t * p, cond_node_t * list,
192255e72915d4cbddceb435e13d81601755714e9fSE Android			      cond_node_t * cn)
193255e72915d4cbddceb435e13d81601755714e9fSE Android{
194255e72915d4cbddceb435e13d81601755714e9fSE Android	int was_created;
195255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_node_t *result = cond_node_find(p, cn, list, &was_created);
196255e72915d4cbddceb435e13d81601755714e9fSE Android	if (result != NULL && was_created) {
197255e72915d4cbddceb435e13d81601755714e9fSE Android		/* add conditional node to policy list */
198255e72915d4cbddceb435e13d81601755714e9fSE Android		result->next = p->cond_list;
199255e72915d4cbddceb435e13d81601755714e9fSE Android		p->cond_list = result;
200255e72915d4cbddceb435e13d81601755714e9fSE Android	}
201255e72915d4cbddceb435e13d81601755714e9fSE Android	return result;
202255e72915d4cbddceb435e13d81601755714e9fSE Android}
203255e72915d4cbddceb435e13d81601755714e9fSE Android
204255e72915d4cbddceb435e13d81601755714e9fSE Android/*
205255e72915d4cbddceb435e13d81601755714e9fSE Android * cond_evaluate_expr evaluates a conditional expr
206255e72915d4cbddceb435e13d81601755714e9fSE Android * in reverse polish notation. It returns true (1), false (0),
207255e72915d4cbddceb435e13d81601755714e9fSE Android * or undefined (-1). Undefined occurs when the expression
208255e72915d4cbddceb435e13d81601755714e9fSE Android * exceeds the stack depth of COND_EXPR_MAXDEPTH.
209255e72915d4cbddceb435e13d81601755714e9fSE Android */
210255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_evaluate_expr(policydb_t * p, cond_expr_t * expr)
211255e72915d4cbddceb435e13d81601755714e9fSE Android{
212255e72915d4cbddceb435e13d81601755714e9fSE Android
213255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_expr_t *cur;
214255e72915d4cbddceb435e13d81601755714e9fSE Android	int s[COND_EXPR_MAXDEPTH];
215255e72915d4cbddceb435e13d81601755714e9fSE Android	int sp = -1;
216255e72915d4cbddceb435e13d81601755714e9fSE Android
217255e72915d4cbddceb435e13d81601755714e9fSE Android	s[0] = -1;
218255e72915d4cbddceb435e13d81601755714e9fSE Android
219255e72915d4cbddceb435e13d81601755714e9fSE Android	for (cur = expr; cur != NULL; cur = cur->next) {
220255e72915d4cbddceb435e13d81601755714e9fSE Android		switch (cur->expr_type) {
221255e72915d4cbddceb435e13d81601755714e9fSE Android		case COND_BOOL:
222255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp == (COND_EXPR_MAXDEPTH - 1))
223255e72915d4cbddceb435e13d81601755714e9fSE Android				return -1;
224255e72915d4cbddceb435e13d81601755714e9fSE Android			sp++;
225255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] = p->bool_val_to_struct[cur->bool - 1]->state;
226255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
227255e72915d4cbddceb435e13d81601755714e9fSE Android		case COND_NOT:
228255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp < 0)
229255e72915d4cbddceb435e13d81601755714e9fSE Android				return -1;
230255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] = !s[sp];
231255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
232255e72915d4cbddceb435e13d81601755714e9fSE Android		case COND_OR:
233255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp < 1)
234255e72915d4cbddceb435e13d81601755714e9fSE Android				return -1;
235255e72915d4cbddceb435e13d81601755714e9fSE Android			sp--;
236255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] |= s[sp + 1];
237255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
238255e72915d4cbddceb435e13d81601755714e9fSE Android		case COND_AND:
239255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp < 1)
240255e72915d4cbddceb435e13d81601755714e9fSE Android				return -1;
241255e72915d4cbddceb435e13d81601755714e9fSE Android			sp--;
242255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] &= s[sp + 1];
243255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
244255e72915d4cbddceb435e13d81601755714e9fSE Android		case COND_XOR:
245255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp < 1)
246255e72915d4cbddceb435e13d81601755714e9fSE Android				return -1;
247255e72915d4cbddceb435e13d81601755714e9fSE Android			sp--;
248255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] ^= s[sp + 1];
249255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
250255e72915d4cbddceb435e13d81601755714e9fSE Android		case COND_EQ:
251255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp < 1)
252255e72915d4cbddceb435e13d81601755714e9fSE Android				return -1;
253255e72915d4cbddceb435e13d81601755714e9fSE Android			sp--;
254255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] = (s[sp] == s[sp + 1]);
255255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
256255e72915d4cbddceb435e13d81601755714e9fSE Android		case COND_NEQ:
257255e72915d4cbddceb435e13d81601755714e9fSE Android			if (sp < 1)
258255e72915d4cbddceb435e13d81601755714e9fSE Android				return -1;
259255e72915d4cbddceb435e13d81601755714e9fSE Android			sp--;
260255e72915d4cbddceb435e13d81601755714e9fSE Android			s[sp] = (s[sp] != s[sp + 1]);
261255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
262255e72915d4cbddceb435e13d81601755714e9fSE Android		default:
263255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
264255e72915d4cbddceb435e13d81601755714e9fSE Android		}
265255e72915d4cbddceb435e13d81601755714e9fSE Android	}
266255e72915d4cbddceb435e13d81601755714e9fSE Android	return s[0];
267255e72915d4cbddceb435e13d81601755714e9fSE Android}
268255e72915d4cbddceb435e13d81601755714e9fSE Android
269255e72915d4cbddceb435e13d81601755714e9fSE Androidcond_expr_t *cond_copy_expr(cond_expr_t * expr)
270255e72915d4cbddceb435e13d81601755714e9fSE Android{
271255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_expr_t *cur, *head, *tail, *new_expr;
272255e72915d4cbddceb435e13d81601755714e9fSE Android	tail = head = NULL;
273255e72915d4cbddceb435e13d81601755714e9fSE Android	cur = expr;
274255e72915d4cbddceb435e13d81601755714e9fSE Android	while (cur) {
275255e72915d4cbddceb435e13d81601755714e9fSE Android		new_expr = (cond_expr_t *) malloc(sizeof(cond_expr_t));
276255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!new_expr)
277255e72915d4cbddceb435e13d81601755714e9fSE Android			goto free_head;
278255e72915d4cbddceb435e13d81601755714e9fSE Android		memset(new_expr, 0, sizeof(cond_expr_t));
279255e72915d4cbddceb435e13d81601755714e9fSE Android
280255e72915d4cbddceb435e13d81601755714e9fSE Android		new_expr->expr_type = cur->expr_type;
281255e72915d4cbddceb435e13d81601755714e9fSE Android		new_expr->bool = cur->bool;
282255e72915d4cbddceb435e13d81601755714e9fSE Android
283255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!head)
284255e72915d4cbddceb435e13d81601755714e9fSE Android			head = new_expr;
285255e72915d4cbddceb435e13d81601755714e9fSE Android		if (tail)
286255e72915d4cbddceb435e13d81601755714e9fSE Android			tail->next = new_expr;
287255e72915d4cbddceb435e13d81601755714e9fSE Android		tail = new_expr;
288255e72915d4cbddceb435e13d81601755714e9fSE Android		cur = cur->next;
289255e72915d4cbddceb435e13d81601755714e9fSE Android	}
290255e72915d4cbddceb435e13d81601755714e9fSE Android	return head;
291255e72915d4cbddceb435e13d81601755714e9fSE Android
292255e72915d4cbddceb435e13d81601755714e9fSE Android      free_head:
293255e72915d4cbddceb435e13d81601755714e9fSE Android	while (head) {
294255e72915d4cbddceb435e13d81601755714e9fSE Android		tail = head->next;
295255e72915d4cbddceb435e13d81601755714e9fSE Android		free(head);
296255e72915d4cbddceb435e13d81601755714e9fSE Android		head = tail;
297255e72915d4cbddceb435e13d81601755714e9fSE Android	}
298255e72915d4cbddceb435e13d81601755714e9fSE Android	return NULL;
299255e72915d4cbddceb435e13d81601755714e9fSE Android}
300255e72915d4cbddceb435e13d81601755714e9fSE Android
301255e72915d4cbddceb435e13d81601755714e9fSE Android/*
302255e72915d4cbddceb435e13d81601755714e9fSE Android * evaluate_cond_node evaluates the conditional stored in
303255e72915d4cbddceb435e13d81601755714e9fSE Android * a cond_node_t and if the result is different than the
304255e72915d4cbddceb435e13d81601755714e9fSE Android * current state of the node it sets the rules in the true/false
305255e72915d4cbddceb435e13d81601755714e9fSE Android * list appropriately. If the result of the expression is undefined
306255e72915d4cbddceb435e13d81601755714e9fSE Android * all of the rules are disabled for safety.
307255e72915d4cbddceb435e13d81601755714e9fSE Android */
308255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int evaluate_cond_node(policydb_t * p, cond_node_t * node)
309255e72915d4cbddceb435e13d81601755714e9fSE Android{
310255e72915d4cbddceb435e13d81601755714e9fSE Android	int new_state;
311255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *cur;
312255e72915d4cbddceb435e13d81601755714e9fSE Android
313255e72915d4cbddceb435e13d81601755714e9fSE Android	new_state = cond_evaluate_expr(p, node->expr);
314255e72915d4cbddceb435e13d81601755714e9fSE Android	if (new_state != node->cur_state) {
315255e72915d4cbddceb435e13d81601755714e9fSE Android		node->cur_state = new_state;
316255e72915d4cbddceb435e13d81601755714e9fSE Android		if (new_state == -1)
317255e72915d4cbddceb435e13d81601755714e9fSE Android			printf
318255e72915d4cbddceb435e13d81601755714e9fSE Android			    ("expression result was undefined - disabling all rules.\n");
319255e72915d4cbddceb435e13d81601755714e9fSE Android		/* turn the rules on or off */
320255e72915d4cbddceb435e13d81601755714e9fSE Android		for (cur = node->true_list; cur != NULL; cur = cur->next) {
321255e72915d4cbddceb435e13d81601755714e9fSE Android			if (new_state <= 0) {
322255e72915d4cbddceb435e13d81601755714e9fSE Android				cur->node->key.specified &= ~AVTAB_ENABLED;
323255e72915d4cbddceb435e13d81601755714e9fSE Android			} else {
324255e72915d4cbddceb435e13d81601755714e9fSE Android				cur->node->key.specified |= AVTAB_ENABLED;
325255e72915d4cbddceb435e13d81601755714e9fSE Android			}
326255e72915d4cbddceb435e13d81601755714e9fSE Android		}
327255e72915d4cbddceb435e13d81601755714e9fSE Android
328255e72915d4cbddceb435e13d81601755714e9fSE Android		for (cur = node->false_list; cur != NULL; cur = cur->next) {
329255e72915d4cbddceb435e13d81601755714e9fSE Android			/* -1 or 1 */
330255e72915d4cbddceb435e13d81601755714e9fSE Android			if (new_state) {
331255e72915d4cbddceb435e13d81601755714e9fSE Android				cur->node->key.specified &= ~AVTAB_ENABLED;
332255e72915d4cbddceb435e13d81601755714e9fSE Android			} else {
333255e72915d4cbddceb435e13d81601755714e9fSE Android				cur->node->key.specified |= AVTAB_ENABLED;
334255e72915d4cbddceb435e13d81601755714e9fSE Android			}
335255e72915d4cbddceb435e13d81601755714e9fSE Android		}
336255e72915d4cbddceb435e13d81601755714e9fSE Android	}
337255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
338255e72915d4cbddceb435e13d81601755714e9fSE Android}
339255e72915d4cbddceb435e13d81601755714e9fSE Android
340255e72915d4cbddceb435e13d81601755714e9fSE Android/* precompute and simplify an expression if possible.  If left with !expression, change
341255e72915d4cbddceb435e13d81601755714e9fSE Android * to expression and switch t and f. precompute expression for expressions with limited
342255e72915d4cbddceb435e13d81601755714e9fSE Android * number of bools.
343255e72915d4cbddceb435e13d81601755714e9fSE Android */
344255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_normalize_expr(policydb_t * p, cond_node_t * cn)
345255e72915d4cbddceb435e13d81601755714e9fSE Android{
346255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_expr_t *ne, *e;
347255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *tmp;
348255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i, j, orig_value[COND_MAX_BOOLS];
349255e72915d4cbddceb435e13d81601755714e9fSE Android	int k;
350255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t test = 0x0;
351255e72915d4cbddceb435e13d81601755714e9fSE Android	avrule_t *tmp2;
352255e72915d4cbddceb435e13d81601755714e9fSE Android
353255e72915d4cbddceb435e13d81601755714e9fSE Android	cn->nbools = 0;
354255e72915d4cbddceb435e13d81601755714e9fSE Android
355255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(cn->bool_ids, 0, sizeof(cn->bool_ids));
356255e72915d4cbddceb435e13d81601755714e9fSE Android	cn->expr_pre_comp = 0x0;
357255e72915d4cbddceb435e13d81601755714e9fSE Android
358255e72915d4cbddceb435e13d81601755714e9fSE Android	/* take care of !expr case */
359255e72915d4cbddceb435e13d81601755714e9fSE Android	ne = NULL;
360255e72915d4cbddceb435e13d81601755714e9fSE Android	e = cn->expr;
361255e72915d4cbddceb435e13d81601755714e9fSE Android
362255e72915d4cbddceb435e13d81601755714e9fSE Android	/* becuase it's RPN look at last element */
363255e72915d4cbddceb435e13d81601755714e9fSE Android	while (e->next != NULL) {
364255e72915d4cbddceb435e13d81601755714e9fSE Android		ne = e;
365255e72915d4cbddceb435e13d81601755714e9fSE Android		e = e->next;
366255e72915d4cbddceb435e13d81601755714e9fSE Android	}
367255e72915d4cbddceb435e13d81601755714e9fSE Android	if (e->expr_type == COND_NOT) {
368255e72915d4cbddceb435e13d81601755714e9fSE Android		if (ne) {
369255e72915d4cbddceb435e13d81601755714e9fSE Android			ne->next = NULL;
370255e72915d4cbddceb435e13d81601755714e9fSE Android		} else {	/* ne should never be NULL */
371255e72915d4cbddceb435e13d81601755714e9fSE Android			printf
372255e72915d4cbddceb435e13d81601755714e9fSE Android			    ("Found expr with no bools and only a ! - this should never happen.\n");
373255e72915d4cbddceb435e13d81601755714e9fSE Android			return -1;
374255e72915d4cbddceb435e13d81601755714e9fSE Android		}
375255e72915d4cbddceb435e13d81601755714e9fSE Android		/* swap the true and false lists */
376255e72915d4cbddceb435e13d81601755714e9fSE Android		tmp = cn->true_list;
377255e72915d4cbddceb435e13d81601755714e9fSE Android		cn->true_list = cn->false_list;
378255e72915d4cbddceb435e13d81601755714e9fSE Android		cn->false_list = tmp;
379255e72915d4cbddceb435e13d81601755714e9fSE Android		tmp2 = cn->avtrue_list;
380255e72915d4cbddceb435e13d81601755714e9fSE Android		cn->avtrue_list = cn->avfalse_list;
381255e72915d4cbddceb435e13d81601755714e9fSE Android		cn->avfalse_list = tmp2;
382255e72915d4cbddceb435e13d81601755714e9fSE Android
383255e72915d4cbddceb435e13d81601755714e9fSE Android		/* free the "not" node in the list */
384255e72915d4cbddceb435e13d81601755714e9fSE Android		free(e);
385255e72915d4cbddceb435e13d81601755714e9fSE Android	}
386255e72915d4cbddceb435e13d81601755714e9fSE Android
387255e72915d4cbddceb435e13d81601755714e9fSE Android	/* find all the bools in the expression */
388255e72915d4cbddceb435e13d81601755714e9fSE Android	for (e = cn->expr; e != NULL; e = e->next) {
389255e72915d4cbddceb435e13d81601755714e9fSE Android		switch (e->expr_type) {
390255e72915d4cbddceb435e13d81601755714e9fSE Android		case COND_BOOL:
391255e72915d4cbddceb435e13d81601755714e9fSE Android			i = 0;
392255e72915d4cbddceb435e13d81601755714e9fSE Android			/* see if we've already seen this bool */
393255e72915d4cbddceb435e13d81601755714e9fSE Android			if (!bool_present(e->bool, cn->bool_ids, cn->nbools)) {
394255e72915d4cbddceb435e13d81601755714e9fSE Android				/* count em all but only record up to COND_MAX_BOOLS */
395255e72915d4cbddceb435e13d81601755714e9fSE Android				if (cn->nbools < COND_MAX_BOOLS)
396255e72915d4cbddceb435e13d81601755714e9fSE Android					cn->bool_ids[cn->nbools++] = e->bool;
397255e72915d4cbddceb435e13d81601755714e9fSE Android				else
398255e72915d4cbddceb435e13d81601755714e9fSE Android					cn->nbools++;
399255e72915d4cbddceb435e13d81601755714e9fSE Android			}
400255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
401255e72915d4cbddceb435e13d81601755714e9fSE Android		default:
402255e72915d4cbddceb435e13d81601755714e9fSE Android			break;
403255e72915d4cbddceb435e13d81601755714e9fSE Android		}
404255e72915d4cbddceb435e13d81601755714e9fSE Android	}
405255e72915d4cbddceb435e13d81601755714e9fSE Android
406255e72915d4cbddceb435e13d81601755714e9fSE Android	/* only precompute for exprs with <= COND_AX_BOOLS */
407255e72915d4cbddceb435e13d81601755714e9fSE Android	if (cn->nbools <= COND_MAX_BOOLS) {
408255e72915d4cbddceb435e13d81601755714e9fSE Android		/* save the default values for the bools so we can play with them */
409255e72915d4cbddceb435e13d81601755714e9fSE Android		for (i = 0; i < cn->nbools; i++) {
410255e72915d4cbddceb435e13d81601755714e9fSE Android			orig_value[i] =
411255e72915d4cbddceb435e13d81601755714e9fSE Android			    p->bool_val_to_struct[cn->bool_ids[i] - 1]->state;
412255e72915d4cbddceb435e13d81601755714e9fSE Android		}
413255e72915d4cbddceb435e13d81601755714e9fSE Android
414255e72915d4cbddceb435e13d81601755714e9fSE Android		/* loop through all possible combinations of values for bools in expression */
415255e72915d4cbddceb435e13d81601755714e9fSE Android		for (test = 0x0; test < (0x1U << cn->nbools); test++) {
416255e72915d4cbddceb435e13d81601755714e9fSE Android			/* temporarily set the value for all the bools in the
417255e72915d4cbddceb435e13d81601755714e9fSE Android			 * expression using the corr.  bit in test */
418255e72915d4cbddceb435e13d81601755714e9fSE Android			for (j = 0; j < cn->nbools; j++) {
419255e72915d4cbddceb435e13d81601755714e9fSE Android				p->bool_val_to_struct[cn->bool_ids[j] -
420255e72915d4cbddceb435e13d81601755714e9fSE Android						      1]->state =
421255e72915d4cbddceb435e13d81601755714e9fSE Android				    (test & (0x1 << j)) ? 1 : 0;
422255e72915d4cbddceb435e13d81601755714e9fSE Android			}
423255e72915d4cbddceb435e13d81601755714e9fSE Android			k = cond_evaluate_expr(p, cn->expr);
424255e72915d4cbddceb435e13d81601755714e9fSE Android			if (k == -1) {
425255e72915d4cbddceb435e13d81601755714e9fSE Android				printf
426255e72915d4cbddceb435e13d81601755714e9fSE Android				    ("While testing expression, expression result "
427255e72915d4cbddceb435e13d81601755714e9fSE Android				     "was undefined - this should never happen.\n");
428255e72915d4cbddceb435e13d81601755714e9fSE Android				return -1;
429255e72915d4cbddceb435e13d81601755714e9fSE Android			}
430255e72915d4cbddceb435e13d81601755714e9fSE Android			/* set the bit if expression evaluates true */
431255e72915d4cbddceb435e13d81601755714e9fSE Android			if (k)
432255e72915d4cbddceb435e13d81601755714e9fSE Android				cn->expr_pre_comp |= 0x1 << test;
433255e72915d4cbddceb435e13d81601755714e9fSE Android		}
434255e72915d4cbddceb435e13d81601755714e9fSE Android
435255e72915d4cbddceb435e13d81601755714e9fSE Android		/* restore bool default values */
436255e72915d4cbddceb435e13d81601755714e9fSE Android		for (i = 0; i < cn->nbools; i++)
437255e72915d4cbddceb435e13d81601755714e9fSE Android			p->bool_val_to_struct[cn->bool_ids[i] - 1]->state =
438255e72915d4cbddceb435e13d81601755714e9fSE Android			    orig_value[i];
439255e72915d4cbddceb435e13d81601755714e9fSE Android	}
440255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
441255e72915d4cbddceb435e13d81601755714e9fSE Android}
442255e72915d4cbddceb435e13d81601755714e9fSE Android
443255e72915d4cbddceb435e13d81601755714e9fSE Androidint evaluate_conds(policydb_t * p)
444255e72915d4cbddceb435e13d81601755714e9fSE Android{
445255e72915d4cbddceb435e13d81601755714e9fSE Android	int ret;
446255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_node_t *cur;
447255e72915d4cbddceb435e13d81601755714e9fSE Android
448255e72915d4cbddceb435e13d81601755714e9fSE Android	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
449255e72915d4cbddceb435e13d81601755714e9fSE Android		ret = evaluate_cond_node(p, cur);
450255e72915d4cbddceb435e13d81601755714e9fSE Android		if (ret)
451255e72915d4cbddceb435e13d81601755714e9fSE Android			return ret;
452255e72915d4cbddceb435e13d81601755714e9fSE Android	}
453255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
454255e72915d4cbddceb435e13d81601755714e9fSE Android}
455255e72915d4cbddceb435e13d81601755714e9fSE Android
456255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_policydb_init(policydb_t * p)
457255e72915d4cbddceb435e13d81601755714e9fSE Android{
458255e72915d4cbddceb435e13d81601755714e9fSE Android	p->bool_val_to_struct = NULL;
459255e72915d4cbddceb435e13d81601755714e9fSE Android	p->cond_list = NULL;
460255e72915d4cbddceb435e13d81601755714e9fSE Android	if (avtab_init(&p->te_cond_avtab))
461255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
462255e72915d4cbddceb435e13d81601755714e9fSE Android
463255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
464255e72915d4cbddceb435e13d81601755714e9fSE Android}
465255e72915d4cbddceb435e13d81601755714e9fSE Android
466255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_av_list_destroy(cond_av_list_t * list)
467255e72915d4cbddceb435e13d81601755714e9fSE Android{
468255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *cur, *next;
469255e72915d4cbddceb435e13d81601755714e9fSE Android	for (cur = list; cur != NULL; cur = next) {
470255e72915d4cbddceb435e13d81601755714e9fSE Android		next = cur->next;
471255e72915d4cbddceb435e13d81601755714e9fSE Android		/* the avtab_ptr_t node is destroy by the avtab */
472255e72915d4cbddceb435e13d81601755714e9fSE Android		free(cur);
473255e72915d4cbddceb435e13d81601755714e9fSE Android	}
474255e72915d4cbddceb435e13d81601755714e9fSE Android}
475255e72915d4cbddceb435e13d81601755714e9fSE Android
476255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_expr_destroy(cond_expr_t * expr)
477255e72915d4cbddceb435e13d81601755714e9fSE Android{
478255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_expr_t *cur_expr, *next_expr;
479255e72915d4cbddceb435e13d81601755714e9fSE Android
480255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!expr)
481255e72915d4cbddceb435e13d81601755714e9fSE Android		return;
482255e72915d4cbddceb435e13d81601755714e9fSE Android
483255e72915d4cbddceb435e13d81601755714e9fSE Android	for (cur_expr = expr; cur_expr != NULL; cur_expr = next_expr) {
484255e72915d4cbddceb435e13d81601755714e9fSE Android		next_expr = cur_expr->next;
485255e72915d4cbddceb435e13d81601755714e9fSE Android		free(cur_expr);
486255e72915d4cbddceb435e13d81601755714e9fSE Android	}
487255e72915d4cbddceb435e13d81601755714e9fSE Android}
488255e72915d4cbddceb435e13d81601755714e9fSE Android
489255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_node_destroy(cond_node_t * node)
490255e72915d4cbddceb435e13d81601755714e9fSE Android{
491255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!node)
492255e72915d4cbddceb435e13d81601755714e9fSE Android		return;
493255e72915d4cbddceb435e13d81601755714e9fSE Android
494255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_expr_destroy(node->expr);
495255e72915d4cbddceb435e13d81601755714e9fSE Android	avrule_list_destroy(node->avtrue_list);
496255e72915d4cbddceb435e13d81601755714e9fSE Android	avrule_list_destroy(node->avfalse_list);
497255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_destroy(node->true_list);
498255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_destroy(node->false_list);
499255e72915d4cbddceb435e13d81601755714e9fSE Android}
500255e72915d4cbddceb435e13d81601755714e9fSE Android
501255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_list_destroy(cond_list_t * list)
502255e72915d4cbddceb435e13d81601755714e9fSE Android{
503255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_node_t *next, *cur;
504255e72915d4cbddceb435e13d81601755714e9fSE Android
505255e72915d4cbddceb435e13d81601755714e9fSE Android	if (list == NULL)
506255e72915d4cbddceb435e13d81601755714e9fSE Android		return;
507255e72915d4cbddceb435e13d81601755714e9fSE Android
508255e72915d4cbddceb435e13d81601755714e9fSE Android	for (cur = list; cur != NULL; cur = next) {
509255e72915d4cbddceb435e13d81601755714e9fSE Android		next = cur->next;
510255e72915d4cbddceb435e13d81601755714e9fSE Android		cond_node_destroy(cur);
511255e72915d4cbddceb435e13d81601755714e9fSE Android		free(cur);
512255e72915d4cbddceb435e13d81601755714e9fSE Android	}
513255e72915d4cbddceb435e13d81601755714e9fSE Android}
514255e72915d4cbddceb435e13d81601755714e9fSE Android
515255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_policydb_destroy(policydb_t * p)
516255e72915d4cbddceb435e13d81601755714e9fSE Android{
517255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->bool_val_to_struct != NULL)
518255e72915d4cbddceb435e13d81601755714e9fSE Android		free(p->bool_val_to_struct);
519255e72915d4cbddceb435e13d81601755714e9fSE Android	avtab_destroy(&p->te_cond_avtab);
520255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_list_destroy(p->cond_list);
521255e72915d4cbddceb435e13d81601755714e9fSE Android}
522255e72915d4cbddceb435e13d81601755714e9fSE Android
523255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_init_bool_indexes(policydb_t * p)
524255e72915d4cbddceb435e13d81601755714e9fSE Android{
525255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->bool_val_to_struct)
526255e72915d4cbddceb435e13d81601755714e9fSE Android		free(p->bool_val_to_struct);
527255e72915d4cbddceb435e13d81601755714e9fSE Android	p->bool_val_to_struct = (cond_bool_datum_t **)
528255e72915d4cbddceb435e13d81601755714e9fSE Android	    malloc(p->p_bools.nprim * sizeof(cond_bool_datum_t *));
529255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!p->bool_val_to_struct)
530255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
531255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
532255e72915d4cbddceb435e13d81601755714e9fSE Android}
533255e72915d4cbddceb435e13d81601755714e9fSE Android
534255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_destroy_bool(hashtab_key_t key, hashtab_datum_t datum, void *p
535255e72915d4cbddceb435e13d81601755714e9fSE Android		      __attribute__ ((unused)))
536255e72915d4cbddceb435e13d81601755714e9fSE Android{
537255e72915d4cbddceb435e13d81601755714e9fSE Android	if (key)
538255e72915d4cbddceb435e13d81601755714e9fSE Android		free(key);
539255e72915d4cbddceb435e13d81601755714e9fSE Android	free(datum);
540255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
541255e72915d4cbddceb435e13d81601755714e9fSE Android}
542255e72915d4cbddceb435e13d81601755714e9fSE Android
543255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_index_bool(hashtab_key_t key, hashtab_datum_t datum, void *datap)
544255e72915d4cbddceb435e13d81601755714e9fSE Android{
545255e72915d4cbddceb435e13d81601755714e9fSE Android	policydb_t *p;
546255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_bool_datum_t *booldatum;
547255e72915d4cbddceb435e13d81601755714e9fSE Android
548255e72915d4cbddceb435e13d81601755714e9fSE Android	booldatum = datum;
549255e72915d4cbddceb435e13d81601755714e9fSE Android	p = datap;
550255e72915d4cbddceb435e13d81601755714e9fSE Android
551255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!booldatum->s.value || booldatum->s.value > p->p_bools.nprim)
552255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
553255e72915d4cbddceb435e13d81601755714e9fSE Android
554255e72915d4cbddceb435e13d81601755714e9fSE Android	p->p_bool_val_to_name[booldatum->s.value - 1] = key;
555255e72915d4cbddceb435e13d81601755714e9fSE Android	p->bool_val_to_struct[booldatum->s.value - 1] = booldatum;
556255e72915d4cbddceb435e13d81601755714e9fSE Android
557255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
558255e72915d4cbddceb435e13d81601755714e9fSE Android}
559255e72915d4cbddceb435e13d81601755714e9fSE Android
560255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int bool_isvalid(cond_bool_datum_t * b)
561255e72915d4cbddceb435e13d81601755714e9fSE Android{
562255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!(b->state == 0 || b->state == 1))
563255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
564255e72915d4cbddceb435e13d81601755714e9fSE Android	return 1;
565255e72915d4cbddceb435e13d81601755714e9fSE Android}
566255e72915d4cbddceb435e13d81601755714e9fSE Android
567fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalleyint cond_read_bool(policydb_t * p,
568fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley		   hashtab_t h,
569255e72915d4cbddceb435e13d81601755714e9fSE Android		   struct policy_file *fp)
570255e72915d4cbddceb435e13d81601755714e9fSE Android{
571255e72915d4cbddceb435e13d81601755714e9fSE Android	char *key = 0;
572255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_bool_datum_t *booldatum;
573255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t buf[3], len;
574255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc;
575255e72915d4cbddceb435e13d81601755714e9fSE Android
576255e72915d4cbddceb435e13d81601755714e9fSE Android	booldatum = malloc(sizeof(cond_bool_datum_t));
577255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!booldatum)
578255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
579255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(booldatum, 0, sizeof(cond_bool_datum_t));
580255e72915d4cbddceb435e13d81601755714e9fSE Android
581255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
582255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0)
583255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
584255e72915d4cbddceb435e13d81601755714e9fSE Android
585255e72915d4cbddceb435e13d81601755714e9fSE Android	booldatum->s.value = le32_to_cpu(buf[0]);
586255e72915d4cbddceb435e13d81601755714e9fSE Android	booldatum->state = le32_to_cpu(buf[1]);
587255e72915d4cbddceb435e13d81601755714e9fSE Android
588255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!bool_isvalid(booldatum))
589255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
590255e72915d4cbddceb435e13d81601755714e9fSE Android
591255e72915d4cbddceb435e13d81601755714e9fSE Android	len = le32_to_cpu(buf[2]);
592255e72915d4cbddceb435e13d81601755714e9fSE Android
593255e72915d4cbddceb435e13d81601755714e9fSE Android	key = malloc(len + 1);
594255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!key)
595255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
596255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(key, fp, len);
597255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0)
598255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
599255e72915d4cbddceb435e13d81601755714e9fSE Android	key[len] = 0;
600fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley
601fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley	if (p->policy_type != POLICY_KERN &&
602fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley	    p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
603fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley		rc = next_entry(buf, fp, sizeof(uint32_t));
604fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley		if (rc < 0)
605fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley			goto err;
606fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley		booldatum->flags = le32_to_cpu(buf[0]);
607fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley	}
608fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley
609255e72915d4cbddceb435e13d81601755714e9fSE Android	if (hashtab_insert(h, key, booldatum))
610255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
611255e72915d4cbddceb435e13d81601755714e9fSE Android
612255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
613255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
614255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_destroy_bool(key, booldatum, 0);
615255e72915d4cbddceb435e13d81601755714e9fSE Android	return -1;
616255e72915d4cbddceb435e13d81601755714e9fSE Android}
617255e72915d4cbddceb435e13d81601755714e9fSE Android
618255e72915d4cbddceb435e13d81601755714e9fSE Androidstruct cond_insertf_data {
619255e72915d4cbddceb435e13d81601755714e9fSE Android	struct policydb *p;
620255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *other;
621255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *head;
622255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *tail;
623255e72915d4cbddceb435e13d81601755714e9fSE Android};
624255e72915d4cbddceb435e13d81601755714e9fSE Android
625255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int cond_insertf(avtab_t * a
626255e72915d4cbddceb435e13d81601755714e9fSE Android			__attribute__ ((unused)), avtab_key_t * k,
627255e72915d4cbddceb435e13d81601755714e9fSE Android			avtab_datum_t * d, void *ptr)
628255e72915d4cbddceb435e13d81601755714e9fSE Android{
629255e72915d4cbddceb435e13d81601755714e9fSE Android	struct cond_insertf_data *data = ptr;
630255e72915d4cbddceb435e13d81601755714e9fSE Android	struct policydb *p = data->p;
631255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *other = data->other, *list, *cur;
632255e72915d4cbddceb435e13d81601755714e9fSE Android	avtab_ptr_t node_ptr;
633255e72915d4cbddceb435e13d81601755714e9fSE Android	uint8_t found;
634255e72915d4cbddceb435e13d81601755714e9fSE Android
635255e72915d4cbddceb435e13d81601755714e9fSE Android	/*
636255e72915d4cbddceb435e13d81601755714e9fSE Android	 * For type rules we have to make certain there aren't any
637255e72915d4cbddceb435e13d81601755714e9fSE Android	 * conflicting rules by searching the te_avtab and the
638255e72915d4cbddceb435e13d81601755714e9fSE Android	 * cond_te_avtab.
639255e72915d4cbddceb435e13d81601755714e9fSE Android	 */
640255e72915d4cbddceb435e13d81601755714e9fSE Android	if (k->specified & AVTAB_TYPE) {
641255e72915d4cbddceb435e13d81601755714e9fSE Android		if (avtab_search(&p->te_avtab, k)) {
642255e72915d4cbddceb435e13d81601755714e9fSE Android			printf
643255e72915d4cbddceb435e13d81601755714e9fSE Android			    ("security: type rule already exists outside of a conditional.");
644255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
645255e72915d4cbddceb435e13d81601755714e9fSE Android		}
646255e72915d4cbddceb435e13d81601755714e9fSE Android		/*
647255e72915d4cbddceb435e13d81601755714e9fSE Android		 * If we are reading the false list other will be a pointer to
648255e72915d4cbddceb435e13d81601755714e9fSE Android		 * the true list. We can have duplicate entries if there is only
649255e72915d4cbddceb435e13d81601755714e9fSE Android		 * 1 other entry and it is in our true list.
650255e72915d4cbddceb435e13d81601755714e9fSE Android		 *
651255e72915d4cbddceb435e13d81601755714e9fSE Android		 * If we are reading the true list (other == NULL) there shouldn't
652255e72915d4cbddceb435e13d81601755714e9fSE Android		 * be any other entries.
653255e72915d4cbddceb435e13d81601755714e9fSE Android		 */
654255e72915d4cbddceb435e13d81601755714e9fSE Android		if (other) {
655255e72915d4cbddceb435e13d81601755714e9fSE Android			node_ptr = avtab_search_node(&p->te_cond_avtab, k);
656255e72915d4cbddceb435e13d81601755714e9fSE Android			if (node_ptr) {
657255e72915d4cbddceb435e13d81601755714e9fSE Android				if (avtab_search_node_next
658255e72915d4cbddceb435e13d81601755714e9fSE Android				    (node_ptr, k->specified)) {
659255e72915d4cbddceb435e13d81601755714e9fSE Android					printf
660255e72915d4cbddceb435e13d81601755714e9fSE Android					    ("security: too many conflicting type rules.");
661255e72915d4cbddceb435e13d81601755714e9fSE Android					goto err;
662255e72915d4cbddceb435e13d81601755714e9fSE Android				}
663255e72915d4cbddceb435e13d81601755714e9fSE Android				found = 0;
664255e72915d4cbddceb435e13d81601755714e9fSE Android				for (cur = other; cur != NULL; cur = cur->next) {
665255e72915d4cbddceb435e13d81601755714e9fSE Android					if (cur->node == node_ptr) {
666255e72915d4cbddceb435e13d81601755714e9fSE Android						found = 1;
667255e72915d4cbddceb435e13d81601755714e9fSE Android						break;
668255e72915d4cbddceb435e13d81601755714e9fSE Android					}
669255e72915d4cbddceb435e13d81601755714e9fSE Android				}
670255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!found) {
671255e72915d4cbddceb435e13d81601755714e9fSE Android					printf
672255e72915d4cbddceb435e13d81601755714e9fSE Android					    ("security: conflicting type rules.\n");
673255e72915d4cbddceb435e13d81601755714e9fSE Android					goto err;
674255e72915d4cbddceb435e13d81601755714e9fSE Android				}
675255e72915d4cbddceb435e13d81601755714e9fSE Android			}
676255e72915d4cbddceb435e13d81601755714e9fSE Android		} else {
677255e72915d4cbddceb435e13d81601755714e9fSE Android			if (avtab_search(&p->te_cond_avtab, k)) {
678255e72915d4cbddceb435e13d81601755714e9fSE Android				printf
679255e72915d4cbddceb435e13d81601755714e9fSE Android				    ("security: conflicting type rules when adding type rule for true.\n");
680255e72915d4cbddceb435e13d81601755714e9fSE Android				goto err;
681255e72915d4cbddceb435e13d81601755714e9fSE Android			}
682255e72915d4cbddceb435e13d81601755714e9fSE Android		}
683255e72915d4cbddceb435e13d81601755714e9fSE Android	}
684255e72915d4cbddceb435e13d81601755714e9fSE Android
685255e72915d4cbddceb435e13d81601755714e9fSE Android	node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
686255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!node_ptr) {
687255e72915d4cbddceb435e13d81601755714e9fSE Android		printf("security: could not insert rule.");
688255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
689255e72915d4cbddceb435e13d81601755714e9fSE Android	}
690255e72915d4cbddceb435e13d81601755714e9fSE Android	node_ptr->parse_context = (void *)1;
691255e72915d4cbddceb435e13d81601755714e9fSE Android
692255e72915d4cbddceb435e13d81601755714e9fSE Android	list = malloc(sizeof(cond_av_list_t));
693255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!list)
694255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
695255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(list, 0, sizeof(cond_av_list_t));
696255e72915d4cbddceb435e13d81601755714e9fSE Android
697255e72915d4cbddceb435e13d81601755714e9fSE Android	list->node = node_ptr;
698255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!data->head)
699255e72915d4cbddceb435e13d81601755714e9fSE Android		data->head = list;
700255e72915d4cbddceb435e13d81601755714e9fSE Android	else
701255e72915d4cbddceb435e13d81601755714e9fSE Android		data->tail->next = list;
702255e72915d4cbddceb435e13d81601755714e9fSE Android	data->tail = list;
703255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
704255e72915d4cbddceb435e13d81601755714e9fSE Android
705255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
706255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_destroy(data->head);
707255e72915d4cbddceb435e13d81601755714e9fSE Android	data->head = NULL;
708255e72915d4cbddceb435e13d81601755714e9fSE Android	return -1;
709255e72915d4cbddceb435e13d81601755714e9fSE Android}
710255e72915d4cbddceb435e13d81601755714e9fSE Android
711255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int cond_read_av_list(policydb_t * p, void *fp,
712255e72915d4cbddceb435e13d81601755714e9fSE Android			     cond_av_list_t ** ret_list, cond_av_list_t * other)
713255e72915d4cbddceb435e13d81601755714e9fSE Android{
714255e72915d4cbddceb435e13d81601755714e9fSE Android	unsigned int i;
715255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc;
716255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t buf[1], len;
717255e72915d4cbddceb435e13d81601755714e9fSE Android	struct cond_insertf_data data;
718255e72915d4cbddceb435e13d81601755714e9fSE Android
719255e72915d4cbddceb435e13d81601755714e9fSE Android	*ret_list = NULL;
720255e72915d4cbddceb435e13d81601755714e9fSE Android
721255e72915d4cbddceb435e13d81601755714e9fSE Android	len = 0;
722255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(buf, fp, sizeof(uint32_t));
723255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0)
724255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
725255e72915d4cbddceb435e13d81601755714e9fSE Android
726255e72915d4cbddceb435e13d81601755714e9fSE Android	len = le32_to_cpu(buf[0]);
727255e72915d4cbddceb435e13d81601755714e9fSE Android	if (len == 0) {
728255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
729255e72915d4cbddceb435e13d81601755714e9fSE Android	}
730255e72915d4cbddceb435e13d81601755714e9fSE Android
731255e72915d4cbddceb435e13d81601755714e9fSE Android	data.p = p;
732255e72915d4cbddceb435e13d81601755714e9fSE Android	data.other = other;
733255e72915d4cbddceb435e13d81601755714e9fSE Android	data.head = NULL;
734255e72915d4cbddceb435e13d81601755714e9fSE Android	data.tail = NULL;
735255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < len; i++) {
736255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab,
737255e72915d4cbddceb435e13d81601755714e9fSE Android				     cond_insertf, &data);
738255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc)
739255e72915d4cbddceb435e13d81601755714e9fSE Android			return rc;
740255e72915d4cbddceb435e13d81601755714e9fSE Android
741255e72915d4cbddceb435e13d81601755714e9fSE Android	}
742255e72915d4cbddceb435e13d81601755714e9fSE Android
743255e72915d4cbddceb435e13d81601755714e9fSE Android	*ret_list = data.head;
744255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
745255e72915d4cbddceb435e13d81601755714e9fSE Android}
746255e72915d4cbddceb435e13d81601755714e9fSE Android
747255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int expr_isvalid(policydb_t * p, cond_expr_t * expr)
748255e72915d4cbddceb435e13d81601755714e9fSE Android{
749255e72915d4cbddceb435e13d81601755714e9fSE Android	if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
750255e72915d4cbddceb435e13d81601755714e9fSE Android		printf
751255e72915d4cbddceb435e13d81601755714e9fSE Android		    ("security: conditional expressions uses unknown operator.\n");
752255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
753255e72915d4cbddceb435e13d81601755714e9fSE Android	}
754255e72915d4cbddceb435e13d81601755714e9fSE Android
755255e72915d4cbddceb435e13d81601755714e9fSE Android	if (expr->bool > p->p_bools.nprim) {
756255e72915d4cbddceb435e13d81601755714e9fSE Android		printf
757255e72915d4cbddceb435e13d81601755714e9fSE Android		    ("security: conditional expressions uses unknown bool.\n");
758255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
759255e72915d4cbddceb435e13d81601755714e9fSE Android	}
760255e72915d4cbddceb435e13d81601755714e9fSE Android	return 1;
761255e72915d4cbddceb435e13d81601755714e9fSE Android}
762255e72915d4cbddceb435e13d81601755714e9fSE Android
763255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int cond_read_node(policydb_t * p, cond_node_t * node, void *fp)
764255e72915d4cbddceb435e13d81601755714e9fSE Android{
765255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t buf[2];
766255e72915d4cbddceb435e13d81601755714e9fSE Android	int len, i, rc;
767255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_expr_t *expr = NULL, *last = NULL;
768255e72915d4cbddceb435e13d81601755714e9fSE Android
769255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(buf, fp, sizeof(uint32_t));
770255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0)
771255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
772255e72915d4cbddceb435e13d81601755714e9fSE Android
773255e72915d4cbddceb435e13d81601755714e9fSE Android	node->cur_state = le32_to_cpu(buf[0]);
774255e72915d4cbddceb435e13d81601755714e9fSE Android
775255e72915d4cbddceb435e13d81601755714e9fSE Android	len = 0;
776255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(buf, fp, sizeof(uint32_t));
777255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0)
778255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
779255e72915d4cbddceb435e13d81601755714e9fSE Android
780255e72915d4cbddceb435e13d81601755714e9fSE Android	/* expr */
781255e72915d4cbddceb435e13d81601755714e9fSE Android	len = le32_to_cpu(buf[0]);
782255e72915d4cbddceb435e13d81601755714e9fSE Android
783255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < len; i++) {
784255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = next_entry(buf, fp, sizeof(uint32_t) * 2);
785255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc < 0)
786255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
787255e72915d4cbddceb435e13d81601755714e9fSE Android
788255e72915d4cbddceb435e13d81601755714e9fSE Android		expr = malloc(sizeof(cond_expr_t));
789255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!expr) {
790255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
791255e72915d4cbddceb435e13d81601755714e9fSE Android		}
792255e72915d4cbddceb435e13d81601755714e9fSE Android		memset(expr, 0, sizeof(cond_expr_t));
793255e72915d4cbddceb435e13d81601755714e9fSE Android
794255e72915d4cbddceb435e13d81601755714e9fSE Android		expr->expr_type = le32_to_cpu(buf[0]);
795255e72915d4cbddceb435e13d81601755714e9fSE Android		expr->bool = le32_to_cpu(buf[1]);
796255e72915d4cbddceb435e13d81601755714e9fSE Android
797255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!expr_isvalid(p, expr)) {
798255e72915d4cbddceb435e13d81601755714e9fSE Android			free(expr);
799255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
800255e72915d4cbddceb435e13d81601755714e9fSE Android		}
801255e72915d4cbddceb435e13d81601755714e9fSE Android
802255e72915d4cbddceb435e13d81601755714e9fSE Android		if (i == 0) {
803255e72915d4cbddceb435e13d81601755714e9fSE Android			node->expr = expr;
804255e72915d4cbddceb435e13d81601755714e9fSE Android		} else {
805255e72915d4cbddceb435e13d81601755714e9fSE Android			last->next = expr;
806255e72915d4cbddceb435e13d81601755714e9fSE Android		}
807255e72915d4cbddceb435e13d81601755714e9fSE Android		last = expr;
808255e72915d4cbddceb435e13d81601755714e9fSE Android	}
809255e72915d4cbddceb435e13d81601755714e9fSE Android
810255e72915d4cbddceb435e13d81601755714e9fSE Android	if (p->policy_type == POLICY_KERN) {
811255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cond_read_av_list(p, fp, &node->true_list, NULL) != 0)
812255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
813255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cond_read_av_list(p, fp, &node->false_list, node->true_list)
814255e72915d4cbddceb435e13d81601755714e9fSE Android		    != 0)
815255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
816255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
817255e72915d4cbddceb435e13d81601755714e9fSE Android		if (avrule_read_list(p, &node->avtrue_list, fp))
818255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
819255e72915d4cbddceb435e13d81601755714e9fSE Android		if (avrule_read_list(p, &node->avfalse_list, fp))
820255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
821255e72915d4cbddceb435e13d81601755714e9fSE Android	}
822255e72915d4cbddceb435e13d81601755714e9fSE Android
823fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley	if (p->policy_type != POLICY_KERN &&
824fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley	    p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
825fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley		rc = next_entry(buf, fp, sizeof(uint32_t));
826fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley		if (rc < 0)
827fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley			goto err;
828fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley		node->flags = le32_to_cpu(buf[0]);
829fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley	}
830fb82f8ed213dd54eebc6bdd5557984c3ba870496Stephen Smalley
831255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
832255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
833255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_node_destroy(node);
834255e72915d4cbddceb435e13d81601755714e9fSE Android	free(node);
835255e72915d4cbddceb435e13d81601755714e9fSE Android	return -1;
836255e72915d4cbddceb435e13d81601755714e9fSE Android}
837255e72915d4cbddceb435e13d81601755714e9fSE Android
838255e72915d4cbddceb435e13d81601755714e9fSE Androidint cond_read_list(policydb_t * p, cond_list_t ** list, void *fp)
839255e72915d4cbddceb435e13d81601755714e9fSE Android{
840255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_node_t *node, *last = NULL;
841255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t buf[1];
842255e72915d4cbddceb435e13d81601755714e9fSE Android	int i, len, rc;
843255e72915d4cbddceb435e13d81601755714e9fSE Android
844255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(buf, fp, sizeof(uint32_t));
845255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0)
846255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
847255e72915d4cbddceb435e13d81601755714e9fSE Android
848255e72915d4cbddceb435e13d81601755714e9fSE Android	len = le32_to_cpu(buf[0]);
849255e72915d4cbddceb435e13d81601755714e9fSE Android
850255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel);
851255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc)
852255e72915d4cbddceb435e13d81601755714e9fSE Android		goto err;
853255e72915d4cbddceb435e13d81601755714e9fSE Android
854255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < len; i++) {
855255e72915d4cbddceb435e13d81601755714e9fSE Android		node = malloc(sizeof(cond_node_t));
856255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!node)
857255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
858255e72915d4cbddceb435e13d81601755714e9fSE Android		memset(node, 0, sizeof(cond_node_t));
859255e72915d4cbddceb435e13d81601755714e9fSE Android
860255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cond_read_node(p, node, fp) != 0)
861255e72915d4cbddceb435e13d81601755714e9fSE Android			goto err;
862255e72915d4cbddceb435e13d81601755714e9fSE Android
863255e72915d4cbddceb435e13d81601755714e9fSE Android		if (i == 0) {
864255e72915d4cbddceb435e13d81601755714e9fSE Android			*list = node;
865255e72915d4cbddceb435e13d81601755714e9fSE Android		} else {
866255e72915d4cbddceb435e13d81601755714e9fSE Android			last->next = node;
867255e72915d4cbddceb435e13d81601755714e9fSE Android		}
868255e72915d4cbddceb435e13d81601755714e9fSE Android		last = node;
869255e72915d4cbddceb435e13d81601755714e9fSE Android	}
870255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
871255e72915d4cbddceb435e13d81601755714e9fSE Android      err:
872255e72915d4cbddceb435e13d81601755714e9fSE Android	return -1;
873255e72915d4cbddceb435e13d81601755714e9fSE Android}
874255e72915d4cbddceb435e13d81601755714e9fSE Android
875255e72915d4cbddceb435e13d81601755714e9fSE Android/* Determine whether additional permissions are granted by the conditional
876255e72915d4cbddceb435e13d81601755714e9fSE Android * av table, and if so, add them to the result
877255e72915d4cbddceb435e13d81601755714e9fSE Android */
878255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid cond_compute_av(avtab_t * ctab, avtab_key_t * key,
879255e72915d4cbddceb435e13d81601755714e9fSE Android		     struct sepol_av_decision *avd)
880255e72915d4cbddceb435e13d81601755714e9fSE Android{
881255e72915d4cbddceb435e13d81601755714e9fSE Android	avtab_ptr_t node;
882255e72915d4cbddceb435e13d81601755714e9fSE Android
883255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!ctab || !key || !avd)
884255e72915d4cbddceb435e13d81601755714e9fSE Android		return;
885255e72915d4cbddceb435e13d81601755714e9fSE Android
886255e72915d4cbddceb435e13d81601755714e9fSE Android	for (node = avtab_search_node(ctab, key); node != NULL;
887255e72915d4cbddceb435e13d81601755714e9fSE Android	     node = avtab_search_node_next(node, key->specified)) {
888255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((uint16_t) (AVTAB_ALLOWED | AVTAB_ENABLED) ==
889255e72915d4cbddceb435e13d81601755714e9fSE Android		    (node->key.specified & (AVTAB_ALLOWED | AVTAB_ENABLED)))
890255e72915d4cbddceb435e13d81601755714e9fSE Android			avd->allowed |= node->datum.data;
891255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((uint16_t) (AVTAB_AUDITDENY | AVTAB_ENABLED) ==
892255e72915d4cbddceb435e13d81601755714e9fSE Android		    (node->key.specified & (AVTAB_AUDITDENY | AVTAB_ENABLED)))
893255e72915d4cbddceb435e13d81601755714e9fSE Android			/* Since a '0' in an auditdeny mask represents a
894255e72915d4cbddceb435e13d81601755714e9fSE Android			 * permission we do NOT want to audit (dontaudit), we use
895255e72915d4cbddceb435e13d81601755714e9fSE Android			 * the '&' operand to ensure that all '0's in the mask
896255e72915d4cbddceb435e13d81601755714e9fSE Android			 * are retained (much unlike the allow and auditallow cases).
897255e72915d4cbddceb435e13d81601755714e9fSE Android			 */
898255e72915d4cbddceb435e13d81601755714e9fSE Android			avd->auditdeny &= node->datum.data;
899255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((uint16_t) (AVTAB_AUDITALLOW | AVTAB_ENABLED) ==
900255e72915d4cbddceb435e13d81601755714e9fSE Android		    (node->key.specified & (AVTAB_AUDITALLOW | AVTAB_ENABLED)))
901255e72915d4cbddceb435e13d81601755714e9fSE Android			avd->auditallow |= node->datum.data;
902255e72915d4cbddceb435e13d81601755714e9fSE Android	}
903255e72915d4cbddceb435e13d81601755714e9fSE Android	return;
904255e72915d4cbddceb435e13d81601755714e9fSE Android}
905255e72915d4cbddceb435e13d81601755714e9fSE Android
906255e72915d4cbddceb435e13d81601755714e9fSE Androidavtab_datum_t *cond_av_list_search(avtab_key_t * key,
907255e72915d4cbddceb435e13d81601755714e9fSE Android				   cond_av_list_t * cond_list)
908255e72915d4cbddceb435e13d81601755714e9fSE Android{
909255e72915d4cbddceb435e13d81601755714e9fSE Android
910255e72915d4cbddceb435e13d81601755714e9fSE Android	cond_av_list_t *cur_av;
911255e72915d4cbddceb435e13d81601755714e9fSE Android
912255e72915d4cbddceb435e13d81601755714e9fSE Android	for (cur_av = cond_list; cur_av != NULL; cur_av = cur_av->next) {
913255e72915d4cbddceb435e13d81601755714e9fSE Android
914255e72915d4cbddceb435e13d81601755714e9fSE Android		if (cur_av->node->key.source_type == key->source_type &&
915255e72915d4cbddceb435e13d81601755714e9fSE Android		    cur_av->node->key.target_type == key->target_type &&
916255e72915d4cbddceb435e13d81601755714e9fSE Android		    cur_av->node->key.target_class == key->target_class)
917255e72915d4cbddceb435e13d81601755714e9fSE Android
918255e72915d4cbddceb435e13d81601755714e9fSE Android			return &cur_av->node->datum;
919255e72915d4cbddceb435e13d81601755714e9fSE Android
920255e72915d4cbddceb435e13d81601755714e9fSE Android	}
921255e72915d4cbddceb435e13d81601755714e9fSE Android	return NULL;
922255e72915d4cbddceb435e13d81601755714e9fSE Android
923255e72915d4cbddceb435e13d81601755714e9fSE Android}
924