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