ebitmap.c revision 255e72915d4cbddceb435e13d81601755714e9f
1255e72915d4cbddceb435e13d81601755714e9fSE Android
2255e72915d4cbddceb435e13d81601755714e9fSE Android/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
3255e72915d4cbddceb435e13d81601755714e9fSE Android
4255e72915d4cbddceb435e13d81601755714e9fSE Android/* FLASK */
5255e72915d4cbddceb435e13d81601755714e9fSE Android
6255e72915d4cbddceb435e13d81601755714e9fSE Android/*
7255e72915d4cbddceb435e13d81601755714e9fSE Android * Implementation of the extensible bitmap type.
8255e72915d4cbddceb435e13d81601755714e9fSE Android */
9255e72915d4cbddceb435e13d81601755714e9fSE Android
10255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h>
11255e72915d4cbddceb435e13d81601755714e9fSE Android
12255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/ebitmap.h>
13255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/policydb.h>
14255e72915d4cbddceb435e13d81601755714e9fSE Android
15255e72915d4cbddceb435e13d81601755714e9fSE Android#include "debug.h"
16255e72915d4cbddceb435e13d81601755714e9fSE Android#include "private.h"
17255e72915d4cbddceb435e13d81601755714e9fSE Android
18255e72915d4cbddceb435e13d81601755714e9fSE Androidint ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2)
19255e72915d4cbddceb435e13d81601755714e9fSE Android{
20255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *n1, *n2, *new, *prev;
21255e72915d4cbddceb435e13d81601755714e9fSE Android
22255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_init(dst);
23255e72915d4cbddceb435e13d81601755714e9fSE Android
24255e72915d4cbddceb435e13d81601755714e9fSE Android	n1 = e1->node;
25255e72915d4cbddceb435e13d81601755714e9fSE Android	n2 = e2->node;
26255e72915d4cbddceb435e13d81601755714e9fSE Android	prev = 0;
27255e72915d4cbddceb435e13d81601755714e9fSE Android	while (n1 || n2) {
28255e72915d4cbddceb435e13d81601755714e9fSE Android		new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
29255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!new) {
30255e72915d4cbddceb435e13d81601755714e9fSE Android			ebitmap_destroy(dst);
31255e72915d4cbddceb435e13d81601755714e9fSE Android			return -ENOMEM;
32255e72915d4cbddceb435e13d81601755714e9fSE Android		}
33255e72915d4cbddceb435e13d81601755714e9fSE Android		memset(new, 0, sizeof(ebitmap_node_t));
34255e72915d4cbddceb435e13d81601755714e9fSE Android		if (n1 && n2 && n1->startbit == n2->startbit) {
35255e72915d4cbddceb435e13d81601755714e9fSE Android			new->startbit = n1->startbit;
36255e72915d4cbddceb435e13d81601755714e9fSE Android			new->map = n1->map | n2->map;
37255e72915d4cbddceb435e13d81601755714e9fSE Android			n1 = n1->next;
38255e72915d4cbddceb435e13d81601755714e9fSE Android			n2 = n2->next;
39255e72915d4cbddceb435e13d81601755714e9fSE Android		} else if (!n2 || (n1 && n1->startbit < n2->startbit)) {
40255e72915d4cbddceb435e13d81601755714e9fSE Android			new->startbit = n1->startbit;
41255e72915d4cbddceb435e13d81601755714e9fSE Android			new->map = n1->map;
42255e72915d4cbddceb435e13d81601755714e9fSE Android			n1 = n1->next;
43255e72915d4cbddceb435e13d81601755714e9fSE Android		} else {
44255e72915d4cbddceb435e13d81601755714e9fSE Android			new->startbit = n2->startbit;
45255e72915d4cbddceb435e13d81601755714e9fSE Android			new->map = n2->map;
46255e72915d4cbddceb435e13d81601755714e9fSE Android			n2 = n2->next;
47255e72915d4cbddceb435e13d81601755714e9fSE Android		}
48255e72915d4cbddceb435e13d81601755714e9fSE Android
49255e72915d4cbddceb435e13d81601755714e9fSE Android		new->next = 0;
50255e72915d4cbddceb435e13d81601755714e9fSE Android		if (prev)
51255e72915d4cbddceb435e13d81601755714e9fSE Android			prev->next = new;
52255e72915d4cbddceb435e13d81601755714e9fSE Android		else
53255e72915d4cbddceb435e13d81601755714e9fSE Android			dst->node = new;
54255e72915d4cbddceb435e13d81601755714e9fSE Android		prev = new;
55255e72915d4cbddceb435e13d81601755714e9fSE Android	}
56255e72915d4cbddceb435e13d81601755714e9fSE Android
57255e72915d4cbddceb435e13d81601755714e9fSE Android	dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit;
58255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
59255e72915d4cbddceb435e13d81601755714e9fSE Android}
60255e72915d4cbddceb435e13d81601755714e9fSE Android
61255e72915d4cbddceb435e13d81601755714e9fSE Androidint ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1)
62255e72915d4cbddceb435e13d81601755714e9fSE Android{
63255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_t tmp;
64255e72915d4cbddceb435e13d81601755714e9fSE Android
65255e72915d4cbddceb435e13d81601755714e9fSE Android	if (ebitmap_or(&tmp, dst, e1))
66255e72915d4cbddceb435e13d81601755714e9fSE Android		return -1;
67255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_destroy(dst);
68255e72915d4cbddceb435e13d81601755714e9fSE Android	dst->node = tmp.node;
69255e72915d4cbddceb435e13d81601755714e9fSE Android	dst->highbit = tmp.highbit;
70255e72915d4cbddceb435e13d81601755714e9fSE Android
71255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
72255e72915d4cbddceb435e13d81601755714e9fSE Android}
73255e72915d4cbddceb435e13d81601755714e9fSE Android
74255e72915d4cbddceb435e13d81601755714e9fSE Androidint ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2)
75255e72915d4cbddceb435e13d81601755714e9fSE Android{
76255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *n1, *n2;
77255e72915d4cbddceb435e13d81601755714e9fSE Android
78255e72915d4cbddceb435e13d81601755714e9fSE Android	if (e1->highbit != e2->highbit)
79255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
80255e72915d4cbddceb435e13d81601755714e9fSE Android
81255e72915d4cbddceb435e13d81601755714e9fSE Android	n1 = e1->node;
82255e72915d4cbddceb435e13d81601755714e9fSE Android	n2 = e2->node;
83255e72915d4cbddceb435e13d81601755714e9fSE Android	while (n1 && n2 &&
84255e72915d4cbddceb435e13d81601755714e9fSE Android	       (n1->startbit == n2->startbit) && (n1->map == n2->map)) {
85255e72915d4cbddceb435e13d81601755714e9fSE Android		n1 = n1->next;
86255e72915d4cbddceb435e13d81601755714e9fSE Android		n2 = n2->next;
87255e72915d4cbddceb435e13d81601755714e9fSE Android	}
88255e72915d4cbddceb435e13d81601755714e9fSE Android
89255e72915d4cbddceb435e13d81601755714e9fSE Android	if (n1 || n2)
90255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
91255e72915d4cbddceb435e13d81601755714e9fSE Android
92255e72915d4cbddceb435e13d81601755714e9fSE Android	return 1;
93255e72915d4cbddceb435e13d81601755714e9fSE Android}
94255e72915d4cbddceb435e13d81601755714e9fSE Android
95255e72915d4cbddceb435e13d81601755714e9fSE Androidint ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src)
96255e72915d4cbddceb435e13d81601755714e9fSE Android{
97255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *n, *new, *prev;
98255e72915d4cbddceb435e13d81601755714e9fSE Android
99255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_init(dst);
100255e72915d4cbddceb435e13d81601755714e9fSE Android	n = src->node;
101255e72915d4cbddceb435e13d81601755714e9fSE Android	prev = 0;
102255e72915d4cbddceb435e13d81601755714e9fSE Android	while (n) {
103255e72915d4cbddceb435e13d81601755714e9fSE Android		new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
104255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!new) {
105255e72915d4cbddceb435e13d81601755714e9fSE Android			ebitmap_destroy(dst);
106255e72915d4cbddceb435e13d81601755714e9fSE Android			return -ENOMEM;
107255e72915d4cbddceb435e13d81601755714e9fSE Android		}
108255e72915d4cbddceb435e13d81601755714e9fSE Android		memset(new, 0, sizeof(ebitmap_node_t));
109255e72915d4cbddceb435e13d81601755714e9fSE Android		new->startbit = n->startbit;
110255e72915d4cbddceb435e13d81601755714e9fSE Android		new->map = n->map;
111255e72915d4cbddceb435e13d81601755714e9fSE Android		new->next = 0;
112255e72915d4cbddceb435e13d81601755714e9fSE Android		if (prev)
113255e72915d4cbddceb435e13d81601755714e9fSE Android			prev->next = new;
114255e72915d4cbddceb435e13d81601755714e9fSE Android		else
115255e72915d4cbddceb435e13d81601755714e9fSE Android			dst->node = new;
116255e72915d4cbddceb435e13d81601755714e9fSE Android		prev = new;
117255e72915d4cbddceb435e13d81601755714e9fSE Android		n = n->next;
118255e72915d4cbddceb435e13d81601755714e9fSE Android	}
119255e72915d4cbddceb435e13d81601755714e9fSE Android
120255e72915d4cbddceb435e13d81601755714e9fSE Android	dst->highbit = src->highbit;
121255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
122255e72915d4cbddceb435e13d81601755714e9fSE Android}
123255e72915d4cbddceb435e13d81601755714e9fSE Android
124255e72915d4cbddceb435e13d81601755714e9fSE Androidint ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2)
125255e72915d4cbddceb435e13d81601755714e9fSE Android{
126255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *n1, *n2;
127255e72915d4cbddceb435e13d81601755714e9fSE Android
128255e72915d4cbddceb435e13d81601755714e9fSE Android	if (e1->highbit < e2->highbit)
129255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
130255e72915d4cbddceb435e13d81601755714e9fSE Android
131255e72915d4cbddceb435e13d81601755714e9fSE Android	n1 = e1->node;
132255e72915d4cbddceb435e13d81601755714e9fSE Android	n2 = e2->node;
133255e72915d4cbddceb435e13d81601755714e9fSE Android	while (n1 && n2 && (n1->startbit <= n2->startbit)) {
134255e72915d4cbddceb435e13d81601755714e9fSE Android		if (n1->startbit < n2->startbit) {
135255e72915d4cbddceb435e13d81601755714e9fSE Android			n1 = n1->next;
136255e72915d4cbddceb435e13d81601755714e9fSE Android			continue;
137255e72915d4cbddceb435e13d81601755714e9fSE Android		}
138255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((n1->map & n2->map) != n2->map)
139255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
140255e72915d4cbddceb435e13d81601755714e9fSE Android
141255e72915d4cbddceb435e13d81601755714e9fSE Android		n1 = n1->next;
142255e72915d4cbddceb435e13d81601755714e9fSE Android		n2 = n2->next;
143255e72915d4cbddceb435e13d81601755714e9fSE Android	}
144255e72915d4cbddceb435e13d81601755714e9fSE Android
145255e72915d4cbddceb435e13d81601755714e9fSE Android	if (n2)
146255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
147255e72915d4cbddceb435e13d81601755714e9fSE Android
148255e72915d4cbddceb435e13d81601755714e9fSE Android	return 1;
149255e72915d4cbddceb435e13d81601755714e9fSE Android}
150255e72915d4cbddceb435e13d81601755714e9fSE Android
151255e72915d4cbddceb435e13d81601755714e9fSE Androidint ebitmap_get_bit(const ebitmap_t * e, unsigned int bit)
152255e72915d4cbddceb435e13d81601755714e9fSE Android{
153255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *n;
154255e72915d4cbddceb435e13d81601755714e9fSE Android
155255e72915d4cbddceb435e13d81601755714e9fSE Android	if (e->highbit < bit)
156255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
157255e72915d4cbddceb435e13d81601755714e9fSE Android
158255e72915d4cbddceb435e13d81601755714e9fSE Android	n = e->node;
159255e72915d4cbddceb435e13d81601755714e9fSE Android	while (n && (n->startbit <= bit)) {
160255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((n->startbit + MAPSIZE) > bit) {
161255e72915d4cbddceb435e13d81601755714e9fSE Android			if (n->map & (MAPBIT << (bit - n->startbit)))
162255e72915d4cbddceb435e13d81601755714e9fSE Android				return 1;
163255e72915d4cbddceb435e13d81601755714e9fSE Android			else
164255e72915d4cbddceb435e13d81601755714e9fSE Android				return 0;
165255e72915d4cbddceb435e13d81601755714e9fSE Android		}
166255e72915d4cbddceb435e13d81601755714e9fSE Android		n = n->next;
167255e72915d4cbddceb435e13d81601755714e9fSE Android	}
168255e72915d4cbddceb435e13d81601755714e9fSE Android
169255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
170255e72915d4cbddceb435e13d81601755714e9fSE Android}
171255e72915d4cbddceb435e13d81601755714e9fSE Android
172255e72915d4cbddceb435e13d81601755714e9fSE Androidint ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value)
173255e72915d4cbddceb435e13d81601755714e9fSE Android{
174255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *n, *prev, *new;
175255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t startbit = bit & ~(MAPSIZE - 1);
176255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t highbit = startbit + MAPSIZE;
177255e72915d4cbddceb435e13d81601755714e9fSE Android
178255e72915d4cbddceb435e13d81601755714e9fSE Android	if (highbit == 0) {
179255e72915d4cbddceb435e13d81601755714e9fSE Android		ERR(NULL, "bitmap overflow, bit 0x%x", bit);
180255e72915d4cbddceb435e13d81601755714e9fSE Android		return -EINVAL;
181255e72915d4cbddceb435e13d81601755714e9fSE Android	}
182255e72915d4cbddceb435e13d81601755714e9fSE Android
183255e72915d4cbddceb435e13d81601755714e9fSE Android	prev = 0;
184255e72915d4cbddceb435e13d81601755714e9fSE Android	n = e->node;
185255e72915d4cbddceb435e13d81601755714e9fSE Android	while (n && n->startbit <= bit) {
186255e72915d4cbddceb435e13d81601755714e9fSE Android		if ((n->startbit + MAPSIZE) > bit) {
187255e72915d4cbddceb435e13d81601755714e9fSE Android			if (value) {
188255e72915d4cbddceb435e13d81601755714e9fSE Android				n->map |= (MAPBIT << (bit - n->startbit));
189255e72915d4cbddceb435e13d81601755714e9fSE Android			} else {
190255e72915d4cbddceb435e13d81601755714e9fSE Android				n->map &= ~(MAPBIT << (bit - n->startbit));
191255e72915d4cbddceb435e13d81601755714e9fSE Android				if (!n->map) {
192255e72915d4cbddceb435e13d81601755714e9fSE Android					/* drop this node from the bitmap */
193255e72915d4cbddceb435e13d81601755714e9fSE Android
194255e72915d4cbddceb435e13d81601755714e9fSE Android					if (!n->next) {
195255e72915d4cbddceb435e13d81601755714e9fSE Android						/*
196255e72915d4cbddceb435e13d81601755714e9fSE Android						 * this was the highest map
197255e72915d4cbddceb435e13d81601755714e9fSE Android						 * within the bitmap
198255e72915d4cbddceb435e13d81601755714e9fSE Android						 */
199255e72915d4cbddceb435e13d81601755714e9fSE Android						if (prev)
200255e72915d4cbddceb435e13d81601755714e9fSE Android							e->highbit =
201255e72915d4cbddceb435e13d81601755714e9fSE Android							    prev->startbit +
202255e72915d4cbddceb435e13d81601755714e9fSE Android							    MAPSIZE;
203255e72915d4cbddceb435e13d81601755714e9fSE Android						else
204255e72915d4cbddceb435e13d81601755714e9fSE Android							e->highbit = 0;
205255e72915d4cbddceb435e13d81601755714e9fSE Android					}
206255e72915d4cbddceb435e13d81601755714e9fSE Android					if (prev)
207255e72915d4cbddceb435e13d81601755714e9fSE Android						prev->next = n->next;
208255e72915d4cbddceb435e13d81601755714e9fSE Android					else
209255e72915d4cbddceb435e13d81601755714e9fSE Android						e->node = n->next;
210255e72915d4cbddceb435e13d81601755714e9fSE Android
211255e72915d4cbddceb435e13d81601755714e9fSE Android					free(n);
212255e72915d4cbddceb435e13d81601755714e9fSE Android				}
213255e72915d4cbddceb435e13d81601755714e9fSE Android			}
214255e72915d4cbddceb435e13d81601755714e9fSE Android			return 0;
215255e72915d4cbddceb435e13d81601755714e9fSE Android		}
216255e72915d4cbddceb435e13d81601755714e9fSE Android		prev = n;
217255e72915d4cbddceb435e13d81601755714e9fSE Android		n = n->next;
218255e72915d4cbddceb435e13d81601755714e9fSE Android	}
219255e72915d4cbddceb435e13d81601755714e9fSE Android
220255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!value)
221255e72915d4cbddceb435e13d81601755714e9fSE Android		return 0;
222255e72915d4cbddceb435e13d81601755714e9fSE Android
223255e72915d4cbddceb435e13d81601755714e9fSE Android	new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
224255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!new)
225255e72915d4cbddceb435e13d81601755714e9fSE Android		return -ENOMEM;
226255e72915d4cbddceb435e13d81601755714e9fSE Android	memset(new, 0, sizeof(ebitmap_node_t));
227255e72915d4cbddceb435e13d81601755714e9fSE Android
228255e72915d4cbddceb435e13d81601755714e9fSE Android	new->startbit = startbit;
229255e72915d4cbddceb435e13d81601755714e9fSE Android	new->map = (MAPBIT << (bit - new->startbit));
230255e72915d4cbddceb435e13d81601755714e9fSE Android
231255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!n) {
232255e72915d4cbddceb435e13d81601755714e9fSE Android		/* this node will be the highest map within the bitmap */
233255e72915d4cbddceb435e13d81601755714e9fSE Android		e->highbit = highbit;
234255e72915d4cbddceb435e13d81601755714e9fSE Android	}
235255e72915d4cbddceb435e13d81601755714e9fSE Android
236255e72915d4cbddceb435e13d81601755714e9fSE Android	if (prev) {
237255e72915d4cbddceb435e13d81601755714e9fSE Android		new->next = prev->next;
238255e72915d4cbddceb435e13d81601755714e9fSE Android		prev->next = new;
239255e72915d4cbddceb435e13d81601755714e9fSE Android	} else {
240255e72915d4cbddceb435e13d81601755714e9fSE Android		new->next = e->node;
241255e72915d4cbddceb435e13d81601755714e9fSE Android		e->node = new;
242255e72915d4cbddceb435e13d81601755714e9fSE Android	}
243255e72915d4cbddceb435e13d81601755714e9fSE Android
244255e72915d4cbddceb435e13d81601755714e9fSE Android	return 0;
245255e72915d4cbddceb435e13d81601755714e9fSE Android}
246255e72915d4cbddceb435e13d81601755714e9fSE Android
247255e72915d4cbddceb435e13d81601755714e9fSE Androidvoid ebitmap_destroy(ebitmap_t * e)
248255e72915d4cbddceb435e13d81601755714e9fSE Android{
249255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *n, *temp;
250255e72915d4cbddceb435e13d81601755714e9fSE Android
251255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!e)
252255e72915d4cbddceb435e13d81601755714e9fSE Android		return;
253255e72915d4cbddceb435e13d81601755714e9fSE Android
254255e72915d4cbddceb435e13d81601755714e9fSE Android	n = e->node;
255255e72915d4cbddceb435e13d81601755714e9fSE Android	while (n) {
256255e72915d4cbddceb435e13d81601755714e9fSE Android		temp = n;
257255e72915d4cbddceb435e13d81601755714e9fSE Android		n = n->next;
258255e72915d4cbddceb435e13d81601755714e9fSE Android		free(temp);
259255e72915d4cbddceb435e13d81601755714e9fSE Android	}
260255e72915d4cbddceb435e13d81601755714e9fSE Android
261255e72915d4cbddceb435e13d81601755714e9fSE Android	e->highbit = 0;
262255e72915d4cbddceb435e13d81601755714e9fSE Android	e->node = 0;
263255e72915d4cbddceb435e13d81601755714e9fSE Android	return;
264255e72915d4cbddceb435e13d81601755714e9fSE Android}
265255e72915d4cbddceb435e13d81601755714e9fSE Android
266255e72915d4cbddceb435e13d81601755714e9fSE Androidint ebitmap_read(ebitmap_t * e, void *fp)
267255e72915d4cbddceb435e13d81601755714e9fSE Android{
268255e72915d4cbddceb435e13d81601755714e9fSE Android	int rc;
269255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_node_t *n, *l;
270255e72915d4cbddceb435e13d81601755714e9fSE Android	uint32_t buf[3], mapsize, count, i;
271255e72915d4cbddceb435e13d81601755714e9fSE Android	uint64_t map;
272255e72915d4cbddceb435e13d81601755714e9fSE Android
273255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_init(e);
274255e72915d4cbddceb435e13d81601755714e9fSE Android
275255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
276255e72915d4cbddceb435e13d81601755714e9fSE Android	if (rc < 0)
277255e72915d4cbddceb435e13d81601755714e9fSE Android		goto bad;
278255e72915d4cbddceb435e13d81601755714e9fSE Android
279255e72915d4cbddceb435e13d81601755714e9fSE Android	mapsize = le32_to_cpu(buf[0]);
280255e72915d4cbddceb435e13d81601755714e9fSE Android	e->highbit = le32_to_cpu(buf[1]);
281255e72915d4cbddceb435e13d81601755714e9fSE Android	count = le32_to_cpu(buf[2]);
282255e72915d4cbddceb435e13d81601755714e9fSE Android
283255e72915d4cbddceb435e13d81601755714e9fSE Android	if (mapsize != MAPSIZE) {
284255e72915d4cbddceb435e13d81601755714e9fSE Android		printf
285255e72915d4cbddceb435e13d81601755714e9fSE Android		    ("security: ebitmap: map size %d does not match my size %zu (high bit was %d)\n",
286255e72915d4cbddceb435e13d81601755714e9fSE Android		     mapsize, MAPSIZE, e->highbit);
287255e72915d4cbddceb435e13d81601755714e9fSE Android		goto bad;
288255e72915d4cbddceb435e13d81601755714e9fSE Android	}
289255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!e->highbit) {
290255e72915d4cbddceb435e13d81601755714e9fSE Android		e->node = NULL;
291255e72915d4cbddceb435e13d81601755714e9fSE Android		goto ok;
292255e72915d4cbddceb435e13d81601755714e9fSE Android	}
293255e72915d4cbddceb435e13d81601755714e9fSE Android	if (e->highbit & (MAPSIZE - 1)) {
294255e72915d4cbddceb435e13d81601755714e9fSE Android		printf
295255e72915d4cbddceb435e13d81601755714e9fSE Android		    ("security: ebitmap: high bit (%d) is not a multiple of the map size (%zu)\n",
296255e72915d4cbddceb435e13d81601755714e9fSE Android		     e->highbit, MAPSIZE);
297255e72915d4cbddceb435e13d81601755714e9fSE Android		goto bad;
298255e72915d4cbddceb435e13d81601755714e9fSE Android	}
299255e72915d4cbddceb435e13d81601755714e9fSE Android	l = NULL;
300255e72915d4cbddceb435e13d81601755714e9fSE Android	for (i = 0; i < count; i++) {
301255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = next_entry(buf, fp, sizeof(uint32_t));
302255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc < 0) {
303255e72915d4cbddceb435e13d81601755714e9fSE Android			printf("security: ebitmap: truncated map\n");
304255e72915d4cbddceb435e13d81601755714e9fSE Android			goto bad;
305255e72915d4cbddceb435e13d81601755714e9fSE Android		}
306255e72915d4cbddceb435e13d81601755714e9fSE Android		n = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
307255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!n) {
308255e72915d4cbddceb435e13d81601755714e9fSE Android			printf("security: ebitmap: out of memory\n");
309255e72915d4cbddceb435e13d81601755714e9fSE Android			rc = -ENOMEM;
310255e72915d4cbddceb435e13d81601755714e9fSE Android			goto bad;
311255e72915d4cbddceb435e13d81601755714e9fSE Android		}
312255e72915d4cbddceb435e13d81601755714e9fSE Android		memset(n, 0, sizeof(ebitmap_node_t));
313255e72915d4cbddceb435e13d81601755714e9fSE Android
314255e72915d4cbddceb435e13d81601755714e9fSE Android		n->startbit = le32_to_cpu(buf[0]);
315255e72915d4cbddceb435e13d81601755714e9fSE Android
316255e72915d4cbddceb435e13d81601755714e9fSE Android		if (n->startbit & (MAPSIZE - 1)) {
317255e72915d4cbddceb435e13d81601755714e9fSE Android			printf
318255e72915d4cbddceb435e13d81601755714e9fSE Android			    ("security: ebitmap start bit (%d) is not a multiple of the map size (%zu)\n",
319255e72915d4cbddceb435e13d81601755714e9fSE Android			     n->startbit, MAPSIZE);
320255e72915d4cbddceb435e13d81601755714e9fSE Android			goto bad_free;
321255e72915d4cbddceb435e13d81601755714e9fSE Android		}
322255e72915d4cbddceb435e13d81601755714e9fSE Android		if (n->startbit > (e->highbit - MAPSIZE)) {
323255e72915d4cbddceb435e13d81601755714e9fSE Android			printf
324255e72915d4cbddceb435e13d81601755714e9fSE Android			    ("security: ebitmap start bit (%d) is beyond the end of the bitmap (%zu)\n",
325255e72915d4cbddceb435e13d81601755714e9fSE Android			     n->startbit, (e->highbit - MAPSIZE));
326255e72915d4cbddceb435e13d81601755714e9fSE Android			goto bad_free;
327255e72915d4cbddceb435e13d81601755714e9fSE Android		}
328255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = next_entry(&map, fp, sizeof(uint64_t));
329255e72915d4cbddceb435e13d81601755714e9fSE Android		if (rc < 0) {
330255e72915d4cbddceb435e13d81601755714e9fSE Android			printf("security: ebitmap: truncated map\n");
331255e72915d4cbddceb435e13d81601755714e9fSE Android			goto bad_free;
332255e72915d4cbddceb435e13d81601755714e9fSE Android		}
333255e72915d4cbddceb435e13d81601755714e9fSE Android		n->map = le64_to_cpu(map);
334255e72915d4cbddceb435e13d81601755714e9fSE Android
335255e72915d4cbddceb435e13d81601755714e9fSE Android		if (!n->map) {
336255e72915d4cbddceb435e13d81601755714e9fSE Android			printf
337255e72915d4cbddceb435e13d81601755714e9fSE Android			    ("security: ebitmap: null map in ebitmap (startbit %d)\n",
338255e72915d4cbddceb435e13d81601755714e9fSE Android			     n->startbit);
339255e72915d4cbddceb435e13d81601755714e9fSE Android			goto bad_free;
340255e72915d4cbddceb435e13d81601755714e9fSE Android		}
341255e72915d4cbddceb435e13d81601755714e9fSE Android		if (l) {
342255e72915d4cbddceb435e13d81601755714e9fSE Android			if (n->startbit <= l->startbit) {
343255e72915d4cbddceb435e13d81601755714e9fSE Android				printf
344255e72915d4cbddceb435e13d81601755714e9fSE Android				    ("security: ebitmap: start bit %d comes after start bit %d\n",
345255e72915d4cbddceb435e13d81601755714e9fSE Android				     n->startbit, l->startbit);
346255e72915d4cbddceb435e13d81601755714e9fSE Android				goto bad_free;
347255e72915d4cbddceb435e13d81601755714e9fSE Android			}
348255e72915d4cbddceb435e13d81601755714e9fSE Android			l->next = n;
349255e72915d4cbddceb435e13d81601755714e9fSE Android		} else
350255e72915d4cbddceb435e13d81601755714e9fSE Android			e->node = n;
351255e72915d4cbddceb435e13d81601755714e9fSE Android
352255e72915d4cbddceb435e13d81601755714e9fSE Android		l = n;
353255e72915d4cbddceb435e13d81601755714e9fSE Android	}
354255e72915d4cbddceb435e13d81601755714e9fSE Android
355255e72915d4cbddceb435e13d81601755714e9fSE Android      ok:
356255e72915d4cbddceb435e13d81601755714e9fSE Android	rc = 0;
357255e72915d4cbddceb435e13d81601755714e9fSE Android      out:
358255e72915d4cbddceb435e13d81601755714e9fSE Android	return rc;
359255e72915d4cbddceb435e13d81601755714e9fSE Android      bad_free:
360255e72915d4cbddceb435e13d81601755714e9fSE Android	free(n);
361255e72915d4cbddceb435e13d81601755714e9fSE Android      bad:
362255e72915d4cbddceb435e13d81601755714e9fSE Android	if (!rc)
363255e72915d4cbddceb435e13d81601755714e9fSE Android		rc = -EINVAL;
364255e72915d4cbddceb435e13d81601755714e9fSE Android	ebitmap_destroy(e);
365255e72915d4cbddceb435e13d81601755714e9fSE Android	goto out;
366255e72915d4cbddceb435e13d81601755714e9fSE Android}
367255e72915d4cbddceb435e13d81601755714e9fSE Android
368255e72915d4cbddceb435e13d81601755714e9fSE Android/* FLASK */
369