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 					return POLICYDB_ERROR;
    899 				}
    900 				break;
    901 			default:
    902 				break;
    903 			}
    904 		}
    905 	}
    906 
    907 	return POLICYDB_SUCCESS;
    908 }
    909 
    910 static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
    911 {
    912 	class_datum_t *cladatum;
    913 	constraint_node_t *c;
    914 	uint32_t buf[32], ncons;
    915 	size_t items, items2, len, len2;
    916 	struct policy_data *pd = ptr;
    917 	struct policy_file *fp = pd->fp;
    918 	struct policydb *p = pd->p;
    919 
    920 	cladatum = (class_datum_t *) datum;
    921 
    922 	len = strlen(key);
    923 	if (cladatum->comkey)
    924 		len2 = strlen(cladatum->comkey);
    925 	else
    926 		len2 = 0;
    927 
    928 	ncons = 0;
    929 	for (c = cladatum->constraints; c; c = c->next) {
    930 		ncons++;
    931 	}
    932 
    933 	items = 0;
    934 	buf[items++] = cpu_to_le32(len);
    935 	buf[items++] = cpu_to_le32(len2);
    936 	buf[items++] = cpu_to_le32(cladatum->s.value);
    937 	buf[items++] = cpu_to_le32(cladatum->permissions.nprim);
    938 	if (cladatum->permissions.table)
    939 		buf[items++] = cpu_to_le32(cladatum->permissions.table->nel);
    940 	else
    941 		buf[items++] = 0;
    942 	buf[items++] = cpu_to_le32(ncons);
    943 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
    944 	if (items != items2)
    945 		return POLICYDB_ERROR;
    946 
    947 	items = put_entry(key, 1, len, fp);
    948 	if (items != len)
    949 		return POLICYDB_ERROR;
    950 
    951 	if (cladatum->comkey) {
    952 		items = put_entry(cladatum->comkey, 1, len2, fp);
    953 		if (items != len2)
    954 			return POLICYDB_ERROR;
    955 	}
    956 	if (hashtab_map(cladatum->permissions.table, perm_write, pd))
    957 		return POLICYDB_ERROR;
    958 
    959 	if (write_cons_helper(p, cladatum->constraints, 0, fp))
    960 		return POLICYDB_ERROR;
    961 
    962 	if ((p->policy_type == POLICY_KERN
    963 	     && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS)
    964 	    || (p->policy_type == POLICY_BASE
    965 		&& p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) {
    966 		/* write out the validatetrans rule */
    967 		ncons = 0;
    968 		for (c = cladatum->validatetrans; c; c = c->next) {
    969 			ncons++;
    970 		}
    971 		buf[0] = cpu_to_le32(ncons);
    972 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
    973 		if (items != 1)
    974 			return POLICYDB_ERROR;
    975 		if (write_cons_helper(p, cladatum->validatetrans, 1, fp))
    976 			return POLICYDB_ERROR;
    977 	}
    978 
    979 	if ((p->policy_type == POLICY_KERN &&
    980 	     p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
    981 	    (p->policy_type == POLICY_BASE &&
    982 	     p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
    983 		buf[0] = cpu_to_le32(cladatum->default_user);
    984 		buf[1] = cpu_to_le32(cladatum->default_role);
    985 		buf[2] = cpu_to_le32(cladatum->default_range);
    986 		items = put_entry(buf, sizeof(uint32_t), 3, fp);
    987 		if (items != 3)
    988 			return POLICYDB_ERROR;
    989 	}
    990 
    991 	return POLICYDB_SUCCESS;
    992 }
    993 
    994 static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
    995 {
    996 	role_datum_t *role;
    997 	uint32_t buf[32];
    998 	size_t items, items2, len;
    999 	struct policy_data *pd = ptr;
   1000 	struct policy_file *fp = pd->fp;
   1001 	struct policydb *p = pd->p;
   1002 
   1003 	role = (role_datum_t *) datum;
   1004 
   1005 	/*
   1006 	 * Role attributes are redundant for policy.X, skip them
   1007 	 * when writing the roles symbol table. They are also skipped
   1008 	 * when pp is downgraded.
   1009 	 *
   1010 	 * Their numbers would be deducted in policydb_write().
   1011 	 */
   1012 	if ((role->flavor == ROLE_ATTRIB) &&
   1013 	    ((p->policy_type == POLICY_KERN) ||
   1014 	     (p->policy_type != POLICY_KERN &&
   1015 	      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
   1016 		return POLICYDB_SUCCESS;
   1017 
   1018 	len = strlen(key);
   1019 	items = 0;
   1020 	buf[items++] = cpu_to_le32(len);
   1021 	buf[items++] = cpu_to_le32(role->s.value);
   1022 	if (policydb_has_boundary_feature(p))
   1023 		buf[items++] = cpu_to_le32(role->bounds);
   1024 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1025 	if (items != items2)
   1026 		return POLICYDB_ERROR;
   1027 
   1028 	items = put_entry(key, 1, len, fp);
   1029 	if (items != len)
   1030 		return POLICYDB_ERROR;
   1031 
   1032 	if (ebitmap_write(&role->dominates, fp))
   1033 		return POLICYDB_ERROR;
   1034 	if (p->policy_type == POLICY_KERN) {
   1035 		if (ebitmap_write(&role->types.types, fp))
   1036 			return POLICYDB_ERROR;
   1037 	} else {
   1038 		if (type_set_write(&role->types, fp))
   1039 			return POLICYDB_ERROR;
   1040 	}
   1041 
   1042 	if (p->policy_type != POLICY_KERN &&
   1043 	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
   1044 		buf[0] = cpu_to_le32(role->flavor);
   1045 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1046 		if (items != 1)
   1047 			return POLICYDB_ERROR;
   1048 
   1049 		if (ebitmap_write(&role->roles, fp))
   1050 			return POLICYDB_ERROR;
   1051 	}
   1052 
   1053 	return POLICYDB_SUCCESS;
   1054 }
   1055 
   1056 static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
   1057 {
   1058 	type_datum_t *typdatum;
   1059 	uint32_t buf[32];
   1060 	size_t items, items2, len;
   1061 	struct policy_data *pd = ptr;
   1062 	struct policy_file *fp = pd->fp;
   1063 	struct policydb *p = pd->p;
   1064 
   1065 	typdatum = (type_datum_t *) datum;
   1066 
   1067 	/*
   1068 	 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY)
   1069 	 * does not support to load entries of attribute, so we skip to write it.
   1070 	 */
   1071 	if (p->policy_type == POLICY_KERN
   1072 	    && p->policyvers < POLICYDB_VERSION_BOUNDARY
   1073 	    && typdatum->flavor == TYPE_ATTRIB)
   1074 		return POLICYDB_SUCCESS;
   1075 
   1076 	len = strlen(key);
   1077 	items = 0;
   1078 	buf[items++] = cpu_to_le32(len);
   1079 	buf[items++] = cpu_to_le32(typdatum->s.value);
   1080 	if (policydb_has_boundary_feature(p)) {
   1081 		uint32_t properties = 0;
   1082 
   1083 		if (p->policy_type != POLICY_KERN
   1084 		    && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
   1085 			buf[items++] = cpu_to_le32(typdatum->primary);
   1086 		}
   1087 
   1088 		if (typdatum->primary)
   1089 			properties |= TYPEDATUM_PROPERTY_PRIMARY;
   1090 
   1091 		if (typdatum->flavor == TYPE_ATTRIB) {
   1092 			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
   1093 		} else if (typdatum->flavor == TYPE_ALIAS
   1094 			   && p->policy_type != POLICY_KERN)
   1095 			properties |= TYPEDATUM_PROPERTY_ALIAS;
   1096 
   1097 		if (typdatum->flags & TYPE_FLAGS_PERMISSIVE
   1098 		    && p->policy_type != POLICY_KERN)
   1099 			properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
   1100 
   1101 		buf[items++] = cpu_to_le32(properties);
   1102 		buf[items++] = cpu_to_le32(typdatum->bounds);
   1103 	} else {
   1104 		buf[items++] = cpu_to_le32(typdatum->primary);
   1105 
   1106 		if (p->policy_type != POLICY_KERN) {
   1107 			buf[items++] = cpu_to_le32(typdatum->flavor);
   1108 
   1109 			if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
   1110 				buf[items++] = cpu_to_le32(typdatum->flags);
   1111 			else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE)
   1112 				WARN(fp->handle, "Warning! Module policy "
   1113 				     "version %d cannot support permissive "
   1114 				     "types, but one was defined",
   1115 				     p->policyvers);
   1116 		}
   1117 	}
   1118 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1119 	if (items != items2)
   1120 		return POLICYDB_ERROR;
   1121 
   1122 	if (p->policy_type != POLICY_KERN) {
   1123 		if (ebitmap_write(&typdatum->types, fp))
   1124 			return POLICYDB_ERROR;
   1125 	}
   1126 
   1127 	items = put_entry(key, 1, len, fp);
   1128 	if (items != len)
   1129 		return POLICYDB_ERROR;
   1130 
   1131 	return POLICYDB_SUCCESS;
   1132 }
   1133 
   1134 static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
   1135 {
   1136 	user_datum_t *usrdatum;
   1137 	uint32_t buf[32];
   1138 	size_t items, items2, len;
   1139 	struct policy_data *pd = ptr;
   1140 	struct policy_file *fp = pd->fp;
   1141 	struct policydb *p = pd->p;
   1142 
   1143 	usrdatum = (user_datum_t *) datum;
   1144 
   1145 	len = strlen(key);
   1146 	items = 0;
   1147 	buf[items++] = cpu_to_le32(len);
   1148 	buf[items++] = cpu_to_le32(usrdatum->s.value);
   1149 	if (policydb_has_boundary_feature(p))
   1150 		buf[items++] = cpu_to_le32(usrdatum->bounds);
   1151 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1152 	if (items != items2)
   1153 		return POLICYDB_ERROR;
   1154 
   1155 	items = put_entry(key, 1, len, fp);
   1156 	if (items != len)
   1157 		return POLICYDB_ERROR;
   1158 
   1159 	if (p->policy_type == POLICY_KERN) {
   1160 		if (ebitmap_write(&usrdatum->roles.roles, fp))
   1161 			return POLICYDB_ERROR;
   1162 	} else {
   1163 		if (role_set_write(&usrdatum->roles, fp))
   1164 			return POLICYDB_ERROR;
   1165 	}
   1166 
   1167 	if ((p->policyvers >= POLICYDB_VERSION_MLS
   1168 	     && p->policy_type == POLICY_KERN)
   1169 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
   1170 		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
   1171 		&& p->policy_type == POLICY_MOD)
   1172 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
   1173 		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
   1174 		&& p->policy_type == POLICY_BASE)) {
   1175 		if (mls_write_range_helper(&usrdatum->exp_range, fp))
   1176 			return POLICYDB_ERROR;
   1177 		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
   1178 			return POLICYDB_ERROR;
   1179 	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
   1180 		    && p->policy_type == POLICY_MOD)
   1181 		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
   1182 		       && p->policy_type == POLICY_BASE)) {
   1183 		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
   1184 			return -1;
   1185 		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
   1186 			return -1;
   1187 	}
   1188 
   1189 	return POLICYDB_SUCCESS;
   1190 }
   1191 
   1192 static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
   1193 				void *datap) = {
   1194 common_write, class_write, role_write, type_write, user_write,
   1195 	    cond_write_bool, sens_write, cat_write,};
   1196 
   1197 static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
   1198 			  struct policy_file *fp)
   1199 {
   1200 	unsigned int i, j;
   1201 	size_t nel, items;
   1202 	uint32_t buf[32];
   1203 	ocontext_t *c;
   1204 	for (i = 0; i < info->ocon_num; i++) {
   1205 		nel = 0;
   1206 		for (c = p->ocontexts[i]; c; c = c->next)
   1207 			nel++;
   1208 		buf[0] = cpu_to_le32(nel);
   1209 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1210 		if (items != 1)
   1211 			return POLICYDB_ERROR;
   1212 		for (c = p->ocontexts[i]; c; c = c->next) {
   1213 			switch (i) {
   1214 			case OCON_XEN_ISID:
   1215 				buf[0] = cpu_to_le32(c->sid[0]);
   1216 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1217 				if (items != 1)
   1218 					return POLICYDB_ERROR;
   1219 				if (context_write(p, &c->context[0], fp))
   1220 					return POLICYDB_ERROR;
   1221 				break;
   1222 			case OCON_XEN_PIRQ:
   1223 				buf[0] = cpu_to_le32(c->u.pirq);
   1224 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1225 				if (items != 1)
   1226 					return POLICYDB_ERROR;
   1227 				if (context_write(p, &c->context[0], fp))
   1228 					return POLICYDB_ERROR;
   1229 				break;
   1230 			case OCON_XEN_IOPORT:
   1231 				buf[0] = c->u.ioport.low_ioport;
   1232 				buf[1] = c->u.ioport.high_ioport;
   1233 				for (j = 0; j < 2; j++)
   1234 					buf[j] = cpu_to_le32(buf[j]);
   1235 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1236 				if (items != 2)
   1237 					return POLICYDB_ERROR;
   1238 				if (context_write(p, &c->context[0], fp))
   1239 					return POLICYDB_ERROR;
   1240 				break;
   1241 			case OCON_XEN_IOMEM:
   1242 				buf[0] = c->u.iomem.low_iomem;
   1243 				buf[1] = c->u.iomem.high_iomem;
   1244 				for (j = 0; j < 2; j++)
   1245 					buf[j] = cpu_to_le32(buf[j]);
   1246 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1247 				if (items != 2)
   1248 					return POLICYDB_ERROR;
   1249 				if (context_write(p, &c->context[0], fp))
   1250 					return POLICYDB_ERROR;
   1251 				break;
   1252 			case OCON_XEN_PCIDEVICE:
   1253 				buf[0] = cpu_to_le32(c->u.device);
   1254 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1255 				if (items != 1)
   1256 					return POLICYDB_ERROR;
   1257 				if (context_write(p, &c->context[0], fp))
   1258 					return POLICYDB_ERROR;
   1259 				break;
   1260 			}
   1261 		}
   1262 	}
   1263 	return POLICYDB_SUCCESS;
   1264 }
   1265 
   1266 static int ocontext_write_selinux(struct policydb_compat_info *info,
   1267 	policydb_t *p, struct policy_file *fp)
   1268 {
   1269 	unsigned int i, j;
   1270 	size_t nel, items, len;
   1271 	uint32_t buf[32];
   1272 	ocontext_t *c;
   1273 	for (i = 0; i < info->ocon_num; i++) {
   1274 		nel = 0;
   1275 		for (c = p->ocontexts[i]; c; c = c->next)
   1276 			nel++;
   1277 		buf[0] = cpu_to_le32(nel);
   1278 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1279 		if (items != 1)
   1280 			return POLICYDB_ERROR;
   1281 		for (c = p->ocontexts[i]; c; c = c->next) {
   1282 			switch (i) {
   1283 			case OCON_ISID:
   1284 				buf[0] = cpu_to_le32(c->sid[0]);
   1285 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1286 				if (items != 1)
   1287 					return POLICYDB_ERROR;
   1288 				if (context_write(p, &c->context[0], fp))
   1289 					return POLICYDB_ERROR;
   1290 				break;
   1291 			case OCON_FS:
   1292 			case OCON_NETIF:
   1293 				len = strlen(c->u.name);
   1294 				buf[0] = cpu_to_le32(len);
   1295 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1296 				if (items != 1)
   1297 					return POLICYDB_ERROR;
   1298 				items = put_entry(c->u.name, 1, len, fp);
   1299 				if (items != len)
   1300 					return POLICYDB_ERROR;
   1301 				if (context_write(p, &c->context[0], fp))
   1302 					return POLICYDB_ERROR;
   1303 				if (context_write(p, &c->context[1], fp))
   1304 					return POLICYDB_ERROR;
   1305 				break;
   1306 			case OCON_PORT:
   1307 				buf[0] = c->u.port.protocol;
   1308 				buf[1] = c->u.port.low_port;
   1309 				buf[2] = c->u.port.high_port;
   1310 				for (j = 0; j < 3; j++) {
   1311 					buf[j] = cpu_to_le32(buf[j]);
   1312 				}
   1313 				items = put_entry(buf, sizeof(uint32_t), 3, fp);
   1314 				if (items != 3)
   1315 					return POLICYDB_ERROR;
   1316 				if (context_write(p, &c->context[0], fp))
   1317 					return POLICYDB_ERROR;
   1318 				break;
   1319 			case OCON_NODE:
   1320 				buf[0] = c->u.node.addr; /* network order */
   1321 				buf[1] = c->u.node.mask; /* network order */
   1322 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1323 				if (items != 2)
   1324 					return POLICYDB_ERROR;
   1325 				if (context_write(p, &c->context[0], fp))
   1326 					return POLICYDB_ERROR;
   1327 				break;
   1328 			case OCON_FSUSE:
   1329 				buf[0] = cpu_to_le32(c->v.behavior);
   1330 				len = strlen(c->u.name);
   1331 				buf[1] = cpu_to_le32(len);
   1332 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1333 				if (items != 2)
   1334 					return POLICYDB_ERROR;
   1335 				items = put_entry(c->u.name, 1, len, fp);
   1336 				if (items != len)
   1337 					return POLICYDB_ERROR;
   1338 				if (context_write(p, &c->context[0], fp))
   1339 					return POLICYDB_ERROR;
   1340 				break;
   1341 			case OCON_NODE6:
   1342 				for (j = 0; j < 4; j++)
   1343 					buf[j] = c->u.node6.addr[j]; /* network order */
   1344 				for (j = 0; j < 4; j++)
   1345 					buf[j + 4] = c->u.node6.mask[j]; /* network order */
   1346 				items = put_entry(buf, sizeof(uint32_t), 8, fp);
   1347 				if (items != 8)
   1348 					return POLICYDB_ERROR;
   1349 				if (context_write(p, &c->context[0], fp))
   1350 					return POLICYDB_ERROR;
   1351 				break;
   1352 			}
   1353 		}
   1354 	}
   1355 	return POLICYDB_SUCCESS;
   1356 }
   1357 
   1358 static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
   1359 	struct policy_file *fp)
   1360 {
   1361 	int rc = POLICYDB_ERROR;
   1362 	switch (p->target_platform) {
   1363 	case SEPOL_TARGET_SELINUX:
   1364 		rc = ocontext_write_selinux(info, p, fp);
   1365 		break;
   1366 	case SEPOL_TARGET_XEN:
   1367 		rc = ocontext_write_xen(info, p, fp);
   1368 		break;
   1369 	}
   1370 	return rc;
   1371 }
   1372 
   1373 static int genfs_write(policydb_t * p, struct policy_file *fp)
   1374 {
   1375 	genfs_t *genfs;
   1376 	ocontext_t *c;
   1377 	size_t nel = 0, items, len;
   1378 	uint32_t buf[32];
   1379 
   1380 	for (genfs = p->genfs; genfs; genfs = genfs->next)
   1381 		nel++;
   1382 	buf[0] = cpu_to_le32(nel);
   1383 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1384 	if (items != 1)
   1385 		return POLICYDB_ERROR;
   1386 	for (genfs = p->genfs; genfs; genfs = genfs->next) {
   1387 		len = strlen(genfs->fstype);
   1388 		buf[0] = cpu_to_le32(len);
   1389 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1390 		if (items != 1)
   1391 			return POLICYDB_ERROR;
   1392 		items = put_entry(genfs->fstype, 1, len, fp);
   1393 		if (items != len)
   1394 			return POLICYDB_ERROR;
   1395 		nel = 0;
   1396 		for (c = genfs->head; c; c = c->next)
   1397 			nel++;
   1398 		buf[0] = cpu_to_le32(nel);
   1399 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1400 		if (items != 1)
   1401 			return POLICYDB_ERROR;
   1402 		for (c = genfs->head; c; c = c->next) {
   1403 			len = strlen(c->u.name);
   1404 			buf[0] = cpu_to_le32(len);
   1405 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1406 			if (items != 1)
   1407 				return POLICYDB_ERROR;
   1408 			items = put_entry(c->u.name, 1, len, fp);
   1409 			if (items != len)
   1410 				return POLICYDB_ERROR;
   1411 			buf[0] = cpu_to_le32(c->v.sclass);
   1412 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1413 			if (items != 1)
   1414 				return POLICYDB_ERROR;
   1415 			if (context_write(p, &c->context[0], fp))
   1416 				return POLICYDB_ERROR;
   1417 		}
   1418 	}
   1419 	return POLICYDB_SUCCESS;
   1420 }
   1421 
   1422 static int range_write(policydb_t * p, struct policy_file *fp)
   1423 {
   1424 	size_t nel, items;
   1425 	struct range_trans *rt;
   1426 	uint32_t buf[2];
   1427 	int new_rangetr = (p->policy_type == POLICY_KERN &&
   1428 			   p->policyvers >= POLICYDB_VERSION_RANGETRANS);
   1429 	int warning_issued = 0;
   1430 
   1431 	nel = 0;
   1432 	for (rt = p->range_tr; rt; rt = rt->next) {
   1433 		/* all range_transitions are written for the new format, only
   1434 		   process related range_transitions are written for the old
   1435 		   format, so count accordingly */
   1436 		if (new_rangetr || rt->target_class == SECCLASS_PROCESS)
   1437 			nel++;
   1438 	}
   1439 	buf[0] = cpu_to_le32(nel);
   1440 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1441 	if (items != 1)
   1442 		return POLICYDB_ERROR;
   1443 	for (rt = p->range_tr; rt; rt = rt->next) {
   1444 		if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
   1445 			if (!warning_issued)
   1446 				WARN(fp->handle, "Discarding range_transition "
   1447 				     "rules for security classes other than "
   1448 				     "\"process\"");
   1449 			warning_issued = 1;
   1450 			continue;
   1451 		}
   1452 		buf[0] = cpu_to_le32(rt->source_type);
   1453 		buf[1] = cpu_to_le32(rt->target_type);
   1454 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1455 		if (items != 2)
   1456 			return POLICYDB_ERROR;
   1457 		if (new_rangetr) {
   1458 			buf[0] = cpu_to_le32(rt->target_class);
   1459 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1460 			if (items != 1)
   1461 				return POLICYDB_ERROR;
   1462 		}
   1463 		if (mls_write_range_helper(&rt->target_range, fp))
   1464 			return POLICYDB_ERROR;
   1465 	}
   1466 	return POLICYDB_SUCCESS;
   1467 }
   1468 
   1469 /************** module writing functions below **************/
   1470 
   1471 static int avrule_write(avrule_t * avrule, struct policy_file *fp)
   1472 {
   1473 	size_t items, items2;
   1474 	uint32_t buf[32], len;
   1475 	class_perm_node_t *cur;
   1476 
   1477 	items = 0;
   1478 	buf[items++] = cpu_to_le32(avrule->specified);
   1479 	buf[items++] = cpu_to_le32(avrule->flags);
   1480 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1481 	if (items2 != items)
   1482 		return POLICYDB_ERROR;
   1483 
   1484 	if (type_set_write(&avrule->stypes, fp))
   1485 		return POLICYDB_ERROR;
   1486 
   1487 	if (type_set_write(&avrule->ttypes, fp))
   1488 		return POLICYDB_ERROR;
   1489 
   1490 	cur = avrule->perms;
   1491 	len = 0;
   1492 	while (cur) {
   1493 		len++;
   1494 		cur = cur->next;
   1495 	}
   1496 	items = 0;
   1497 	buf[items++] = cpu_to_le32(len);
   1498 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1499 	if (items2 != items)
   1500 		return POLICYDB_ERROR;
   1501 	cur = avrule->perms;
   1502 	while (cur) {
   1503 		items = 0;
   1504 		buf[items++] = cpu_to_le32(cur->class);
   1505 		buf[items++] = cpu_to_le32(cur->data);
   1506 		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1507 		if (items2 != items)
   1508 			return POLICYDB_ERROR;
   1509 
   1510 		cur = cur->next;
   1511 	}
   1512 
   1513 	return POLICYDB_SUCCESS;
   1514 }
   1515 
   1516 static int avrule_write_list(avrule_t * avrules, struct policy_file *fp)
   1517 {
   1518 	uint32_t buf[32], len;
   1519 	avrule_t *avrule;
   1520 
   1521 	avrule = avrules;
   1522 	len = 0;
   1523 	while (avrule) {
   1524 		len++;
   1525 		avrule = avrule->next;
   1526 	}
   1527 
   1528 	buf[0] = cpu_to_le32(len);
   1529 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
   1530 		return POLICYDB_ERROR;
   1531 
   1532 	avrule = avrules;
   1533 	while (avrule) {
   1534 		avrule_write(avrule, fp);
   1535 		avrule = avrule->next;
   1536 	}
   1537 
   1538 	return POLICYDB_SUCCESS;
   1539 }
   1540 
   1541 static int only_process(ebitmap_t *in)
   1542 {
   1543 	unsigned int i;
   1544 	ebitmap_node_t *node;
   1545 
   1546 	ebitmap_for_each_bit(in, node, i) {
   1547 		if (ebitmap_node_get_bit(node, i) &&
   1548 		    i != SECCLASS_PROCESS - 1)
   1549 			return 0;
   1550 	}
   1551 	return 1;
   1552 }
   1553 
   1554 static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
   1555 				 struct policy_file *fp)
   1556 {
   1557 	int nel = 0;
   1558 	size_t items;
   1559 	uint32_t buf[1];
   1560 	role_trans_rule_t *tr;
   1561 	int warned = 0;
   1562 	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
   1563 
   1564 	for (tr = t; tr; tr = tr->next)
   1565 		if (new_role || only_process(&tr->classes))
   1566 			nel++;
   1567 
   1568 	buf[0] = cpu_to_le32(nel);
   1569 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1570 	if (items != 1)
   1571 		return POLICYDB_ERROR;
   1572 	for (tr = t; tr; tr = tr->next) {
   1573 		if (!new_role && !only_process(&tr->classes)) {
   1574 			if (!warned)
   1575 				WARN(fp->handle, "Discarding role_transition "
   1576 					"rules for security classes other than "
   1577 					"\"process\"");
   1578 			warned = 1;
   1579 			continue;
   1580 		}
   1581 		if (role_set_write(&tr->roles, fp))
   1582 			return POLICYDB_ERROR;
   1583 		if (type_set_write(&tr->types, fp))
   1584 			return POLICYDB_ERROR;
   1585 		if (new_role)
   1586 			if (ebitmap_write(&tr->classes, fp))
   1587 				return POLICYDB_ERROR;
   1588 		buf[0] = cpu_to_le32(tr->new_role);
   1589 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1590 		if (items != 1)
   1591 			return POLICYDB_ERROR;
   1592 	}
   1593 	return POLICYDB_SUCCESS;
   1594 }
   1595 
   1596 static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
   1597 {
   1598 	int nel = 0;
   1599 	size_t items;
   1600 	uint32_t buf[1];
   1601 	role_allow_rule_t *ra;
   1602 
   1603 	for (ra = r; ra; ra = ra->next)
   1604 		nel++;
   1605 	buf[0] = cpu_to_le32(nel);
   1606 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1607 	if (items != 1)
   1608 		return POLICYDB_ERROR;
   1609 	for (ra = r; ra; ra = ra->next) {
   1610 		if (role_set_write(&ra->roles, fp))
   1611 			return POLICYDB_ERROR;
   1612 		if (role_set_write(&ra->new_roles, fp))
   1613 			return POLICYDB_ERROR;
   1614 	}
   1615 	return POLICYDB_SUCCESS;
   1616 }
   1617 
   1618 static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp)
   1619 {
   1620 	int nel = 0;
   1621 	size_t items;
   1622 	uint32_t buf[2], len;
   1623 	filename_trans_rule_t *ftr;
   1624 
   1625 	for (ftr = t; ftr; ftr = ftr->next)
   1626 		nel++;
   1627 
   1628 	buf[0] = cpu_to_le32(nel);
   1629 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1630 	if (items != 1)
   1631 		return POLICYDB_ERROR;
   1632 
   1633 	for (ftr = t; ftr; ftr = ftr->next) {
   1634 		len = strlen(ftr->name);
   1635 		buf[0] = cpu_to_le32(len);
   1636 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1637 		if (items != 1)
   1638 			return POLICYDB_ERROR;
   1639 
   1640 		items = put_entry(ftr->name, sizeof(char), len, fp);
   1641 		if (items != len)
   1642 			return POLICYDB_ERROR;
   1643 
   1644 		if (type_set_write(&ftr->stypes, fp))
   1645 			return POLICYDB_ERROR;
   1646 		if (type_set_write(&ftr->ttypes, fp))
   1647 			return POLICYDB_ERROR;
   1648 
   1649 		buf[0] = cpu_to_le32(ftr->tclass);
   1650 		buf[1] = cpu_to_le32(ftr->otype);
   1651 
   1652 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
   1653 		if (items != 2)
   1654 			return POLICYDB_ERROR;
   1655 	}
   1656 	return POLICYDB_SUCCESS;
   1657 }
   1658 
   1659 static int range_trans_rule_write(range_trans_rule_t * t,
   1660 				  struct policy_file *fp)
   1661 {
   1662 	int nel = 0;
   1663 	size_t items;
   1664 	uint32_t buf[1];
   1665 	range_trans_rule_t *rt;
   1666 
   1667 	for (rt = t; rt; rt = rt->next)
   1668 		nel++;
   1669 	buf[0] = cpu_to_le32(nel);
   1670 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1671 	if (items != 1)
   1672 		return POLICYDB_ERROR;
   1673 	for (rt = t; rt; rt = rt->next) {
   1674 		if (type_set_write(&rt->stypes, fp))
   1675 			return POLICYDB_ERROR;
   1676 		if (type_set_write(&rt->ttypes, fp))
   1677 			return POLICYDB_ERROR;
   1678 		if (ebitmap_write(&rt->tclasses, fp))
   1679 			return POLICYDB_ERROR;
   1680 		if (mls_write_semantic_range_helper(&rt->trange, fp))
   1681 			return POLICYDB_ERROR;
   1682 	}
   1683 	return POLICYDB_SUCCESS;
   1684 }
   1685 
   1686 static int scope_index_write(scope_index_t * scope_index,
   1687 			     unsigned int num_scope_syms,
   1688 			     struct policy_file *fp)
   1689 {
   1690 	unsigned int i;
   1691 	uint32_t buf[1];
   1692 	for (i = 0; i < num_scope_syms; i++) {
   1693 		if (ebitmap_write(scope_index->scope + i, fp) == -1) {
   1694 			return POLICYDB_ERROR;
   1695 		}
   1696 	}
   1697 	buf[0] = cpu_to_le32(scope_index->class_perms_len);
   1698 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
   1699 		return POLICYDB_ERROR;
   1700 	}
   1701 	for (i = 0; i < scope_index->class_perms_len; i++) {
   1702 		if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
   1703 			return POLICYDB_ERROR;
   1704 		}
   1705 	}
   1706 	return POLICYDB_SUCCESS;
   1707 }
   1708 
   1709 static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
   1710 			     policydb_t * p, struct policy_file *fp)
   1711 {
   1712 	struct policy_data pd;
   1713 	uint32_t buf[2];
   1714 	int i;
   1715 	buf[0] = cpu_to_le32(decl->decl_id);
   1716 	buf[1] = cpu_to_le32(decl->enabled);
   1717 	if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
   1718 		return POLICYDB_ERROR;
   1719 	}
   1720 	if (cond_write_list(p, decl->cond_list, fp) == -1 ||
   1721 	    avrule_write_list(decl->avrules, fp) == -1 ||
   1722 	    role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
   1723 	    role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
   1724 		return POLICYDB_ERROR;
   1725 	}
   1726 
   1727 	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
   1728 	    filename_trans_rule_write(decl->filename_trans_rules, fp))
   1729 		return POLICYDB_ERROR;
   1730 
   1731 	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
   1732 	    range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
   1733 		return POLICYDB_ERROR;
   1734 	}
   1735 	if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
   1736 	    scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
   1737 		return POLICYDB_ERROR;
   1738 	}
   1739 	pd.fp = fp;
   1740 	pd.p = p;
   1741 	for (i = 0; i < num_scope_syms; i++) {
   1742 		buf[0] = cpu_to_le32(decl->symtab[i].nprim);
   1743 		buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
   1744 		if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
   1745 			return POLICYDB_ERROR;
   1746 		}
   1747 		if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
   1748 			return POLICYDB_ERROR;
   1749 		}
   1750 	}
   1751 	return POLICYDB_SUCCESS;
   1752 }
   1753 
   1754 static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
   1755 			      policydb_t * p, struct policy_file *fp)
   1756 {
   1757 	/* first write a count of the total number of blocks */
   1758 	uint32_t buf[1], num_blocks = 0;
   1759 	avrule_block_t *cur;
   1760 	for (cur = block; cur != NULL; cur = cur->next) {
   1761 		num_blocks++;
   1762 	}
   1763 	buf[0] = cpu_to_le32(num_blocks);
   1764 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
   1765 		return POLICYDB_ERROR;
   1766 	}
   1767 
   1768 	/* now write each block */
   1769 	for (cur = block; cur != NULL; cur = cur->next) {
   1770 		uint32_t num_decls = 0;
   1771 		avrule_decl_t *decl;
   1772 		/* write a count of number of branches */
   1773 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
   1774 			num_decls++;
   1775 		}
   1776 		buf[0] = cpu_to_le32(num_decls);
   1777 		if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
   1778 			return POLICYDB_ERROR;
   1779 		}
   1780 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
   1781 			if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
   1782 			    -1) {
   1783 				return POLICYDB_ERROR;
   1784 			}
   1785 		}
   1786 	}
   1787 	return POLICYDB_SUCCESS;
   1788 }
   1789 
   1790 static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
   1791 {
   1792 	scope_datum_t *scope = (scope_datum_t *) datum;
   1793 	struct policy_data *pd = ptr;
   1794 	struct policy_file *fp = pd->fp;
   1795 	uint32_t static_buf[32], *dyn_buf = NULL, *buf;
   1796 	size_t key_len = strlen(key);
   1797 	unsigned int items = 2 + scope->decl_ids_len, i;
   1798 
   1799 	if (items >= (sizeof(static_buf) / 4)) {
   1800 		/* too many things required, so dynamically create a
   1801 		 * buffer.  this would have been easier with C99's
   1802 		 * dynamic arrays... */
   1803 		if ((dyn_buf = malloc(items * sizeof(*dyn_buf))) == NULL) {
   1804 			return POLICYDB_ERROR;
   1805 		}
   1806 		buf = dyn_buf;
   1807 	} else {
   1808 		buf = static_buf;
   1809 	}
   1810 	buf[0] = cpu_to_le32(key_len);
   1811 	if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
   1812 	    put_entry(key, 1, key_len, fp) != key_len) {
   1813 		free(dyn_buf);
   1814 		return POLICYDB_ERROR;
   1815 	}
   1816 	buf[0] = cpu_to_le32(scope->scope);
   1817 	buf[1] = cpu_to_le32(scope->decl_ids_len);
   1818 	for (i = 0; i < scope->decl_ids_len; i++) {
   1819 		buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
   1820 	}
   1821 	if (put_entry(buf, sizeof(*buf), items, fp) != items) {
   1822 		free(dyn_buf);
   1823 		return POLICYDB_ERROR;
   1824 	}
   1825 	free(dyn_buf);
   1826 	return POLICYDB_SUCCESS;
   1827 }
   1828 
   1829 static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
   1830 			     hashtab_datum_t datum, void *args)
   1831 {
   1832 	type_datum_t *typdatum = datum;
   1833 	uint32_t *p_nel = args;
   1834 
   1835 	if (typdatum->flavor == TYPE_ATTRIB) {
   1836 		/* uncount attribute from total number of types */
   1837 		(*p_nel)--;
   1838 	}
   1839 	return 0;
   1840 }
   1841 
   1842 static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
   1843 			     hashtab_datum_t datum, void *args)
   1844 {
   1845 	role_datum_t *role = datum;
   1846 	uint32_t *p_nel = args;
   1847 
   1848 	if (role->flavor == ROLE_ATTRIB) {
   1849 		/* uncount attribute from total number of roles */
   1850 		(*p_nel)--;
   1851 	}
   1852 	return 0;
   1853 }
   1854 
   1855 /*
   1856  * Write the configuration data in a policy database
   1857  * structure to a policy database binary representation
   1858  * file.
   1859  */
   1860 int policydb_write(policydb_t * p, struct policy_file *fp)
   1861 {
   1862 	unsigned int i, num_syms;
   1863 	uint32_t buf[32], config;
   1864 	size_t items, items2, len;
   1865 	struct policydb_compat_info *info;
   1866 	struct policy_data pd;
   1867 	char *policydb_str;
   1868 
   1869 	if (p->unsupported_format)
   1870 		return POLICYDB_UNSUPPORTED;
   1871 
   1872 	pd.fp = fp;
   1873 	pd.p = p;
   1874 
   1875 	config = 0;
   1876 	if (p->mls) {
   1877 		if ((p->policyvers < POLICYDB_VERSION_MLS &&
   1878 		    p->policy_type == POLICY_KERN) ||
   1879 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
   1880 		    p->policy_type == POLICY_BASE) ||
   1881 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
   1882 		    p->policy_type == POLICY_MOD)) {
   1883 			ERR(fp->handle, "policy version %d cannot support MLS",
   1884 			    p->policyvers);
   1885 			return POLICYDB_ERROR;
   1886 		}
   1887 		config |= POLICYDB_CONFIG_MLS;
   1888 	}
   1889 
   1890 	config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
   1891 
   1892 	/* Write the magic number and string identifiers. */
   1893 	items = 0;
   1894 	if (p->policy_type == POLICY_KERN) {
   1895 		buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
   1896 		len = strlen(policydb_target_strings[p->target_platform]);
   1897 		policydb_str = policydb_target_strings[p->target_platform];
   1898 	} else {
   1899 		buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
   1900 		len = strlen(POLICYDB_MOD_STRING);
   1901 		policydb_str = POLICYDB_MOD_STRING;
   1902 	}
   1903 	buf[items++] = cpu_to_le32(len);
   1904 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1905 	if (items != items2)
   1906 		return POLICYDB_ERROR;
   1907 	items = put_entry(policydb_str, 1, len, fp);
   1908 	if (items != len)
   1909 		return POLICYDB_ERROR;
   1910 
   1911 	/* Write the version, config, and table sizes. */
   1912 	items = 0;
   1913 	info = policydb_lookup_compat(p->policyvers, p->policy_type,
   1914 					p->target_platform);
   1915 	if (!info) {
   1916 		ERR(fp->handle, "compatibility lookup failed for policy "
   1917 		    "version %d", p->policyvers);
   1918 		return POLICYDB_ERROR;
   1919 	}
   1920 
   1921 	if (p->policy_type != POLICY_KERN) {
   1922 		buf[items++] = cpu_to_le32(p->policy_type);
   1923 	}
   1924 	buf[items++] = cpu_to_le32(p->policyvers);
   1925 	buf[items++] = cpu_to_le32(config);
   1926 	buf[items++] = cpu_to_le32(info->sym_num);
   1927 	buf[items++] = cpu_to_le32(info->ocon_num);
   1928 
   1929 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
   1930 	if (items != items2)
   1931 		return POLICYDB_ERROR;
   1932 
   1933 	if (p->policy_type == POLICY_MOD) {
   1934 		/* Write module name and version */
   1935 		len = strlen(p->name);
   1936 		buf[0] = cpu_to_le32(len);
   1937 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1938 		if (items != 1)
   1939 			return POLICYDB_ERROR;
   1940 		items = put_entry(p->name, 1, len, fp);
   1941 		if (items != len)
   1942 			return POLICYDB_ERROR;
   1943 		len = strlen(p->version);
   1944 		buf[0] = cpu_to_le32(len);
   1945 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
   1946 		if (items != 1)
   1947 			return POLICYDB_ERROR;
   1948 		items = put_entry(p->version, 1, len, fp);
   1949 		if (items != len)
   1950 			return POLICYDB_ERROR;
   1951 	}
   1952 
   1953 	if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
   1954 	     p->policy_type == POLICY_KERN) ||
   1955 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
   1956 	     p->policy_type == POLICY_BASE) ||
   1957 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
   1958 	     p->policy_type == POLICY_MOD)) {
   1959 		if (ebitmap_write(&p->policycaps, fp) == -1)
   1960 			return POLICYDB_ERROR;
   1961 	}
   1962 
   1963 	if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
   1964 	    p->policy_type == POLICY_KERN) {
   1965 		ebitmap_node_t *tnode;
   1966 
   1967 		ebitmap_for_each_bit(&p->permissive_map, tnode, i) {
   1968 			if (ebitmap_node_get_bit(tnode, i)) {
   1969 				WARN(fp->handle, "Warning! Policy version %d cannot "
   1970 				     "support permissive types, but some were defined",
   1971 				     p->policyvers);
   1972 				break;
   1973 			}
   1974 		}
   1975 	}
   1976 
   1977 	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
   1978 	    p->policy_type == POLICY_KERN) {
   1979 		if (ebitmap_write(&p->permissive_map, fp) == -1)
   1980 			return POLICYDB_ERROR;
   1981 	}
   1982 
   1983 	num_syms = info->sym_num;
   1984 	for (i = 0; i < num_syms; i++) {
   1985 		buf[0] = cpu_to_le32(p->symtab[i].nprim);
   1986 		buf[1] = p->symtab[i].table->nel;
   1987 
   1988 		/*
   1989 		 * A special case when writing type/attribute symbol table.
   1990 		 * The kernel policy version less than 24 does not support
   1991 		 * to load entries of attribute, so we have to re-calculate
   1992 		 * the actual number of types except for attributes.
   1993 		 */
   1994 		if (i == SYM_TYPES &&
   1995 		    p->policyvers < POLICYDB_VERSION_BOUNDARY &&
   1996 		    p->policy_type == POLICY_KERN) {
   1997 			hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
   1998 		}
   1999 
   2000 		/*
   2001 		 * Another special case when writing role/attribute symbol
   2002 		 * table, role attributes are redundant for policy.X, or
   2003 		 * when the pp's version is not big enough. So deduct
   2004 		 * their numbers from p_roles.table->nel.
   2005 		 */
   2006 		if ((i == SYM_ROLES) &&
   2007 		    ((p->policy_type == POLICY_KERN) ||
   2008 		     (p->policy_type != POLICY_KERN &&
   2009 		      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
   2010 			hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
   2011 
   2012 		buf[1] = cpu_to_le32(buf[1]);
   2013 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
   2014 		if (items != 2)
   2015 			return POLICYDB_ERROR;
   2016 		if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
   2017 			return POLICYDB_ERROR;
   2018 	}
   2019 
   2020 	if (p->policy_type == POLICY_KERN) {
   2021 		if (avtab_write(p, &p->te_avtab, fp))
   2022 			return POLICYDB_ERROR;
   2023 		if (p->policyvers < POLICYDB_VERSION_BOOL) {
   2024 			if (p->p_bools.nprim)
   2025 				WARN(fp->handle, "Discarding "
   2026 				     "booleans and conditional rules");
   2027 		} else {
   2028 			if (cond_write_list(p, p->cond_list, fp))
   2029 				return POLICYDB_ERROR;
   2030 		}
   2031 		if (role_trans_write(p, fp))
   2032 			return POLICYDB_ERROR;
   2033 		if (role_allow_write(p->role_allow, fp))
   2034 			return POLICYDB_ERROR;
   2035 		if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
   2036 			if (filename_trans_write(p->filename_trans, fp))
   2037 				return POLICYDB_ERROR;
   2038 		} else {
   2039 			if (p->filename_trans)
   2040 				WARN(fp->handle, "Discarding filename type transition rules");
   2041 		}
   2042 	} else {
   2043 		if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
   2044 			return POLICYDB_ERROR;
   2045 		}
   2046 
   2047 		for (i = 0; i < num_syms; i++) {
   2048 			buf[0] = cpu_to_le32(p->scope[i].table->nel);
   2049 			if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
   2050 				return POLICYDB_ERROR;
   2051 			}
   2052 			if (hashtab_map(p->scope[i].table, scope_write, &pd))
   2053 				return POLICYDB_ERROR;
   2054 		}
   2055 	}
   2056 
   2057 	if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
   2058 		return POLICYDB_ERROR;
   2059 	}
   2060 
   2061 	if ((p->policyvers >= POLICYDB_VERSION_MLS
   2062 	     && p->policy_type == POLICY_KERN)
   2063 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
   2064 		&& p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
   2065 		&& p->policy_type == POLICY_BASE)) {
   2066 		if (range_write(p, fp)) {
   2067 			return POLICYDB_ERROR;
   2068 		}
   2069 	}
   2070 
   2071 	if (p->policy_type == POLICY_KERN
   2072 	    && p->policyvers >= POLICYDB_VERSION_AVTAB) {
   2073 		for (i = 0; i < p->p_types.nprim; i++) {
   2074 			if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
   2075 				return POLICYDB_ERROR;
   2076 		}
   2077 	}
   2078 
   2079 	return POLICYDB_SUCCESS;
   2080 }
   2081