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