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