xref: /aosp_15_r20/external/selinux/libsepol/src/avtab.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker 
2*2d543d20SAndroid Build Coastguard Worker /* Author : Stephen Smalley, <[email protected]> */
3*2d543d20SAndroid Build Coastguard Worker 
4*2d543d20SAndroid Build Coastguard Worker /*
5*2d543d20SAndroid Build Coastguard Worker  * Updated: Yuichi Nakamura <[email protected]>
6*2d543d20SAndroid Build Coastguard Worker  * 	Tuned number of hash slots for avtab to reduce memory usage
7*2d543d20SAndroid Build Coastguard Worker  */
8*2d543d20SAndroid Build Coastguard Worker 
9*2d543d20SAndroid Build Coastguard Worker /* Updated: Frank Mayer <[email protected]>
10*2d543d20SAndroid Build Coastguard Worker  *          and Karl MacMillan <[email protected]>
11*2d543d20SAndroid Build Coastguard Worker  *
12*2d543d20SAndroid Build Coastguard Worker  * 	Added conditional policy language extensions
13*2d543d20SAndroid Build Coastguard Worker  *
14*2d543d20SAndroid Build Coastguard Worker  * Updated: Red Hat, Inc.  James Morris <[email protected]>
15*2d543d20SAndroid Build Coastguard Worker  *
16*2d543d20SAndroid Build Coastguard Worker  *      Code cleanup
17*2d543d20SAndroid Build Coastguard Worker  *
18*2d543d20SAndroid Build Coastguard Worker  * Updated: Karl MacMillan <[email protected]>
19*2d543d20SAndroid Build Coastguard Worker  *
20*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2003 Tresys Technology, LLC
21*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2003,2007 Red Hat, Inc.
22*2d543d20SAndroid Build Coastguard Worker  *
23*2d543d20SAndroid Build Coastguard Worker  *  This library is free software; you can redistribute it and/or
24*2d543d20SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU Lesser General Public
25*2d543d20SAndroid Build Coastguard Worker  *  License as published by the Free Software Foundation; either
26*2d543d20SAndroid Build Coastguard Worker  *  version 2.1 of the License, or (at your option) any later version.
27*2d543d20SAndroid Build Coastguard Worker  *
28*2d543d20SAndroid Build Coastguard Worker  *  This library is distributed in the hope that it will be useful,
29*2d543d20SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
30*2d543d20SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31*2d543d20SAndroid Build Coastguard Worker  *  Lesser General Public License for more details.
32*2d543d20SAndroid Build Coastguard Worker  *
33*2d543d20SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU Lesser General Public
34*2d543d20SAndroid Build Coastguard Worker  *  License along with this library; if not, write to the Free Software
35*2d543d20SAndroid Build Coastguard Worker  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
36*2d543d20SAndroid Build Coastguard Worker  */
37*2d543d20SAndroid Build Coastguard Worker 
38*2d543d20SAndroid Build Coastguard Worker /* FLASK */
39*2d543d20SAndroid Build Coastguard Worker 
40*2d543d20SAndroid Build Coastguard Worker /*
41*2d543d20SAndroid Build Coastguard Worker  * Implementation of the access vector table type.
42*2d543d20SAndroid Build Coastguard Worker  */
43*2d543d20SAndroid Build Coastguard Worker 
44*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
45*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/avtab.h>
46*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
47*2d543d20SAndroid Build Coastguard Worker #include <sepol/errcodes.h>
48*2d543d20SAndroid Build Coastguard Worker 
49*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
50*2d543d20SAndroid Build Coastguard Worker #include "private.h"
51*2d543d20SAndroid Build Coastguard Worker 
52*2d543d20SAndroid Build Coastguard Worker /* Based on MurmurHash3, written by Austin Appleby and placed in the
53*2d543d20SAndroid Build Coastguard Worker  * public domain.
54*2d543d20SAndroid Build Coastguard Worker  */
55*2d543d20SAndroid Build Coastguard Worker ignore_unsigned_overflow_
avtab_hash(struct avtab_key * keyp,uint32_t mask)56*2d543d20SAndroid Build Coastguard Worker static inline int avtab_hash(struct avtab_key *keyp, uint32_t mask)
57*2d543d20SAndroid Build Coastguard Worker {
58*2d543d20SAndroid Build Coastguard Worker 	static const uint32_t c1 = 0xcc9e2d51;
59*2d543d20SAndroid Build Coastguard Worker 	static const uint32_t c2 = 0x1b873593;
60*2d543d20SAndroid Build Coastguard Worker 	static const uint32_t r1 = 15;
61*2d543d20SAndroid Build Coastguard Worker 	static const uint32_t r2 = 13;
62*2d543d20SAndroid Build Coastguard Worker 	static const uint32_t m  = 5;
63*2d543d20SAndroid Build Coastguard Worker 	static const uint32_t n  = 0xe6546b64;
64*2d543d20SAndroid Build Coastguard Worker 
65*2d543d20SAndroid Build Coastguard Worker 	uint32_t hash = 0;
66*2d543d20SAndroid Build Coastguard Worker 
67*2d543d20SAndroid Build Coastguard Worker #define mix(input) do { \
68*2d543d20SAndroid Build Coastguard Worker 	uint32_t v = input; \
69*2d543d20SAndroid Build Coastguard Worker 	v *= c1; \
70*2d543d20SAndroid Build Coastguard Worker 	v = (v << r1) | (v >> (32 - r1)); \
71*2d543d20SAndroid Build Coastguard Worker 	v *= c2; \
72*2d543d20SAndroid Build Coastguard Worker 	hash ^= v; \
73*2d543d20SAndroid Build Coastguard Worker 	hash = (hash << r2) | (hash >> (32 - r2)); \
74*2d543d20SAndroid Build Coastguard Worker 	hash = hash * m + n; \
75*2d543d20SAndroid Build Coastguard Worker } while (0)
76*2d543d20SAndroid Build Coastguard Worker 
77*2d543d20SAndroid Build Coastguard Worker 	mix(keyp->target_class);
78*2d543d20SAndroid Build Coastguard Worker 	mix(keyp->target_type);
79*2d543d20SAndroid Build Coastguard Worker 	mix(keyp->source_type);
80*2d543d20SAndroid Build Coastguard Worker 
81*2d543d20SAndroid Build Coastguard Worker #undef mix
82*2d543d20SAndroid Build Coastguard Worker 
83*2d543d20SAndroid Build Coastguard Worker 	hash ^= hash >> 16;
84*2d543d20SAndroid Build Coastguard Worker 	hash *= 0x85ebca6b;
85*2d543d20SAndroid Build Coastguard Worker 	hash ^= hash >> 13;
86*2d543d20SAndroid Build Coastguard Worker 	hash *= 0xc2b2ae35;
87*2d543d20SAndroid Build Coastguard Worker 	hash ^= hash >> 16;
88*2d543d20SAndroid Build Coastguard Worker 
89*2d543d20SAndroid Build Coastguard Worker 	return hash & mask;
90*2d543d20SAndroid Build Coastguard Worker }
91*2d543d20SAndroid Build Coastguard Worker 
92*2d543d20SAndroid Build Coastguard Worker static avtab_ptr_t
avtab_insert_node(avtab_t * h,int hvalue,avtab_ptr_t prev,avtab_key_t * key,avtab_datum_t * datum)93*2d543d20SAndroid Build Coastguard Worker avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key,
94*2d543d20SAndroid Build Coastguard Worker 		  avtab_datum_t * datum)
95*2d543d20SAndroid Build Coastguard Worker {
96*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t newnode;
97*2d543d20SAndroid Build Coastguard Worker 	avtab_extended_perms_t *xperms;
98*2d543d20SAndroid Build Coastguard Worker 
99*2d543d20SAndroid Build Coastguard Worker 	newnode = (avtab_ptr_t) malloc(sizeof(struct avtab_node));
100*2d543d20SAndroid Build Coastguard Worker 	if (newnode == NULL)
101*2d543d20SAndroid Build Coastguard Worker 		return NULL;
102*2d543d20SAndroid Build Coastguard Worker 	memset(newnode, 0, sizeof(struct avtab_node));
103*2d543d20SAndroid Build Coastguard Worker 	newnode->key = *key;
104*2d543d20SAndroid Build Coastguard Worker 
105*2d543d20SAndroid Build Coastguard Worker 	if (key->specified & AVTAB_XPERMS) {
106*2d543d20SAndroid Build Coastguard Worker 		xperms = calloc(1, sizeof(avtab_extended_perms_t));
107*2d543d20SAndroid Build Coastguard Worker 		if (xperms == NULL) {
108*2d543d20SAndroid Build Coastguard Worker 			free(newnode);
109*2d543d20SAndroid Build Coastguard Worker 			return NULL;
110*2d543d20SAndroid Build Coastguard Worker 		}
111*2d543d20SAndroid Build Coastguard Worker 		if (datum->xperms) /* else caller populates xperms */
112*2d543d20SAndroid Build Coastguard Worker 			*xperms = *(datum->xperms);
113*2d543d20SAndroid Build Coastguard Worker 
114*2d543d20SAndroid Build Coastguard Worker 		newnode->datum.xperms = xperms;
115*2d543d20SAndroid Build Coastguard Worker 		/* data is usually ignored with xperms, except in the case of
116*2d543d20SAndroid Build Coastguard Worker 		 * neverallow checking, which requires permission bits to be set.
117*2d543d20SAndroid Build Coastguard Worker 		 * So copy data so it is set in the avtab
118*2d543d20SAndroid Build Coastguard Worker 		 */
119*2d543d20SAndroid Build Coastguard Worker 		newnode->datum.data = datum->data;
120*2d543d20SAndroid Build Coastguard Worker 	} else {
121*2d543d20SAndroid Build Coastguard Worker 		newnode->datum = *datum;
122*2d543d20SAndroid Build Coastguard Worker 	}
123*2d543d20SAndroid Build Coastguard Worker 
124*2d543d20SAndroid Build Coastguard Worker 	if (prev) {
125*2d543d20SAndroid Build Coastguard Worker 		newnode->next = prev->next;
126*2d543d20SAndroid Build Coastguard Worker 		prev->next = newnode;
127*2d543d20SAndroid Build Coastguard Worker 	} else {
128*2d543d20SAndroid Build Coastguard Worker 		newnode->next = h->htable[hvalue];
129*2d543d20SAndroid Build Coastguard Worker 		h->htable[hvalue] = newnode;
130*2d543d20SAndroid Build Coastguard Worker 	}
131*2d543d20SAndroid Build Coastguard Worker 
132*2d543d20SAndroid Build Coastguard Worker 	h->nel++;
133*2d543d20SAndroid Build Coastguard Worker 	return newnode;
134*2d543d20SAndroid Build Coastguard Worker }
135*2d543d20SAndroid Build Coastguard Worker 
avtab_insert(avtab_t * h,avtab_key_t * key,avtab_datum_t * datum)136*2d543d20SAndroid Build Coastguard Worker int avtab_insert(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
137*2d543d20SAndroid Build Coastguard Worker {
138*2d543d20SAndroid Build Coastguard Worker 	int hvalue;
139*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t prev, cur, newnode;
140*2d543d20SAndroid Build Coastguard Worker 	uint16_t specified =
141*2d543d20SAndroid Build Coastguard Worker 	    key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
142*2d543d20SAndroid Build Coastguard Worker 
143*2d543d20SAndroid Build Coastguard Worker 	if (!h || !h->htable)
144*2d543d20SAndroid Build Coastguard Worker 		return SEPOL_ENOMEM;
145*2d543d20SAndroid Build Coastguard Worker 
146*2d543d20SAndroid Build Coastguard Worker 	hvalue = avtab_hash(key, h->mask);
147*2d543d20SAndroid Build Coastguard Worker 	for (prev = NULL, cur = h->htable[hvalue];
148*2d543d20SAndroid Build Coastguard Worker 	     cur; prev = cur, cur = cur->next) {
149*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
150*2d543d20SAndroid Build Coastguard Worker 		    key->target_type == cur->key.target_type &&
151*2d543d20SAndroid Build Coastguard Worker 		    key->target_class == cur->key.target_class &&
152*2d543d20SAndroid Build Coastguard Worker 		    (specified & cur->key.specified)) {
153*2d543d20SAndroid Build Coastguard Worker 			/* Extended permissions are not necessarily unique */
154*2d543d20SAndroid Build Coastguard Worker 			if (specified & AVTAB_XPERMS)
155*2d543d20SAndroid Build Coastguard Worker 				break;
156*2d543d20SAndroid Build Coastguard Worker 			return SEPOL_EEXIST;
157*2d543d20SAndroid Build Coastguard Worker 		}
158*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type < cur->key.source_type)
159*2d543d20SAndroid Build Coastguard Worker 			break;
160*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
161*2d543d20SAndroid Build Coastguard Worker 		    key->target_type < cur->key.target_type)
162*2d543d20SAndroid Build Coastguard Worker 			break;
163*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
164*2d543d20SAndroid Build Coastguard Worker 		    key->target_type == cur->key.target_type &&
165*2d543d20SAndroid Build Coastguard Worker 		    key->target_class < cur->key.target_class)
166*2d543d20SAndroid Build Coastguard Worker 			break;
167*2d543d20SAndroid Build Coastguard Worker 	}
168*2d543d20SAndroid Build Coastguard Worker 
169*2d543d20SAndroid Build Coastguard Worker 	newnode = avtab_insert_node(h, hvalue, prev, key, datum);
170*2d543d20SAndroid Build Coastguard Worker 	if (!newnode)
171*2d543d20SAndroid Build Coastguard Worker 		return SEPOL_ENOMEM;
172*2d543d20SAndroid Build Coastguard Worker 
173*2d543d20SAndroid Build Coastguard Worker 	return 0;
174*2d543d20SAndroid Build Coastguard Worker }
175*2d543d20SAndroid Build Coastguard Worker 
176*2d543d20SAndroid Build Coastguard Worker /* Unlike avtab_insert(), this function allow multiple insertions of the same
177*2d543d20SAndroid Build Coastguard Worker  * key/specified mask into the table, as needed by the conditional avtab.
178*2d543d20SAndroid Build Coastguard Worker  * It also returns a pointer to the node inserted.
179*2d543d20SAndroid Build Coastguard Worker  */
180*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t
avtab_insert_nonunique(avtab_t * h,avtab_key_t * key,avtab_datum_t * datum)181*2d543d20SAndroid Build Coastguard Worker avtab_insert_nonunique(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
182*2d543d20SAndroid Build Coastguard Worker {
183*2d543d20SAndroid Build Coastguard Worker 	int hvalue;
184*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t prev, cur, newnode;
185*2d543d20SAndroid Build Coastguard Worker 	uint16_t specified =
186*2d543d20SAndroid Build Coastguard Worker 	    key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
187*2d543d20SAndroid Build Coastguard Worker 
188*2d543d20SAndroid Build Coastguard Worker 	if (!h || !h->htable)
189*2d543d20SAndroid Build Coastguard Worker 		return NULL;
190*2d543d20SAndroid Build Coastguard Worker 	hvalue = avtab_hash(key, h->mask);
191*2d543d20SAndroid Build Coastguard Worker 	for (prev = NULL, cur = h->htable[hvalue];
192*2d543d20SAndroid Build Coastguard Worker 	     cur; prev = cur, cur = cur->next) {
193*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
194*2d543d20SAndroid Build Coastguard Worker 		    key->target_type == cur->key.target_type &&
195*2d543d20SAndroid Build Coastguard Worker 		    key->target_class == cur->key.target_class &&
196*2d543d20SAndroid Build Coastguard Worker 		    (specified & cur->key.specified))
197*2d543d20SAndroid Build Coastguard Worker 			break;
198*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type < cur->key.source_type)
199*2d543d20SAndroid Build Coastguard Worker 			break;
200*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
201*2d543d20SAndroid Build Coastguard Worker 		    key->target_type < cur->key.target_type)
202*2d543d20SAndroid Build Coastguard Worker 			break;
203*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
204*2d543d20SAndroid Build Coastguard Worker 		    key->target_type == cur->key.target_type &&
205*2d543d20SAndroid Build Coastguard Worker 		    key->target_class < cur->key.target_class)
206*2d543d20SAndroid Build Coastguard Worker 			break;
207*2d543d20SAndroid Build Coastguard Worker 	}
208*2d543d20SAndroid Build Coastguard Worker 	newnode = avtab_insert_node(h, hvalue, prev, key, datum);
209*2d543d20SAndroid Build Coastguard Worker 
210*2d543d20SAndroid Build Coastguard Worker 	return newnode;
211*2d543d20SAndroid Build Coastguard Worker }
212*2d543d20SAndroid Build Coastguard Worker 
avtab_search(avtab_t * h,avtab_key_t * key)213*2d543d20SAndroid Build Coastguard Worker avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * key)
214*2d543d20SAndroid Build Coastguard Worker {
215*2d543d20SAndroid Build Coastguard Worker 	int hvalue;
216*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t cur;
217*2d543d20SAndroid Build Coastguard Worker 	uint16_t specified =
218*2d543d20SAndroid Build Coastguard Worker 	    key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
219*2d543d20SAndroid Build Coastguard Worker 
220*2d543d20SAndroid Build Coastguard Worker 	if (!h || !h->htable)
221*2d543d20SAndroid Build Coastguard Worker 		return NULL;
222*2d543d20SAndroid Build Coastguard Worker 
223*2d543d20SAndroid Build Coastguard Worker 	hvalue = avtab_hash(key, h->mask);
224*2d543d20SAndroid Build Coastguard Worker 	for (cur = h->htable[hvalue]; cur; cur = cur->next) {
225*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
226*2d543d20SAndroid Build Coastguard Worker 		    key->target_type == cur->key.target_type &&
227*2d543d20SAndroid Build Coastguard Worker 		    key->target_class == cur->key.target_class &&
228*2d543d20SAndroid Build Coastguard Worker 		    (specified & cur->key.specified))
229*2d543d20SAndroid Build Coastguard Worker 			return &cur->datum;
230*2d543d20SAndroid Build Coastguard Worker 
231*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type < cur->key.source_type)
232*2d543d20SAndroid Build Coastguard Worker 			break;
233*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
234*2d543d20SAndroid Build Coastguard Worker 		    key->target_type < cur->key.target_type)
235*2d543d20SAndroid Build Coastguard Worker 			break;
236*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
237*2d543d20SAndroid Build Coastguard Worker 		    key->target_type == cur->key.target_type &&
238*2d543d20SAndroid Build Coastguard Worker 		    key->target_class < cur->key.target_class)
239*2d543d20SAndroid Build Coastguard Worker 			break;
240*2d543d20SAndroid Build Coastguard Worker 	}
241*2d543d20SAndroid Build Coastguard Worker 
242*2d543d20SAndroid Build Coastguard Worker 	return NULL;
243*2d543d20SAndroid Build Coastguard Worker }
244*2d543d20SAndroid Build Coastguard Worker 
245*2d543d20SAndroid Build Coastguard Worker /* This search function returns a node pointer, and can be used in
246*2d543d20SAndroid Build Coastguard Worker  * conjunction with avtab_search_next_node()
247*2d543d20SAndroid Build Coastguard Worker  */
avtab_search_node(avtab_t * h,avtab_key_t * key)248*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t avtab_search_node(avtab_t * h, avtab_key_t * key)
249*2d543d20SAndroid Build Coastguard Worker {
250*2d543d20SAndroid Build Coastguard Worker 	int hvalue;
251*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t cur;
252*2d543d20SAndroid Build Coastguard Worker 	uint16_t specified =
253*2d543d20SAndroid Build Coastguard Worker 	    key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
254*2d543d20SAndroid Build Coastguard Worker 
255*2d543d20SAndroid Build Coastguard Worker 	if (!h || !h->htable)
256*2d543d20SAndroid Build Coastguard Worker 		return NULL;
257*2d543d20SAndroid Build Coastguard Worker 
258*2d543d20SAndroid Build Coastguard Worker 	hvalue = avtab_hash(key, h->mask);
259*2d543d20SAndroid Build Coastguard Worker 	for (cur = h->htable[hvalue]; cur; cur = cur->next) {
260*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
261*2d543d20SAndroid Build Coastguard Worker 		    key->target_type == cur->key.target_type &&
262*2d543d20SAndroid Build Coastguard Worker 		    key->target_class == cur->key.target_class &&
263*2d543d20SAndroid Build Coastguard Worker 		    (specified & cur->key.specified))
264*2d543d20SAndroid Build Coastguard Worker 			return cur;
265*2d543d20SAndroid Build Coastguard Worker 
266*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type < cur->key.source_type)
267*2d543d20SAndroid Build Coastguard Worker 			break;
268*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
269*2d543d20SAndroid Build Coastguard Worker 		    key->target_type < cur->key.target_type)
270*2d543d20SAndroid Build Coastguard Worker 			break;
271*2d543d20SAndroid Build Coastguard Worker 		if (key->source_type == cur->key.source_type &&
272*2d543d20SAndroid Build Coastguard Worker 		    key->target_type == cur->key.target_type &&
273*2d543d20SAndroid Build Coastguard Worker 		    key->target_class < cur->key.target_class)
274*2d543d20SAndroid Build Coastguard Worker 			break;
275*2d543d20SAndroid Build Coastguard Worker 	}
276*2d543d20SAndroid Build Coastguard Worker 	return NULL;
277*2d543d20SAndroid Build Coastguard Worker }
278*2d543d20SAndroid Build Coastguard Worker 
avtab_search_node_next(avtab_ptr_t node,int specified)279*2d543d20SAndroid Build Coastguard Worker avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified)
280*2d543d20SAndroid Build Coastguard Worker {
281*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t cur;
282*2d543d20SAndroid Build Coastguard Worker 
283*2d543d20SAndroid Build Coastguard Worker 	if (!node)
284*2d543d20SAndroid Build Coastguard Worker 		return NULL;
285*2d543d20SAndroid Build Coastguard Worker 
286*2d543d20SAndroid Build Coastguard Worker 	specified &= ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
287*2d543d20SAndroid Build Coastguard Worker 	for (cur = node->next; cur; cur = cur->next) {
288*2d543d20SAndroid Build Coastguard Worker 		if (node->key.source_type == cur->key.source_type &&
289*2d543d20SAndroid Build Coastguard Worker 		    node->key.target_type == cur->key.target_type &&
290*2d543d20SAndroid Build Coastguard Worker 		    node->key.target_class == cur->key.target_class &&
291*2d543d20SAndroid Build Coastguard Worker 		    (specified & cur->key.specified))
292*2d543d20SAndroid Build Coastguard Worker 			return cur;
293*2d543d20SAndroid Build Coastguard Worker 
294*2d543d20SAndroid Build Coastguard Worker 		if (node->key.source_type < cur->key.source_type)
295*2d543d20SAndroid Build Coastguard Worker 			break;
296*2d543d20SAndroid Build Coastguard Worker 		if (node->key.source_type == cur->key.source_type &&
297*2d543d20SAndroid Build Coastguard Worker 		    node->key.target_type < cur->key.target_type)
298*2d543d20SAndroid Build Coastguard Worker 			break;
299*2d543d20SAndroid Build Coastguard Worker 		if (node->key.source_type == cur->key.source_type &&
300*2d543d20SAndroid Build Coastguard Worker 		    node->key.target_type == cur->key.target_type &&
301*2d543d20SAndroid Build Coastguard Worker 		    node->key.target_class < cur->key.target_class)
302*2d543d20SAndroid Build Coastguard Worker 			break;
303*2d543d20SAndroid Build Coastguard Worker 	}
304*2d543d20SAndroid Build Coastguard Worker 	return NULL;
305*2d543d20SAndroid Build Coastguard Worker }
306*2d543d20SAndroid Build Coastguard Worker 
avtab_destroy(avtab_t * h)307*2d543d20SAndroid Build Coastguard Worker void avtab_destroy(avtab_t * h)
308*2d543d20SAndroid Build Coastguard Worker {
309*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
310*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t cur, temp;
311*2d543d20SAndroid Build Coastguard Worker 
312*2d543d20SAndroid Build Coastguard Worker 	if (!h || !h->htable)
313*2d543d20SAndroid Build Coastguard Worker 		return;
314*2d543d20SAndroid Build Coastguard Worker 
315*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < h->nslot; i++) {
316*2d543d20SAndroid Build Coastguard Worker 		cur = h->htable[i];
317*2d543d20SAndroid Build Coastguard Worker 		while (cur != NULL) {
318*2d543d20SAndroid Build Coastguard Worker 			if (cur->key.specified & AVTAB_XPERMS) {
319*2d543d20SAndroid Build Coastguard Worker 				free(cur->datum.xperms);
320*2d543d20SAndroid Build Coastguard Worker 			}
321*2d543d20SAndroid Build Coastguard Worker 			temp = cur;
322*2d543d20SAndroid Build Coastguard Worker 			cur = cur->next;
323*2d543d20SAndroid Build Coastguard Worker 			free(temp);
324*2d543d20SAndroid Build Coastguard Worker 		}
325*2d543d20SAndroid Build Coastguard Worker 		h->htable[i] = NULL;
326*2d543d20SAndroid Build Coastguard Worker 	}
327*2d543d20SAndroid Build Coastguard Worker 	free(h->htable);
328*2d543d20SAndroid Build Coastguard Worker 	h->htable = NULL;
329*2d543d20SAndroid Build Coastguard Worker 	h->nslot = 0;
330*2d543d20SAndroid Build Coastguard Worker 	h->mask = 0;
331*2d543d20SAndroid Build Coastguard Worker }
332*2d543d20SAndroid Build Coastguard Worker 
avtab_map(const avtab_t * h,int (* apply)(avtab_key_t * k,avtab_datum_t * d,void * args),void * args)333*2d543d20SAndroid Build Coastguard Worker int avtab_map(const avtab_t * h,
334*2d543d20SAndroid Build Coastguard Worker 	      int (*apply) (avtab_key_t * k,
335*2d543d20SAndroid Build Coastguard Worker 			    avtab_datum_t * d, void *args), void *args)
336*2d543d20SAndroid Build Coastguard Worker {
337*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
338*2d543d20SAndroid Build Coastguard Worker 	int ret;
339*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t cur;
340*2d543d20SAndroid Build Coastguard Worker 
341*2d543d20SAndroid Build Coastguard Worker 	if (!h)
342*2d543d20SAndroid Build Coastguard Worker 		return 0;
343*2d543d20SAndroid Build Coastguard Worker 
344*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < h->nslot; i++) {
345*2d543d20SAndroid Build Coastguard Worker 		cur = h->htable[i];
346*2d543d20SAndroid Build Coastguard Worker 		while (cur != NULL) {
347*2d543d20SAndroid Build Coastguard Worker 			ret = apply(&cur->key, &cur->datum, args);
348*2d543d20SAndroid Build Coastguard Worker 			if (ret)
349*2d543d20SAndroid Build Coastguard Worker 				return ret;
350*2d543d20SAndroid Build Coastguard Worker 			cur = cur->next;
351*2d543d20SAndroid Build Coastguard Worker 		}
352*2d543d20SAndroid Build Coastguard Worker 	}
353*2d543d20SAndroid Build Coastguard Worker 	return 0;
354*2d543d20SAndroid Build Coastguard Worker }
355*2d543d20SAndroid Build Coastguard Worker 
avtab_init(avtab_t * h)356*2d543d20SAndroid Build Coastguard Worker int avtab_init(avtab_t * h)
357*2d543d20SAndroid Build Coastguard Worker {
358*2d543d20SAndroid Build Coastguard Worker 	h->htable = NULL;
359*2d543d20SAndroid Build Coastguard Worker 	h->nel = 0;
360*2d543d20SAndroid Build Coastguard Worker 	return 0;
361*2d543d20SAndroid Build Coastguard Worker }
362*2d543d20SAndroid Build Coastguard Worker 
avtab_alloc(avtab_t * h,uint32_t nrules)363*2d543d20SAndroid Build Coastguard Worker int avtab_alloc(avtab_t *h, uint32_t nrules)
364*2d543d20SAndroid Build Coastguard Worker {
365*2d543d20SAndroid Build Coastguard Worker 	uint32_t mask = 0;
366*2d543d20SAndroid Build Coastguard Worker 	uint32_t shift = 0;
367*2d543d20SAndroid Build Coastguard Worker 	uint32_t work = nrules;
368*2d543d20SAndroid Build Coastguard Worker 	uint32_t nslot = 0;
369*2d543d20SAndroid Build Coastguard Worker 
370*2d543d20SAndroid Build Coastguard Worker 	if (nrules == 0)
371*2d543d20SAndroid Build Coastguard Worker 		goto out;
372*2d543d20SAndroid Build Coastguard Worker 
373*2d543d20SAndroid Build Coastguard Worker 	while (work) {
374*2d543d20SAndroid Build Coastguard Worker 		work  = work >> 1;
375*2d543d20SAndroid Build Coastguard Worker 		shift++;
376*2d543d20SAndroid Build Coastguard Worker 	}
377*2d543d20SAndroid Build Coastguard Worker 	if (shift > 2)
378*2d543d20SAndroid Build Coastguard Worker 		shift = shift - 2;
379*2d543d20SAndroid Build Coastguard Worker 	nslot = UINT32_C(1) << shift;
380*2d543d20SAndroid Build Coastguard Worker 	if (nslot > MAX_AVTAB_HASH_BUCKETS)
381*2d543d20SAndroid Build Coastguard Worker 		nslot = MAX_AVTAB_HASH_BUCKETS;
382*2d543d20SAndroid Build Coastguard Worker 	mask = nslot - 1;
383*2d543d20SAndroid Build Coastguard Worker 
384*2d543d20SAndroid Build Coastguard Worker 	h->htable = calloc(nslot, sizeof(avtab_ptr_t));
385*2d543d20SAndroid Build Coastguard Worker 	if (!h->htable)
386*2d543d20SAndroid Build Coastguard Worker 		return -1;
387*2d543d20SAndroid Build Coastguard Worker out:
388*2d543d20SAndroid Build Coastguard Worker 	h->nel = 0;
389*2d543d20SAndroid Build Coastguard Worker 	h->nslot = nslot;
390*2d543d20SAndroid Build Coastguard Worker 	h->mask = mask;
391*2d543d20SAndroid Build Coastguard Worker 	return 0;
392*2d543d20SAndroid Build Coastguard Worker }
393*2d543d20SAndroid Build Coastguard Worker 
avtab_hash_eval(avtab_t * h,char * tag)394*2d543d20SAndroid Build Coastguard Worker void avtab_hash_eval(avtab_t * h, char *tag)
395*2d543d20SAndroid Build Coastguard Worker {
396*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, chain_len, slots_used, max_chain_len;
397*2d543d20SAndroid Build Coastguard Worker 	avtab_ptr_t cur;
398*2d543d20SAndroid Build Coastguard Worker 
399*2d543d20SAndroid Build Coastguard Worker 	slots_used = 0;
400*2d543d20SAndroid Build Coastguard Worker 	max_chain_len = 0;
401*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < h->nslot; i++) {
402*2d543d20SAndroid Build Coastguard Worker 		cur = h->htable[i];
403*2d543d20SAndroid Build Coastguard Worker 		if (cur) {
404*2d543d20SAndroid Build Coastguard Worker 			slots_used++;
405*2d543d20SAndroid Build Coastguard Worker 			chain_len = 0;
406*2d543d20SAndroid Build Coastguard Worker 			while (cur) {
407*2d543d20SAndroid Build Coastguard Worker 				chain_len++;
408*2d543d20SAndroid Build Coastguard Worker 				cur = cur->next;
409*2d543d20SAndroid Build Coastguard Worker 			}
410*2d543d20SAndroid Build Coastguard Worker 
411*2d543d20SAndroid Build Coastguard Worker 			if (chain_len > max_chain_len)
412*2d543d20SAndroid Build Coastguard Worker 				max_chain_len = chain_len;
413*2d543d20SAndroid Build Coastguard Worker 		}
414*2d543d20SAndroid Build Coastguard Worker 	}
415*2d543d20SAndroid Build Coastguard Worker 
416*2d543d20SAndroid Build Coastguard Worker 	printf
417*2d543d20SAndroid Build Coastguard Worker 	    ("%s:  %d entries and %d/%d buckets used, longest chain length %d\n",
418*2d543d20SAndroid Build Coastguard Worker 	     tag, h->nel, slots_used, h->nslot, max_chain_len);
419*2d543d20SAndroid Build Coastguard Worker }
420*2d543d20SAndroid Build Coastguard Worker 
421*2d543d20SAndroid Build Coastguard Worker /* Ordering of datums in the original avtab format in the policy file. */
422*2d543d20SAndroid Build Coastguard Worker static const uint16_t spec_order[] = {
423*2d543d20SAndroid Build Coastguard Worker 	AVTAB_ALLOWED,
424*2d543d20SAndroid Build Coastguard Worker 	AVTAB_AUDITDENY,
425*2d543d20SAndroid Build Coastguard Worker 	AVTAB_AUDITALLOW,
426*2d543d20SAndroid Build Coastguard Worker 	AVTAB_TRANSITION,
427*2d543d20SAndroid Build Coastguard Worker 	AVTAB_CHANGE,
428*2d543d20SAndroid Build Coastguard Worker 	AVTAB_MEMBER,
429*2d543d20SAndroid Build Coastguard Worker 	AVTAB_XPERMS_ALLOWED,
430*2d543d20SAndroid Build Coastguard Worker 	AVTAB_XPERMS_AUDITALLOW,
431*2d543d20SAndroid Build Coastguard Worker 	AVTAB_XPERMS_DONTAUDIT
432*2d543d20SAndroid Build Coastguard Worker };
433*2d543d20SAndroid Build Coastguard Worker 
avtab_read_item(struct policy_file * fp,uint32_t vers,avtab_t * a,int (* insertf)(avtab_t * a,avtab_key_t * k,avtab_datum_t * d,void * p),void * p)434*2d543d20SAndroid Build Coastguard Worker int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
435*2d543d20SAndroid Build Coastguard Worker 		    int (*insertf) (avtab_t * a, avtab_key_t * k,
436*2d543d20SAndroid Build Coastguard Worker 				    avtab_datum_t * d, void *p), void *p)
437*2d543d20SAndroid Build Coastguard Worker {
438*2d543d20SAndroid Build Coastguard Worker 	uint8_t buf8;
439*2d543d20SAndroid Build Coastguard Worker 	uint16_t buf16[4], enabled;
440*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf32[8], items, items2, val;
441*2d543d20SAndroid Build Coastguard Worker 	avtab_key_t key;
442*2d543d20SAndroid Build Coastguard Worker 	avtab_datum_t datum;
443*2d543d20SAndroid Build Coastguard Worker 	avtab_extended_perms_t xperms;
444*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
445*2d543d20SAndroid Build Coastguard Worker 	int rc;
446*2d543d20SAndroid Build Coastguard Worker 
447*2d543d20SAndroid Build Coastguard Worker 	memset(&key, 0, sizeof(avtab_key_t));
448*2d543d20SAndroid Build Coastguard Worker 	memset(&datum, 0, sizeof(avtab_datum_t));
449*2d543d20SAndroid Build Coastguard Worker 	memset(&xperms, 0, sizeof(avtab_extended_perms_t));
450*2d543d20SAndroid Build Coastguard Worker 
451*2d543d20SAndroid Build Coastguard Worker 	if (vers < POLICYDB_VERSION_AVTAB) {
452*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(buf32, fp, sizeof(uint32_t));
453*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
454*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated entry");
455*2d543d20SAndroid Build Coastguard Worker 			return -1;
456*2d543d20SAndroid Build Coastguard Worker 		}
457*2d543d20SAndroid Build Coastguard Worker 		items2 = le32_to_cpu(buf32[0]);
458*2d543d20SAndroid Build Coastguard Worker 
459*2d543d20SAndroid Build Coastguard Worker 		if (items2 < 5 || items2 > ARRAY_SIZE(buf32)) {
460*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "invalid item count");
461*2d543d20SAndroid Build Coastguard Worker 			return -1;
462*2d543d20SAndroid Build Coastguard Worker 		}
463*2d543d20SAndroid Build Coastguard Worker 
464*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(buf32, fp, sizeof(uint32_t) * items2);
465*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
466*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated entry");
467*2d543d20SAndroid Build Coastguard Worker 			return -1;
468*2d543d20SAndroid Build Coastguard Worker 		}
469*2d543d20SAndroid Build Coastguard Worker 
470*2d543d20SAndroid Build Coastguard Worker 		items = 0;
471*2d543d20SAndroid Build Coastguard Worker 		val = le32_to_cpu(buf32[items++]);
472*2d543d20SAndroid Build Coastguard Worker 		key.source_type = (uint16_t) val;
473*2d543d20SAndroid Build Coastguard Worker 		if (key.source_type != val) {
474*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated source type");
475*2d543d20SAndroid Build Coastguard Worker 			return -1;
476*2d543d20SAndroid Build Coastguard Worker 		}
477*2d543d20SAndroid Build Coastguard Worker 		val = le32_to_cpu(buf32[items++]);
478*2d543d20SAndroid Build Coastguard Worker 		key.target_type = (uint16_t) val;
479*2d543d20SAndroid Build Coastguard Worker 		if (key.target_type != val) {
480*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated target type");
481*2d543d20SAndroid Build Coastguard Worker 			return -1;
482*2d543d20SAndroid Build Coastguard Worker 		}
483*2d543d20SAndroid Build Coastguard Worker 		val = le32_to_cpu(buf32[items++]);
484*2d543d20SAndroid Build Coastguard Worker 		key.target_class = (uint16_t) val;
485*2d543d20SAndroid Build Coastguard Worker 		if (key.target_class != val) {
486*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated target class");
487*2d543d20SAndroid Build Coastguard Worker 			return -1;
488*2d543d20SAndroid Build Coastguard Worker 		}
489*2d543d20SAndroid Build Coastguard Worker 
490*2d543d20SAndroid Build Coastguard Worker 		val = le32_to_cpu(buf32[items++]);
491*2d543d20SAndroid Build Coastguard Worker 		enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
492*2d543d20SAndroid Build Coastguard Worker 
493*2d543d20SAndroid Build Coastguard Worker 		if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
494*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "null entry");
495*2d543d20SAndroid Build Coastguard Worker 			return -1;
496*2d543d20SAndroid Build Coastguard Worker 		}
497*2d543d20SAndroid Build Coastguard Worker 		if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) {
498*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "entry has both access "
499*2d543d20SAndroid Build Coastguard Worker 			    "vectors and types");
500*2d543d20SAndroid Build Coastguard Worker 			return -1;
501*2d543d20SAndroid Build Coastguard Worker 		}
502*2d543d20SAndroid Build Coastguard Worker 
503*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
504*2d543d20SAndroid Build Coastguard Worker 			if (val & spec_order[i]) {
505*2d543d20SAndroid Build Coastguard Worker 				if (items >= items2) { /* items is index, items2 is total number */
506*2d543d20SAndroid Build Coastguard Worker 					ERR(fp->handle, "entry has too many items (%d/%d)",
507*2d543d20SAndroid Build Coastguard Worker 					    items + 1, items2);
508*2d543d20SAndroid Build Coastguard Worker 					return -1;
509*2d543d20SAndroid Build Coastguard Worker 				}
510*2d543d20SAndroid Build Coastguard Worker 				key.specified = spec_order[i] | enabled;
511*2d543d20SAndroid Build Coastguard Worker 				datum.data = le32_to_cpu(buf32[items++]);
512*2d543d20SAndroid Build Coastguard Worker 				rc = insertf(a, &key, &datum, p);
513*2d543d20SAndroid Build Coastguard Worker 				if (rc)
514*2d543d20SAndroid Build Coastguard Worker 					return rc;
515*2d543d20SAndroid Build Coastguard Worker 			}
516*2d543d20SAndroid Build Coastguard Worker 		}
517*2d543d20SAndroid Build Coastguard Worker 
518*2d543d20SAndroid Build Coastguard Worker 		if (items != items2) {
519*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "entry only had %d items, "
520*2d543d20SAndroid Build Coastguard Worker 			    "expected %d", items2, items);
521*2d543d20SAndroid Build Coastguard Worker 			return -1;
522*2d543d20SAndroid Build Coastguard Worker 		}
523*2d543d20SAndroid Build Coastguard Worker 		return 0;
524*2d543d20SAndroid Build Coastguard Worker 	}
525*2d543d20SAndroid Build Coastguard Worker 
526*2d543d20SAndroid Build Coastguard Worker 	rc = next_entry(buf16, fp, sizeof(uint16_t) * 4);
527*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
528*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "truncated entry");
529*2d543d20SAndroid Build Coastguard Worker 		return -1;
530*2d543d20SAndroid Build Coastguard Worker 	}
531*2d543d20SAndroid Build Coastguard Worker 	items = 0;
532*2d543d20SAndroid Build Coastguard Worker 	key.source_type = le16_to_cpu(buf16[items++]);
533*2d543d20SAndroid Build Coastguard Worker 	key.target_type = le16_to_cpu(buf16[items++]);
534*2d543d20SAndroid Build Coastguard Worker 	key.target_class = le16_to_cpu(buf16[items++]);
535*2d543d20SAndroid Build Coastguard Worker 	key.specified = le16_to_cpu(buf16[items++]);
536*2d543d20SAndroid Build Coastguard Worker 
537*2d543d20SAndroid Build Coastguard Worker 	if (key.specified & ~(AVTAB_AV | AVTAB_TYPE | AVTAB_XPERMS | AVTAB_ENABLED)) {
538*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "invalid specifier");
539*2d543d20SAndroid Build Coastguard Worker 		return -1;
540*2d543d20SAndroid Build Coastguard Worker 	}
541*2d543d20SAndroid Build Coastguard Worker 
542*2d543d20SAndroid Build Coastguard Worker 	if (__builtin_popcount(key.specified & ~AVTAB_ENABLED) != 1) {
543*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "not exactly one specifier");
544*2d543d20SAndroid Build Coastguard Worker 		return -1;
545*2d543d20SAndroid Build Coastguard Worker 	}
546*2d543d20SAndroid Build Coastguard Worker 
547*2d543d20SAndroid Build Coastguard Worker 	if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) &&
548*2d543d20SAndroid Build Coastguard Worker 			(key.specified & AVTAB_XPERMS)) {
549*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "policy version %u does not support extended "
550*2d543d20SAndroid Build Coastguard Worker 				"permissions rules and one was specified", vers);
551*2d543d20SAndroid Build Coastguard Worker 		return -1;
552*2d543d20SAndroid Build Coastguard Worker 	} else if (key.specified & AVTAB_XPERMS) {
553*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(&buf8, fp, sizeof(uint8_t));
554*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
555*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated entry");
556*2d543d20SAndroid Build Coastguard Worker 			return -1;
557*2d543d20SAndroid Build Coastguard Worker 		}
558*2d543d20SAndroid Build Coastguard Worker 		xperms.specified = buf8;
559*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(&buf8, fp, sizeof(uint8_t));
560*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
561*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated entry");
562*2d543d20SAndroid Build Coastguard Worker 			return -1;
563*2d543d20SAndroid Build Coastguard Worker 		}
564*2d543d20SAndroid Build Coastguard Worker 		xperms.driver = buf8;
565*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(buf32, fp, sizeof(uint32_t)*8);
566*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
567*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated entry");
568*2d543d20SAndroid Build Coastguard Worker 			return -1;
569*2d543d20SAndroid Build Coastguard Worker 		}
570*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < ARRAY_SIZE(xperms.perms); i++)
571*2d543d20SAndroid Build Coastguard Worker 			xperms.perms[i] = le32_to_cpu(buf32[i]);
572*2d543d20SAndroid Build Coastguard Worker 		datum.xperms = &xperms;
573*2d543d20SAndroid Build Coastguard Worker 	} else {
574*2d543d20SAndroid Build Coastguard Worker 		rc = next_entry(buf32, fp, sizeof(uint32_t));
575*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
576*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "truncated entry");
577*2d543d20SAndroid Build Coastguard Worker 			return -1;
578*2d543d20SAndroid Build Coastguard Worker 		}
579*2d543d20SAndroid Build Coastguard Worker 		datum.data = le32_to_cpu(*buf32);
580*2d543d20SAndroid Build Coastguard Worker 	}
581*2d543d20SAndroid Build Coastguard Worker 	return insertf(a, &key, &datum, p);
582*2d543d20SAndroid Build Coastguard Worker }
583*2d543d20SAndroid Build Coastguard Worker 
avtab_insertf(avtab_t * a,avtab_key_t * k,avtab_datum_t * d,void * p)584*2d543d20SAndroid Build Coastguard Worker static int avtab_insertf(avtab_t * a, avtab_key_t * k, avtab_datum_t * d,
585*2d543d20SAndroid Build Coastguard Worker 			 void *p __attribute__ ((unused)))
586*2d543d20SAndroid Build Coastguard Worker {
587*2d543d20SAndroid Build Coastguard Worker 	return avtab_insert(a, k, d);
588*2d543d20SAndroid Build Coastguard Worker }
589*2d543d20SAndroid Build Coastguard Worker 
avtab_read(avtab_t * a,struct policy_file * fp,uint32_t vers)590*2d543d20SAndroid Build Coastguard Worker int avtab_read(avtab_t * a, struct policy_file *fp, uint32_t vers)
591*2d543d20SAndroid Build Coastguard Worker {
592*2d543d20SAndroid Build Coastguard Worker 	unsigned int i;
593*2d543d20SAndroid Build Coastguard Worker 	int rc;
594*2d543d20SAndroid Build Coastguard Worker 	uint32_t buf[1];
595*2d543d20SAndroid Build Coastguard Worker 	uint32_t nel;
596*2d543d20SAndroid Build Coastguard Worker 
597*2d543d20SAndroid Build Coastguard Worker 	rc = next_entry(buf, fp, sizeof(uint32_t));
598*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
599*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "truncated table");
600*2d543d20SAndroid Build Coastguard Worker 		goto bad;
601*2d543d20SAndroid Build Coastguard Worker 	}
602*2d543d20SAndroid Build Coastguard Worker 	nel = le32_to_cpu(buf[0]);
603*2d543d20SAndroid Build Coastguard Worker 	if (zero_or_saturated(nel) || exceeds_available_bytes(fp, nel, sizeof(uint32_t) * 3)) {
604*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "table is empty");
605*2d543d20SAndroid Build Coastguard Worker 		goto bad;
606*2d543d20SAndroid Build Coastguard Worker 	}
607*2d543d20SAndroid Build Coastguard Worker 
608*2d543d20SAndroid Build Coastguard Worker 	rc = avtab_alloc(a, nel);
609*2d543d20SAndroid Build Coastguard Worker 	if (rc) {
610*2d543d20SAndroid Build Coastguard Worker 		ERR(fp->handle, "out of memory");
611*2d543d20SAndroid Build Coastguard Worker 		goto bad;
612*2d543d20SAndroid Build Coastguard Worker 	}
613*2d543d20SAndroid Build Coastguard Worker 
614*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < nel; i++) {
615*2d543d20SAndroid Build Coastguard Worker 		rc = avtab_read_item(fp, vers, a, avtab_insertf, NULL);
616*2d543d20SAndroid Build Coastguard Worker 		if (rc) {
617*2d543d20SAndroid Build Coastguard Worker 			if (rc == SEPOL_ENOMEM)
618*2d543d20SAndroid Build Coastguard Worker 				ERR(fp->handle, "out of memory");
619*2d543d20SAndroid Build Coastguard Worker 			if (rc == SEPOL_EEXIST)
620*2d543d20SAndroid Build Coastguard Worker 				ERR(fp->handle, "duplicate entry");
621*2d543d20SAndroid Build Coastguard Worker 			ERR(fp->handle, "failed on entry %d of %u", i, nel);
622*2d543d20SAndroid Build Coastguard Worker 			goto bad;
623*2d543d20SAndroid Build Coastguard Worker 		}
624*2d543d20SAndroid Build Coastguard Worker 	}
625*2d543d20SAndroid Build Coastguard Worker 
626*2d543d20SAndroid Build Coastguard Worker 	return 0;
627*2d543d20SAndroid Build Coastguard Worker 
628*2d543d20SAndroid Build Coastguard Worker       bad:
629*2d543d20SAndroid Build Coastguard Worker 	avtab_destroy(a);
630*2d543d20SAndroid Build Coastguard Worker 	return -1;
631*2d543d20SAndroid Build Coastguard Worker }
632