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