Home | History | Annotate | Download | only in src
      1 
      2 /* Author : Stephen Smalley, <sds (at) epoch.ncsc.mil> */
      3 
      4 /* FLASK */
      5 
      6 /*
      7  * Implementation of the extensible bitmap type.
      8  */
      9 
     10 #include <stdlib.h>
     11 
     12 #include <sepol/policydb/ebitmap.h>
     13 #include <sepol/policydb/policydb.h>
     14 
     15 #include "debug.h"
     16 #include "private.h"
     17 
     18 int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2)
     19 {
     20 	ebitmap_node_t *n1, *n2, *new, *prev;
     21 
     22 	ebitmap_init(dst);
     23 
     24 	n1 = e1->node;
     25 	n2 = e2->node;
     26 	prev = 0;
     27 	while (n1 || n2) {
     28 		new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
     29 		if (!new) {
     30 			ebitmap_destroy(dst);
     31 			return -ENOMEM;
     32 		}
     33 		memset(new, 0, sizeof(ebitmap_node_t));
     34 		if (n1 && n2 && n1->startbit == n2->startbit) {
     35 			new->startbit = n1->startbit;
     36 			new->map = n1->map | n2->map;
     37 			n1 = n1->next;
     38 			n2 = n2->next;
     39 		} else if (!n2 || (n1 && n1->startbit < n2->startbit)) {
     40 			new->startbit = n1->startbit;
     41 			new->map = n1->map;
     42 			n1 = n1->next;
     43 		} else {
     44 			new->startbit = n2->startbit;
     45 			new->map = n2->map;
     46 			n2 = n2->next;
     47 		}
     48 
     49 		new->next = 0;
     50 		if (prev)
     51 			prev->next = new;
     52 		else
     53 			dst->node = new;
     54 		prev = new;
     55 	}
     56 
     57 	dst->highbit = (e1->highbit > e2->highbit) ? e1->highbit : e2->highbit;
     58 	return 0;
     59 }
     60 
     61 int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1)
     62 {
     63 	ebitmap_t tmp;
     64 
     65 	if (ebitmap_or(&tmp, dst, e1))
     66 		return -1;
     67 	ebitmap_destroy(dst);
     68 	dst->node = tmp.node;
     69 	dst->highbit = tmp.highbit;
     70 
     71 	return 0;
     72 }
     73 
     74 int ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
     75 {
     76 	unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2));
     77 	ebitmap_init(dst);
     78 	for (i=0; i < length; i++) {
     79 		if (ebitmap_get_bit(e1, i) && ebitmap_get_bit(e2, i)) {
     80 			int rc = ebitmap_set_bit(dst, i, 1);
     81 			if (rc < 0)
     82 				return rc;
     83 		}
     84 	}
     85 	return 0;
     86 }
     87 
     88 int ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2)
     89 {
     90 	unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2));
     91 	ebitmap_init(dst);
     92 	for (i=0; i < length; i++) {
     93 		int val = ebitmap_get_bit(e1, i) ^ ebitmap_get_bit(e2, i);
     94 		int rc = ebitmap_set_bit(dst, i, val);
     95 		if (rc < 0)
     96 			return rc;
     97 	}
     98 	return 0;
     99 }
    100 
    101 int ebitmap_not(ebitmap_t *dst, ebitmap_t *e1, unsigned int maxbit)
    102 {
    103 	unsigned int i;
    104 	ebitmap_init(dst);
    105 	for (i=0; i < maxbit; i++) {
    106 		int val = ebitmap_get_bit(e1, i);
    107 		int rc = ebitmap_set_bit(dst, i, !val);
    108 		if (rc < 0)
    109 			return rc;
    110 	}
    111 	return 0;
    112 }
    113 
    114 int ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2, unsigned int maxbit)
    115 {
    116 	ebitmap_t e3;
    117 	ebitmap_init(dst);
    118 	int rc = ebitmap_not(&e3, e2, maxbit);
    119 	if (rc < 0)
    120 		return rc;
    121 	rc = ebitmap_and(dst, e1, &e3);
    122 	ebitmap_destroy(&e3);
    123 	if (rc < 0)
    124 		return rc;
    125 	return 0;
    126 }
    127 
    128 unsigned int ebitmap_cardinality(ebitmap_t *e1)
    129 {
    130 	unsigned int i, count = 0;
    131 	for (i=ebitmap_startbit(e1); i < ebitmap_length(e1); i++)
    132 		if (ebitmap_get_bit(e1, i))
    133 			count++;
    134 	return count;
    135 }
    136 
    137 int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2)
    138 {
    139 	if (ebitmap_cmp(e1, e2))
    140 		return 0;
    141 	ebitmap_t tmp;
    142 	int rc = ebitmap_xor(&tmp, e1, e2);
    143 	if (rc < 0)
    144 		return -1;
    145 	int distance = ebitmap_cardinality(&tmp);
    146 	ebitmap_destroy(&tmp);
    147 	return distance;
    148 }
    149 
    150 int ebitmap_cmp(const ebitmap_t * e1, const ebitmap_t * e2)
    151 {
    152 	ebitmap_node_t *n1, *n2;
    153 
    154 	if (e1->highbit != e2->highbit)
    155 		return 0;
    156 
    157 	n1 = e1->node;
    158 	n2 = e2->node;
    159 	while (n1 && n2 &&
    160 	       (n1->startbit == n2->startbit) && (n1->map == n2->map)) {
    161 		n1 = n1->next;
    162 		n2 = n2->next;
    163 	}
    164 
    165 	if (n1 || n2)
    166 		return 0;
    167 
    168 	return 1;
    169 }
    170 
    171 int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src)
    172 {
    173 	ebitmap_node_t *n, *new, *prev;
    174 
    175 	ebitmap_init(dst);
    176 	n = src->node;
    177 	prev = 0;
    178 	while (n) {
    179 		new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
    180 		if (!new) {
    181 			ebitmap_destroy(dst);
    182 			return -ENOMEM;
    183 		}
    184 		memset(new, 0, sizeof(ebitmap_node_t));
    185 		new->startbit = n->startbit;
    186 		new->map = n->map;
    187 		new->next = 0;
    188 		if (prev)
    189 			prev->next = new;
    190 		else
    191 			dst->node = new;
    192 		prev = new;
    193 		n = n->next;
    194 	}
    195 
    196 	dst->highbit = src->highbit;
    197 	return 0;
    198 }
    199 
    200 int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2)
    201 {
    202 	ebitmap_node_t *n1, *n2;
    203 
    204 	if (e1->highbit < e2->highbit)
    205 		return 0;
    206 
    207 	n1 = e1->node;
    208 	n2 = e2->node;
    209 	while (n1 && n2 && (n1->startbit <= n2->startbit)) {
    210 		if (n1->startbit < n2->startbit) {
    211 			n1 = n1->next;
    212 			continue;
    213 		}
    214 		if ((n1->map & n2->map) != n2->map)
    215 			return 0;
    216 
    217 		n1 = n1->next;
    218 		n2 = n2->next;
    219 	}
    220 
    221 	if (n2)
    222 		return 0;
    223 
    224 	return 1;
    225 }
    226 
    227 int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit)
    228 {
    229 	ebitmap_node_t *n;
    230 
    231 	if (e->highbit < bit)
    232 		return 0;
    233 
    234 	n = e->node;
    235 	while (n && (n->startbit <= bit)) {
    236 		if ((n->startbit + MAPSIZE) > bit) {
    237 			if (n->map & (MAPBIT << (bit - n->startbit)))
    238 				return 1;
    239 			else
    240 				return 0;
    241 		}
    242 		n = n->next;
    243 	}
    244 
    245 	return 0;
    246 }
    247 
    248 int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value)
    249 {
    250 	ebitmap_node_t *n, *prev, *new;
    251 	uint32_t startbit = bit & ~(MAPSIZE - 1);
    252 	uint32_t highbit = startbit + MAPSIZE;
    253 
    254 	if (highbit == 0) {
    255 		ERR(NULL, "bitmap overflow, bit 0x%x", bit);
    256 		return -EINVAL;
    257 	}
    258 
    259 	prev = 0;
    260 	n = e->node;
    261 	while (n && n->startbit <= bit) {
    262 		if ((n->startbit + MAPSIZE) > bit) {
    263 			if (value) {
    264 				n->map |= (MAPBIT << (bit - n->startbit));
    265 			} else {
    266 				n->map &= ~(MAPBIT << (bit - n->startbit));
    267 				if (!n->map) {
    268 					/* drop this node from the bitmap */
    269 
    270 					if (!n->next) {
    271 						/*
    272 						 * this was the highest map
    273 						 * within the bitmap
    274 						 */
    275 						if (prev)
    276 							e->highbit =
    277 							    prev->startbit +
    278 							    MAPSIZE;
    279 						else
    280 							e->highbit = 0;
    281 					}
    282 					if (prev)
    283 						prev->next = n->next;
    284 					else
    285 						e->node = n->next;
    286 
    287 					free(n);
    288 				}
    289 			}
    290 			return 0;
    291 		}
    292 		prev = n;
    293 		n = n->next;
    294 	}
    295 
    296 	if (!value)
    297 		return 0;
    298 
    299 	new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
    300 	if (!new)
    301 		return -ENOMEM;
    302 	memset(new, 0, sizeof(ebitmap_node_t));
    303 
    304 	new->startbit = startbit;
    305 	new->map = (MAPBIT << (bit - new->startbit));
    306 
    307 	if (!n) {
    308 		/* this node will be the highest map within the bitmap */
    309 		e->highbit = highbit;
    310 	}
    311 
    312 	if (prev) {
    313 		new->next = prev->next;
    314 		prev->next = new;
    315 	} else {
    316 		new->next = e->node;
    317 		e->node = new;
    318 	}
    319 
    320 	return 0;
    321 }
    322 
    323 void ebitmap_destroy(ebitmap_t * e)
    324 {
    325 	ebitmap_node_t *n, *temp;
    326 
    327 	if (!e)
    328 		return;
    329 
    330 	n = e->node;
    331 	while (n) {
    332 		temp = n;
    333 		n = n->next;
    334 		free(temp);
    335 	}
    336 
    337 	e->highbit = 0;
    338 	e->node = 0;
    339 	return;
    340 }
    341 
    342 int ebitmap_read(ebitmap_t * e, void *fp)
    343 {
    344 	int rc;
    345 	ebitmap_node_t *n, *l;
    346 	uint32_t buf[3], mapsize, count, i;
    347 	uint64_t map;
    348 
    349 	ebitmap_init(e);
    350 
    351 	rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
    352 	if (rc < 0)
    353 		goto bad;
    354 
    355 	mapsize = le32_to_cpu(buf[0]);
    356 	e->highbit = le32_to_cpu(buf[1]);
    357 	count = le32_to_cpu(buf[2]);
    358 
    359 	if (mapsize != MAPSIZE) {
    360 		printf
    361 		    ("security: ebitmap: map size %d does not match my size %zu (high bit was %d)\n",
    362 		     mapsize, MAPSIZE, e->highbit);
    363 		goto bad;
    364 	}
    365 	if (!e->highbit) {
    366 		e->node = NULL;
    367 		goto ok;
    368 	}
    369 	if (e->highbit & (MAPSIZE - 1)) {
    370 		printf
    371 		    ("security: ebitmap: high bit (%d) is not a multiple of the map size (%zu)\n",
    372 		     e->highbit, MAPSIZE);
    373 		goto bad;
    374 	}
    375 	l = NULL;
    376 	for (i = 0; i < count; i++) {
    377 		rc = next_entry(buf, fp, sizeof(uint32_t));
    378 		if (rc < 0) {
    379 			printf("security: ebitmap: truncated map\n");
    380 			goto bad;
    381 		}
    382 		n = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t));
    383 		if (!n) {
    384 			printf("security: ebitmap: out of memory\n");
    385 			rc = -ENOMEM;
    386 			goto bad;
    387 		}
    388 		memset(n, 0, sizeof(ebitmap_node_t));
    389 
    390 		n->startbit = le32_to_cpu(buf[0]);
    391 
    392 		if (n->startbit & (MAPSIZE - 1)) {
    393 			printf
    394 			    ("security: ebitmap start bit (%d) is not a multiple of the map size (%zu)\n",
    395 			     n->startbit, MAPSIZE);
    396 			goto bad_free;
    397 		}
    398 		if (n->startbit > (e->highbit - MAPSIZE)) {
    399 			printf
    400 			    ("security: ebitmap start bit (%d) is beyond the end of the bitmap (%zu)\n",
    401 			     n->startbit, (e->highbit - MAPSIZE));
    402 			goto bad_free;
    403 		}
    404 		rc = next_entry(&map, fp, sizeof(uint64_t));
    405 		if (rc < 0) {
    406 			printf("security: ebitmap: truncated map\n");
    407 			goto bad_free;
    408 		}
    409 		n->map = le64_to_cpu(map);
    410 
    411 		if (!n->map) {
    412 			printf
    413 			    ("security: ebitmap: null map in ebitmap (startbit %d)\n",
    414 			     n->startbit);
    415 			goto bad_free;
    416 		}
    417 		if (l) {
    418 			if (n->startbit <= l->startbit) {
    419 				printf
    420 				    ("security: ebitmap: start bit %d comes after start bit %d\n",
    421 				     n->startbit, l->startbit);
    422 				goto bad_free;
    423 			}
    424 			l->next = n;
    425 		} else
    426 			e->node = n;
    427 
    428 		l = n;
    429 	}
    430 
    431       ok:
    432 	rc = 0;
    433       out:
    434 	return rc;
    435       bad_free:
    436 	free(n);
    437       bad:
    438 	if (!rc)
    439 		rc = -EINVAL;
    440 	ebitmap_destroy(e);
    441 	goto out;
    442 }
    443 
    444 /* FLASK */
    445