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