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