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