• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		buf[0] = cpu_to_le32(cladatum->default_user);
1101 		buf[1] = cpu_to_le32(cladatum->default_role);
1102 		if (!glblub_version && cladatum->default_range == DEFAULT_GLBLUB) {
1103 			WARN(fp->handle,
1104                              "class %s default_range set to GLBLUB but policy version is %d (%d required), discarding",
1105                              p->p_class_val_to_name[cladatum->s.value - 1], p->policyvers,
1106                              p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB);
1107                         cladatum->default_range = 0;
1108                 }
1109 		buf[2] = cpu_to_le32(cladatum->default_range);
1110 		items = put_entry(buf, sizeof(uint32_t), 3, fp);
1111 		if (items != 3)
1112 			return POLICYDB_ERROR;
1113 	}
1114 
1115 	if ((p->policy_type == POLICY_KERN &&
1116 	     p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) ||
1117 	    (p->policy_type == POLICY_BASE &&
1118 	     p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) {
1119 		buf[0] = cpu_to_le32(cladatum->default_type);
1120 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1121 		if (items != 1)
1122 			return POLICYDB_ERROR;
1123 	}
1124 
1125 	return POLICYDB_SUCCESS;
1126 }
1127 
role_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1128 static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1129 {
1130 	role_datum_t *role;
1131 	uint32_t buf[32];
1132 	size_t items, items2, len;
1133 	struct policy_data *pd = ptr;
1134 	struct policy_file *fp = pd->fp;
1135 	struct policydb *p = pd->p;
1136 
1137 	role = (role_datum_t *) datum;
1138 
1139 	/*
1140 	 * Role attributes are redundant for policy.X, skip them
1141 	 * when writing the roles symbol table. They are also skipped
1142 	 * when pp is downgraded.
1143 	 *
1144 	 * Their numbers would be deducted in policydb_write().
1145 	 */
1146 	if ((role->flavor == ROLE_ATTRIB) &&
1147 	    ((p->policy_type == POLICY_KERN) ||
1148 	     (p->policy_type != POLICY_KERN &&
1149 	      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
1150 		return POLICYDB_SUCCESS;
1151 
1152 	len = strlen(key);
1153 	items = 0;
1154 	buf[items++] = cpu_to_le32(len);
1155 	buf[items++] = cpu_to_le32(role->s.value);
1156 	if (policydb_has_boundary_feature(p))
1157 		buf[items++] = cpu_to_le32(role->bounds);
1158 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1159 	if (items != items2)
1160 		return POLICYDB_ERROR;
1161 
1162 	items = put_entry(key, 1, len, fp);
1163 	if (items != len)
1164 		return POLICYDB_ERROR;
1165 
1166 	if (ebitmap_write(&role->dominates, fp))
1167 		return POLICYDB_ERROR;
1168 	if (p->policy_type == POLICY_KERN) {
1169 		if (role->s.value == OBJECT_R_VAL) {
1170 			/*
1171 			 * CIL populates object_r's types map
1172 			 * rather than handling it as a special case.
1173 			 * However, this creates an inconsistency with
1174 			 * the kernel policy read from /sys/fs/selinux/policy
1175 			 * because the kernel ignores everything except for
1176 			 * object_r's value from the policy file.
1177 			 * Make them consistent by writing an empty
1178 			 * ebitmap instead.
1179 			 */
1180 			ebitmap_t empty;
1181 			ebitmap_init(&empty);
1182 			if (ebitmap_write(&empty, fp))
1183 				return POLICYDB_ERROR;
1184 		} else {
1185 			if (ebitmap_write(&role->types.types, fp))
1186 				return POLICYDB_ERROR;
1187 		}
1188 	} else {
1189 		if (type_set_write(&role->types, fp))
1190 			return POLICYDB_ERROR;
1191 	}
1192 
1193 	if (p->policy_type != POLICY_KERN &&
1194 	    p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
1195 		buf[0] = cpu_to_le32(role->flavor);
1196 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1197 		if (items != 1)
1198 			return POLICYDB_ERROR;
1199 
1200 		if (ebitmap_write(&role->roles, fp))
1201 			return POLICYDB_ERROR;
1202 	}
1203 
1204 	return POLICYDB_SUCCESS;
1205 }
1206 
type_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1207 static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1208 {
1209 	type_datum_t *typdatum;
1210 	uint32_t buf[32];
1211 	size_t items, items2, len;
1212 	struct policy_data *pd = ptr;
1213 	struct policy_file *fp = pd->fp;
1214 	struct policydb *p = pd->p;
1215 
1216 	typdatum = (type_datum_t *) datum;
1217 
1218 	/*
1219 	 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY)
1220 	 * does not support to load entries of attribute, so we skip to write it.
1221 	 */
1222 	if (p->policy_type == POLICY_KERN
1223 	    && p->policyvers < POLICYDB_VERSION_BOUNDARY
1224 	    && typdatum->flavor == TYPE_ATTRIB)
1225 		return POLICYDB_SUCCESS;
1226 
1227 	len = strlen(key);
1228 	items = 0;
1229 	buf[items++] = cpu_to_le32(len);
1230 	buf[items++] = cpu_to_le32(typdatum->s.value);
1231 	if (policydb_has_boundary_feature(p)) {
1232 		uint32_t properties = 0;
1233 
1234 		if (p->policy_type != POLICY_KERN
1235 		    && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
1236 			buf[items++] = cpu_to_le32(typdatum->primary);
1237 		}
1238 
1239 		if (typdatum->primary)
1240 			properties |= TYPEDATUM_PROPERTY_PRIMARY;
1241 
1242 		if (typdatum->flavor == TYPE_ATTRIB) {
1243 			properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
1244 		} else if (typdatum->flavor == TYPE_ALIAS
1245 			   && p->policy_type != POLICY_KERN)
1246 			properties |= TYPEDATUM_PROPERTY_ALIAS;
1247 
1248 		if (typdatum->flags & TYPE_FLAGS_PERMISSIVE
1249 		    && p->policy_type != POLICY_KERN)
1250 			properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
1251 
1252 		buf[items++] = cpu_to_le32(properties);
1253 		buf[items++] = cpu_to_le32(typdatum->bounds);
1254 	} else {
1255 		buf[items++] = cpu_to_le32(typdatum->primary);
1256 
1257 		if (p->policy_type != POLICY_KERN) {
1258 			buf[items++] = cpu_to_le32(typdatum->flavor);
1259 
1260 			if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
1261 				buf[items++] = cpu_to_le32(typdatum->flags);
1262 			else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE)
1263 				WARN(fp->handle, "Warning! Module policy "
1264 				     "version %d cannot support permissive "
1265 				     "types, but one was defined",
1266 				     p->policyvers);
1267 		}
1268 	}
1269 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1270 	if (items != items2)
1271 		return POLICYDB_ERROR;
1272 
1273 	if (p->policy_type != POLICY_KERN) {
1274 		if (ebitmap_write(&typdatum->types, fp))
1275 			return POLICYDB_ERROR;
1276 	}
1277 
1278 	items = put_entry(key, 1, len, fp);
1279 	if (items != len)
1280 		return POLICYDB_ERROR;
1281 
1282 	return POLICYDB_SUCCESS;
1283 }
1284 
user_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1285 static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1286 {
1287 	user_datum_t *usrdatum;
1288 	uint32_t buf[32];
1289 	size_t items, items2, len;
1290 	struct policy_data *pd = ptr;
1291 	struct policy_file *fp = pd->fp;
1292 	struct policydb *p = pd->p;
1293 
1294 	usrdatum = (user_datum_t *) datum;
1295 
1296 	len = strlen(key);
1297 	items = 0;
1298 	buf[items++] = cpu_to_le32(len);
1299 	buf[items++] = cpu_to_le32(usrdatum->s.value);
1300 	if (policydb_has_boundary_feature(p))
1301 		buf[items++] = cpu_to_le32(usrdatum->bounds);
1302 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1303 	if (items != items2)
1304 		return POLICYDB_ERROR;
1305 
1306 	items = put_entry(key, 1, len, fp);
1307 	if (items != len)
1308 		return POLICYDB_ERROR;
1309 
1310 	if (p->policy_type == POLICY_KERN) {
1311 		if (ebitmap_write(&usrdatum->roles.roles, fp))
1312 			return POLICYDB_ERROR;
1313 	} else {
1314 		if (role_set_write(&usrdatum->roles, fp))
1315 			return POLICYDB_ERROR;
1316 	}
1317 
1318 	if ((p->policyvers >= POLICYDB_VERSION_MLS
1319 	     && p->policy_type == POLICY_KERN)
1320 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1321 		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1322 		&& p->policy_type == POLICY_MOD)
1323 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1324 		&& p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1325 		&& p->policy_type == POLICY_BASE)) {
1326 		if (mls_write_range_helper(&usrdatum->exp_range, fp))
1327 			return POLICYDB_ERROR;
1328 		if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
1329 			return POLICYDB_ERROR;
1330 	} else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1331 		    && p->policy_type == POLICY_MOD)
1332 		   || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1333 		       && p->policy_type == POLICY_BASE)) {
1334 		if (mls_write_semantic_range_helper(&usrdatum->range, fp))
1335 			return -1;
1336 		if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
1337 			return -1;
1338 	}
1339 
1340 	return POLICYDB_SUCCESS;
1341 }
1342 
1343 static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1344 				void *datap) = {
1345 common_write, class_write, role_write, type_write, user_write,
1346 	    cond_write_bool, sens_write, cat_write,};
1347 
ocontext_write_xen(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1348 static int ocontext_write_xen(const struct policydb_compat_info *info, policydb_t *p,
1349 			  struct policy_file *fp)
1350 {
1351 	unsigned int i, j;
1352 	size_t nel, items, len;
1353 	uint32_t buf[32];
1354 	ocontext_t *c;
1355 	for (i = 0; i < info->ocon_num; i++) {
1356 		nel = 0;
1357 		for (c = p->ocontexts[i]; c; c = c->next) {
1358 			if (i == OCON_XEN_ISID && !c->context[0].user) {
1359 				INFO(fp->handle,
1360 				     "No context assigned to SID %s, omitting from policy",
1361 				     c->u.name);
1362 				continue;
1363 			}
1364 			nel++;
1365 		}
1366 		buf[0] = cpu_to_le32(nel);
1367 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1368 		if (items != 1)
1369 			return POLICYDB_ERROR;
1370 		for (c = p->ocontexts[i]; c; c = c->next) {
1371 			switch (i) {
1372 			case OCON_XEN_ISID:
1373 				if (!c->context[0].user)
1374 					break;
1375 				buf[0] = cpu_to_le32(c->sid[0]);
1376 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1377 				if (items != 1)
1378 					return POLICYDB_ERROR;
1379 				if (context_write(p, &c->context[0], fp))
1380 					return POLICYDB_ERROR;
1381 				break;
1382 			case OCON_XEN_PIRQ:
1383 				buf[0] = cpu_to_le32(c->u.pirq);
1384 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1385 				if (items != 1)
1386 					return POLICYDB_ERROR;
1387 				if (context_write(p, &c->context[0], fp))
1388 					return POLICYDB_ERROR;
1389 				break;
1390 			case OCON_XEN_IOPORT:
1391 				buf[0] = c->u.ioport.low_ioport;
1392 				buf[1] = c->u.ioport.high_ioport;
1393 				for (j = 0; j < 2; j++)
1394 					buf[j] = cpu_to_le32(buf[j]);
1395 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1396 				if (items != 2)
1397 					return POLICYDB_ERROR;
1398 				if (context_write(p, &c->context[0], fp))
1399 					return POLICYDB_ERROR;
1400 				break;
1401 			case OCON_XEN_IOMEM:
1402 				if (p->policyvers >= POLICYDB_VERSION_XEN_DEVICETREE) {
1403 					uint64_t b64[2];
1404 					b64[0] = c->u.iomem.low_iomem;
1405 					b64[1] = c->u.iomem.high_iomem;
1406 					for (j = 0; j < 2; j++)
1407 						b64[j] = cpu_to_le64(b64[j]);
1408 					items = put_entry(b64, sizeof(uint64_t), 2, fp);
1409 					if (items != 2)
1410 						return POLICYDB_ERROR;
1411 				} else {
1412 					if (c->u.iomem.high_iomem > 0xFFFFFFFFULL) {
1413 						ERR(fp->handle, "policy version %d"
1414 							" cannot represent IOMEM addresses over 16TB",
1415 							p->policyvers);
1416 						return POLICYDB_ERROR;
1417 					}
1418 
1419 					buf[0] = c->u.iomem.low_iomem;
1420 					buf[1] = c->u.iomem.high_iomem;
1421 					for (j = 0; j < 2; j++)
1422 						buf[j] = cpu_to_le32(buf[j]);
1423 					items = put_entry(buf, sizeof(uint32_t), 2, fp);
1424 					if (items != 2)
1425 						return POLICYDB_ERROR;
1426 				}
1427 				if (context_write(p, &c->context[0], fp))
1428 					return POLICYDB_ERROR;
1429 				break;
1430 			case OCON_XEN_PCIDEVICE:
1431 				buf[0] = cpu_to_le32(c->u.device);
1432 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1433 				if (items != 1)
1434 					return POLICYDB_ERROR;
1435 				if (context_write(p, &c->context[0], fp))
1436 					return POLICYDB_ERROR;
1437 				break;
1438 			case OCON_XEN_DEVICETREE:
1439 				len = strlen(c->u.name);
1440 				buf[0] = cpu_to_le32(len);
1441 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1442 				if (items != 1)
1443 					return POLICYDB_ERROR;
1444 				items = put_entry(c->u.name, 1, len, fp);
1445 				if (items != len)
1446 					return POLICYDB_ERROR;
1447 				if (context_write(p, &c->context[0], fp))
1448 					return POLICYDB_ERROR;
1449 				break;
1450 			}
1451 		}
1452 	}
1453 	return POLICYDB_SUCCESS;
1454 }
1455 
ocontext_write_selinux(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1456 static int ocontext_write_selinux(const struct policydb_compat_info *info,
1457 	policydb_t *p, struct policy_file *fp)
1458 {
1459 	unsigned int i, j;
1460 	size_t nel, items, len;
1461 	uint32_t buf[32];
1462 	ocontext_t *c;
1463 	for (i = 0; i < info->ocon_num; i++) {
1464 		nel = 0;
1465 		for (c = p->ocontexts[i]; c; c = c->next) {
1466 			if (i == OCON_ISID && !c->context[0].user) {
1467 				INFO(fp->handle,
1468 				     "No context assigned to SID %s, omitting from policy",
1469 				     c->u.name);
1470 				continue;
1471 			}
1472 			nel++;
1473 		}
1474 		buf[0] = cpu_to_le32(nel);
1475 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1476 		if (items != 1)
1477 			return POLICYDB_ERROR;
1478 		for (c = p->ocontexts[i]; c; c = c->next) {
1479 			switch (i) {
1480 			case OCON_ISID:
1481 				if (!c->context[0].user)
1482 					break;
1483 				buf[0] = cpu_to_le32(c->sid[0]);
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 				break;
1490 			case OCON_FS:
1491 			case OCON_NETIF:
1492 				len = strlen(c->u.name);
1493 				buf[0] = cpu_to_le32(len);
1494 				items = put_entry(buf, sizeof(uint32_t), 1, fp);
1495 				if (items != 1)
1496 					return POLICYDB_ERROR;
1497 				items = put_entry(c->u.name, 1, len, fp);
1498 				if (items != len)
1499 					return POLICYDB_ERROR;
1500 				if (context_write(p, &c->context[0], fp))
1501 					return POLICYDB_ERROR;
1502 				if (context_write(p, &c->context[1], fp))
1503 					return POLICYDB_ERROR;
1504 				break;
1505 			case OCON_IBPKEY:
1506 				 /* The subnet prefix is in network order */
1507 				memcpy(buf, &c->u.ibpkey.subnet_prefix,
1508 				       sizeof(c->u.ibpkey.subnet_prefix));
1509 
1510 				buf[2] = cpu_to_le32(c->u.ibpkey.low_pkey);
1511 				buf[3] = cpu_to_le32(c->u.ibpkey.high_pkey);
1512 
1513 				items = put_entry(buf, sizeof(uint32_t), 4, fp);
1514 				if (items != 4)
1515 					return POLICYDB_ERROR;
1516 
1517 				if (context_write(p, &c->context[0], fp))
1518 					return POLICYDB_ERROR;
1519 				break;
1520 			case OCON_IBENDPORT:
1521 				len = strlen(c->u.ibendport.dev_name);
1522 				buf[0] = cpu_to_le32(len);
1523 				buf[1] = cpu_to_le32(c->u.ibendport.port);
1524 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1525 				if (items != 2)
1526 					return POLICYDB_ERROR;
1527 				items = put_entry(c->u.ibendport.dev_name, 1, len, fp);
1528 				if (items != len)
1529 					return POLICYDB_ERROR;
1530 
1531 				if (context_write(p, &c->context[0], fp))
1532 					return POLICYDB_ERROR;
1533 				break;
1534 			case OCON_PORT:
1535 				buf[0] = c->u.port.protocol;
1536 				buf[1] = c->u.port.low_port;
1537 				buf[2] = c->u.port.high_port;
1538 				for (j = 0; j < 3; j++) {
1539 					buf[j] = cpu_to_le32(buf[j]);
1540 				}
1541 				items = put_entry(buf, sizeof(uint32_t), 3, fp);
1542 				if (items != 3)
1543 					return POLICYDB_ERROR;
1544 				if (context_write(p, &c->context[0], fp))
1545 					return POLICYDB_ERROR;
1546 				break;
1547 			case OCON_NODE:
1548 				buf[0] = c->u.node.addr; /* network order */
1549 				buf[1] = c->u.node.mask; /* network order */
1550 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1551 				if (items != 2)
1552 					return POLICYDB_ERROR;
1553 				if (context_write(p, &c->context[0], fp))
1554 					return POLICYDB_ERROR;
1555 				break;
1556 			case OCON_FSUSE:
1557 				buf[0] = cpu_to_le32(c->v.behavior);
1558 				len = strlen(c->u.name);
1559 				buf[1] = cpu_to_le32(len);
1560 				items = put_entry(buf, sizeof(uint32_t), 2, fp);
1561 				if (items != 2)
1562 					return POLICYDB_ERROR;
1563 				items = put_entry(c->u.name, 1, len, fp);
1564 				if (items != len)
1565 					return POLICYDB_ERROR;
1566 				if (context_write(p, &c->context[0], fp))
1567 					return POLICYDB_ERROR;
1568 				break;
1569 			case OCON_NODE6:
1570 				for (j = 0; j < 4; j++)
1571 					buf[j] = c->u.node6.addr[j]; /* network order */
1572 				for (j = 0; j < 4; j++)
1573 					buf[j + 4] = c->u.node6.mask[j]; /* network order */
1574 				items = put_entry(buf, sizeof(uint32_t), 8, fp);
1575 				if (items != 8)
1576 					return POLICYDB_ERROR;
1577 				if (context_write(p, &c->context[0], fp))
1578 					return POLICYDB_ERROR;
1579 				break;
1580 			}
1581 		}
1582 	}
1583 	return POLICYDB_SUCCESS;
1584 }
1585 
ocontext_write(const struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1586 static int ocontext_write(const struct policydb_compat_info *info, policydb_t * p,
1587 	struct policy_file *fp)
1588 {
1589 	int rc = POLICYDB_ERROR;
1590 	switch (p->target_platform) {
1591 	case SEPOL_TARGET_SELINUX:
1592 		rc = ocontext_write_selinux(info, p, fp);
1593 		break;
1594 	case SEPOL_TARGET_XEN:
1595 		rc = ocontext_write_xen(info, p, fp);
1596 		break;
1597 	}
1598 	return rc;
1599 }
1600 
genfs_write(policydb_t * p,struct policy_file * fp)1601 static int genfs_write(policydb_t * p, struct policy_file *fp)
1602 {
1603 	genfs_t *genfs;
1604 	ocontext_t *c;
1605 	size_t nel = 0, items, len;
1606 	uint32_t buf[32];
1607 
1608 	for (genfs = p->genfs; genfs; genfs = genfs->next)
1609 		nel++;
1610 	buf[0] = cpu_to_le32(nel);
1611 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1612 	if (items != 1)
1613 		return POLICYDB_ERROR;
1614 	for (genfs = p->genfs; genfs; genfs = genfs->next) {
1615 		len = strlen(genfs->fstype);
1616 		buf[0] = cpu_to_le32(len);
1617 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1618 		if (items != 1)
1619 			return POLICYDB_ERROR;
1620 		items = put_entry(genfs->fstype, 1, len, fp);
1621 		if (items != len)
1622 			return POLICYDB_ERROR;
1623 		nel = 0;
1624 		for (c = genfs->head; c; c = c->next)
1625 			nel++;
1626 		buf[0] = cpu_to_le32(nel);
1627 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1628 		if (items != 1)
1629 			return POLICYDB_ERROR;
1630 		for (c = genfs->head; c; c = c->next) {
1631 			len = strlen(c->u.name);
1632 			buf[0] = cpu_to_le32(len);
1633 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1634 			if (items != 1)
1635 				return POLICYDB_ERROR;
1636 			items = put_entry(c->u.name, 1, len, fp);
1637 			if (items != len)
1638 				return POLICYDB_ERROR;
1639 			buf[0] = cpu_to_le32(c->v.sclass);
1640 			items = put_entry(buf, sizeof(uint32_t), 1, fp);
1641 			if (items != 1)
1642 				return POLICYDB_ERROR;
1643 			if (context_write(p, &c->context[0], fp))
1644 				return POLICYDB_ERROR;
1645 		}
1646 	}
1647 	return POLICYDB_SUCCESS;
1648 }
1649 
1650 
1651 struct rangetrans_write_args {
1652 	size_t nel;
1653 	int new_rangetr;
1654 	struct policy_file *fp;
1655 	struct policydb *p;
1656 };
1657 
rangetrans_count(hashtab_key_t key,void * data,void * ptr)1658 static int rangetrans_count(hashtab_key_t key,
1659 			    void *data __attribute__ ((unused)),
1660 			    void *ptr)
1661 {
1662 	struct range_trans *rt = (struct range_trans *)key;
1663 	struct rangetrans_write_args *args = ptr;
1664 	struct policydb *p = args->p;
1665 
1666 	/* all range_transitions are written for the new format, only
1667 	   process related range_transitions are written for the old
1668 	   format, so count accordingly */
1669 	if (args->new_rangetr || rt->target_class == p->process_class)
1670 		args->nel++;
1671 	return 0;
1672 }
1673 
range_write_helper(hashtab_key_t key,void * data,void * ptr)1674 static int range_write_helper(hashtab_key_t key, void *data, void *ptr)
1675 {
1676 	uint32_t buf[2];
1677 	struct range_trans *rt = (struct range_trans *)key;
1678 	struct mls_range *r = data;
1679 	struct rangetrans_write_args *args = ptr;
1680 	struct policy_file *fp = args->fp;
1681 	struct policydb *p = args->p;
1682 	int new_rangetr = args->new_rangetr;
1683 	size_t items;
1684 	static int warning_issued = 0;
1685 	int rc;
1686 
1687 	if (!new_rangetr && rt->target_class != p->process_class) {
1688 		if (!warning_issued)
1689 			WARN(fp->handle, "Discarding range_transition "
1690 			     "rules for security classes other than "
1691 			     "\"process\"");
1692 		warning_issued = 1;
1693 		return 0;
1694 	}
1695 
1696 	buf[0] = cpu_to_le32(rt->source_type);
1697 	buf[1] = cpu_to_le32(rt->target_type);
1698 	items = put_entry(buf, sizeof(uint32_t), 2, fp);
1699 	if (items != 2)
1700 		return POLICYDB_ERROR;
1701 	if (new_rangetr) {
1702 		buf[0] = cpu_to_le32(rt->target_class);
1703 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1704 		if (items != 1)
1705 			return POLICYDB_ERROR;
1706 	}
1707 	rc = mls_write_range_helper(r, fp);
1708 	if (rc)
1709 		return rc;
1710 
1711 	return 0;
1712 }
1713 
range_write(policydb_t * p,struct policy_file * fp)1714 static int range_write(policydb_t * p, struct policy_file *fp)
1715 {
1716 	size_t items;
1717 	uint32_t buf[2];
1718 	int new_rangetr = (p->policy_type == POLICY_KERN &&
1719 			   p->policyvers >= POLICYDB_VERSION_RANGETRANS);
1720 	struct rangetrans_write_args args;
1721 	int rc;
1722 
1723 	args.nel = 0;
1724 	args.new_rangetr = new_rangetr;
1725 	args.fp = fp;
1726 	args.p = p;
1727 	rc = hashtab_map(p->range_tr, rangetrans_count, &args);
1728 	if (rc)
1729 		return rc;
1730 
1731 	buf[0] = cpu_to_le32(args.nel);
1732 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1733 	if (items != 1)
1734 		return POLICYDB_ERROR;
1735 
1736 	return hashtab_map(p->range_tr, range_write_helper, &args);
1737 }
1738 
1739 /************** module writing functions below **************/
1740 
avrule_write(policydb_t * p,avrule_t * avrule,struct policy_file * fp)1741 static int avrule_write(policydb_t *p, avrule_t * avrule,
1742 			struct policy_file *fp)
1743 {
1744 	size_t items, items2;
1745 	uint32_t buf[32], len;
1746 	class_perm_node_t *cur;
1747 
1748 	if (p->policyvers < MOD_POLICYDB_VERSION_SELF_TYPETRANS &&
1749 	    (avrule->specified & AVRULE_TYPE) &&
1750 	    (avrule->flags & RULE_SELF)) {
1751 		ERR(fp->handle,
1752 		    "Module contains a self rule not supported by the target module policy version");
1753 		return POLICYDB_ERROR;
1754 	}
1755 
1756 	items = 0;
1757 	buf[items++] = cpu_to_le32(avrule->specified);
1758 	buf[items++] = cpu_to_le32(avrule->flags);
1759 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1760 	if (items2 != items)
1761 		return POLICYDB_ERROR;
1762 
1763 	if (type_set_write(&avrule->stypes, fp))
1764 		return POLICYDB_ERROR;
1765 
1766 	if (type_set_write(&avrule->ttypes, fp))
1767 		return POLICYDB_ERROR;
1768 
1769 	cur = avrule->perms;
1770 	len = 0;
1771 	while (cur) {
1772 		len++;
1773 		cur = cur->next;
1774 	}
1775 	items = 0;
1776 	buf[items++] = cpu_to_le32(len);
1777 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1778 	if (items2 != items)
1779 		return POLICYDB_ERROR;
1780 	cur = avrule->perms;
1781 	while (cur) {
1782 		items = 0;
1783 		buf[items++] = cpu_to_le32(cur->tclass);
1784 		buf[items++] = cpu_to_le32(cur->data);
1785 		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1786 		if (items2 != items)
1787 			return POLICYDB_ERROR;
1788 
1789 		cur = cur->next;
1790 	}
1791 
1792 	if (avrule->specified & AVRULE_XPERMS) {
1793 		size_t nel = ARRAY_SIZE(avrule->xperms->perms);
1794 		uint32_t buf32[nel];
1795 		uint8_t buf8;
1796 		unsigned int i;
1797 
1798 		if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
1799 			ERR(fp->handle,
1800 			    "module policy version %u does not support ioctl"
1801 			    " extended permissions rules and one was specified",
1802 			    p->policyvers);
1803 			return POLICYDB_ERROR;
1804 		}
1805 
1806 		if (p->target_platform != SEPOL_TARGET_SELINUX) {
1807 			ERR(fp->handle,
1808 			    "Target platform %s does not support ioctl"
1809 			    " extended permissions rules and one was specified",
1810 			    policydb_target_strings[p->target_platform]);
1811 			return POLICYDB_ERROR;
1812 		}
1813 
1814 		buf8 = avrule->xperms->specified;
1815 		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1816 		if (items != 1)
1817 			return POLICYDB_ERROR;
1818 		buf8 = avrule->xperms->driver;
1819 		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1820 		if (items != 1)
1821 			return POLICYDB_ERROR;
1822 		for (i = 0; i < nel; i++)
1823 			buf32[i] = cpu_to_le32(avrule->xperms->perms[i]);
1824 		items = put_entry(buf32, sizeof(uint32_t), nel, fp);
1825 		if (items != nel)
1826 			return POLICYDB_ERROR;
1827 	}
1828 
1829 	return POLICYDB_SUCCESS;
1830 }
1831 
avrule_write_list(policydb_t * p,avrule_t * avrules,struct policy_file * fp)1832 static int avrule_write_list(policydb_t *p, avrule_t * avrules,
1833 			     struct policy_file *fp)
1834 {
1835 	uint32_t buf[32], len;
1836 	avrule_t *avrule;
1837 
1838 	avrule = avrules;
1839 	len = 0;
1840 	while (avrule) {
1841 		len++;
1842 		avrule = avrule->next;
1843 	}
1844 
1845 	buf[0] = cpu_to_le32(len);
1846 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1847 		return POLICYDB_ERROR;
1848 
1849 	avrule = avrules;
1850 	while (avrule) {
1851 		if (avrule_write(p, avrule, fp))
1852 			return POLICYDB_ERROR;
1853 		avrule = avrule->next;
1854 	}
1855 
1856 	return POLICYDB_SUCCESS;
1857 }
1858 
only_process(ebitmap_t * in,struct policydb * p)1859 static int only_process(ebitmap_t *in, struct policydb *p)
1860 {
1861 	unsigned int i, value;
1862 	ebitmap_node_t *node;
1863 
1864 	if (!p->process_class)
1865 		return 0;
1866 
1867 	value = p->process_class - 1;
1868 
1869 	ebitmap_for_each_positive_bit(in, node, i) {
1870 		if (i != value)
1871 			return 0;
1872 	}
1873 	return 1;
1874 }
1875 
role_trans_rule_write(policydb_t * p,role_trans_rule_t * t,struct policy_file * fp)1876 static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
1877 				 struct policy_file *fp)
1878 {
1879 	int nel = 0;
1880 	size_t items;
1881 	uint32_t buf[1];
1882 	role_trans_rule_t *tr;
1883 	int warned = 0;
1884 	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1885 
1886 	for (tr = t; tr; tr = tr->next)
1887 		if (new_role || only_process(&tr->classes, p))
1888 			nel++;
1889 
1890 	buf[0] = cpu_to_le32(nel);
1891 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1892 	if (items != 1)
1893 		return POLICYDB_ERROR;
1894 	for (tr = t; tr; tr = tr->next) {
1895 		if (!new_role && !only_process(&tr->classes, p)) {
1896 			if (!warned)
1897 				WARN(fp->handle, "Discarding role_transition "
1898 					"rules for security classes other than "
1899 					"\"process\"");
1900 			warned = 1;
1901 			continue;
1902 		}
1903 		if (role_set_write(&tr->roles, fp))
1904 			return POLICYDB_ERROR;
1905 		if (type_set_write(&tr->types, fp))
1906 			return POLICYDB_ERROR;
1907 		if (new_role)
1908 			if (ebitmap_write(&tr->classes, fp))
1909 				return POLICYDB_ERROR;
1910 		buf[0] = cpu_to_le32(tr->new_role);
1911 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1912 		if (items != 1)
1913 			return POLICYDB_ERROR;
1914 	}
1915 	return POLICYDB_SUCCESS;
1916 }
1917 
role_allow_rule_write(role_allow_rule_t * r,struct policy_file * fp)1918 static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
1919 {
1920 	int nel = 0;
1921 	size_t items;
1922 	uint32_t buf[1];
1923 	role_allow_rule_t *ra;
1924 
1925 	for (ra = r; ra; ra = ra->next)
1926 		nel++;
1927 	buf[0] = cpu_to_le32(nel);
1928 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1929 	if (items != 1)
1930 		return POLICYDB_ERROR;
1931 	for (ra = r; ra; ra = ra->next) {
1932 		if (role_set_write(&ra->roles, fp))
1933 			return POLICYDB_ERROR;
1934 		if (role_set_write(&ra->new_roles, fp))
1935 			return POLICYDB_ERROR;
1936 	}
1937 	return POLICYDB_SUCCESS;
1938 }
1939 
filename_trans_rule_write(policydb_t * p,filename_trans_rule_t * t,struct policy_file * fp)1940 static int filename_trans_rule_write(policydb_t *p, filename_trans_rule_t *t,
1941 				     struct policy_file *fp)
1942 {
1943 	int nel = 0;
1944 	size_t items, entries;
1945 	uint32_t buf[3], len;
1946 	filename_trans_rule_t *ftr;
1947 
1948 	for (ftr = t; ftr; ftr = ftr->next)
1949 		nel++;
1950 
1951 	buf[0] = cpu_to_le32(nel);
1952 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1953 	if (items != 1)
1954 		return POLICYDB_ERROR;
1955 
1956 	for (ftr = t; ftr; ftr = ftr->next) {
1957 		len = strlen(ftr->name);
1958 		buf[0] = cpu_to_le32(len);
1959 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1960 		if (items != 1)
1961 			return POLICYDB_ERROR;
1962 
1963 		items = put_entry(ftr->name, sizeof(char), len, fp);
1964 		if (items != len)
1965 			return POLICYDB_ERROR;
1966 
1967 		if (type_set_write(&ftr->stypes, fp))
1968 			return POLICYDB_ERROR;
1969 		if (type_set_write(&ftr->ttypes, fp))
1970 			return POLICYDB_ERROR;
1971 
1972 		buf[0] = cpu_to_le32(ftr->tclass);
1973 		buf[1] = cpu_to_le32(ftr->otype);
1974 		buf[2] = cpu_to_le32(ftr->flags);
1975 
1976 		if (p->policyvers >= MOD_POLICYDB_VERSION_SELF_TYPETRANS) {
1977 			entries = 3;
1978 		} else if (!(ftr->flags & RULE_SELF)) {
1979 			entries = 2;
1980 		} else {
1981 			ERR(fp->handle,
1982 			    "Module contains a self rule not supported by the target module policy version");
1983 			return POLICYDB_ERROR;
1984 		}
1985 
1986 		items = put_entry(buf, sizeof(uint32_t), entries, fp);
1987 		if (items != entries)
1988 			return POLICYDB_ERROR;
1989 	}
1990 	return POLICYDB_SUCCESS;
1991 }
1992 
range_trans_rule_write(range_trans_rule_t * t,struct policy_file * fp)1993 static int range_trans_rule_write(range_trans_rule_t * t,
1994 				  struct policy_file *fp)
1995 {
1996 	int nel = 0;
1997 	size_t items;
1998 	uint32_t buf[1];
1999 	range_trans_rule_t *rt;
2000 
2001 	for (rt = t; rt; rt = rt->next)
2002 		nel++;
2003 	buf[0] = cpu_to_le32(nel);
2004 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
2005 	if (items != 1)
2006 		return POLICYDB_ERROR;
2007 	for (rt = t; rt; rt = rt->next) {
2008 		if (type_set_write(&rt->stypes, fp))
2009 			return POLICYDB_ERROR;
2010 		if (type_set_write(&rt->ttypes, fp))
2011 			return POLICYDB_ERROR;
2012 		if (ebitmap_write(&rt->tclasses, fp))
2013 			return POLICYDB_ERROR;
2014 		if (mls_write_semantic_range_helper(&rt->trange, fp))
2015 			return POLICYDB_ERROR;
2016 	}
2017 	return POLICYDB_SUCCESS;
2018 }
2019 
scope_index_write(scope_index_t * scope_index,unsigned int num_scope_syms,struct policy_file * fp)2020 static int scope_index_write(scope_index_t * scope_index,
2021 			     unsigned int num_scope_syms,
2022 			     struct policy_file *fp)
2023 {
2024 	unsigned int i;
2025 	uint32_t buf[1];
2026 	for (i = 0; i < num_scope_syms; i++) {
2027 		if (ebitmap_write(scope_index->scope + i, fp) == -1) {
2028 			return POLICYDB_ERROR;
2029 		}
2030 	}
2031 	buf[0] = cpu_to_le32(scope_index->class_perms_len);
2032 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2033 		return POLICYDB_ERROR;
2034 	}
2035 	for (i = 0; i < scope_index->class_perms_len; i++) {
2036 		if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
2037 			return POLICYDB_ERROR;
2038 		}
2039 	}
2040 	return POLICYDB_SUCCESS;
2041 }
2042 
avrule_decl_write(avrule_decl_t * decl,int num_scope_syms,policydb_t * p,struct policy_file * fp)2043 static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
2044 			     policydb_t * p, struct policy_file *fp)
2045 {
2046 	struct policy_data pd;
2047 	uint32_t buf[2];
2048 	int i;
2049 	buf[0] = cpu_to_le32(decl->decl_id);
2050 	buf[1] = cpu_to_le32(decl->enabled);
2051 	if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2052 		return POLICYDB_ERROR;
2053 	}
2054 	if (cond_write_list(p, decl->cond_list, fp) == -1 ||
2055 	    avrule_write_list(p, decl->avrules, fp) == -1 ||
2056 	    role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
2057 	    role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
2058 		return POLICYDB_ERROR;
2059 	}
2060 
2061 	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
2062 	    filename_trans_rule_write(p, decl->filename_trans_rules, fp))
2063 		return POLICYDB_ERROR;
2064 
2065 	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
2066 	    range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
2067 		return POLICYDB_ERROR;
2068 	}
2069 	if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
2070 	    scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
2071 		return POLICYDB_ERROR;
2072 	}
2073 	pd.fp = fp;
2074 	pd.p = p;
2075 	for (i = 0; i < num_scope_syms; i++) {
2076 		buf[0] = cpu_to_le32(decl->symtab[i].nprim);
2077 		buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
2078 		if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2079 			return POLICYDB_ERROR;
2080 		}
2081 		if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
2082 			return POLICYDB_ERROR;
2083 		}
2084 	}
2085 	return POLICYDB_SUCCESS;
2086 }
2087 
avrule_block_write(avrule_block_t * block,int num_scope_syms,policydb_t * p,struct policy_file * fp)2088 static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
2089 			      policydb_t * p, struct policy_file *fp)
2090 {
2091 	/* first write a count of the total number of blocks */
2092 	uint32_t buf[1], num_blocks = 0;
2093 	avrule_block_t *cur;
2094 	for (cur = block; cur != NULL; cur = cur->next) {
2095 		num_blocks++;
2096 	}
2097 	buf[0] = cpu_to_le32(num_blocks);
2098 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2099 		return POLICYDB_ERROR;
2100 	}
2101 
2102 	/* now write each block */
2103 	for (cur = block; cur != NULL; cur = cur->next) {
2104 		uint32_t num_decls = 0;
2105 		avrule_decl_t *decl;
2106 		/* write a count of number of branches */
2107 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2108 			num_decls++;
2109 		}
2110 		buf[0] = cpu_to_le32(num_decls);
2111 		if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2112 			return POLICYDB_ERROR;
2113 		}
2114 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2115 			if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
2116 			    -1) {
2117 				return POLICYDB_ERROR;
2118 			}
2119 		}
2120 	}
2121 	return POLICYDB_SUCCESS;
2122 }
2123 
scope_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)2124 static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
2125 {
2126 	scope_datum_t *scope = (scope_datum_t *) datum;
2127 	struct policy_data *pd = ptr;
2128 	struct policy_file *fp = pd->fp;
2129 	uint32_t static_buf[32], *dyn_buf = NULL, *buf;
2130 	size_t key_len = strlen(key);
2131 	unsigned int items = 2 + scope->decl_ids_len, i;
2132 	int rc;
2133 
2134 	buf = static_buf;
2135 	if (items >= (sizeof(static_buf) / 4)) {
2136 		/* too many things required, so dynamically create a
2137 		 * buffer.  this would have been easier with C99's
2138 		 * dynamic arrays... */
2139 		rc = POLICYDB_ERROR;
2140 		dyn_buf = calloc(items, sizeof(*dyn_buf));
2141 		if (!dyn_buf)
2142 			goto err;
2143 		buf = dyn_buf;
2144 	}
2145 	buf[0] = cpu_to_le32(key_len);
2146 
2147 	rc = POLICYDB_ERROR;
2148 	if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
2149 	    put_entry(key, 1, key_len, fp) != key_len)
2150 		goto err;
2151 	buf[0] = cpu_to_le32(scope->scope);
2152 	buf[1] = cpu_to_le32(scope->decl_ids_len);
2153 
2154 	for (i = 0; i < scope->decl_ids_len; i++)
2155 		buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
2156 
2157 	rc = POLICYDB_ERROR;
2158 	if (put_entry(buf, sizeof(*buf), items, fp) != items)
2159 		goto err;
2160 	rc = POLICYDB_SUCCESS;
2161 err:
2162 	free(dyn_buf);
2163 	return rc;
2164 }
2165 
type_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2166 static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2167 			     hashtab_datum_t datum, void *args)
2168 {
2169 	type_datum_t *typdatum = datum;
2170 	uint32_t *p_nel = args;
2171 
2172 	if (typdatum->flavor == TYPE_ATTRIB) {
2173 		/* uncount attribute from total number of types */
2174 		(*p_nel)--;
2175 	}
2176 	return 0;
2177 }
2178 
role_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2179 static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2180 			     hashtab_datum_t datum, void *args)
2181 {
2182 	role_datum_t *role = datum;
2183 	uint32_t *p_nel = args;
2184 
2185 	if (role->flavor == ROLE_ATTRIB) {
2186 		/* uncount attribute from total number of roles */
2187 		(*p_nel)--;
2188 	}
2189 	return 0;
2190 }
2191 
2192 /*
2193  * Write the configuration data in a policy database
2194  * structure to a policy database binary representation
2195  * file.
2196  */
policydb_write(policydb_t * p,struct policy_file * fp)2197 int policydb_write(policydb_t * p, struct policy_file *fp)
2198 {
2199 	unsigned int i, num_syms;
2200 	uint32_t buf[32], config;
2201 	size_t items, items2, len;
2202 	const struct policydb_compat_info *info;
2203 	struct policy_data pd;
2204 	const char *policydb_str;
2205 
2206 	if (p->unsupported_format)
2207 		return POLICYDB_UNSUPPORTED;
2208 
2209 	pd.fp = fp;
2210 	pd.p = p;
2211 
2212 	config = 0;
2213 	if (p->mls) {
2214 		if ((p->policyvers < POLICYDB_VERSION_MLS &&
2215 		    p->policy_type == POLICY_KERN) ||
2216 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2217 		    p->policy_type == POLICY_BASE) ||
2218 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2219 		    p->policy_type == POLICY_MOD)) {
2220 			ERR(fp->handle, "policy version %d cannot support MLS",
2221 			    p->policyvers);
2222 			return POLICYDB_ERROR;
2223 		}
2224 		config |= POLICYDB_CONFIG_MLS;
2225 	}
2226 
2227 	config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
2228 
2229 	/* Write the magic number and string identifiers. */
2230 	items = 0;
2231 	if (p->policy_type == POLICY_KERN) {
2232 		buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
2233 		len = strlen(policydb_target_strings[p->target_platform]);
2234 		policydb_str = policydb_target_strings[p->target_platform];
2235 	} else {
2236 		buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
2237 		len = strlen(POLICYDB_MOD_STRING);
2238 		policydb_str = POLICYDB_MOD_STRING;
2239 	}
2240 	buf[items++] = cpu_to_le32(len);
2241 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2242 	if (items != items2)
2243 		return POLICYDB_ERROR;
2244 	items = put_entry(policydb_str, 1, len, fp);
2245 	if (items != len)
2246 		return POLICYDB_ERROR;
2247 
2248 	/* Write the version, config, and table sizes. */
2249 	items = 0;
2250 	info = policydb_lookup_compat(p->policyvers, p->policy_type,
2251 					p->target_platform);
2252 	if (!info) {
2253 		ERR(fp->handle, "compatibility lookup failed for policy "
2254 		    "version %d", p->policyvers);
2255 		return POLICYDB_ERROR;
2256 	}
2257 
2258 	if (p->policy_type != POLICY_KERN) {
2259 		buf[items++] = cpu_to_le32(p->policy_type);
2260 	}
2261 	buf[items++] = cpu_to_le32(p->policyvers);
2262 	buf[items++] = cpu_to_le32(config);
2263 	buf[items++] = cpu_to_le32(info->sym_num);
2264 	buf[items++] = cpu_to_le32(info->ocon_num);
2265 
2266 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2267 	if (items != items2)
2268 		return POLICYDB_ERROR;
2269 
2270 	if (p->policy_type == POLICY_MOD) {
2271 		/* Write module name and version */
2272 		len = strlen(p->name);
2273 		buf[0] = cpu_to_le32(len);
2274 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
2275 		if (items != 1)
2276 			return POLICYDB_ERROR;
2277 		items = put_entry(p->name, 1, len, fp);
2278 		if (items != len)
2279 			return POLICYDB_ERROR;
2280 		len = strlen(p->version);
2281 		buf[0] = cpu_to_le32(len);
2282 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
2283 		if (items != 1)
2284 			return POLICYDB_ERROR;
2285 		items = put_entry(p->version, 1, len, fp);
2286 		if (items != len)
2287 			return POLICYDB_ERROR;
2288 	}
2289 
2290 	if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
2291 	     p->policy_type == POLICY_KERN) ||
2292 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2293 	     p->policy_type == POLICY_BASE) ||
2294 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2295 	     p->policy_type == POLICY_MOD)) {
2296 		if (ebitmap_write(&p->policycaps, fp) == -1)
2297 			return POLICYDB_ERROR;
2298 	}
2299 
2300 	if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
2301 	    p->policy_type == POLICY_KERN) {
2302 		ebitmap_node_t *tnode;
2303 
2304 		ebitmap_for_each_positive_bit(&p->permissive_map, tnode, i) {
2305 			WARN(fp->handle, "Warning! Policy version %d cannot "
2306 			     "support permissive types, but some were defined",
2307 			     p->policyvers);
2308 			break;
2309 		}
2310 	}
2311 
2312 	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
2313 	    p->policy_type == POLICY_KERN) {
2314 		if (ebitmap_write(&p->permissive_map, fp) == -1)
2315 			return POLICYDB_ERROR;
2316 	}
2317 
2318 	num_syms = info->sym_num;
2319 	for (i = 0; i < num_syms; i++) {
2320 		buf[0] = cpu_to_le32(p->symtab[i].nprim);
2321 		buf[1] = p->symtab[i].table->nel;
2322 
2323 		/*
2324 		 * A special case when writing type/attribute symbol table.
2325 		 * The kernel policy version less than 24 does not support
2326 		 * to load entries of attribute, so we have to re-calculate
2327 		 * the actual number of types except for attributes.
2328 		 */
2329 		if (i == SYM_TYPES &&
2330 		    p->policyvers < POLICYDB_VERSION_BOUNDARY &&
2331 		    p->policy_type == POLICY_KERN) {
2332 			hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
2333 		}
2334 
2335 		/*
2336 		 * Another special case when writing role/attribute symbol
2337 		 * table, role attributes are redundant for policy.X, or
2338 		 * when the pp's version is not big enough. So deduct
2339 		 * their numbers from p_roles.table->nel.
2340 		 */
2341 		if ((i == SYM_ROLES) &&
2342 		    ((p->policy_type == POLICY_KERN) ||
2343 		     (p->policy_type != POLICY_KERN &&
2344 		      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2345 			(void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
2346 
2347 		buf[1] = cpu_to_le32(buf[1]);
2348 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
2349 		if (items != 2)
2350 			return POLICYDB_ERROR;
2351 		if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
2352 			return POLICYDB_ERROR;
2353 	}
2354 
2355 	if (p->policy_type == POLICY_KERN) {
2356 		if (avtab_write(p, &p->te_avtab, fp))
2357 			return POLICYDB_ERROR;
2358 		if (p->policyvers < POLICYDB_VERSION_BOOL) {
2359 			if (p->p_bools.nprim)
2360 				WARN(fp->handle, "Discarding "
2361 				     "booleans and conditional rules");
2362 		} else {
2363 			if (cond_write_list(p, p->cond_list, fp))
2364 				return POLICYDB_ERROR;
2365 		}
2366 		if (role_trans_write(p, fp))
2367 			return POLICYDB_ERROR;
2368 		if (role_allow_write(p->role_allow, fp))
2369 			return POLICYDB_ERROR;
2370 		if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
2371 			if (filename_trans_write(p, fp))
2372 				return POLICYDB_ERROR;
2373 		} else {
2374 			if (p->filename_trans)
2375 				WARN(fp->handle, "Discarding filename type transition rules");
2376 		}
2377 	} else {
2378 		if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
2379 			return POLICYDB_ERROR;
2380 		}
2381 
2382 		for (i = 0; i < num_syms; i++) {
2383 			buf[0] = cpu_to_le32(p->scope[i].table->nel);
2384 			if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2385 				return POLICYDB_ERROR;
2386 			}
2387 			if (hashtab_map(p->scope[i].table, scope_write, &pd))
2388 				return POLICYDB_ERROR;
2389 		}
2390 	}
2391 
2392 	if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
2393 		return POLICYDB_ERROR;
2394 	}
2395 
2396 	if ((p->policyvers >= POLICYDB_VERSION_MLS
2397 	     && p->policy_type == POLICY_KERN)
2398 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
2399 		&& p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
2400 		&& p->policy_type == POLICY_BASE)) {
2401 		if (range_write(p, fp)) {
2402 			return POLICYDB_ERROR;
2403 		}
2404 	}
2405 
2406 	if (p->policy_type == POLICY_KERN
2407 	    && p->policyvers >= POLICYDB_VERSION_AVTAB) {
2408 		for (i = 0; i < p->p_types.nprim; i++) {
2409 			if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2410 				return POLICYDB_ERROR;
2411 		}
2412 	}
2413 
2414 	return POLICYDB_SUCCESS;
2415 }
2416