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