Home | History | Annotate | Download | only in src
      1 
      2 /* Author : Stephen Smalley, <sds (at) epoch.ncsc.mil> */
      3 
      4 /*
      5  * Updated: Trusted Computer Solutions, Inc. <dgoeddel (at) trustedcs.com>
      6  *
      7  *	Support for enhanced MLS infrastructure.
      8  *
      9  * Updated: Frank Mayer <mayerf (at) tresys.com> and Karl MacMillan <kmacmillan (at) tresys.com>
     10  *
     11  * 	Added conditional policy language extensions
     12  *
     13  * Updated: Joshua Brindle <jbrindle (at) tresys.com> and Jason Tang <jtang (at) tresys.org>
     14  *
     15  *	Module writing support
     16  *
     17  * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
     18  * Copyright (C) 2003-2005 Tresys Technology, LLC
     19  *
     20  *  This library is free software; you can redistribute it and/or
     21  *  modify it under the terms of the GNU Lesser General Public
     22  *  License as published by the Free Software Foundation; either
     23  *  version 2.1 of the License, or (at your option) any later version.
     24  *
     25  *  This library is distributed in the hope that it will be useful,
     26  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     27  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     28  *  Lesser General Public License for more details.
     29  *
     30  *  You should have received a copy of the GNU Lesser General Public
     31  *  License along with this library; if not, write to the Free Software
     32  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     33  */
     34 #include <assert.h>
     35 #include <stdlib.h>
     36 
     37 #include <sepol/policydb/ebitmap.h>
     38 #include <sepol/policydb/avtab.h>
     39 #include <sepol/policydb/policydb.h>
     40 #include <sepol/policydb/conditional.h>
     41 #include <sepol/policydb/expand.h>
     42 #include <sepol/policydb/flask.h>
     43 
     44 #include "debug.h"
     45 #include "private.h"
     46 #include "mls.h"
     47 
     48 struct policy_data {
     49 	struct policy_file *fp;
     50 	struct policydb *p;
     51 };
     52 
     53 static int avrule_write_list(avrule_t * avrules, struct policy_file *fp);
     54 
     55 static int ebitmap_write(ebitmap_t * e, struct policy_file *fp)
     56 {
     57 	ebitmap_node_t *n;
     58 	uint32_t buf[32], bit, count;
     59 	uint64_t map;
     60 	size_t items;
     61 
     62 	buf[0] = cpu_to_le32(MAPSIZE);
     63 	buf[1] = cpu_to_le32(e->highbit);
     64 
     65 	count = 0;
     66 	for (n = e->node; n; n = n->next)
     67 		count++;
     68 	buf[2] = cpu_to_le32(count);
     69 
     70 	items = put_entry(buf, sizeof(uint32_t), 3, fp);
     71 	if (items != 3)
     72 		return POLICYDB_ERROR;
     73 
     74 	for (n = e->node; n; n = n->next) {
     75 		bit = cpu_to_le32(n->startbit);
     76 		items = put_entry(&bit, sizeof(uint32_t), 1, fp);
     77 		if (items != 1)
     78 			return POLICYDB_ERROR;
     79 		map = cpu_to_le64(n->map);
     80 		items = put_entry(&map, sizeof(uint64_t), 1, fp);
     81 		if (items != 1)
     82 			return POLICYDB_ERROR;
     83 
     84 	}
     85 
     86 	return POLICYDB_SUCCESS;
     87 }
     88 
     89 /* Ordering of datums in the original avtab format in the policy file. */
     90 static uint16_t spec_order[] = {
     91 	AVTAB_ALLOWED,
     92 	AVTAB_AUDITDENY,
     93 	AVTAB_AUDITALLOW,
     94 	AVTAB_TRANSITION,
     95 	AVTAB_CHANGE,
     96 	AVTAB_MEMBER
     97 };
     98 
     99 static int avtab_write_item(policydb_t * p,
    100 			    avtab_ptr_t cur, struct policy_file *fp,
    101 			    unsigned merge, unsigned commit, uint32_t * nel)
    102 {
    103 	avtab_ptr_t node;
    104 	uint16_t buf16[4];
    105 	uint32_t buf32[10], lookup, val;
    106 	size_t items, items2;
    107 	unsigned set;
    108 	unsigned int oldvers = (p->policy_type == POLICY_KERN
    109 				&& p->policyvers < POLICYDB_VERSION_AVTAB);
    110 	unsigned int i;
    111 
    112 	if (oldvers) {
    113 		/* Generate the old avtab format.
    114 		   Requires merging similar entries if uncond avtab. */
    115 		if (merge) {
    116 			if (cur->merged)
    117 				return POLICYDB_SUCCESS;	/* already merged by prior merge */
    118 		}
    119 
    120 		items = 1;	/* item 0 is used for the item count */
    121 		val = cur->key.source_type;
    122 		buf32[items++] = cpu_to_le32(val);
    123 		val = cur->key.target_type;
    124 		buf32[items++] = cpu_to_le32(val);
    125 		val = cur->key.target_class;
    126 		buf32[items++] = cpu_to_le32(val);
    127 
    128 		val = cur->key.specified & ~AVTAB_ENABLED;
    129 		if (cur->key.specified & AVTAB_ENABLED)
    130 			val |= AVTAB_ENABLED_OLD;
    131 		set = 1;
    132 
    133 		if (merge) {
    134 			/* Merge specifier values for all similar (av or type)
    135 			   entries that have the same key. */
    136 			if (val & AVTAB_AV)
    137 				lookup = AVTAB_AV;
    138 			else if (val & AVTAB_TYPE)
    139 				lookup = AVTAB_TYPE;
    140 			else
    141 				return POLICYDB_ERROR;
    142 			for (node = avtab_search_node_next(cur, lookup);
    143 			     node;
    144 			     node = avtab_search_node_next(node, lookup)) {
    145 				val |= (node->key.specified & ~AVTAB_ENABLED);
    146 				set++;
    147 				if (node->key.specified & AVTAB_ENABLED)
    148 					val |= AVTAB_ENABLED_OLD;
    149 			}
    150 		}
    151 
    152 		if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
    153 			ERR(fp->handle, "null entry");
    154 			return POLICYDB_ERROR;
    155 		}
    156 		if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) {
    157 			ERR(fp->handle, "entry has both access "
    158 			    "vectors and types");
    159 			return POLICYDB_ERROR;
    160 		}
    161 
    162 		buf32[items++] = cpu_to_le32(val);
    163 
    164 		if (merge) {
    165 			/* Include datums for all similar (av or type)
    166 			   entries that have the same key. */
    167 			for (i = 0;
    168 			     i < (sizeof(spec_order) / sizeof(spec_order[0]));
    169 			     i++) {
    170 				if (val & spec_order[i]) {
    171 					if (cur->key.specified & spec_order[i])
    172 						node = cur;
    173 					else {
    174 						node =
    175 						    avtab_search_node_next(cur,
    176 									   spec_order
    177 									   [i]);
    178 						if (nel)
    179 							(*nel)--;	/* one less node */
    180 					}
    181 
    182 					if (!node) {
    183 						ERR(fp->handle, "missing node");
    184 						return POLICYDB_ERROR;
    185 					}
    186 					buf32[items++] =
    187 					    cpu_to_le32(node->datum.data);
    188 					set--;
    189 					node->merged = 1;
    190 				}
    191 			}
    192 		} else {
    193 			buf32[items++] = cpu_to_le32(cur->datum.data);
    194 			cur->merged = 1;
    195 			set--;
    196 		}
    197 
    198 		if (set) {
    199 			ERR(fp->handle, "data count wrong");
    200 			return POLICYDB_ERROR;
    201 		}
    202 
    203 		buf32[0] = cpu_to_le32(items - 1);
    204 
    205 		if (commit) {
    206 			/* Commit this item to the policy file. */
    207 			items2 = put_entry(buf32, sizeof(uint32_t), items, fp);
    208 			if (items != items2)
    209 				return POLICYDB_ERROR;
    210 		}
    211 
    212 		return POLICYDB_SUCCESS;
    213 	}
    214 
    215 	/* Generate the new avtab format. */
    216 	buf16[0] = cpu_to_le16(cur->key.source_type);
    217 	buf16[1] = cpu_to_le16(cur->key.target_type);
    218 	buf16[2] = cpu_to_le16(cur->key.target_class);
    219 	buf16[3] = cpu_to_le16(cur->key.specified);
    220 	items = put_entry(buf16, sizeof(uint16_t), 4, fp);
    221 	if (items != 4)
    222 		return POLICYDB_ERROR;
    223 	buf32[0] = cpu_to_le32(cur->datum.data);
    224 	items = put_entry(buf32, sizeof(uint32_t), 1, fp);
    225 	if (items != 1)
    226 		return POLICYDB_ERROR;
    227 	return POLICYDB_SUCCESS;
    228 }
    229 
    230 static inline void avtab_reset_merged(avtab_t * a)
    231 {
    232 	unsigned int i;
    233 	avtab_ptr_t cur;
    234 	for (i = 0; i < a->nslot; i++) {
    235 		for (cur = a->htable[i]; cur; cur = cur->next)
    236 			cur->merged = 0;
    237 	}
    238 }
    239 
    240 static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp)
    241 {
    242 	unsigned int i;
    243 	int rc;
    244 	avtab_t expa;
    245 	avtab_ptr_t cur;
    246 	uint32_t nel;
    247 	size_t items;
    248 	unsigned int oldvers = (p->policy_type == POLICY_KERN
    249 				&& p->policyvers < POLICYDB_VERSION_AVTAB);
    250 
    251 	if (oldvers) {
    252 		/* Old avtab format.
    253 		   First, we need to expand attributes.  Then, we need to
    254 		   merge similar entries, so we need to track merged nodes
    255 		   and compute the final nel. */
    256 		if (avtab_init(&expa))
    257 			return POLICYDB_ERROR;
    258 		if (expand_avtab(p, a, &expa)) {
    259 			rc = -1;
    260 			goto out;
    261 		}
    262 		a = &expa;
    263 		avtab_reset_merged(a);
    264 		nel = a->nel;
    265 	} else {
    266 		/* New avtab format.  nel is good to go. */
    267 		nel = cpu_to_le32(a->nel);
    268 		items = put_entry(&nel, sizeof(uint32_t), 1, fp);
    269 		if (items != 1)
    270 			return POLICYDB_ERROR;
    271 	}
    272 
    273 	for (i = 0; i < a->nslot; i++) {
    274 		for (cur = a->htable[i]; cur; cur = cur->next) {
    275 			/* If old format, compute final nel.
    276 			   If new format, write out the items. */
    277 			if (avtab_write_item(p, cur, fp, 1, !oldvers, &nel)) {
    278 				rc = -1;
    279 				goto out;
    280 			}
    281 		}
    282 	}
    283 
    284 	if (oldvers) {
    285 		/* Old avtab format.
    286 		   Write the computed nel value, then write the items. */
    287 		nel = cpu_to_le32(nel);
    288 		items = put_entry(&nel, sizeof(uint32_t), 1, fp);
    289 		if (items != 1) {
    290 			rc = -1;
    291 			goto out;
    292 		}
    293 		avtab_reset_merged(a);
    294 		for (i = 0; i < a->nslot; i++) {
    295 			for (cur = a->htable[i]; cur; cur = cur->next) {
    296 				if (avtab_write_item(p, cur, fp, 1, 1, NULL)) {
    297 					rc = -1;
    298 					goto out;
    299 				}
    300 			}
    301 		}
    302 	}
    303 
    304 	rc = 0;
    305       out:
    306 	if (oldvers)
    307 		avtab_destroy(&expa);
    308 	return rc;
    309 }
    310 
    311 /*
    312  * Write a semantic MLS level structure to a policydb binary
    313  * representation file.
    314  */
    315 static int mls_write_semantic_level_helper(mls_semantic_level_t * l,
    316 					   struct policy_file *fp)
    317 {
    318 	uint32_t buf[2], ncat = 0;
    319 	size_t items;
    320 	mls_semantic_cat_t *cat;
    321 
    322 	for (cat = l->cat; cat; cat = cat->next)
    323 		ncat++;
    324 
    325 	buf[0] = cpu_to_le32(l->sens);
    326 	buf[1] = cpu_to_le32(ncat);
    327 	items = put_entry(buf, sizeof(uint32_t), 2, fp);
    328 	if (items != 2)
    329 		return POLICYDB_ERROR;
    330 
    331 	for (cat = l->cat; cat; cat = cat->next) {
    332 		buf[0] = cpu_to_le32(cat->low);
    333 		buf[1] = cpu_to_le32(cat->high);
    334 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
    335 		if (items != 2)
    336 			return POLICYDB_ERROR;
    337 	}
    338 
    339 	return POLICYDB_SUCCESS;
    340 }
    341 
    342 /*
    343  * Read a semantic MLS range structure to a policydb binary
    344  * representation file.
    345  */
    346 static int mls_write_semantic_range_helper(mls_semantic_range_t * r,
    347 					   struct policy_file *fp)
    348 {
    349 	int rc;
    350 
    351 	rc = mls_write_semantic_level_helper(&r->level[0], fp);
    352 	if (rc)
    353 		return rc;
    354 
    355 	rc = mls_write_semantic_level_helper(&r->level[1], fp);
    356 
    357 	return rc;
    358 }
    359 
    360 /*
    361  * Write a MLS level structure to a policydb binary
    362  * representation file.
    363  */
    364 static int mls_write_level(mls_level_t * l, struct policy_file *fp)
    365 {
    366 	uint32_t sens;
    367 	size_t items;
    368 
    369 	sens = cpu_to_le32(l->sens);
    370 	items = put_entry(&sens, sizeof(uint32_t), 1, fp);
    371 	if (items != 1)
    372 		return POLICYDB_ERROR;
    373 
    374 	if (ebitmap_write(&l->cat, fp))
    375 		return POLICYDB_ERROR;
    376 
    377 	return POLICYDB_SUCCESS;
    378 }
    379 
    380 /*
    381  * Write a MLS range structure to a policydb binary
    382  * representation file.
    383  */
    384 static int mls_write_range_helper(mls_range_t * r, struct policy_file *fp)
    385 {
    386 	uint32_t buf[3];
    387 	size_t items, items2;
    388 	int eq;
    389 
    390 	eq = mls_level_eq(&r->level[1], &r->level[0]);
    391 
    392 	items = 1;		/* item 0 is used for the item count */
    393 	buf[items++] = cpu_to_le32(r->level[0].sens);
    394 	if (!eq)
    395 		buf[items++] = cpu_to_le32(r->level[1].sens);
    396 	buf[0] = cpu_to_le32(items - 1);
    397 
    398 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    399 	if (items2 != items)
    400 		return POLICYDB_ERROR;
    401 
    402 	if (ebitmap_write(&r->level[0].cat, fp))
    403 		return POLICYDB_ERROR;
    404 	if (!eq)
    405 		if (ebitmap_write(&r->level[1].cat, fp))
    406 			return POLICYDB_ERROR;
    407 
    408 	return POLICYDB_SUCCESS;
    409 }
    410 
    411 static int sens_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
    412 {
    413 	level_datum_t *levdatum;
    414 	uint32_t buf[32];
    415 	size_t items, items2, len;
    416 	struct policy_data *pd = ptr;
    417 	struct policy_file *fp = pd->fp;
    418 
    419 	levdatum = (level_datum_t *) datum;
    420 
    421 	len = strlen(key);
    422 	items = 0;
    423 	buf[items++] = cpu_to_le32(len);
    424 	buf[items++] = cpu_to_le32(levdatum->isalias);
    425 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    426 	if (items != items2)
    427 		return POLICYDB_ERROR;
    428 
    429 	items = put_entry(key, 1, len, fp);
    430 	if (items != len)
    431 		return POLICYDB_ERROR;
    432 
    433 	if (mls_write_level(levdatum->level, fp))
    434 		return POLICYDB_ERROR;
    435 
    436 	return POLICYDB_SUCCESS;
    437 }
    438 
    439 static int cat_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
    440 {
    441 	cat_datum_t *catdatum;
    442 	uint32_t buf[32];
    443 	size_t items, items2, len;
    444 	struct policy_data *pd = ptr;
    445 	struct policy_file *fp = pd->fp;
    446 
    447 	catdatum = (cat_datum_t *) datum;
    448 
    449 	len = strlen(key);
    450 	items = 0;
    451 	buf[items++] = cpu_to_le32(len);
    452 	buf[items++] = cpu_to_le32(catdatum->s.value);
    453 	buf[items++] = cpu_to_le32(catdatum->isalias);
    454 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    455 	if (items != items2)
    456 		return POLICYDB_ERROR;
    457 
    458 	items = put_entry(key, 1, len, fp);
    459 	if (items != len)
    460 		return POLICYDB_ERROR;
    461 
    462 	return POLICYDB_SUCCESS;
    463 }
    464 
    465 static int role_trans_write(policydb_t *p, struct policy_file *fp)
    466 {
    467 	role_trans_t *r = p->role_tr;
    468 	role_trans_t *tr;
    469 	uint32_t buf[3];
    470 	size_t nel, items;
    471 	int new_roletr = (p->policy_type == POLICY_KERN &&
    472 			  p->policyvers >= POLICYDB_VERSION_ROLETRANS);
    473 	int warning_issued = 0;
    474 
    475 	nel = 0;
    476 	for (tr = r; tr; tr = tr->next)
    477 		if(new_roletr || tr->tclass == SECCLASS_PROCESS)
    478 			nel++;
    479 
    480 	buf[0] = cpu_to_le32(nel);
    481 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    482 	if (items != 1)
    483 		return POLICYDB_ERROR;
    484 	for (tr = r; tr; tr = tr->next) {
    485 		if (!new_roletr && tr->tclass != SECCLASS_PROCESS) {
    486 			if (!warning_issued)
    487 				WARN(fp->handle, "Discarding role_transition "
    488 				     "rules for security classes other than "
    489 				     "\"process\"");
    490 			warning_issued = 1;
    491 			continue;
    492 		}
    493 		buf[0] = cpu_to_le32(tr->role);
    494 		buf[1] = cpu_to_le32(tr->type);
    495 		buf[2] = cpu_to_le32(tr->new_role);
    496 		items = put_entry(buf, sizeof(uint32_t), 3, fp);
    497 		if (items != 3)
    498 			return POLICYDB_ERROR;
    499 		if (new_roletr) {
    500 			buf[0] = cpu_to_le32(tr->tclass);
    501 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
    502 			if (items != 1)
    503 				return POLICYDB_ERROR;
    504 		}
    505 	}
    506 
    507 	return POLICYDB_SUCCESS;
    508 }
    509 
    510 static int role_allow_write(role_allow_t * r, struct policy_file *fp)
    511 {
    512 	role_allow_t *ra;
    513 	uint32_t buf[2];
    514 	size_t nel, items;
    515 
    516 	nel = 0;
    517 	for (ra = r; ra; ra = ra->next)
    518 		nel++;
    519 	buf[0] = cpu_to_le32(nel);
    520 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    521 	if (items != 1)
    522 		return POLICYDB_ERROR;
    523 	for (ra = r; ra; ra = ra->next) {
    524 		buf[0] = cpu_to_le32(ra->role);
    525 		buf[1] = cpu_to_le32(ra->new_role);
    526 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
    527 		if (items != 2)
    528 			return POLICYDB_ERROR;
    529 	}
    530 	return POLICYDB_SUCCESS;
    531 }
    532 
    533 static int filename_trans_write(filename_trans_t * r, struct policy_file *fp)
    534 {
    535 	filename_trans_t *ft;
    536 	uint32_t buf[4];
    537 	size_t nel, items, len;
    538 
    539 	nel = 0;
    540 	for (ft = r; ft; ft = ft->next)
    541 		nel++;
    542 	buf[0] = cpu_to_le32(nel);
    543 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    544 	if (items != 1)
    545 		return POLICYDB_ERROR;
    546 	for (ft = r; ft; ft = ft->next) {
    547 		len = strlen(ft->name);
    548 		buf[0] = cpu_to_le32(len);
    549 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
    550 		if (items != 1)
    551 			return POLICYDB_ERROR;
    552 
    553 		items = put_entry(ft->name, sizeof(char), len, fp);
    554 		if (items != len)
    555 			return POLICYDB_ERROR;
    556 
    557 		buf[0] = cpu_to_le32(ft->stype);
    558 		buf[1] = cpu_to_le32(ft->ttype);
    559 		buf[2] = cpu_to_le32(ft->tclass);
    560 		buf[3] = cpu_to_le32(ft->otype);
    561 		items = put_entry(buf, sizeof(uint32_t), 4, fp);
    562 		if (items != 4)
    563 			return POLICYDB_ERROR;
    564 	}
    565 
    566 	return POLICYDB_SUCCESS;
    567 }
    568 
    569 static int role_set_write(role_set_t * x, struct policy_file *fp)
    570 {
    571 	size_t items;
    572 	uint32_t buf[1];
    573 
    574 	if (ebitmap_write(&x->roles, fp))
    575 		return POLICYDB_ERROR;
    576 
    577 	buf[0] = cpu_to_le32(x->flags);
    578 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    579 	if (items != 1)
    580 		return POLICYDB_ERROR;
    581 
    582 	return POLICYDB_SUCCESS;
    583 }
    584 
    585 static int type_set_write(type_set_t * x, struct policy_file *fp)
    586 {
    587 	size_t items;
    588 	uint32_t buf[1];
    589 
    590 	if (ebitmap_write(&x->types, fp))
    591 		return POLICYDB_ERROR;
    592 	if (ebitmap_write(&x->negset, fp))
    593 		return POLICYDB_ERROR;
    594 
    595 	buf[0] = cpu_to_le32(x->flags);
    596 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    597 	if (items != 1)
    598 		return POLICYDB_ERROR;
    599 
    600 	return POLICYDB_SUCCESS;
    601 }
    602 
    603 static int cond_write_bool(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
    604 {
    605 	cond_bool_datum_t *booldatum;
    606 	uint32_t buf[3], len;
    607 	unsigned int items, items2;
    608 	struct policy_data *pd = ptr;
    609 	struct policy_file *fp = pd->fp;
    610 	struct policydb *p = pd->p;
    611 
    612 	booldatum = (cond_bool_datum_t *) datum;
    613 
    614 	len = strlen(key);
    615 	items = 0;
    616 	buf[items++] = cpu_to_le32(booldatum->s.value);
    617 	buf[items++] = cpu_to_le32(booldatum->state);
    618 	buf[items++] = cpu_to_le32(len);
    619 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    620 	if (items != items2)
    621 		return POLICYDB_ERROR;
    622 	items = put_entry(key, 1, len, fp);
    623 	if (items != len)
    624 		return POLICYDB_ERROR;
    625 
    626 	if (p->policy_type != POLICY_KERN &&
    627 	    p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
    628 		buf[0] = cpu_to_le32(booldatum->flags);
    629 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
    630 		if (items != 1)
    631 			return POLICYDB_ERROR;
    632 	}
    633 
    634 	return POLICYDB_SUCCESS;
    635 }
    636 
    637 /*
    638  * cond_write_cond_av_list doesn't write out the av_list nodes.
    639  * Instead it writes out the key/value pairs from the avtab. This
    640  * is necessary because there is no way to uniquely identifying rules
    641  * in the avtab so it is not possible to associate individual rules
    642  * in the avtab with a conditional without saving them as part of
    643  * the conditional. This means that the avtab with the conditional
    644  * rules will not be saved but will be rebuilt on policy load.
    645  */
    646 static int cond_write_av_list(policydb_t * p,
    647 			      cond_av_list_t * list, struct policy_file *fp)
    648 {
    649 	uint32_t buf[4];
    650 	cond_av_list_t *cur_list, *new_list = NULL;
    651 	avtab_t expa;
    652 	uint32_t len, items;
    653 	unsigned int oldvers = (p->policy_type == POLICY_KERN
    654 				&& p->policyvers < POLICYDB_VERSION_AVTAB);
    655 	int rc = -1;
    656 
    657 	if (oldvers) {
    658 		if (avtab_init(&expa))
    659 			return POLICYDB_ERROR;
    660 		if (expand_cond_av_list(p, list, &new_list, &expa))
    661 			goto out;
    662 		list = new_list;
    663 	}
    664 
    665 	len = 0;
    666 	for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
    667 		if (cur_list->node->parse_context)
    668 			len++;
    669 	}
    670 
    671 	buf[0] = cpu_to_le32(len);
    672 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    673 	if (items != 1)
    674 		goto out;
    675 
    676 	if (len == 0) {
    677 		rc = 0;
    678 		goto out;
    679 	}
    680 
    681 	for (cur_list = list; cur_list != NULL; cur_list = cur_list->next) {
    682 		if (cur_list->node->parse_context)
    683 			if (avtab_write_item(p, cur_list->node, fp, 0, 1, NULL))
    684 				goto out;
    685 	}
    686 
    687 	rc = 0;
    688       out:
    689 	if (oldvers) {
    690 		cond_av_list_destroy(new_list);
    691 		avtab_destroy(&expa);
    692 	}
    693 
    694 	return rc;
    695 }
    696 
    697 static int cond_write_node(policydb_t * p,
    698 			   cond_node_t * node, struct policy_file *fp)
    699 {
    700 	cond_expr_t *cur_expr;
    701 	uint32_t buf[2];
    702 	uint32_t items, items2, len;
    703 
    704 	buf[0] = cpu_to_le32(node->cur_state);
    705 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    706 	if (items != 1)
    707 		return POLICYDB_ERROR;
    708 
    709 	/* expr */
    710 	len = 0;
    711 	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next)
    712 		len++;
    713 
    714 	buf[0] = cpu_to_le32(len);
    715 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    716 	if (items != 1)
    717 		return POLICYDB_ERROR;
    718 
    719 	for (cur_expr = node->expr; cur_expr != NULL; cur_expr = cur_expr->next) {
    720 		items = 0;
    721 		buf[items++] = cpu_to_le32(cur_expr->expr_type);
    722 		buf[items++] = cpu_to_le32(cur_expr->bool);
    723 		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    724 		if (items2 != items)
    725 			return POLICYDB_ERROR;
    726 	}
    727 
    728 	if (p->policy_type == POLICY_KERN) {
    729 		if (cond_write_av_list(p, node->true_list, fp) != 0)
    730 			return POLICYDB_ERROR;
    731 		if (cond_write_av_list(p, node->false_list, fp) != 0)
    732 			return POLICYDB_ERROR;
    733 	} else {
    734 		if (avrule_write_list(node->avtrue_list, fp))
    735 			return POLICYDB_ERROR;
    736 		if (avrule_write_list(node->avfalse_list, fp))
    737 			return POLICYDB_ERROR;
    738 	}
    739 
    740 	if (p->policy_type != POLICY_KERN &&
    741 	    p->policyvers >= MOD_POLICYDB_VERSION_TUNABLE_SEP) {
    742 		buf[0] = cpu_to_le32(node->flags);
    743 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
    744 		if (items != 1)
    745 			return POLICYDB_ERROR;
    746 	}
    747 
    748 	return POLICYDB_SUCCESS;
    749 }
    750 
    751 static int cond_write_list(policydb_t * p, cond_list_t * list,
    752 			   struct policy_file *fp)
    753 {
    754 	cond_node_t *cur;
    755 	uint32_t len, items;
    756 	uint32_t buf[1];
    757 
    758 	len = 0;
    759 	for (cur = list; cur != NULL; cur = cur->next)
    760 		len++;
    761 	buf[0] = cpu_to_le32(len);
    762 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
    763 	if (items != 1)
    764 		return POLICYDB_ERROR;
    765 
    766 	for (cur = list; cur != NULL; cur = cur->next) {
    767 		if (cond_write_node(p, cur, fp) != 0)
    768 			return POLICYDB_ERROR;
    769 	}
    770 	return POLICYDB_SUCCESS;
    771 }
    772 
    773 /*
    774  * Write a security context structure
    775  * to a policydb binary representation file.
    776  */
    777 static int context_write(struct policydb *p, context_struct_t * c,
    778 			 struct policy_file *fp)
    779 {
    780 	uint32_t buf[32];
    781 	size_t items, items2;
    782 
    783 	items = 0;
    784 	buf[items++] = cpu_to_le32(c->user);
    785 	buf[items++] = cpu_to_le32(c->role);
    786 	buf[items++] = cpu_to_le32(c->type);
    787 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    788 	if (items2 != items)
    789 		return POLICYDB_ERROR;
    790 	if ((p->policyvers >= POLICYDB_VERSION_MLS
    791 	     && p->policy_type == POLICY_KERN)
    792 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
    793 		&& p->policy_type == POLICY_BASE))
    794 		if (mls_write_range_helper(&c->range, fp))
    795 			return POLICYDB_ERROR;
    796 
    797 	return POLICYDB_SUCCESS;
    798 }
    799 
    800 /*
    801  * The following *_write functions are used to
    802  * write the symbol data to a policy database
    803  * binary representation file.
    804  */
    805 
    806 static int perm_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
    807 {
    808 	perm_datum_t *perdatum;
    809 	uint32_t buf[32];
    810 	size_t items, items2, len;
    811 	struct policy_data *pd = ptr;
    812 	struct policy_file *fp = pd->fp;
    813 
    814 	perdatum = (perm_datum_t *) datum;
    815 
    816 	len = strlen(key);
    817 	items = 0;
    818 	buf[items++] = cpu_to_le32(len);
    819 	buf[items++] = cpu_to_le32(perdatum->s.value);
    820 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    821 	if (items != items2)
    822 		return POLICYDB_ERROR;
    823 
    824 	items = put_entry(key, 1, len, fp);
    825 	if (items != len)
    826 		return POLICYDB_ERROR;
    827 
    828 	return POLICYDB_SUCCESS;
    829 }
    830 
    831 static int common_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
    832 {
    833 	common_datum_t *comdatum;
    834 	uint32_t buf[32];
    835 	size_t items, items2, len;
    836 	struct policy_data *pd = ptr;
    837 	struct policy_file *fp = pd->fp;
    838 
    839 	comdatum = (common_datum_t *) datum;
    840 
    841 	len = strlen(key);
    842 	items = 0;
    843 	buf[items++] = cpu_to_le32(len);
    844 	buf[items++] = cpu_to_le32(comdatum->s.value);
    845 	buf[items++] = cpu_to_le32(comdatum->permissions.nprim);
    846 	buf[items++] = cpu_to_le32(comdatum->permissions.table->nel);
    847 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    848 	if (items != items2)
    849 		return POLICYDB_ERROR;
    850 
    851 	items = put_entry(key, 1, len, fp);
    852 	if (items != len)
    853 		return POLICYDB_ERROR;
    854 
    855 	if (hashtab_map(comdatum->permissions.table, perm_write, pd))
    856 		return POLICYDB_ERROR;
    857 
    858 	return POLICYDB_SUCCESS;
    859 }
    860 
    861 static int write_cons_helper(policydb_t * p,
    862 			     constraint_node_t * node, int allowxtarget,
    863 			     struct policy_file *fp)
    864 {
    865 	constraint_node_t *c;
    866 	constraint_expr_t *e;
    867 	uint32_t buf[3], nexpr;
    868 	int items;
    869 
    870 	for (c = node; c; c = c->next) {
    871 		nexpr = 0;
    872 		for (e = c->expr; e; e = e->next) {
    873 			nexpr++;
    874 		}
    875 		buf[0] = cpu_to_le32(c->permissions);
    876 		buf[1] = cpu_to_le32(nexpr);
    877 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
    878 		if (items != 2)
    879 			return POLICYDB_ERROR;
    880 		for (e = c->expr; e; e = e->next) {
    881 			items = 0;
    882 			buf[0] = cpu_to_le32(e->expr_type);
    883 			buf[1] = cpu_to_le32(e->attr);
    884 			buf[2] = cpu_to_le32(e->op);
    885 			items = put_entry(buf, sizeof(uint32_t), 3, fp);
    886 			if (items != 3)
    887 				return POLICYDB_ERROR;
    888 
    889 			switch (e->expr_type) {
    890 			case CEXPR_NAMES:
    891 				if (!allowxtarget && (e->attr & CEXPR_XTARGET))
    892 					return POLICYDB_ERROR;
    893 				if (ebitmap_write(&e->names, fp)) {
    894 					return POLICYDB_ERROR;
    895 				}
    896 				if ((p->policy_type != POLICY_KERN &&
    897 						type_set_write(e->type_names, fp)) ||
    898 						(p->policy_type == POLICY_KERN &&
    899 						(p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) &&
    900 						type_set_write(e->type_names, fp))) {
    901 					return POLICYDB_ERROR;
    902 				}
    903 				break;
    904 			default:
    905 				break;
    906 			}
    907 		}
    908 	}
    909 
    910 	return POLICYDB_SUCCESS;
    911 }
    912 
    913 static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
    914 {
    915 	class_datum_t *cladatum;
    916 	constraint_node_t *c;
    917 	uint32_t buf[32], ncons;
    918 	size_t items, items2, len, len2;
    919 	struct policy_data *pd = ptr;
    920 	struct policy_file *fp = pd->fp;
    921 	struct policydb *p = pd->p;
    922 
    923 	cladatum = (class_datum_t *) datum;
    924 
    925 	len = strlen(key);
    926 	if (cladatum->comkey)
    927 		len2 = strlen(cladatum->comkey);
    928 	else
    929 		len2 = 0;
    930 
    931 	ncons = 0;
    932 	for (c = cladatum->constraints; c; c = c->next) {
    933 		ncons++;
    934 	}
    935 
    936 	items = 0;
    937 	buf[items++] = cpu_to_le32(len);
    938 	buf[items++] = cpu_to_le32(len2);
    939 	buf[items++] = cpu_to_le32(cladatum->s.value);
    940 	buf[items++] = cpu_to_le32(cladatum->permissions.nprim);
    941 	if (cladatum->permissions.table)
    942 		buf[items++] = cpu_to_le32(cladatum->permissions.table->nel);
    943 	else
    944 		buf[items++] = 0;
    945 	buf[items++] = cpu_to_le32(ncons);
    946 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    947 	if (items != items2)
    948 		return POLICYDB_ERROR;
    949 
    950 	items = put_entry(key, 1, len, fp);
    951 	if (items != len)
    952 		return POLICYDB_ERROR;
    953 
    954 	if (cladatum->comkey) {
    955 		items = put_entry(cladatum->comkey, 1, len2, fp);
    956 		if (items != len2)
    957 			return POLICYDB_ERROR;
    958 	}
    959 	if (hashtab_map(cladatum->permissions.table, perm_write, pd))
    960 		return POLICYDB_ERROR;
    961 
    962 	if (write_cons_helper(p, cladatum->constraints, 0, fp))
    963 		return POLICYDB_ERROR;
    964 
    965 	if ((p->policy_type == POLICY_KERN
    966 	     && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS)
    967 	    || (p->policy_type == POLICY_BASE
    968 		&& p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) {
    969 		/* write out the validatetrans rule */
    970 		ncons = 0;
    971 		for (c = cladatum->validatetrans; c; c = c->next) {
    972 			ncons++;
    973 		}
    974 		buf[0] = cpu_to_le32(ncons);
    975 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
    976 		if (items != 1)
    977 			return POLICYDB_ERROR;
    978 		if (write_cons_helper(p, cladatum->validatetrans, 1, fp))
    979 			return POLICYDB_ERROR;
    980 	}
    981 
    982 	if ((p->policy_type == POLICY_KERN &&
    983 	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
    984 	    (p->policy_type == POLICY_BASE &&
    985 	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
    986 		buf[0] = cpu_to_le32(cladatum->default_user);
    987 		buf[1] = cpu_to_le32(cladatum->default_role);
    988 		buf[2] = cpu_to_le32(cladatum->default_range);
    989 		items = put_entry(buf, sizeof(uint32_t), 3, fp);
    990 		if (items != 3)
    991 			return POLICYDB_ERROR;
    992 	}
    993 
    994 	if ((p->policy_type == POLICY_KERN &&
    995 	     p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) ||
    996 	    (p->policy_type == POLICY_BASE &&
    997 	     p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) {
    998 		buf[0] = cpu_to_le32(cladatum->default_type);
    999 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1000 		if (items != 1)
   1001 			return POLICYDB_ERROR;
   1002 	}
   1003 
   1004 	return POLICYDB_SUCCESS;
   1005 }
   1006 
   1007 static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
   1008 {
   1009 	role_datum_t *role;
   1010 	uint32_t buf[32];
   1011 	size_t items, items2, len;
   1012 	struct policy_data *pd = ptr;
   1013 	struct policy_file *fp = pd->fp;
   1014 	struct policydb *p = pd->p;
   1015 
   1016 	role = (role_datum_t *) datum;
   1017 
   1018 	/*
   1019 	 * Role attributes are redundant for policy.X, skip them
   1020 	 * when writing the roles symbol table. They are also skipped
   1021 	 * when pp is downgraded.
   1022 	 *
   1023 	 * Their numbers would be deducted in policydb_write().
   1024 	 */
   1025 	if ((role->flavor == ROLE_ATTRIB) &&
   1026 	    ((p->policy_type == POLICY_KERN) ||
   1027 	     (p->policy_type != POLICY_KERN &&
   1028 	      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
   1029 		return POLICYDB_SUCCESS;
   1030 
   1031 	len = strlen(key);
   1032 	items = 0;
   1033 	buf[items++] = cpu_to_le32(len);
   1034 	buf[items++] = cpu_to_le32(role->s.value);
   1035 	if (policydb_has_boundary_feature(p))
   1036 		buf[items++] = cpu_to_le32(role->bounds);
   1037 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1038 	if (items != items2)
   1039 		return POLICYDB_ERROR;
   1040 
   1041 	items = put_entry(key, 1, len, fp);
   1042 	if (items != len)
   1043 		return POLICYDB_ERROR;
   1044 
   1045 	if (ebitmap_write(&role->dominates, fp))
   1046 		return POLICYDB_ERROR;
   1047 	if (p->policy_type == POLICY_KERN) {
   1048 		if (ebitmap_write(&role->types.types, fp))
   1049 			return POLICYDB_ERROR;
   1050 	} else {
   1051 		if (type_set_write(&role->types, fp))
   1052 			return POLICYDB_ERROR;
   1053 	}
   1054 
   1055 	if (p->policy_type != POLICY_KERN &&
   1056 	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
   1057 		buf[0] = cpu_to_le32(role->flavor);
   1058 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1059 		if (items != 1)
   1060 			return POLICYDB_ERROR;
   1061 
   1062 		if (ebitmap_write(&role->roles, fp))
   1063 			return POLICYDB_ERROR;
   1064 	}
   1065 
   1066 	return POLICYDB_SUCCESS;
   1067 }
   1068 
   1069 static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
   1070 {
   1071 	type_datum_t *typdatum;
   1072 	uint32_t buf[32];
   1073 	size_t items, items2, len;
   1074 	struct policy_data *pd = ptr;
   1075 	struct policy_file *fp = pd->fp;
   1076 	struct policydb *p = pd->p;
   1077 
   1078 	typdatum = (type_datum_t *) datum;
   1079 
   1080 	/*
   1081 	 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY)
   1082 	 * does not support to load entries of attribute, so we skip to write it.
   1083 	 */
   1084 	if (p->policy_type == POLICY_KERN
   1085 	    && p->policyvers < POLICYDB_VERSION_BOUNDARY
   1086 	    && typdatum->flavor == TYPE_ATTRIB)
   1087 		return POLICYDB_SUCCESS;
   1088 
   1089 	len = strlen(key);
   1090 	items = 0;
   1091 	buf[items++] = cpu_to_le32(len);
   1092 	buf[items++] = cpu_to_le32(typdatum->s.value);
   1093 	if (policydb_has_boundary_feature(p)) {
   1094 		uint32_t properties = 0;
   1095 
   1096 		if (p->policy_type != POLICY_KERN
   1097 		    && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
   1098 			buf[items++] = cpu_to_le32(typdatum->primary);
   1099 		}
   1100 
   1101 		if (typdatum->primary)
   1102 			properties |= TYPEDATUM_PROPERTY_PRIMARY;
   1103 
   1104 		if (typdatum->flavor == TYPE_ATTRIB) {
   1105 			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
   1106 		} else if (typdatum->flavor == TYPE_ALIAS
   1107 			   && p->policy_type != POLICY_KERN)
   1108 			properties |= TYPEDATUM_PROPERTY_ALIAS;
   1109 
   1110 		if (typdatum->flags & TYPE_FLAGS_PERMISSIVE
   1111 		    && p->policy_type != POLICY_KERN)
   1112 			properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
   1113 
   1114 		buf[items++] = cpu_to_le32(properties);
   1115 		buf[items++] = cpu_to_le32(typdatum->bounds);
   1116 	} else {
   1117 		buf[items++] = cpu_to_le32(typdatum->primary);
   1118 
   1119 		if (p->policy_type != POLICY_KERN) {
   1120 			buf[items++] = cpu_to_le32(typdatum->flavor);
   1121 
   1122 			if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
   1123 				buf[items++] = cpu_to_le32(typdatum->flags);
   1124 			else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE)
   1125 				WARN(fp->handle, "Warning! Module policy "
   1126 				     "version %d cannot support permissive "
   1127 				     "types, but one was defined",
   1128 				     p->policyvers);
   1129 		}
   1130 	}
   1131 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1132 	if (items != items2)
   1133 		return POLICYDB_ERROR;
   1134 
   1135 	if (p->policy_type != POLICY_KERN) {
   1136 		if (ebitmap_write(&typdatum->types, fp))
   1137 			return POLICYDB_ERROR;
   1138 	}
   1139 
   1140 	items = put_entry(key, 1, len, fp);
   1141 	if (items != len)
   1142 		return POLICYDB_ERROR;
   1143 
   1144 	return POLICYDB_SUCCESS;
   1145 }
   1146 
   1147 static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
   1148 {
   1149 	user_datum_t *usrdatum;
   1150 	uint32_t buf[32];
   1151 	size_t items, items2, len;
   1152 	struct policy_data *pd = ptr;
   1153 	struct policy_file *fp = pd->fp;
   1154 	struct policydb *p = pd->p;
   1155 
   1156 	usrdatum = (user_datum_t *) datum;
   1157 
   1158 	len = strlen(key);
   1159 	items = 0;
   1160 	buf[items++] = cpu_to_le32(len);
   1161 	buf[items++] = cpu_to_le32(usrdatum->s.value);
   1162 	if (policydb_has_boundary_feature(p))
   1163 		buf[items++] = cpu_to_le32(usrdatum->bounds);
   1164 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1165 	if (items != items2)
   1166 		return POLICYDB_ERROR;
   1167 
   1168 	items = put_entry(key, 1, len, fp);
   1169 	if (items != len)
   1170 		return POLICYDB_ERROR;
   1171 
   1172 	if (p->policy_type == POLICY_KERN) {
   1173 		if (ebitmap_write(&usrdatum->roles.roles, fp))
   1174 			return POLICYDB_ERROR;
   1175 	} else {
   1176 		if (role_set_write(&usrdatum->roles, fp))
   1177 			return POLICYDB_ERROR;
   1178 	}
   1179 
   1180 	if ((p->policyvers >= POLICYDB_VERSION_MLS
   1181 	     && p->policy_type == POLICY_KERN)
   1182 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
   1183 		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
   1184 		&& p->policy_type == POLICY_MOD)
   1185 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
   1186 		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
   1187 		&& p->policy_type == POLICY_BASE)) {
   1188 		if (mls_write_range_helper(&usrdatum->exp_range, fp))
   1189 			return POLICYDB_ERROR;
   1190 		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
   1191 			return POLICYDB_ERROR;
   1192 	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
   1193 		    && p->policy_type == POLICY_MOD)
   1194 		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
   1195 		       && p->policy_type == POLICY_BASE)) {
   1196 		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
   1197 			return -1;
   1198 		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
   1199 			return -1;
   1200 	}
   1201 
   1202 	return POLICYDB_SUCCESS;
   1203 }
   1204 
   1205 static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
   1206 				void *datap) = {
   1207 common_write, class_write, role_write, type_write, user_write,
   1208 	    cond_write_bool, sens_write, cat_write,};
   1209 
   1210 static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
   1211 			  struct policy_file *fp)
   1212 {
   1213 	unsigned int i, j;
   1214 	size_t nel, items;
   1215 	uint32_t buf[32];
   1216 	ocontext_t *c;
   1217 	for (i = 0; i < info->ocon_num; i++) {
   1218 		nel = 0;
   1219 		for (c = p->ocontexts[i]; c; c = c->next)
   1220 			nel++;
   1221 		buf[0] = cpu_to_le32(nel);
   1222 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1223 		if (items != 1)
   1224 			return POLICYDB_ERROR;
   1225 		for (c = p->ocontexts[i]; c; c = c->next) {
   1226 			switch (i) {
   1227 			case OCON_XEN_ISID:
   1228 				buf[0] = cpu_to_le32(c->sid[0]);
   1229 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1230 				if (items != 1)
   1231 					return POLICYDB_ERROR;
   1232 				if (context_write(p, &c->context[0], fp))
   1233 					return POLICYDB_ERROR;
   1234 				break;
   1235 			case OCON_XEN_PIRQ:
   1236 				buf[0] = cpu_to_le32(c->u.pirq);
   1237 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1238 				if (items != 1)
   1239 					return POLICYDB_ERROR;
   1240 				if (context_write(p, &c->context[0], fp))
   1241 					return POLICYDB_ERROR;
   1242 				break;
   1243 			case OCON_XEN_IOPORT:
   1244 				buf[0] = c->u.ioport.low_ioport;
   1245 				buf[1] = c->u.ioport.high_ioport;
   1246 				for (j = 0; j < 2; j++)
   1247 					buf[j] = cpu_to_le32(buf[j]);
   1248 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1249 				if (items != 2)
   1250 					return POLICYDB_ERROR;
   1251 				if (context_write(p, &c->context[0], fp))
   1252 					return POLICYDB_ERROR;
   1253 				break;
   1254 			case OCON_XEN_IOMEM:
   1255 				buf[0] = c->u.iomem.low_iomem;
   1256 				buf[1] = c->u.iomem.high_iomem;
   1257 				for (j = 0; j < 2; j++)
   1258 					buf[j] = cpu_to_le32(buf[j]);
   1259 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1260 				if (items != 2)
   1261 					return POLICYDB_ERROR;
   1262 				if (context_write(p, &c->context[0], fp))
   1263 					return POLICYDB_ERROR;
   1264 				break;
   1265 			case OCON_XEN_PCIDEVICE:
   1266 				buf[0] = cpu_to_le32(c->u.device);
   1267 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1268 				if (items != 1)
   1269 					return POLICYDB_ERROR;
   1270 				if (context_write(p, &c->context[0], fp))
   1271 					return POLICYDB_ERROR;
   1272 				break;
   1273 			}
   1274 		}
   1275 	}
   1276 	return POLICYDB_SUCCESS;
   1277 }
   1278 
   1279 static int ocontext_write_selinux(struct policydb_compat_info *info,
   1280 	policydb_t *p, struct policy_file *fp)
   1281 {
   1282 	unsigned int i, j;
   1283 	size_t nel, items, len;
   1284 	uint32_t buf[32];
   1285 	ocontext_t *c;
   1286 	for (i = 0; i < info->ocon_num; i++) {
   1287 		nel = 0;
   1288 		for (c = p->ocontexts[i]; c; c = c->next)
   1289 			nel++;
   1290 		buf[0] = cpu_to_le32(nel);
   1291 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1292 		if (items != 1)
   1293 			return POLICYDB_ERROR;
   1294 		for (c = p->ocontexts[i]; c; c = c->next) {
   1295 			switch (i) {
   1296 			case OCON_ISID:
   1297 				buf[0] = cpu_to_le32(c->sid[0]);
   1298 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1299 				if (items != 1)
   1300 					return POLICYDB_ERROR;
   1301 				if (context_write(p, &c->context[0], fp))
   1302 					return POLICYDB_ERROR;
   1303 				break;
   1304 			case OCON_FS:
   1305 			case OCON_NETIF:
   1306 				len = strlen(c->u.name);
   1307 				buf[0] = cpu_to_le32(len);
   1308 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1309 				if (items != 1)
   1310 					return POLICYDB_ERROR;
   1311 				items = put_entry(c->u.name, 1, len, fp);
   1312 				if (items != len)
   1313 					return POLICYDB_ERROR;
   1314 				if (context_write(p, &c->context[0], fp))
   1315 					return POLICYDB_ERROR;
   1316 				if (context_write(p, &c->context[1], fp))
   1317 					return POLICYDB_ERROR;
   1318 				break;
   1319 			case OCON_PORT:
   1320 				buf[0] = c->u.port.protocol;
   1321 				buf[1] = c->u.port.low_port;
   1322 				buf[2] = c->u.port.high_port;
   1323 				for (j = 0; j < 3; j++) {
   1324 					buf[j] = cpu_to_le32(buf[j]);
   1325 				}
   1326 				items = put_entry(buf, sizeof(uint32_t), 3, fp);
   1327 				if (items != 3)
   1328 					return POLICYDB_ERROR;
   1329 				if (context_write(p, &c->context[0], fp))
   1330 					return POLICYDB_ERROR;
   1331 				break;
   1332 			case OCON_NODE:
   1333 				buf[0] = c->u.node.addr; /* network order */
   1334 				buf[1] = c->u.node.mask; /* network order */
   1335 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1336 				if (items != 2)
   1337 					return POLICYDB_ERROR;
   1338 				if (context_write(p, &c->context[0], fp))
   1339 					return POLICYDB_ERROR;
   1340 				break;
   1341 			case OCON_FSUSE:
   1342 				buf[0] = cpu_to_le32(c->v.behavior);
   1343 				len = strlen(c->u.name);
   1344 				buf[1] = cpu_to_le32(len);
   1345 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1346 				if (items != 2)
   1347 					return POLICYDB_ERROR;
   1348 				items = put_entry(c->u.name, 1, len, fp);
   1349 				if (items != len)
   1350 					return POLICYDB_ERROR;
   1351 				if (context_write(p, &c->context[0], fp))
   1352 					return POLICYDB_ERROR;
   1353 				break;
   1354 			case OCON_NODE6:
   1355 				for (j = 0; j < 4; j++)
   1356 					buf[j] = c->u.node6.addr[j]; /* network order */
   1357 				for (j = 0; j < 4; j++)
   1358 					buf[j + 4] = c->u.node6.mask[j]; /* network order */
   1359 				items = put_entry(buf, sizeof(uint32_t), 8, fp);
   1360 				if (items != 8)
   1361 					return POLICYDB_ERROR;
   1362 				if (context_write(p, &c->context[0], fp))
   1363 					return POLICYDB_ERROR;
   1364 				break;
   1365 			}
   1366 		}
   1367 	}
   1368 	return POLICYDB_SUCCESS;
   1369 }
   1370 
   1371 static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
   1372 	struct policy_file *fp)
   1373 {
   1374 	int rc = POLICYDB_ERROR;
   1375 	switch (p->target_platform) {
   1376 	case SEPOL_TARGET_SELINUX:
   1377 		rc = ocontext_write_selinux(info, p, fp);
   1378 		break;
   1379 	case SEPOL_TARGET_XEN:
   1380 		rc = ocontext_write_xen(info, p, fp);
   1381 		break;
   1382 	}
   1383 	return rc;
   1384 }
   1385 
   1386 static int genfs_write(policydb_t * p, struct policy_file *fp)
   1387 {
   1388 	genfs_t *genfs;
   1389 	ocontext_t *c;
   1390 	size_t nel = 0, items, len;
   1391 	uint32_t buf[32];
   1392 
   1393 	for (genfs = p->genfs; genfs; genfs = genfs->next)
   1394 		nel++;
   1395 	buf[0] = cpu_to_le32(nel);
   1396 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1397 	if (items != 1)
   1398 		return POLICYDB_ERROR;
   1399 	for (genfs = p->genfs; genfs; genfs = genfs->next) {
   1400 		len = strlen(genfs->fstype);
   1401 		buf[0] = cpu_to_le32(len);
   1402 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1403 		if (items != 1)
   1404 			return POLICYDB_ERROR;
   1405 		items = put_entry(genfs->fstype, 1, len, fp);
   1406 		if (items != len)
   1407 			return POLICYDB_ERROR;
   1408 		nel = 0;
   1409 		for (c = genfs->head; c; c = c->next)
   1410 			nel++;
   1411 		buf[0] = cpu_to_le32(nel);
   1412 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1413 		if (items != 1)
   1414 			return POLICYDB_ERROR;
   1415 		for (c = genfs->head; c; c = c->next) {
   1416 			len = strlen(c->u.name);
   1417 			buf[0] = cpu_to_le32(len);
   1418 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1419 			if (items != 1)
   1420 				return POLICYDB_ERROR;
   1421 			items = put_entry(c->u.name, 1, len, fp);
   1422 			if (items != len)
   1423 				return POLICYDB_ERROR;
   1424 			buf[0] = cpu_to_le32(c->v.sclass);
   1425 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1426 			if (items != 1)
   1427 				return POLICYDB_ERROR;
   1428 			if (context_write(p, &c->context[0], fp))
   1429 				return POLICYDB_ERROR;
   1430 		}
   1431 	}
   1432 	return POLICYDB_SUCCESS;
   1433 }
   1434 
   1435 static int range_write(policydb_t * p, struct policy_file *fp)
   1436 {
   1437 	size_t nel, items;
   1438 	struct range_trans *rt;
   1439 	uint32_t buf[2];
   1440 	int new_rangetr = (p->policy_type == POLICY_KERN &&
   1441 			   p->policyvers >= POLICYDB_VERSION_RANGETRANS);
   1442 	int warning_issued = 0;
   1443 
   1444 	nel = 0;
   1445 	for (rt = p->range_tr; rt; rt = rt->next) {
   1446 		/* all range_transitions are written for the new format, only
   1447 		   process related range_transitions are written for the old
   1448 		   format, so count accordingly */
   1449 		if (new_rangetr || rt->target_class == SECCLASS_PROCESS)
   1450 			nel++;
   1451 	}
   1452 	buf[0] = cpu_to_le32(nel);
   1453 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1454 	if (items != 1)
   1455 		return POLICYDB_ERROR;
   1456 	for (rt = p->range_tr; rt; rt = rt->next) {
   1457 		if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
   1458 			if (!warning_issued)
   1459 				WARN(fp->handle, "Discarding range_transition "
   1460 				     "rules for security classes other than "
   1461 				     "\"process\"");
   1462 			warning_issued = 1;
   1463 			continue;
   1464 		}
   1465 		buf[0] = cpu_to_le32(rt->source_type);
   1466 		buf[1] = cpu_to_le32(rt->target_type);
   1467 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1468 		if (items != 2)
   1469 			return POLICYDB_ERROR;
   1470 		if (new_rangetr) {
   1471 			buf[0] = cpu_to_le32(rt->target_class);
   1472 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1473 			if (items != 1)
   1474 				return POLICYDB_ERROR;
   1475 		}
   1476 		if (mls_write_range_helper(&rt->target_range, fp))
   1477 			return POLICYDB_ERROR;
   1478 	}
   1479 	return POLICYDB_SUCCESS;
   1480 }
   1481 
   1482 /************** module writing functions below **************/
   1483 
   1484 static int avrule_write(avrule_t * avrule, struct policy_file *fp)
   1485 {
   1486 	size_t items, items2;
   1487 	uint32_t buf[32], len;
   1488 	class_perm_node_t *cur;
   1489 
   1490 	items = 0;
   1491 	buf[items++] = cpu_to_le32(avrule->specified);
   1492 	buf[items++] = cpu_to_le32(avrule->flags);
   1493 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1494 	if (items2 != items)
   1495 		return POLICYDB_ERROR;
   1496 
   1497 	if (type_set_write(&avrule->stypes, fp))
   1498 		return POLICYDB_ERROR;
   1499 
   1500 	if (type_set_write(&avrule->ttypes, fp))
   1501 		return POLICYDB_ERROR;
   1502 
   1503 	cur = avrule->perms;
   1504 	len = 0;
   1505 	while (cur) {
   1506 		len++;
   1507 		cur = cur->next;
   1508 	}
   1509 	items = 0;
   1510 	buf[items++] = cpu_to_le32(len);
   1511 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1512 	if (items2 != items)
   1513 		return POLICYDB_ERROR;
   1514 	cur = avrule->perms;
   1515 	while (cur) {
   1516 		items = 0;
   1517 		buf[items++] = cpu_to_le32(cur->class);
   1518 		buf[items++] = cpu_to_le32(cur->data);
   1519 		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1520 		if (items2 != items)
   1521 			return POLICYDB_ERROR;
   1522 
   1523 		cur = cur->next;
   1524 	}
   1525 
   1526 	return POLICYDB_SUCCESS;
   1527 }
   1528 
   1529 static int avrule_write_list(avrule_t * avrules, struct policy_file *fp)
   1530 {
   1531 	uint32_t buf[32], len;
   1532 	avrule_t *avrule;
   1533 
   1534 	avrule = avrules;
   1535 	len = 0;
   1536 	while (avrule) {
   1537 		len++;
   1538 		avrule = avrule->next;
   1539 	}
   1540 
   1541 	buf[0] = cpu_to_le32(len);
   1542 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
   1543 		return POLICYDB_ERROR;
   1544 
   1545 	avrule = avrules;
   1546 	while (avrule) {
   1547 		avrule_write(avrule, fp);
   1548 		avrule = avrule->next;
   1549 	}
   1550 
   1551 	return POLICYDB_SUCCESS;
   1552 }
   1553 
   1554 static int only_process(ebitmap_t *in)
   1555 {
   1556 	unsigned int i;
   1557 	ebitmap_node_t *node;
   1558 
   1559 	ebitmap_for_each_bit(in, node, i) {
   1560 		if (ebitmap_node_get_bit(node, i) &&
   1561 		    i != SECCLASS_PROCESS - 1)
   1562 			return 0;
   1563 	}
   1564 	return 1;
   1565 }
   1566 
   1567 static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
   1568 				 struct policy_file *fp)
   1569 {
   1570 	int nel = 0;
   1571 	size_t items;
   1572 	uint32_t buf[1];
   1573 	role_trans_rule_t *tr;
   1574 	int warned = 0;
   1575 	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
   1576 
   1577 	for (tr = t; tr; tr = tr->next)
   1578 		if (new_role || only_process(&tr->classes))
   1579 			nel++;
   1580 
   1581 	buf[0] = cpu_to_le32(nel);
   1582 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1583 	if (items != 1)
   1584 		return POLICYDB_ERROR;
   1585 	for (tr = t; tr; tr = tr->next) {
   1586 		if (!new_role && !only_process(&tr->classes)) {
   1587 			if (!warned)
   1588 				WARN(fp->handle, "Discarding role_transition "
   1589 					"rules for security classes other than "
   1590 					"\"process\"");
   1591 			warned = 1;
   1592 			continue;
   1593 		}
   1594 		if (role_set_write(&tr->roles, fp))
   1595 			return POLICYDB_ERROR;
   1596 		if (type_set_write(&tr->types, fp))
   1597 			return POLICYDB_ERROR;
   1598 		if (new_role)
   1599 			if (ebitmap_write(&tr->classes, fp))
   1600 				return POLICYDB_ERROR;
   1601 		buf[0] = cpu_to_le32(tr->new_role);
   1602 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1603 		if (items != 1)
   1604 			return POLICYDB_ERROR;
   1605 	}
   1606 	return POLICYDB_SUCCESS;
   1607 }
   1608 
   1609 static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
   1610 {
   1611 	int nel = 0;
   1612 	size_t items;
   1613 	uint32_t buf[1];
   1614 	role_allow_rule_t *ra;
   1615 
   1616 	for (ra = r; ra; ra = ra->next)
   1617 		nel++;
   1618 	buf[0] = cpu_to_le32(nel);
   1619 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1620 	if (items != 1)
   1621 		return POLICYDB_ERROR;
   1622 	for (ra = r; ra; ra = ra->next) {
   1623 		if (role_set_write(&ra->roles, fp))
   1624 			return POLICYDB_ERROR;
   1625 		if (role_set_write(&ra->new_roles, fp))
   1626 			return POLICYDB_ERROR;
   1627 	}
   1628 	return POLICYDB_SUCCESS;
   1629 }
   1630 
   1631 static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp)
   1632 {
   1633 	int nel = 0;
   1634 	size_t items;
   1635 	uint32_t buf[2], len;
   1636 	filename_trans_rule_t *ftr;
   1637 
   1638 	for (ftr = t; ftr; ftr = ftr->next)
   1639 		nel++;
   1640 
   1641 	buf[0] = cpu_to_le32(nel);
   1642 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1643 	if (items != 1)
   1644 		return POLICYDB_ERROR;
   1645 
   1646 	for (ftr = t; ftr; ftr = ftr->next) {
   1647 		len = strlen(ftr->name);
   1648 		buf[0] = cpu_to_le32(len);
   1649 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1650 		if (items != 1)
   1651 			return POLICYDB_ERROR;
   1652 
   1653 		items = put_entry(ftr->name, sizeof(char), len, fp);
   1654 		if (items != len)
   1655 			return POLICYDB_ERROR;
   1656 
   1657 		if (type_set_write(&ftr->stypes, fp))
   1658 			return POLICYDB_ERROR;
   1659 		if (type_set_write(&ftr->ttypes, fp))
   1660 			return POLICYDB_ERROR;
   1661 
   1662 		buf[0] = cpu_to_le32(ftr->tclass);
   1663 		buf[1] = cpu_to_le32(ftr->otype);
   1664 
   1665 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1666 		if (items != 2)
   1667 			return POLICYDB_ERROR;
   1668 	}
   1669 	return POLICYDB_SUCCESS;
   1670 }
   1671 
   1672 static int range_trans_rule_write(range_trans_rule_t * t,
   1673 				  struct policy_file *fp)
   1674 {
   1675 	int nel = 0;
   1676 	size_t items;
   1677 	uint32_t buf[1];
   1678 	range_trans_rule_t *rt;
   1679 
   1680 	for (rt = t; rt; rt = rt->next)
   1681 		nel++;
   1682 	buf[0] = cpu_to_le32(nel);
   1683 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1684 	if (items != 1)
   1685 		return POLICYDB_ERROR;
   1686 	for (rt = t; rt; rt = rt->next) {
   1687 		if (type_set_write(&rt->stypes, fp))
   1688 			return POLICYDB_ERROR;
   1689 		if (type_set_write(&rt->ttypes, fp))
   1690 			return POLICYDB_ERROR;
   1691 		if (ebitmap_write(&rt->tclasses, fp))
   1692 			return POLICYDB_ERROR;
   1693 		if (mls_write_semantic_range_helper(&rt->trange, fp))
   1694 			return POLICYDB_ERROR;
   1695 	}
   1696 	return POLICYDB_SUCCESS;
   1697 }
   1698 
   1699 static int scope_index_write(scope_index_t * scope_index,
   1700 			     unsigned int num_scope_syms,
   1701 			     struct policy_file *fp)
   1702 {
   1703 	unsigned int i;
   1704 	uint32_t buf[1];
   1705 	for (i = 0; i < num_scope_syms; i++) {
   1706 		if (ebitmap_write(scope_index->scope + i, fp) == -1) {
   1707 			return POLICYDB_ERROR;
   1708 		}
   1709 	}
   1710 	buf[0] = cpu_to_le32(scope_index->class_perms_len);
   1711 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
   1712 		return POLICYDB_ERROR;
   1713 	}
   1714 	for (i = 0; i < scope_index->class_perms_len; i++) {
   1715 		if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
   1716 			return POLICYDB_ERROR;
   1717 		}
   1718 	}
   1719 	return POLICYDB_SUCCESS;
   1720 }
   1721 
   1722 static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
   1723 			     policydb_t * p, struct policy_file *fp)
   1724 {
   1725 	struct policy_data pd;
   1726 	uint32_t buf[2];
   1727 	int i;
   1728 	buf[0] = cpu_to_le32(decl->decl_id);
   1729 	buf[1] = cpu_to_le32(decl->enabled);
   1730 	if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
   1731 		return POLICYDB_ERROR;
   1732 	}
   1733 	if (cond_write_list(p, decl->cond_list, fp) == -1 ||
   1734 	    avrule_write_list(decl->avrules, fp) == -1 ||
   1735 	    role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
   1736 	    role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
   1737 		return POLICYDB_ERROR;
   1738 	}
   1739 
   1740 	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
   1741 	    filename_trans_rule_write(decl->filename_trans_rules, fp))
   1742 		return POLICYDB_ERROR;
   1743 
   1744 	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
   1745 	    range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
   1746 		return POLICYDB_ERROR;
   1747 	}
   1748 	if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
   1749 	    scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
   1750 		return POLICYDB_ERROR;
   1751 	}
   1752 	pd.fp = fp;
   1753 	pd.p = p;
   1754 	for (i = 0; i < num_scope_syms; i++) {
   1755 		buf[0] = cpu_to_le32(decl->symtab[i].nprim);
   1756 		buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
   1757 		if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
   1758 			return POLICYDB_ERROR;
   1759 		}
   1760 		if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
   1761 			return POLICYDB_ERROR;
   1762 		}
   1763 	}
   1764 	return POLICYDB_SUCCESS;
   1765 }
   1766 
   1767 static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
   1768 			      policydb_t * p, struct policy_file *fp)
   1769 {
   1770 	/* first write a count of the total number of blocks */
   1771 	uint32_t buf[1], num_blocks = 0;
   1772 	avrule_block_t *cur;
   1773 	for (cur = block; cur != NULL; cur = cur->next) {
   1774 		num_blocks++;
   1775 	}
   1776 	buf[0] = cpu_to_le32(num_blocks);
   1777 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
   1778 		return POLICYDB_ERROR;
   1779 	}
   1780 
   1781 	/* now write each block */
   1782 	for (cur = block; cur != NULL; cur = cur->next) {
   1783 		uint32_t num_decls = 0;
   1784 		avrule_decl_t *decl;
   1785 		/* write a count of number of branches */
   1786 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
   1787 			num_decls++;
   1788 		}
   1789 		buf[0] = cpu_to_le32(num_decls);
   1790 		if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
   1791 			return POLICYDB_ERROR;
   1792 		}
   1793 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
   1794 			if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
   1795 			    -1) {
   1796 				return POLICYDB_ERROR;
   1797 			}
   1798 		}
   1799 	}
   1800 	return POLICYDB_SUCCESS;
   1801 }
   1802 
   1803 static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
   1804 {
   1805 	scope_datum_t *scope = (scope_datum_t *) datum;
   1806 	struct policy_data *pd = ptr;
   1807 	struct policy_file *fp = pd->fp;
   1808 	uint32_t static_buf[32], *dyn_buf = NULL, *buf;
   1809 	size_t key_len = strlen(key);
   1810 	unsigned int items = 2 + scope->decl_ids_len, i;
   1811 	int rc;
   1812 
   1813 	buf = static_buf;
   1814 	if (items >= (sizeof(static_buf) / 4)) {
   1815 		/* too many things required, so dynamically create a
   1816 		 * buffer.  this would have been easier with C99's
   1817 		 * dynamic arrays... */
   1818 		rc = POLICYDB_ERROR;
   1819 		dyn_buf = malloc(items * sizeof(*dyn_buf));
   1820 		if (!dyn_buf)
   1821 			goto err;
   1822 		buf = dyn_buf;
   1823 	}
   1824 	buf[0] = cpu_to_le32(key_len);
   1825 
   1826 	rc = POLICYDB_ERROR;
   1827 	if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
   1828 	    put_entry(key, 1, key_len, fp) != key_len)
   1829 		goto err;
   1830 	buf[0] = cpu_to_le32(scope->scope);
   1831 	buf[1] = cpu_to_le32(scope->decl_ids_len);
   1832 
   1833 	for (i = 0; i < scope->decl_ids_len; i++)
   1834 		buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
   1835 
   1836 	rc = POLICYDB_ERROR;
   1837 	if (put_entry(buf, sizeof(*buf), items, fp) != items)
   1838 		goto err;
   1839 	rc = POLICYDB_SUCCESS;
   1840 err:
   1841 	free(dyn_buf);
   1842 	return rc;
   1843 }
   1844 
   1845 static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
   1846 			     hashtab_datum_t datum, void *args)
   1847 {
   1848 	type_datum_t *typdatum = datum;
   1849 	uint32_t *p_nel = args;
   1850 
   1851 	if (typdatum->flavor == TYPE_ATTRIB) {
   1852 		/* uncount attribute from total number of types */
   1853 		(*p_nel)--;
   1854 	}
   1855 	return 0;
   1856 }
   1857 
   1858 static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
   1859 			     hashtab_datum_t datum, void *args)
   1860 {
   1861 	role_datum_t *role = datum;
   1862 	uint32_t *p_nel = args;
   1863 
   1864 	if (role->flavor == ROLE_ATTRIB) {
   1865 		/* uncount attribute from total number of roles */
   1866 		(*p_nel)--;
   1867 	}
   1868 	return 0;
   1869 }
   1870 
   1871 /*
   1872  * Write the configuration data in a policy database
   1873  * structure to a policy database binary representation
   1874  * file.
   1875  */
   1876 int policydb_write(policydb_t * p, struct policy_file *fp)
   1877 {
   1878 	unsigned int i, num_syms;
   1879 	uint32_t buf[32], config;
   1880 	size_t items, items2, len;
   1881 	struct policydb_compat_info *info;
   1882 	struct policy_data pd;
   1883 	char *policydb_str;
   1884 
   1885 	if (p->unsupported_format)
   1886 		return POLICYDB_UNSUPPORTED;
   1887 
   1888 	pd.fp = fp;
   1889 	pd.p = p;
   1890 
   1891 	config = 0;
   1892 	if (p->mls) {
   1893 		if ((p->policyvers < POLICYDB_VERSION_MLS &&
   1894 		    p->policy_type == POLICY_KERN) ||
   1895 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
   1896 		    p->policy_type == POLICY_BASE) ||
   1897 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
   1898 		    p->policy_type == POLICY_MOD)) {
   1899 			ERR(fp->handle, "policy version %d cannot support MLS",
   1900 			    p->policyvers);
   1901 			return POLICYDB_ERROR;
   1902 		}
   1903 		config |= POLICYDB_CONFIG_MLS;
   1904 	}
   1905 
   1906 	config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
   1907 
   1908 	/* Write the magic number and string identifiers. */
   1909 	items = 0;
   1910 	if (p->policy_type == POLICY_KERN) {
   1911 		buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
   1912 		len = strlen(policydb_target_strings[p->target_platform]);
   1913 		policydb_str = policydb_target_strings[p->target_platform];
   1914 	} else {
   1915 		buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
   1916 		len = strlen(POLICYDB_MOD_STRING);
   1917 		policydb_str = POLICYDB_MOD_STRING;
   1918 	}
   1919 	buf[items++] = cpu_to_le32(len);
   1920 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1921 	if (items != items2)
   1922 		return POLICYDB_ERROR;
   1923 	items = put_entry(policydb_str, 1, len, fp);
   1924 	if (items != len)
   1925 		return POLICYDB_ERROR;
   1926 
   1927 	/* Write the version, config, and table sizes. */
   1928 	items = 0;
   1929 	info = policydb_lookup_compat(p->policyvers, p->policy_type,
   1930 					p->target_platform);
   1931 	if (!info) {
   1932 		ERR(fp->handle, "compatibility lookup failed for policy "
   1933 		    "version %d", p->policyvers);
   1934 		return POLICYDB_ERROR;
   1935 	}
   1936 
   1937 	if (p->policy_type != POLICY_KERN) {
   1938 		buf[items++] = cpu_to_le32(p->policy_type);
   1939 	}
   1940 	buf[items++] = cpu_to_le32(p->policyvers);
   1941 	buf[items++] = cpu_to_le32(config);
   1942 	buf[items++] = cpu_to_le32(info->sym_num);
   1943 	buf[items++] = cpu_to_le32(info->ocon_num);
   1944 
   1945 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1946 	if (items != items2)
   1947 		return POLICYDB_ERROR;
   1948 
   1949 	if (p->policy_type == POLICY_MOD) {
   1950 		/* Write module name and version */
   1951 		len = strlen(p->name);
   1952 		buf[0] = cpu_to_le32(len);
   1953 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1954 		if (items != 1)
   1955 			return POLICYDB_ERROR;
   1956 		items = put_entry(p->name, 1, len, fp);
   1957 		if (items != len)
   1958 			return POLICYDB_ERROR;
   1959 		len = strlen(p->version);
   1960 		buf[0] = cpu_to_le32(len);
   1961 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1962 		if (items != 1)
   1963 			return POLICYDB_ERROR;
   1964 		items = put_entry(p->version, 1, len, fp);
   1965 		if (items != len)
   1966 			return POLICYDB_ERROR;
   1967 	}
   1968 
   1969 	if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
   1970 	     p->policy_type == POLICY_KERN) ||
   1971 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
   1972 	     p->policy_type == POLICY_BASE) ||
   1973 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
   1974 	     p->policy_type == POLICY_MOD)) {
   1975 		if (ebitmap_write(&p->policycaps, fp) == -1)
   1976 			return POLICYDB_ERROR;
   1977 	}
   1978 
   1979 	if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
   1980 	    p->policy_type == POLICY_KERN) {
   1981 		ebitmap_node_t *tnode;
   1982 
   1983 		ebitmap_for_each_bit(&p->permissive_map, tnode, i) {
   1984 			if (ebitmap_node_get_bit(tnode, i)) {
   1985 				WARN(fp->handle, "Warning! Policy version %d cannot "
   1986 				     "support permissive types, but some were defined",
   1987 				     p->policyvers);
   1988 				break;
   1989 			}
   1990 		}
   1991 	}
   1992 
   1993 	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
   1994 	    p->policy_type == POLICY_KERN) {
   1995 		if (ebitmap_write(&p->permissive_map, fp) == -1)
   1996 			return POLICYDB_ERROR;
   1997 	}
   1998 
   1999 	num_syms = info->sym_num;
   2000 	for (i = 0; i < num_syms; i++) {
   2001 		buf[0] = cpu_to_le32(p->symtab[i].nprim);
   2002 		buf[1] = p->symtab[i].table->nel;
   2003 
   2004 		/*
   2005 		 * A special case when writing type/attribute symbol table.
   2006 		 * The kernel policy version less than 24 does not support
   2007 		 * to load entries of attribute, so we have to re-calculate
   2008 		 * the actual number of types except for attributes.
   2009 		 */
   2010 		if (i == SYM_TYPES &&
   2011 		    p->policyvers < POLICYDB_VERSION_BOUNDARY &&
   2012 		    p->policy_type == POLICY_KERN) {
   2013 			hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
   2014 		}
   2015 
   2016 		/*
   2017 		 * Another special case when writing role/attribute symbol
   2018 		 * table, role attributes are redundant for policy.X, or
   2019 		 * when the pp's version is not big enough. So deduct
   2020 		 * their numbers from p_roles.table->nel.
   2021 		 */
   2022 		if ((i == SYM_ROLES) &&
   2023 		    ((p->policy_type == POLICY_KERN) ||
   2024 		     (p->policy_type != POLICY_KERN &&
   2025 		      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
   2026 			(void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
   2027 
   2028 		buf[1] = cpu_to_le32(buf[1]);
   2029 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
   2030 		if (items != 2)
   2031 			return POLICYDB_ERROR;
   2032 		if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
   2033 			return POLICYDB_ERROR;
   2034 	}
   2035 
   2036 	if (p->policy_type == POLICY_KERN) {
   2037 		if (avtab_write(p, &p->te_avtab, fp))
   2038 			return POLICYDB_ERROR;
   2039 		if (p->policyvers < POLICYDB_VERSION_BOOL) {
   2040 			if (p->p_bools.nprim)
   2041 				WARN(fp->handle, "Discarding "
   2042 				     "booleans and conditional rules");
   2043 		} else {
   2044 			if (cond_write_list(p, p->cond_list, fp))
   2045 				return POLICYDB_ERROR;
   2046 		}
   2047 		if (role_trans_write(p, fp))
   2048 			return POLICYDB_ERROR;
   2049 		if (role_allow_write(p->role_allow, fp))
   2050 			return POLICYDB_ERROR;
   2051 		if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
   2052 			if (filename_trans_write(p->filename_trans, fp))
   2053 				return POLICYDB_ERROR;
   2054 		} else {
   2055 			if (p->filename_trans)
   2056 				WARN(fp->handle, "Discarding filename type transition rules");
   2057 		}
   2058 	} else {
   2059 		if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
   2060 			return POLICYDB_ERROR;
   2061 		}
   2062 
   2063 		for (i = 0; i < num_syms; i++) {
   2064 			buf[0] = cpu_to_le32(p->scope[i].table->nel);
   2065 			if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
   2066 				return POLICYDB_ERROR;
   2067 			}
   2068 			if (hashtab_map(p->scope[i].table, scope_write, &pd))
   2069 				return POLICYDB_ERROR;
   2070 		}
   2071 	}
   2072 
   2073 	if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
   2074 		return POLICYDB_ERROR;
   2075 	}
   2076 
   2077 	if ((p->policyvers >= POLICYDB_VERSION_MLS
   2078 	     && p->policy_type == POLICY_KERN)
   2079 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
   2080 		&& p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
   2081 		&& p->policy_type == POLICY_BASE)) {
   2082 		if (range_write(p, fp)) {
   2083 			return POLICYDB_ERROR;
   2084 		}
   2085 	}
   2086 
   2087 	if (p->policy_type == POLICY_KERN
   2088 	    && p->policyvers >= POLICYDB_VERSION_AVTAB) {
   2089 		for (i = 0; i < p->p_types.nprim; i++) {
   2090 			if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
   2091 				return POLICYDB_ERROR;
   2092 		}
   2093 	}
   2094 
   2095 	return POLICYDB_SUCCESS;
   2096 }
   2097