• 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 	items = 0;
1749 	buf[items++] = cpu_to_le32(avrule->specified);
1750 	buf[items++] = cpu_to_le32(avrule->flags);
1751 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1752 	if (items2 != items)
1753 		return POLICYDB_ERROR;
1754 
1755 	if (type_set_write(&avrule->stypes, fp))
1756 		return POLICYDB_ERROR;
1757 
1758 	if (type_set_write(&avrule->ttypes, fp))
1759 		return POLICYDB_ERROR;
1760 
1761 	cur = avrule->perms;
1762 	len = 0;
1763 	while (cur) {
1764 		len++;
1765 		cur = cur->next;
1766 	}
1767 	items = 0;
1768 	buf[items++] = cpu_to_le32(len);
1769 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1770 	if (items2 != items)
1771 		return POLICYDB_ERROR;
1772 	cur = avrule->perms;
1773 	while (cur) {
1774 		items = 0;
1775 		buf[items++] = cpu_to_le32(cur->tclass);
1776 		buf[items++] = cpu_to_le32(cur->data);
1777 		items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1778 		if (items2 != items)
1779 			return POLICYDB_ERROR;
1780 
1781 		cur = cur->next;
1782 	}
1783 
1784 	if (avrule->specified & AVRULE_XPERMS) {
1785 		size_t nel = ARRAY_SIZE(avrule->xperms->perms);
1786 		uint32_t buf32[nel];
1787 		uint8_t buf8;
1788 		unsigned int i;
1789 
1790 		if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
1791 			ERR(fp->handle,
1792 			    "module policy version %u does not support ioctl"
1793 			    " extended permissions rules and one was specified",
1794 			    p->policyvers);
1795 			return POLICYDB_ERROR;
1796 		}
1797 
1798 		if (p->target_platform != SEPOL_TARGET_SELINUX) {
1799 			ERR(fp->handle,
1800 			    "Target platform %s does not support ioctl"
1801 			    " extended permissions rules and one was specified",
1802 			    policydb_target_strings[p->target_platform]);
1803 			return POLICYDB_ERROR;
1804 		}
1805 
1806 		buf8 = avrule->xperms->specified;
1807 		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1808 		if (items != 1)
1809 			return POLICYDB_ERROR;
1810 		buf8 = avrule->xperms->driver;
1811 		items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1812 		if (items != 1)
1813 			return POLICYDB_ERROR;
1814 		for (i = 0; i < nel; i++)
1815 			buf32[i] = cpu_to_le32(avrule->xperms->perms[i]);
1816 		items = put_entry(buf32, sizeof(uint32_t), nel, fp);
1817 		if (items != nel)
1818 			return POLICYDB_ERROR;
1819 	}
1820 
1821 	return POLICYDB_SUCCESS;
1822 }
1823 
avrule_write_list(policydb_t * p,avrule_t * avrules,struct policy_file * fp)1824 static int avrule_write_list(policydb_t *p, avrule_t * avrules,
1825 			     struct policy_file *fp)
1826 {
1827 	uint32_t buf[32], len;
1828 	avrule_t *avrule;
1829 
1830 	avrule = avrules;
1831 	len = 0;
1832 	while (avrule) {
1833 		len++;
1834 		avrule = avrule->next;
1835 	}
1836 
1837 	buf[0] = cpu_to_le32(len);
1838 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1839 		return POLICYDB_ERROR;
1840 
1841 	avrule = avrules;
1842 	while (avrule) {
1843 		if (avrule_write(p, avrule, fp))
1844 			return POLICYDB_ERROR;
1845 		avrule = avrule->next;
1846 	}
1847 
1848 	return POLICYDB_SUCCESS;
1849 }
1850 
only_process(ebitmap_t * in,struct policydb * p)1851 static int only_process(ebitmap_t *in, struct policydb *p)
1852 {
1853 	unsigned int i, value;
1854 	ebitmap_node_t *node;
1855 
1856 	if (!p->process_class)
1857 		return 0;
1858 
1859 	value = p->process_class - 1;
1860 
1861 	ebitmap_for_each_positive_bit(in, node, i) {
1862 		if (i != value)
1863 			return 0;
1864 	}
1865 	return 1;
1866 }
1867 
role_trans_rule_write(policydb_t * p,role_trans_rule_t * t,struct policy_file * fp)1868 static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
1869 				 struct policy_file *fp)
1870 {
1871 	int nel = 0;
1872 	size_t items;
1873 	uint32_t buf[1];
1874 	role_trans_rule_t *tr;
1875 	int warned = 0;
1876 	int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1877 
1878 	for (tr = t; tr; tr = tr->next)
1879 		if (new_role || only_process(&tr->classes, p))
1880 			nel++;
1881 
1882 	buf[0] = cpu_to_le32(nel);
1883 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1884 	if (items != 1)
1885 		return POLICYDB_ERROR;
1886 	for (tr = t; tr; tr = tr->next) {
1887 		if (!new_role && !only_process(&tr->classes, p)) {
1888 			if (!warned)
1889 				WARN(fp->handle, "Discarding role_transition "
1890 					"rules for security classes other than "
1891 					"\"process\"");
1892 			warned = 1;
1893 			continue;
1894 		}
1895 		if (role_set_write(&tr->roles, fp))
1896 			return POLICYDB_ERROR;
1897 		if (type_set_write(&tr->types, fp))
1898 			return POLICYDB_ERROR;
1899 		if (new_role)
1900 			if (ebitmap_write(&tr->classes, fp))
1901 				return POLICYDB_ERROR;
1902 		buf[0] = cpu_to_le32(tr->new_role);
1903 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1904 		if (items != 1)
1905 			return POLICYDB_ERROR;
1906 	}
1907 	return POLICYDB_SUCCESS;
1908 }
1909 
role_allow_rule_write(role_allow_rule_t * r,struct policy_file * fp)1910 static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
1911 {
1912 	int nel = 0;
1913 	size_t items;
1914 	uint32_t buf[1];
1915 	role_allow_rule_t *ra;
1916 
1917 	for (ra = r; ra; ra = ra->next)
1918 		nel++;
1919 	buf[0] = cpu_to_le32(nel);
1920 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1921 	if (items != 1)
1922 		return POLICYDB_ERROR;
1923 	for (ra = r; ra; ra = ra->next) {
1924 		if (role_set_write(&ra->roles, fp))
1925 			return POLICYDB_ERROR;
1926 		if (role_set_write(&ra->new_roles, fp))
1927 			return POLICYDB_ERROR;
1928 	}
1929 	return POLICYDB_SUCCESS;
1930 }
1931 
filename_trans_rule_write(filename_trans_rule_t * t,struct policy_file * fp)1932 static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp)
1933 {
1934 	int nel = 0;
1935 	size_t items;
1936 	uint32_t buf[2], len;
1937 	filename_trans_rule_t *ftr;
1938 
1939 	for (ftr = t; ftr; ftr = ftr->next)
1940 		nel++;
1941 
1942 	buf[0] = cpu_to_le32(nel);
1943 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1944 	if (items != 1)
1945 		return POLICYDB_ERROR;
1946 
1947 	for (ftr = t; ftr; ftr = ftr->next) {
1948 		len = strlen(ftr->name);
1949 		buf[0] = cpu_to_le32(len);
1950 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
1951 		if (items != 1)
1952 			return POLICYDB_ERROR;
1953 
1954 		items = put_entry(ftr->name, sizeof(char), len, fp);
1955 		if (items != len)
1956 			return POLICYDB_ERROR;
1957 
1958 		if (type_set_write(&ftr->stypes, fp))
1959 			return POLICYDB_ERROR;
1960 		if (type_set_write(&ftr->ttypes, fp))
1961 			return POLICYDB_ERROR;
1962 
1963 		buf[0] = cpu_to_le32(ftr->tclass);
1964 		buf[1] = cpu_to_le32(ftr->otype);
1965 
1966 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
1967 		if (items != 2)
1968 			return POLICYDB_ERROR;
1969 	}
1970 	return POLICYDB_SUCCESS;
1971 }
1972 
range_trans_rule_write(range_trans_rule_t * t,struct policy_file * fp)1973 static int range_trans_rule_write(range_trans_rule_t * t,
1974 				  struct policy_file *fp)
1975 {
1976 	int nel = 0;
1977 	size_t items;
1978 	uint32_t buf[1];
1979 	range_trans_rule_t *rt;
1980 
1981 	for (rt = t; rt; rt = rt->next)
1982 		nel++;
1983 	buf[0] = cpu_to_le32(nel);
1984 	items = put_entry(buf, sizeof(uint32_t), 1, fp);
1985 	if (items != 1)
1986 		return POLICYDB_ERROR;
1987 	for (rt = t; rt; rt = rt->next) {
1988 		if (type_set_write(&rt->stypes, fp))
1989 			return POLICYDB_ERROR;
1990 		if (type_set_write(&rt->ttypes, fp))
1991 			return POLICYDB_ERROR;
1992 		if (ebitmap_write(&rt->tclasses, fp))
1993 			return POLICYDB_ERROR;
1994 		if (mls_write_semantic_range_helper(&rt->trange, fp))
1995 			return POLICYDB_ERROR;
1996 	}
1997 	return POLICYDB_SUCCESS;
1998 }
1999 
scope_index_write(scope_index_t * scope_index,unsigned int num_scope_syms,struct policy_file * fp)2000 static int scope_index_write(scope_index_t * scope_index,
2001 			     unsigned int num_scope_syms,
2002 			     struct policy_file *fp)
2003 {
2004 	unsigned int i;
2005 	uint32_t buf[1];
2006 	for (i = 0; i < num_scope_syms; i++) {
2007 		if (ebitmap_write(scope_index->scope + i, fp) == -1) {
2008 			return POLICYDB_ERROR;
2009 		}
2010 	}
2011 	buf[0] = cpu_to_le32(scope_index->class_perms_len);
2012 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2013 		return POLICYDB_ERROR;
2014 	}
2015 	for (i = 0; i < scope_index->class_perms_len; i++) {
2016 		if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
2017 			return POLICYDB_ERROR;
2018 		}
2019 	}
2020 	return POLICYDB_SUCCESS;
2021 }
2022 
avrule_decl_write(avrule_decl_t * decl,int num_scope_syms,policydb_t * p,struct policy_file * fp)2023 static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
2024 			     policydb_t * p, struct policy_file *fp)
2025 {
2026 	struct policy_data pd;
2027 	uint32_t buf[2];
2028 	int i;
2029 	buf[0] = cpu_to_le32(decl->decl_id);
2030 	buf[1] = cpu_to_le32(decl->enabled);
2031 	if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2032 		return POLICYDB_ERROR;
2033 	}
2034 	if (cond_write_list(p, decl->cond_list, fp) == -1 ||
2035 	    avrule_write_list(p, decl->avrules, fp) == -1 ||
2036 	    role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
2037 	    role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
2038 		return POLICYDB_ERROR;
2039 	}
2040 
2041 	if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
2042 	    filename_trans_rule_write(decl->filename_trans_rules, fp))
2043 		return POLICYDB_ERROR;
2044 
2045 	if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
2046 	    range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
2047 		return POLICYDB_ERROR;
2048 	}
2049 	if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
2050 	    scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
2051 		return POLICYDB_ERROR;
2052 	}
2053 	pd.fp = fp;
2054 	pd.p = p;
2055 	for (i = 0; i < num_scope_syms; i++) {
2056 		buf[0] = cpu_to_le32(decl->symtab[i].nprim);
2057 		buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
2058 		if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2059 			return POLICYDB_ERROR;
2060 		}
2061 		if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
2062 			return POLICYDB_ERROR;
2063 		}
2064 	}
2065 	return POLICYDB_SUCCESS;
2066 }
2067 
avrule_block_write(avrule_block_t * block,int num_scope_syms,policydb_t * p,struct policy_file * fp)2068 static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
2069 			      policydb_t * p, struct policy_file *fp)
2070 {
2071 	/* first write a count of the total number of blocks */
2072 	uint32_t buf[1], num_blocks = 0;
2073 	avrule_block_t *cur;
2074 	for (cur = block; cur != NULL; cur = cur->next) {
2075 		num_blocks++;
2076 	}
2077 	buf[0] = cpu_to_le32(num_blocks);
2078 	if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2079 		return POLICYDB_ERROR;
2080 	}
2081 
2082 	/* now write each block */
2083 	for (cur = block; cur != NULL; cur = cur->next) {
2084 		uint32_t num_decls = 0;
2085 		avrule_decl_t *decl;
2086 		/* write a count of number of branches */
2087 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2088 			num_decls++;
2089 		}
2090 		buf[0] = cpu_to_le32(num_decls);
2091 		if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2092 			return POLICYDB_ERROR;
2093 		}
2094 		for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2095 			if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
2096 			    -1) {
2097 				return POLICYDB_ERROR;
2098 			}
2099 		}
2100 	}
2101 	return POLICYDB_SUCCESS;
2102 }
2103 
scope_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)2104 static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
2105 {
2106 	scope_datum_t *scope = (scope_datum_t *) datum;
2107 	struct policy_data *pd = ptr;
2108 	struct policy_file *fp = pd->fp;
2109 	uint32_t static_buf[32], *dyn_buf = NULL, *buf;
2110 	size_t key_len = strlen(key);
2111 	unsigned int items = 2 + scope->decl_ids_len, i;
2112 	int rc;
2113 
2114 	buf = static_buf;
2115 	if (items >= (sizeof(static_buf) / 4)) {
2116 		/* too many things required, so dynamically create a
2117 		 * buffer.  this would have been easier with C99's
2118 		 * dynamic arrays... */
2119 		rc = POLICYDB_ERROR;
2120 		dyn_buf = malloc(items * sizeof(*dyn_buf));
2121 		if (!dyn_buf)
2122 			goto err;
2123 		buf = dyn_buf;
2124 	}
2125 	buf[0] = cpu_to_le32(key_len);
2126 
2127 	rc = POLICYDB_ERROR;
2128 	if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
2129 	    put_entry(key, 1, key_len, fp) != key_len)
2130 		goto err;
2131 	buf[0] = cpu_to_le32(scope->scope);
2132 	buf[1] = cpu_to_le32(scope->decl_ids_len);
2133 
2134 	for (i = 0; i < scope->decl_ids_len; i++)
2135 		buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
2136 
2137 	rc = POLICYDB_ERROR;
2138 	if (put_entry(buf, sizeof(*buf), items, fp) != items)
2139 		goto err;
2140 	rc = POLICYDB_SUCCESS;
2141 err:
2142 	free(dyn_buf);
2143 	return rc;
2144 }
2145 
type_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2146 static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2147 			     hashtab_datum_t datum, void *args)
2148 {
2149 	type_datum_t *typdatum = datum;
2150 	uint32_t *p_nel = args;
2151 
2152 	if (typdatum->flavor == TYPE_ATTRIB) {
2153 		/* uncount attribute from total number of types */
2154 		(*p_nel)--;
2155 	}
2156 	return 0;
2157 }
2158 
role_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2159 static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2160 			     hashtab_datum_t datum, void *args)
2161 {
2162 	role_datum_t *role = datum;
2163 	uint32_t *p_nel = args;
2164 
2165 	if (role->flavor == ROLE_ATTRIB) {
2166 		/* uncount attribute from total number of roles */
2167 		(*p_nel)--;
2168 	}
2169 	return 0;
2170 }
2171 
2172 /*
2173  * Write the configuration data in a policy database
2174  * structure to a policy database binary representation
2175  * file.
2176  */
policydb_write(policydb_t * p,struct policy_file * fp)2177 int policydb_write(policydb_t * p, struct policy_file *fp)
2178 {
2179 	unsigned int i, num_syms;
2180 	uint32_t buf[32], config;
2181 	size_t items, items2, len;
2182 	const struct policydb_compat_info *info;
2183 	struct policy_data pd;
2184 	const char *policydb_str;
2185 
2186 	if (p->unsupported_format)
2187 		return POLICYDB_UNSUPPORTED;
2188 
2189 	pd.fp = fp;
2190 	pd.p = p;
2191 
2192 	config = 0;
2193 	if (p->mls) {
2194 		if ((p->policyvers < POLICYDB_VERSION_MLS &&
2195 		    p->policy_type == POLICY_KERN) ||
2196 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2197 		    p->policy_type == POLICY_BASE) ||
2198 		    (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2199 		    p->policy_type == POLICY_MOD)) {
2200 			ERR(fp->handle, "policy version %d cannot support MLS",
2201 			    p->policyvers);
2202 			return POLICYDB_ERROR;
2203 		}
2204 		config |= POLICYDB_CONFIG_MLS;
2205 	}
2206 
2207 	config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
2208 
2209 	/* Write the magic number and string identifiers. */
2210 	items = 0;
2211 	if (p->policy_type == POLICY_KERN) {
2212 		buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
2213 		len = strlen(policydb_target_strings[p->target_platform]);
2214 		policydb_str = policydb_target_strings[p->target_platform];
2215 	} else {
2216 		buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
2217 		len = strlen(POLICYDB_MOD_STRING);
2218 		policydb_str = POLICYDB_MOD_STRING;
2219 	}
2220 	buf[items++] = cpu_to_le32(len);
2221 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2222 	if (items != items2)
2223 		return POLICYDB_ERROR;
2224 	items = put_entry(policydb_str, 1, len, fp);
2225 	if (items != len)
2226 		return POLICYDB_ERROR;
2227 
2228 	/* Write the version, config, and table sizes. */
2229 	items = 0;
2230 	info = policydb_lookup_compat(p->policyvers, p->policy_type,
2231 					p->target_platform);
2232 	if (!info) {
2233 		ERR(fp->handle, "compatibility lookup failed for policy "
2234 		    "version %d", p->policyvers);
2235 		return POLICYDB_ERROR;
2236 	}
2237 
2238 	if (p->policy_type != POLICY_KERN) {
2239 		buf[items++] = cpu_to_le32(p->policy_type);
2240 	}
2241 	buf[items++] = cpu_to_le32(p->policyvers);
2242 	buf[items++] = cpu_to_le32(config);
2243 	buf[items++] = cpu_to_le32(info->sym_num);
2244 	buf[items++] = cpu_to_le32(info->ocon_num);
2245 
2246 	items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2247 	if (items != items2)
2248 		return POLICYDB_ERROR;
2249 
2250 	if (p->policy_type == POLICY_MOD) {
2251 		/* Write module name and version */
2252 		len = strlen(p->name);
2253 		buf[0] = cpu_to_le32(len);
2254 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
2255 		if (items != 1)
2256 			return POLICYDB_ERROR;
2257 		items = put_entry(p->name, 1, len, fp);
2258 		if (items != len)
2259 			return POLICYDB_ERROR;
2260 		len = strlen(p->version);
2261 		buf[0] = cpu_to_le32(len);
2262 		items = put_entry(buf, sizeof(uint32_t), 1, fp);
2263 		if (items != 1)
2264 			return POLICYDB_ERROR;
2265 		items = put_entry(p->version, 1, len, fp);
2266 		if (items != len)
2267 			return POLICYDB_ERROR;
2268 	}
2269 
2270 	if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
2271 	     p->policy_type == POLICY_KERN) ||
2272 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2273 	     p->policy_type == POLICY_BASE) ||
2274 	    (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2275 	     p->policy_type == POLICY_MOD)) {
2276 		if (ebitmap_write(&p->policycaps, fp) == -1)
2277 			return POLICYDB_ERROR;
2278 	}
2279 
2280 	if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
2281 	    p->policy_type == POLICY_KERN) {
2282 		ebitmap_node_t *tnode;
2283 
2284 		ebitmap_for_each_positive_bit(&p->permissive_map, tnode, i) {
2285 			WARN(fp->handle, "Warning! Policy version %d cannot "
2286 			     "support permissive types, but some were defined",
2287 			     p->policyvers);
2288 			break;
2289 		}
2290 	}
2291 
2292 	if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
2293 	    p->policy_type == POLICY_KERN) {
2294 		if (ebitmap_write(&p->permissive_map, fp) == -1)
2295 			return POLICYDB_ERROR;
2296 	}
2297 
2298 	num_syms = info->sym_num;
2299 	for (i = 0; i < num_syms; i++) {
2300 		buf[0] = cpu_to_le32(p->symtab[i].nprim);
2301 		buf[1] = p->symtab[i].table->nel;
2302 
2303 		/*
2304 		 * A special case when writing type/attribute symbol table.
2305 		 * The kernel policy version less than 24 does not support
2306 		 * to load entries of attribute, so we have to re-calculate
2307 		 * the actual number of types except for attributes.
2308 		 */
2309 		if (i == SYM_TYPES &&
2310 		    p->policyvers < POLICYDB_VERSION_BOUNDARY &&
2311 		    p->policy_type == POLICY_KERN) {
2312 			hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
2313 		}
2314 
2315 		/*
2316 		 * Another special case when writing role/attribute symbol
2317 		 * table, role attributes are redundant for policy.X, or
2318 		 * when the pp's version is not big enough. So deduct
2319 		 * their numbers from p_roles.table->nel.
2320 		 */
2321 		if ((i == SYM_ROLES) &&
2322 		    ((p->policy_type == POLICY_KERN) ||
2323 		     (p->policy_type != POLICY_KERN &&
2324 		      p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2325 			(void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
2326 
2327 		buf[1] = cpu_to_le32(buf[1]);
2328 		items = put_entry(buf, sizeof(uint32_t), 2, fp);
2329 		if (items != 2)
2330 			return POLICYDB_ERROR;
2331 		if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
2332 			return POLICYDB_ERROR;
2333 	}
2334 
2335 	if (p->policy_type == POLICY_KERN) {
2336 		if (avtab_write(p, &p->te_avtab, fp))
2337 			return POLICYDB_ERROR;
2338 		if (p->policyvers < POLICYDB_VERSION_BOOL) {
2339 			if (p->p_bools.nprim)
2340 				WARN(fp->handle, "Discarding "
2341 				     "booleans and conditional rules");
2342 		} else {
2343 			if (cond_write_list(p, p->cond_list, fp))
2344 				return POLICYDB_ERROR;
2345 		}
2346 		if (role_trans_write(p, fp))
2347 			return POLICYDB_ERROR;
2348 		if (role_allow_write(p->role_allow, fp))
2349 			return POLICYDB_ERROR;
2350 		if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
2351 			if (filename_trans_write(p, fp))
2352 				return POLICYDB_ERROR;
2353 		} else {
2354 			if (p->filename_trans)
2355 				WARN(fp->handle, "Discarding filename type transition rules");
2356 		}
2357 	} else {
2358 		if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
2359 			return POLICYDB_ERROR;
2360 		}
2361 
2362 		for (i = 0; i < num_syms; i++) {
2363 			buf[0] = cpu_to_le32(p->scope[i].table->nel);
2364 			if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2365 				return POLICYDB_ERROR;
2366 			}
2367 			if (hashtab_map(p->scope[i].table, scope_write, &pd))
2368 				return POLICYDB_ERROR;
2369 		}
2370 	}
2371 
2372 	if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
2373 		return POLICYDB_ERROR;
2374 	}
2375 
2376 	if ((p->policyvers >= POLICYDB_VERSION_MLS
2377 	     && p->policy_type == POLICY_KERN)
2378 	    || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
2379 		&& p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
2380 		&& p->policy_type == POLICY_BASE)) {
2381 		if (range_write(p, fp)) {
2382 			return POLICYDB_ERROR;
2383 		}
2384 	}
2385 
2386 	if (p->policy_type == POLICY_KERN
2387 	    && p->policyvers >= POLICYDB_VERSION_AVTAB) {
2388 		for (i = 0; i < p->p_types.nprim; i++) {
2389 			if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2390 				return POLICYDB_ERROR;
2391 		}
2392 	}
2393 
2394 	return POLICYDB_SUCCESS;
2395 }
2396