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