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