1
2 /* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
3
4 /*
5 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
6 *
7 * Support for enhanced MLS infrastructure.
8 *
9 * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
10 *
11 * Added conditional policy language extensions
12 *
13 * Updated: Joshua Brindle <jbrindle@tresys.com> and Jason Tang <jtang@tresys.org>
14 *
15 * Module writing support
16 *
17 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
18 * Copyright (C) 2003-2005 Tresys Technology, LLC
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This library is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34 #include <assert.h>
35 #include <stdlib.h>
36
37 #include <sepol/policydb/ebitmap.h>
38 #include <sepol/policydb/avtab.h>
39 #include <sepol/policydb/policydb.h>
40 #include <sepol/policydb/conditional.h>
41 #include <sepol/policydb/expand.h>
42 #include <sepol/policydb/flask.h>
43
44 #include "debug.h"
45 #include "private.h"
46 #include "mls.h"
47
48 struct policy_data {
49 struct policy_file *fp;
50 struct policydb *p;
51 };
52
53 static int avrule_write_list(avrule_t * avrules, struct policy_file *fp);
54
ebitmap_write(ebitmap_t * e,struct policy_file * fp)55 static int ebitmap_write(ebitmap_t * e, struct policy_file *fp)
56 {
57 ebitmap_node_t *n;
58 uint32_t buf[32], bit, count;
59 uint64_t map;
60 size_t items;
61
62 buf[0] = cpu_to_le32(MAPSIZE);
63 buf[1] = cpu_to_le32(e->highbit);
64
65 count = 0;
66 for (n = e->node; n; n = n->next)
67 count++;
68 buf[2] = cpu_to_le32(count);
69
70 items = put_entry(buf, sizeof(uint32_t), 3, fp);
71 if (items != 3)
72 return POLICYDB_ERROR;
73
74 for (n = e->node; n; n = n->next) {
75 bit = cpu_to_le32(n->startbit);
76 items = put_entry(&bit, sizeof(uint32_t), 1, fp);
77 if (items != 1)
78 return POLICYDB_ERROR;
79 map = cpu_to_le64(n->map);
80 items = put_entry(&map, sizeof(uint64_t), 1, fp);
81 if (items != 1)
82 return POLICYDB_ERROR;
83
84 }
85
86 return POLICYDB_SUCCESS;
87 }
88
89 /* Ordering of datums in the original avtab format in the policy file. */
90 static uint16_t spec_order[] = {
91 AVTAB_ALLOWED,
92 AVTAB_AUDITDENY,
93 AVTAB_AUDITALLOW,
94 AVTAB_TRANSITION,
95 AVTAB_CHANGE,
96 AVTAB_MEMBER
97 };
98
avtab_write_item(policydb_t * p,avtab_ptr_t cur,struct policy_file * fp,unsigned merge,unsigned commit,uint32_t * nel)99 static int avtab_write_item(policydb_t * p,
100 avtab_ptr_t cur, struct policy_file *fp,
101 unsigned merge, unsigned commit, uint32_t * nel)
102 {
103 avtab_ptr_t node;
104 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
avtab_reset_merged(avtab_t * a)230 static 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
avtab_write(struct policydb * p,avtab_t * a,struct policy_file * fp)240 static 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 */
mls_write_semantic_level_helper(mls_semantic_level_t * l,struct policy_file * fp)315 static 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 */
mls_write_semantic_range_helper(mls_semantic_range_t * r,struct policy_file * fp)346 static 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 */
mls_write_level(mls_level_t * l,struct policy_file * fp)364 static 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 */
mls_write_range_helper(mls_range_t * r,struct policy_file * fp)384 static 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
sens_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)411 static 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
cat_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)439 static 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
role_trans_write(policydb_t * p,struct policy_file * fp)465 static 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
role_allow_write(role_allow_t * r,struct policy_file * fp)510 static 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
filename_trans_write(filename_trans_t * r,struct policy_file * fp)533 static 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
role_set_write(role_set_t * x,struct policy_file * fp)569 static 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
type_set_write(type_set_t * x,struct policy_file * fp)585 static 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
cond_write_bool(hashtab_key_t key,hashtab_datum_t datum,void * ptr)603 static 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 */
cond_write_av_list(policydb_t * p,cond_av_list_t * list,struct policy_file * fp)646 static 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
cond_write_node(policydb_t * p,cond_node_t * node,struct policy_file * fp)697 static 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
cond_write_list(policydb_t * p,cond_list_t * list,struct policy_file * fp)751 static 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 */
context_write(struct policydb * p,context_struct_t * c,struct policy_file * fp)777 static 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
perm_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)806 static 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
common_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)831 static 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
write_cons_helper(policydb_t * p,constraint_node_t * node,int allowxtarget,struct policy_file * fp)861 static 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 (p->policy_type == POLICY_KERN &&
899 (p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) &&
900 type_set_write(e->type_names, fp))) {
901 return POLICYDB_ERROR;
902 }
903 break;
904 default:
905 break;
906 }
907 }
908 }
909
910 return POLICYDB_SUCCESS;
911 }
912
class_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)913 static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
914 {
915 class_datum_t *cladatum;
916 constraint_node_t *c;
917 uint32_t buf[32], ncons;
918 size_t items, items2, len, len2;
919 struct policy_data *pd = ptr;
920 struct policy_file *fp = pd->fp;
921 struct policydb *p = pd->p;
922
923 cladatum = (class_datum_t *) datum;
924
925 len = strlen(key);
926 if (cladatum->comkey)
927 len2 = strlen(cladatum->comkey);
928 else
929 len2 = 0;
930
931 ncons = 0;
932 for (c = cladatum->constraints; c; c = c->next) {
933 ncons++;
934 }
935
936 items = 0;
937 buf[items++] = cpu_to_le32(len);
938 buf[items++] = cpu_to_le32(len2);
939 buf[items++] = cpu_to_le32(cladatum->s.value);
940 buf[items++] = cpu_to_le32(cladatum->permissions.nprim);
941 if (cladatum->permissions.table)
942 buf[items++] = cpu_to_le32(cladatum->permissions.table->nel);
943 else
944 buf[items++] = 0;
945 buf[items++] = cpu_to_le32(ncons);
946 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
947 if (items != items2)
948 return POLICYDB_ERROR;
949
950 items = put_entry(key, 1, len, fp);
951 if (items != len)
952 return POLICYDB_ERROR;
953
954 if (cladatum->comkey) {
955 items = put_entry(cladatum->comkey, 1, len2, fp);
956 if (items != len2)
957 return POLICYDB_ERROR;
958 }
959 if (hashtab_map(cladatum->permissions.table, perm_write, pd))
960 return POLICYDB_ERROR;
961
962 if (write_cons_helper(p, cladatum->constraints, 0, fp))
963 return POLICYDB_ERROR;
964
965 if ((p->policy_type == POLICY_KERN
966 && p->policyvers >= POLICYDB_VERSION_VALIDATETRANS)
967 || (p->policy_type == POLICY_BASE
968 && p->policyvers >= MOD_POLICYDB_VERSION_VALIDATETRANS)) {
969 /* write out the validatetrans rule */
970 ncons = 0;
971 for (c = cladatum->validatetrans; c; c = c->next) {
972 ncons++;
973 }
974 buf[0] = cpu_to_le32(ncons);
975 items = put_entry(buf, sizeof(uint32_t), 1, fp);
976 if (items != 1)
977 return POLICYDB_ERROR;
978 if (write_cons_helper(p, cladatum->validatetrans, 1, fp))
979 return POLICYDB_ERROR;
980 }
981
982 if ((p->policy_type == POLICY_KERN &&
983 p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) ||
984 (p->policy_type == POLICY_BASE &&
985 p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) {
986 buf[0] = cpu_to_le32(cladatum->default_user);
987 buf[1] = cpu_to_le32(cladatum->default_role);
988 buf[2] = cpu_to_le32(cladatum->default_range);
989 items = put_entry(buf, sizeof(uint32_t), 3, fp);
990 if (items != 3)
991 return POLICYDB_ERROR;
992 }
993
994 if ((p->policy_type == POLICY_KERN &&
995 p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) ||
996 (p->policy_type == POLICY_BASE &&
997 p->policyvers >= MOD_POLICYDB_VERSION_DEFAULT_TYPE)) {
998 buf[0] = cpu_to_le32(cladatum->default_type);
999 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1000 if (items != 1)
1001 return POLICYDB_ERROR;
1002 }
1003
1004 return POLICYDB_SUCCESS;
1005 }
1006
role_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1007 static int role_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1008 {
1009 role_datum_t *role;
1010 uint32_t buf[32];
1011 size_t items, items2, len;
1012 struct policy_data *pd = ptr;
1013 struct policy_file *fp = pd->fp;
1014 struct policydb *p = pd->p;
1015
1016 role = (role_datum_t *) datum;
1017
1018 /*
1019 * Role attributes are redundant for policy.X, skip them
1020 * when writing the roles symbol table. They are also skipped
1021 * when pp is downgraded.
1022 *
1023 * Their numbers would be deducted in policydb_write().
1024 */
1025 if ((role->flavor == ROLE_ATTRIB) &&
1026 ((p->policy_type == POLICY_KERN) ||
1027 (p->policy_type != POLICY_KERN &&
1028 p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
1029 return POLICYDB_SUCCESS;
1030
1031 len = strlen(key);
1032 items = 0;
1033 buf[items++] = cpu_to_le32(len);
1034 buf[items++] = cpu_to_le32(role->s.value);
1035 if (policydb_has_boundary_feature(p))
1036 buf[items++] = cpu_to_le32(role->bounds);
1037 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1038 if (items != items2)
1039 return POLICYDB_ERROR;
1040
1041 items = put_entry(key, 1, len, fp);
1042 if (items != len)
1043 return POLICYDB_ERROR;
1044
1045 if (ebitmap_write(&role->dominates, fp))
1046 return POLICYDB_ERROR;
1047 if (p->policy_type == POLICY_KERN) {
1048 if (ebitmap_write(&role->types.types, fp))
1049 return POLICYDB_ERROR;
1050 } else {
1051 if (type_set_write(&role->types, fp))
1052 return POLICYDB_ERROR;
1053 }
1054
1055 if (p->policy_type != POLICY_KERN &&
1056 p->policyvers >= MOD_POLICYDB_VERSION_ROLEATTRIB) {
1057 buf[0] = cpu_to_le32(role->flavor);
1058 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1059 if (items != 1)
1060 return POLICYDB_ERROR;
1061
1062 if (ebitmap_write(&role->roles, fp))
1063 return POLICYDB_ERROR;
1064 }
1065
1066 return POLICYDB_SUCCESS;
1067 }
1068
type_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1069 static int type_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1070 {
1071 type_datum_t *typdatum;
1072 uint32_t buf[32];
1073 size_t items, items2, len;
1074 struct policy_data *pd = ptr;
1075 struct policy_file *fp = pd->fp;
1076 struct policydb *p = pd->p;
1077
1078 typdatum = (type_datum_t *) datum;
1079
1080 /*
1081 * The kernel policy version less than 24 (= POLICYDB_VERSION_BOUNDARY)
1082 * does not support to load entries of attribute, so we skip to write it.
1083 */
1084 if (p->policy_type == POLICY_KERN
1085 && p->policyvers < POLICYDB_VERSION_BOUNDARY
1086 && typdatum->flavor == TYPE_ATTRIB)
1087 return POLICYDB_SUCCESS;
1088
1089 len = strlen(key);
1090 items = 0;
1091 buf[items++] = cpu_to_le32(len);
1092 buf[items++] = cpu_to_le32(typdatum->s.value);
1093 if (policydb_has_boundary_feature(p)) {
1094 uint32_t properties = 0;
1095
1096 if (p->policy_type != POLICY_KERN
1097 && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY_ALIAS) {
1098 buf[items++] = cpu_to_le32(typdatum->primary);
1099 }
1100
1101 if (typdatum->primary)
1102 properties |= TYPEDATUM_PROPERTY_PRIMARY;
1103
1104 if (typdatum->flavor == TYPE_ATTRIB) {
1105 properties |= TYPEDATUM_PROPERTY_ATTRIBUTE;
1106 } else if (typdatum->flavor == TYPE_ALIAS
1107 && p->policy_type != POLICY_KERN)
1108 properties |= TYPEDATUM_PROPERTY_ALIAS;
1109
1110 if (typdatum->flags & TYPE_FLAGS_PERMISSIVE
1111 && p->policy_type != POLICY_KERN)
1112 properties |= TYPEDATUM_PROPERTY_PERMISSIVE;
1113
1114 buf[items++] = cpu_to_le32(properties);
1115 buf[items++] = cpu_to_le32(typdatum->bounds);
1116 } else {
1117 buf[items++] = cpu_to_le32(typdatum->primary);
1118
1119 if (p->policy_type != POLICY_KERN) {
1120 buf[items++] = cpu_to_le32(typdatum->flavor);
1121
1122 if (p->policyvers >= MOD_POLICYDB_VERSION_PERMISSIVE)
1123 buf[items++] = cpu_to_le32(typdatum->flags);
1124 else if (typdatum->flags & TYPE_FLAGS_PERMISSIVE)
1125 WARN(fp->handle, "Warning! Module policy "
1126 "version %d cannot support permissive "
1127 "types, but one was defined",
1128 p->policyvers);
1129 }
1130 }
1131 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1132 if (items != items2)
1133 return POLICYDB_ERROR;
1134
1135 if (p->policy_type != POLICY_KERN) {
1136 if (ebitmap_write(&typdatum->types, fp))
1137 return POLICYDB_ERROR;
1138 }
1139
1140 items = put_entry(key, 1, len, fp);
1141 if (items != len)
1142 return POLICYDB_ERROR;
1143
1144 return POLICYDB_SUCCESS;
1145 }
1146
user_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1147 static int user_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1148 {
1149 user_datum_t *usrdatum;
1150 uint32_t buf[32];
1151 size_t items, items2, len;
1152 struct policy_data *pd = ptr;
1153 struct policy_file *fp = pd->fp;
1154 struct policydb *p = pd->p;
1155
1156 usrdatum = (user_datum_t *) datum;
1157
1158 len = strlen(key);
1159 items = 0;
1160 buf[items++] = cpu_to_le32(len);
1161 buf[items++] = cpu_to_le32(usrdatum->s.value);
1162 if (policydb_has_boundary_feature(p))
1163 buf[items++] = cpu_to_le32(usrdatum->bounds);
1164 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1165 if (items != items2)
1166 return POLICYDB_ERROR;
1167
1168 items = put_entry(key, 1, len, fp);
1169 if (items != len)
1170 return POLICYDB_ERROR;
1171
1172 if (p->policy_type == POLICY_KERN) {
1173 if (ebitmap_write(&usrdatum->roles.roles, fp))
1174 return POLICYDB_ERROR;
1175 } else {
1176 if (role_set_write(&usrdatum->roles, fp))
1177 return POLICYDB_ERROR;
1178 }
1179
1180 if ((p->policyvers >= POLICYDB_VERSION_MLS
1181 && p->policy_type == POLICY_KERN)
1182 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1183 && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1184 && p->policy_type == POLICY_MOD)
1185 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
1186 && p->policyvers < MOD_POLICYDB_VERSION_MLS_USERS
1187 && p->policy_type == POLICY_BASE)) {
1188 if (mls_write_range_helper(&usrdatum->exp_range, fp))
1189 return POLICYDB_ERROR;
1190 if (mls_write_level(&usrdatum->exp_dfltlevel, fp))
1191 return POLICYDB_ERROR;
1192 } else if ((p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1193 && p->policy_type == POLICY_MOD)
1194 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS_USERS
1195 && p->policy_type == POLICY_BASE)) {
1196 if (mls_write_semantic_range_helper(&usrdatum->range, fp))
1197 return -1;
1198 if (mls_write_semantic_level_helper(&usrdatum->dfltlevel, fp))
1199 return -1;
1200 }
1201
1202 return POLICYDB_SUCCESS;
1203 }
1204
1205 static int (*write_f[SYM_NUM]) (hashtab_key_t key, hashtab_datum_t datum,
1206 void *datap) = {
1207 common_write, class_write, role_write, type_write, user_write,
1208 cond_write_bool, sens_write, cat_write,};
1209
ocontext_write_xen(struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1210 static int ocontext_write_xen(struct policydb_compat_info *info, policydb_t *p,
1211 struct policy_file *fp)
1212 {
1213 unsigned int i, j;
1214 size_t nel, items;
1215 uint32_t buf[32];
1216 ocontext_t *c;
1217 for (i = 0; i < info->ocon_num; i++) {
1218 nel = 0;
1219 for (c = p->ocontexts[i]; c; c = c->next)
1220 nel++;
1221 buf[0] = cpu_to_le32(nel);
1222 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1223 if (items != 1)
1224 return POLICYDB_ERROR;
1225 for (c = p->ocontexts[i]; c; c = c->next) {
1226 switch (i) {
1227 case OCON_XEN_ISID:
1228 buf[0] = cpu_to_le32(c->sid[0]);
1229 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1230 if (items != 1)
1231 return POLICYDB_ERROR;
1232 if (context_write(p, &c->context[0], fp))
1233 return POLICYDB_ERROR;
1234 break;
1235 case OCON_XEN_PIRQ:
1236 buf[0] = cpu_to_le32(c->u.pirq);
1237 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1238 if (items != 1)
1239 return POLICYDB_ERROR;
1240 if (context_write(p, &c->context[0], fp))
1241 return POLICYDB_ERROR;
1242 break;
1243 case OCON_XEN_IOPORT:
1244 buf[0] = c->u.ioport.low_ioport;
1245 buf[1] = c->u.ioport.high_ioport;
1246 for (j = 0; j < 2; j++)
1247 buf[j] = cpu_to_le32(buf[j]);
1248 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1249 if (items != 2)
1250 return POLICYDB_ERROR;
1251 if (context_write(p, &c->context[0], fp))
1252 return POLICYDB_ERROR;
1253 break;
1254 case OCON_XEN_IOMEM:
1255 buf[0] = c->u.iomem.low_iomem;
1256 buf[1] = c->u.iomem.high_iomem;
1257 for (j = 0; j < 2; j++)
1258 buf[j] = cpu_to_le32(buf[j]);
1259 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1260 if (items != 2)
1261 return POLICYDB_ERROR;
1262 if (context_write(p, &c->context[0], fp))
1263 return POLICYDB_ERROR;
1264 break;
1265 case OCON_XEN_PCIDEVICE:
1266 buf[0] = cpu_to_le32(c->u.device);
1267 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1268 if (items != 1)
1269 return POLICYDB_ERROR;
1270 if (context_write(p, &c->context[0], fp))
1271 return POLICYDB_ERROR;
1272 break;
1273 }
1274 }
1275 }
1276 return POLICYDB_SUCCESS;
1277 }
1278
ocontext_write_selinux(struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1279 static int ocontext_write_selinux(struct policydb_compat_info *info,
1280 policydb_t *p, struct policy_file *fp)
1281 {
1282 unsigned int i, j;
1283 size_t nel, items, len;
1284 uint32_t buf[32];
1285 ocontext_t *c;
1286 for (i = 0; i < info->ocon_num; i++) {
1287 nel = 0;
1288 for (c = p->ocontexts[i]; c; c = c->next)
1289 nel++;
1290 buf[0] = cpu_to_le32(nel);
1291 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1292 if (items != 1)
1293 return POLICYDB_ERROR;
1294 for (c = p->ocontexts[i]; c; c = c->next) {
1295 switch (i) {
1296 case OCON_ISID:
1297 buf[0] = cpu_to_le32(c->sid[0]);
1298 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1299 if (items != 1)
1300 return POLICYDB_ERROR;
1301 if (context_write(p, &c->context[0], fp))
1302 return POLICYDB_ERROR;
1303 break;
1304 case OCON_FS:
1305 case OCON_NETIF:
1306 len = strlen(c->u.name);
1307 buf[0] = cpu_to_le32(len);
1308 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1309 if (items != 1)
1310 return POLICYDB_ERROR;
1311 items = put_entry(c->u.name, 1, len, fp);
1312 if (items != len)
1313 return POLICYDB_ERROR;
1314 if (context_write(p, &c->context[0], fp))
1315 return POLICYDB_ERROR;
1316 if (context_write(p, &c->context[1], fp))
1317 return POLICYDB_ERROR;
1318 break;
1319 case OCON_PORT:
1320 buf[0] = c->u.port.protocol;
1321 buf[1] = c->u.port.low_port;
1322 buf[2] = c->u.port.high_port;
1323 for (j = 0; j < 3; j++) {
1324 buf[j] = cpu_to_le32(buf[j]);
1325 }
1326 items = put_entry(buf, sizeof(uint32_t), 3, fp);
1327 if (items != 3)
1328 return POLICYDB_ERROR;
1329 if (context_write(p, &c->context[0], fp))
1330 return POLICYDB_ERROR;
1331 break;
1332 case OCON_NODE:
1333 buf[0] = c->u.node.addr; /* network order */
1334 buf[1] = c->u.node.mask; /* network order */
1335 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1336 if (items != 2)
1337 return POLICYDB_ERROR;
1338 if (context_write(p, &c->context[0], fp))
1339 return POLICYDB_ERROR;
1340 break;
1341 case OCON_FSUSE:
1342 buf[0] = cpu_to_le32(c->v.behavior);
1343 len = strlen(c->u.name);
1344 buf[1] = cpu_to_le32(len);
1345 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1346 if (items != 2)
1347 return POLICYDB_ERROR;
1348 items = put_entry(c->u.name, 1, len, fp);
1349 if (items != len)
1350 return POLICYDB_ERROR;
1351 if (context_write(p, &c->context[0], fp))
1352 return POLICYDB_ERROR;
1353 break;
1354 case OCON_NODE6:
1355 for (j = 0; j < 4; j++)
1356 buf[j] = c->u.node6.addr[j]; /* network order */
1357 for (j = 0; j < 4; j++)
1358 buf[j + 4] = c->u.node6.mask[j]; /* network order */
1359 items = put_entry(buf, sizeof(uint32_t), 8, fp);
1360 if (items != 8)
1361 return POLICYDB_ERROR;
1362 if (context_write(p, &c->context[0], fp))
1363 return POLICYDB_ERROR;
1364 break;
1365 }
1366 }
1367 }
1368 return POLICYDB_SUCCESS;
1369 }
1370
ocontext_write(struct policydb_compat_info * info,policydb_t * p,struct policy_file * fp)1371 static int ocontext_write(struct policydb_compat_info *info, policydb_t * p,
1372 struct policy_file *fp)
1373 {
1374 int rc = POLICYDB_ERROR;
1375 switch (p->target_platform) {
1376 case SEPOL_TARGET_SELINUX:
1377 rc = ocontext_write_selinux(info, p, fp);
1378 break;
1379 case SEPOL_TARGET_XEN:
1380 rc = ocontext_write_xen(info, p, fp);
1381 break;
1382 }
1383 return rc;
1384 }
1385
genfs_write(policydb_t * p,struct policy_file * fp)1386 static int genfs_write(policydb_t * p, struct policy_file *fp)
1387 {
1388 genfs_t *genfs;
1389 ocontext_t *c;
1390 size_t nel = 0, items, len;
1391 uint32_t buf[32];
1392
1393 for (genfs = p->genfs; genfs; genfs = genfs->next)
1394 nel++;
1395 buf[0] = cpu_to_le32(nel);
1396 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1397 if (items != 1)
1398 return POLICYDB_ERROR;
1399 for (genfs = p->genfs; genfs; genfs = genfs->next) {
1400 len = strlen(genfs->fstype);
1401 buf[0] = cpu_to_le32(len);
1402 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1403 if (items != 1)
1404 return POLICYDB_ERROR;
1405 items = put_entry(genfs->fstype, 1, len, fp);
1406 if (items != len)
1407 return POLICYDB_ERROR;
1408 nel = 0;
1409 for (c = genfs->head; c; c = c->next)
1410 nel++;
1411 buf[0] = cpu_to_le32(nel);
1412 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1413 if (items != 1)
1414 return POLICYDB_ERROR;
1415 for (c = genfs->head; c; c = c->next) {
1416 len = strlen(c->u.name);
1417 buf[0] = cpu_to_le32(len);
1418 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1419 if (items != 1)
1420 return POLICYDB_ERROR;
1421 items = put_entry(c->u.name, 1, len, fp);
1422 if (items != len)
1423 return POLICYDB_ERROR;
1424 buf[0] = cpu_to_le32(c->v.sclass);
1425 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1426 if (items != 1)
1427 return POLICYDB_ERROR;
1428 if (context_write(p, &c->context[0], fp))
1429 return POLICYDB_ERROR;
1430 }
1431 }
1432 return POLICYDB_SUCCESS;
1433 }
1434
range_write(policydb_t * p,struct policy_file * fp)1435 static int range_write(policydb_t * p, struct policy_file *fp)
1436 {
1437 size_t nel, items;
1438 struct range_trans *rt;
1439 uint32_t buf[2];
1440 int new_rangetr = (p->policy_type == POLICY_KERN &&
1441 p->policyvers >= POLICYDB_VERSION_RANGETRANS);
1442 int warning_issued = 0;
1443
1444 nel = 0;
1445 for (rt = p->range_tr; rt; rt = rt->next) {
1446 /* all range_transitions are written for the new format, only
1447 process related range_transitions are written for the old
1448 format, so count accordingly */
1449 if (new_rangetr || rt->target_class == SECCLASS_PROCESS)
1450 nel++;
1451 }
1452 buf[0] = cpu_to_le32(nel);
1453 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1454 if (items != 1)
1455 return POLICYDB_ERROR;
1456 for (rt = p->range_tr; rt; rt = rt->next) {
1457 if (!new_rangetr && rt->target_class != SECCLASS_PROCESS) {
1458 if (!warning_issued)
1459 WARN(fp->handle, "Discarding range_transition "
1460 "rules for security classes other than "
1461 "\"process\"");
1462 warning_issued = 1;
1463 continue;
1464 }
1465 buf[0] = cpu_to_le32(rt->source_type);
1466 buf[1] = cpu_to_le32(rt->target_type);
1467 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1468 if (items != 2)
1469 return POLICYDB_ERROR;
1470 if (new_rangetr) {
1471 buf[0] = cpu_to_le32(rt->target_class);
1472 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1473 if (items != 1)
1474 return POLICYDB_ERROR;
1475 }
1476 if (mls_write_range_helper(&rt->target_range, fp))
1477 return POLICYDB_ERROR;
1478 }
1479 return POLICYDB_SUCCESS;
1480 }
1481
1482 /************** module writing functions below **************/
1483
avrule_write(avrule_t * avrule,struct policy_file * fp)1484 static int avrule_write(avrule_t * avrule, struct policy_file *fp)
1485 {
1486 size_t items, items2;
1487 uint32_t buf[32], len;
1488 class_perm_node_t *cur;
1489
1490 items = 0;
1491 buf[items++] = cpu_to_le32(avrule->specified);
1492 buf[items++] = cpu_to_le32(avrule->flags);
1493 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1494 if (items2 != items)
1495 return POLICYDB_ERROR;
1496
1497 if (type_set_write(&avrule->stypes, fp))
1498 return POLICYDB_ERROR;
1499
1500 if (type_set_write(&avrule->ttypes, fp))
1501 return POLICYDB_ERROR;
1502
1503 cur = avrule->perms;
1504 len = 0;
1505 while (cur) {
1506 len++;
1507 cur = cur->next;
1508 }
1509 items = 0;
1510 buf[items++] = cpu_to_le32(len);
1511 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1512 if (items2 != items)
1513 return POLICYDB_ERROR;
1514 cur = avrule->perms;
1515 while (cur) {
1516 items = 0;
1517 buf[items++] = cpu_to_le32(cur->class);
1518 buf[items++] = cpu_to_le32(cur->data);
1519 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1520 if (items2 != items)
1521 return POLICYDB_ERROR;
1522
1523 cur = cur->next;
1524 }
1525
1526 return POLICYDB_SUCCESS;
1527 }
1528
avrule_write_list(avrule_t * avrules,struct policy_file * fp)1529 static int avrule_write_list(avrule_t * avrules, struct policy_file *fp)
1530 {
1531 uint32_t buf[32], len;
1532 avrule_t *avrule;
1533
1534 avrule = avrules;
1535 len = 0;
1536 while (avrule) {
1537 len++;
1538 avrule = avrule->next;
1539 }
1540
1541 buf[0] = cpu_to_le32(len);
1542 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1543 return POLICYDB_ERROR;
1544
1545 avrule = avrules;
1546 while (avrule) {
1547 avrule_write(avrule, fp);
1548 avrule = avrule->next;
1549 }
1550
1551 return POLICYDB_SUCCESS;
1552 }
1553
only_process(ebitmap_t * in)1554 static int only_process(ebitmap_t *in)
1555 {
1556 unsigned int i;
1557 ebitmap_node_t *node;
1558
1559 ebitmap_for_each_bit(in, node, i) {
1560 if (ebitmap_node_get_bit(node, i) &&
1561 i != SECCLASS_PROCESS - 1)
1562 return 0;
1563 }
1564 return 1;
1565 }
1566
role_trans_rule_write(policydb_t * p,role_trans_rule_t * t,struct policy_file * fp)1567 static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
1568 struct policy_file *fp)
1569 {
1570 int nel = 0;
1571 size_t items;
1572 uint32_t buf[1];
1573 role_trans_rule_t *tr;
1574 int warned = 0;
1575 int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1576
1577 for (tr = t; tr; tr = tr->next)
1578 if (new_role || only_process(&tr->classes))
1579 nel++;
1580
1581 buf[0] = cpu_to_le32(nel);
1582 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1583 if (items != 1)
1584 return POLICYDB_ERROR;
1585 for (tr = t; tr; tr = tr->next) {
1586 if (!new_role && !only_process(&tr->classes)) {
1587 if (!warned)
1588 WARN(fp->handle, "Discarding role_transition "
1589 "rules for security classes other than "
1590 "\"process\"");
1591 warned = 1;
1592 continue;
1593 }
1594 if (role_set_write(&tr->roles, fp))
1595 return POLICYDB_ERROR;
1596 if (type_set_write(&tr->types, fp))
1597 return POLICYDB_ERROR;
1598 if (new_role)
1599 if (ebitmap_write(&tr->classes, fp))
1600 return POLICYDB_ERROR;
1601 buf[0] = cpu_to_le32(tr->new_role);
1602 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1603 if (items != 1)
1604 return POLICYDB_ERROR;
1605 }
1606 return POLICYDB_SUCCESS;
1607 }
1608
role_allow_rule_write(role_allow_rule_t * r,struct policy_file * fp)1609 static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
1610 {
1611 int nel = 0;
1612 size_t items;
1613 uint32_t buf[1];
1614 role_allow_rule_t *ra;
1615
1616 for (ra = r; ra; ra = ra->next)
1617 nel++;
1618 buf[0] = cpu_to_le32(nel);
1619 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1620 if (items != 1)
1621 return POLICYDB_ERROR;
1622 for (ra = r; ra; ra = ra->next) {
1623 if (role_set_write(&ra->roles, fp))
1624 return POLICYDB_ERROR;
1625 if (role_set_write(&ra->new_roles, fp))
1626 return POLICYDB_ERROR;
1627 }
1628 return POLICYDB_SUCCESS;
1629 }
1630
filename_trans_rule_write(filename_trans_rule_t * t,struct policy_file * fp)1631 static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp)
1632 {
1633 int nel = 0;
1634 size_t items;
1635 uint32_t buf[2], len;
1636 filename_trans_rule_t *ftr;
1637
1638 for (ftr = t; ftr; ftr = ftr->next)
1639 nel++;
1640
1641 buf[0] = cpu_to_le32(nel);
1642 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1643 if (items != 1)
1644 return POLICYDB_ERROR;
1645
1646 for (ftr = t; ftr; ftr = ftr->next) {
1647 len = strlen(ftr->name);
1648 buf[0] = cpu_to_le32(len);
1649 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1650 if (items != 1)
1651 return POLICYDB_ERROR;
1652
1653 items = put_entry(ftr->name, sizeof(char), len, fp);
1654 if (items != len)
1655 return POLICYDB_ERROR;
1656
1657 if (type_set_write(&ftr->stypes, fp))
1658 return POLICYDB_ERROR;
1659 if (type_set_write(&ftr->ttypes, fp))
1660 return POLICYDB_ERROR;
1661
1662 buf[0] = cpu_to_le32(ftr->tclass);
1663 buf[1] = cpu_to_le32(ftr->otype);
1664
1665 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1666 if (items != 2)
1667 return POLICYDB_ERROR;
1668 }
1669 return POLICYDB_SUCCESS;
1670 }
1671
range_trans_rule_write(range_trans_rule_t * t,struct policy_file * fp)1672 static int range_trans_rule_write(range_trans_rule_t * t,
1673 struct policy_file *fp)
1674 {
1675 int nel = 0;
1676 size_t items;
1677 uint32_t buf[1];
1678 range_trans_rule_t *rt;
1679
1680 for (rt = t; rt; rt = rt->next)
1681 nel++;
1682 buf[0] = cpu_to_le32(nel);
1683 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1684 if (items != 1)
1685 return POLICYDB_ERROR;
1686 for (rt = t; rt; rt = rt->next) {
1687 if (type_set_write(&rt->stypes, fp))
1688 return POLICYDB_ERROR;
1689 if (type_set_write(&rt->ttypes, fp))
1690 return POLICYDB_ERROR;
1691 if (ebitmap_write(&rt->tclasses, fp))
1692 return POLICYDB_ERROR;
1693 if (mls_write_semantic_range_helper(&rt->trange, fp))
1694 return POLICYDB_ERROR;
1695 }
1696 return POLICYDB_SUCCESS;
1697 }
1698
scope_index_write(scope_index_t * scope_index,unsigned int num_scope_syms,struct policy_file * fp)1699 static int scope_index_write(scope_index_t * scope_index,
1700 unsigned int num_scope_syms,
1701 struct policy_file *fp)
1702 {
1703 unsigned int i;
1704 uint32_t buf[1];
1705 for (i = 0; i < num_scope_syms; i++) {
1706 if (ebitmap_write(scope_index->scope + i, fp) == -1) {
1707 return POLICYDB_ERROR;
1708 }
1709 }
1710 buf[0] = cpu_to_le32(scope_index->class_perms_len);
1711 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1712 return POLICYDB_ERROR;
1713 }
1714 for (i = 0; i < scope_index->class_perms_len; i++) {
1715 if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
1716 return POLICYDB_ERROR;
1717 }
1718 }
1719 return POLICYDB_SUCCESS;
1720 }
1721
avrule_decl_write(avrule_decl_t * decl,int num_scope_syms,policydb_t * p,struct policy_file * fp)1722 static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
1723 policydb_t * p, struct policy_file *fp)
1724 {
1725 struct policy_data pd;
1726 uint32_t buf[2];
1727 int i;
1728 buf[0] = cpu_to_le32(decl->decl_id);
1729 buf[1] = cpu_to_le32(decl->enabled);
1730 if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
1731 return POLICYDB_ERROR;
1732 }
1733 if (cond_write_list(p, decl->cond_list, fp) == -1 ||
1734 avrule_write_list(decl->avrules, fp) == -1 ||
1735 role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
1736 role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
1737 return POLICYDB_ERROR;
1738 }
1739
1740 if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
1741 filename_trans_rule_write(decl->filename_trans_rules, fp))
1742 return POLICYDB_ERROR;
1743
1744 if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
1745 range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
1746 return POLICYDB_ERROR;
1747 }
1748 if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
1749 scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
1750 return POLICYDB_ERROR;
1751 }
1752 pd.fp = fp;
1753 pd.p = p;
1754 for (i = 0; i < num_scope_syms; i++) {
1755 buf[0] = cpu_to_le32(decl->symtab[i].nprim);
1756 buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
1757 if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
1758 return POLICYDB_ERROR;
1759 }
1760 if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
1761 return POLICYDB_ERROR;
1762 }
1763 }
1764 return POLICYDB_SUCCESS;
1765 }
1766
avrule_block_write(avrule_block_t * block,int num_scope_syms,policydb_t * p,struct policy_file * fp)1767 static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
1768 policydb_t * p, struct policy_file *fp)
1769 {
1770 /* first write a count of the total number of blocks */
1771 uint32_t buf[1], num_blocks = 0;
1772 avrule_block_t *cur;
1773 for (cur = block; cur != NULL; cur = cur->next) {
1774 num_blocks++;
1775 }
1776 buf[0] = cpu_to_le32(num_blocks);
1777 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1778 return POLICYDB_ERROR;
1779 }
1780
1781 /* now write each block */
1782 for (cur = block; cur != NULL; cur = cur->next) {
1783 uint32_t num_decls = 0;
1784 avrule_decl_t *decl;
1785 /* write a count of number of branches */
1786 for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
1787 num_decls++;
1788 }
1789 buf[0] = cpu_to_le32(num_decls);
1790 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
1791 return POLICYDB_ERROR;
1792 }
1793 for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
1794 if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
1795 -1) {
1796 return POLICYDB_ERROR;
1797 }
1798 }
1799 }
1800 return POLICYDB_SUCCESS;
1801 }
1802
scope_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)1803 static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
1804 {
1805 scope_datum_t *scope = (scope_datum_t *) datum;
1806 struct policy_data *pd = ptr;
1807 struct policy_file *fp = pd->fp;
1808 uint32_t static_buf[32], *dyn_buf = NULL, *buf;
1809 size_t key_len = strlen(key);
1810 unsigned int items = 2 + scope->decl_ids_len, i;
1811 int rc;
1812
1813 buf = static_buf;
1814 if (items >= (sizeof(static_buf) / 4)) {
1815 /* too many things required, so dynamically create a
1816 * buffer. this would have been easier with C99's
1817 * dynamic arrays... */
1818 rc = POLICYDB_ERROR;
1819 dyn_buf = malloc(items * sizeof(*dyn_buf));
1820 if (!dyn_buf)
1821 goto err;
1822 buf = dyn_buf;
1823 }
1824 buf[0] = cpu_to_le32(key_len);
1825
1826 rc = POLICYDB_ERROR;
1827 if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
1828 put_entry(key, 1, key_len, fp) != key_len)
1829 goto err;
1830 buf[0] = cpu_to_le32(scope->scope);
1831 buf[1] = cpu_to_le32(scope->decl_ids_len);
1832
1833 for (i = 0; i < scope->decl_ids_len; i++)
1834 buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
1835
1836 rc = POLICYDB_ERROR;
1837 if (put_entry(buf, sizeof(*buf), items, fp) != items)
1838 goto err;
1839 rc = POLICYDB_SUCCESS;
1840 err:
1841 free(dyn_buf);
1842 return rc;
1843 }
1844
type_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)1845 static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
1846 hashtab_datum_t datum, void *args)
1847 {
1848 type_datum_t *typdatum = datum;
1849 uint32_t *p_nel = args;
1850
1851 if (typdatum->flavor == TYPE_ATTRIB) {
1852 /* uncount attribute from total number of types */
1853 (*p_nel)--;
1854 }
1855 return 0;
1856 }
1857
role_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)1858 static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
1859 hashtab_datum_t datum, void *args)
1860 {
1861 role_datum_t *role = datum;
1862 uint32_t *p_nel = args;
1863
1864 if (role->flavor == ROLE_ATTRIB) {
1865 /* uncount attribute from total number of roles */
1866 (*p_nel)--;
1867 }
1868 return 0;
1869 }
1870
1871 /*
1872 * Write the configuration data in a policy database
1873 * structure to a policy database binary representation
1874 * file.
1875 */
policydb_write(policydb_t * p,struct policy_file * fp)1876 int policydb_write(policydb_t * p, struct policy_file *fp)
1877 {
1878 unsigned int i, num_syms;
1879 uint32_t buf[32], config;
1880 size_t items, items2, len;
1881 struct policydb_compat_info *info;
1882 struct policy_data pd;
1883 char *policydb_str;
1884
1885 if (p->unsupported_format)
1886 return POLICYDB_UNSUPPORTED;
1887
1888 pd.fp = fp;
1889 pd.p = p;
1890
1891 config = 0;
1892 if (p->mls) {
1893 if ((p->policyvers < POLICYDB_VERSION_MLS &&
1894 p->policy_type == POLICY_KERN) ||
1895 (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
1896 p->policy_type == POLICY_BASE) ||
1897 (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
1898 p->policy_type == POLICY_MOD)) {
1899 ERR(fp->handle, "policy version %d cannot support MLS",
1900 p->policyvers);
1901 return POLICYDB_ERROR;
1902 }
1903 config |= POLICYDB_CONFIG_MLS;
1904 }
1905
1906 config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
1907
1908 /* Write the magic number and string identifiers. */
1909 items = 0;
1910 if (p->policy_type == POLICY_KERN) {
1911 buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
1912 len = strlen(policydb_target_strings[p->target_platform]);
1913 policydb_str = policydb_target_strings[p->target_platform];
1914 } else {
1915 buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
1916 len = strlen(POLICYDB_MOD_STRING);
1917 policydb_str = POLICYDB_MOD_STRING;
1918 }
1919 buf[items++] = cpu_to_le32(len);
1920 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1921 if (items != items2)
1922 return POLICYDB_ERROR;
1923 items = put_entry(policydb_str, 1, len, fp);
1924 if (items != len)
1925 return POLICYDB_ERROR;
1926
1927 /* Write the version, config, and table sizes. */
1928 items = 0;
1929 info = policydb_lookup_compat(p->policyvers, p->policy_type,
1930 p->target_platform);
1931 if (!info) {
1932 ERR(fp->handle, "compatibility lookup failed for policy "
1933 "version %d", p->policyvers);
1934 return POLICYDB_ERROR;
1935 }
1936
1937 if (p->policy_type != POLICY_KERN) {
1938 buf[items++] = cpu_to_le32(p->policy_type);
1939 }
1940 buf[items++] = cpu_to_le32(p->policyvers);
1941 buf[items++] = cpu_to_le32(config);
1942 buf[items++] = cpu_to_le32(info->sym_num);
1943 buf[items++] = cpu_to_le32(info->ocon_num);
1944
1945 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1946 if (items != items2)
1947 return POLICYDB_ERROR;
1948
1949 if (p->policy_type == POLICY_MOD) {
1950 /* Write module name and version */
1951 len = strlen(p->name);
1952 buf[0] = cpu_to_le32(len);
1953 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1954 if (items != 1)
1955 return POLICYDB_ERROR;
1956 items = put_entry(p->name, 1, len, fp);
1957 if (items != len)
1958 return POLICYDB_ERROR;
1959 len = strlen(p->version);
1960 buf[0] = cpu_to_le32(len);
1961 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1962 if (items != 1)
1963 return POLICYDB_ERROR;
1964 items = put_entry(p->version, 1, len, fp);
1965 if (items != len)
1966 return POLICYDB_ERROR;
1967 }
1968
1969 if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
1970 p->policy_type == POLICY_KERN) ||
1971 (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
1972 p->policy_type == POLICY_BASE) ||
1973 (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
1974 p->policy_type == POLICY_MOD)) {
1975 if (ebitmap_write(&p->policycaps, fp) == -1)
1976 return POLICYDB_ERROR;
1977 }
1978
1979 if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
1980 p->policy_type == POLICY_KERN) {
1981 ebitmap_node_t *tnode;
1982
1983 ebitmap_for_each_bit(&p->permissive_map, tnode, i) {
1984 if (ebitmap_node_get_bit(tnode, i)) {
1985 WARN(fp->handle, "Warning! Policy version %d cannot "
1986 "support permissive types, but some were defined",
1987 p->policyvers);
1988 break;
1989 }
1990 }
1991 }
1992
1993 if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
1994 p->policy_type == POLICY_KERN) {
1995 if (ebitmap_write(&p->permissive_map, fp) == -1)
1996 return POLICYDB_ERROR;
1997 }
1998
1999 num_syms = info->sym_num;
2000 for (i = 0; i < num_syms; i++) {
2001 buf[0] = cpu_to_le32(p->symtab[i].nprim);
2002 buf[1] = p->symtab[i].table->nel;
2003
2004 /*
2005 * A special case when writing type/attribute symbol table.
2006 * The kernel policy version less than 24 does not support
2007 * to load entries of attribute, so we have to re-calculate
2008 * the actual number of types except for attributes.
2009 */
2010 if (i == SYM_TYPES &&
2011 p->policyvers < POLICYDB_VERSION_BOUNDARY &&
2012 p->policy_type == POLICY_KERN) {
2013 hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
2014 }
2015
2016 /*
2017 * Another special case when writing role/attribute symbol
2018 * table, role attributes are redundant for policy.X, or
2019 * when the pp's version is not big enough. So deduct
2020 * their numbers from p_roles.table->nel.
2021 */
2022 if ((i == SYM_ROLES) &&
2023 ((p->policy_type == POLICY_KERN) ||
2024 (p->policy_type != POLICY_KERN &&
2025 p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2026 (void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
2027
2028 buf[1] = cpu_to_le32(buf[1]);
2029 items = put_entry(buf, sizeof(uint32_t), 2, fp);
2030 if (items != 2)
2031 return POLICYDB_ERROR;
2032 if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
2033 return POLICYDB_ERROR;
2034 }
2035
2036 if (p->policy_type == POLICY_KERN) {
2037 if (avtab_write(p, &p->te_avtab, fp))
2038 return POLICYDB_ERROR;
2039 if (p->policyvers < POLICYDB_VERSION_BOOL) {
2040 if (p->p_bools.nprim)
2041 WARN(fp->handle, "Discarding "
2042 "booleans and conditional rules");
2043 } else {
2044 if (cond_write_list(p, p->cond_list, fp))
2045 return POLICYDB_ERROR;
2046 }
2047 if (role_trans_write(p, fp))
2048 return POLICYDB_ERROR;
2049 if (role_allow_write(p->role_allow, fp))
2050 return POLICYDB_ERROR;
2051 if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
2052 if (filename_trans_write(p->filename_trans, fp))
2053 return POLICYDB_ERROR;
2054 } else {
2055 if (p->filename_trans)
2056 WARN(fp->handle, "Discarding filename type transition rules");
2057 }
2058 } else {
2059 if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
2060 return POLICYDB_ERROR;
2061 }
2062
2063 for (i = 0; i < num_syms; i++) {
2064 buf[0] = cpu_to_le32(p->scope[i].table->nel);
2065 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2066 return POLICYDB_ERROR;
2067 }
2068 if (hashtab_map(p->scope[i].table, scope_write, &pd))
2069 return POLICYDB_ERROR;
2070 }
2071 }
2072
2073 if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
2074 return POLICYDB_ERROR;
2075 }
2076
2077 if ((p->policyvers >= POLICYDB_VERSION_MLS
2078 && p->policy_type == POLICY_KERN)
2079 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
2080 && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
2081 && p->policy_type == POLICY_BASE)) {
2082 if (range_write(p, fp)) {
2083 return POLICYDB_ERROR;
2084 }
2085 }
2086
2087 if (p->policy_type == POLICY_KERN
2088 && p->policyvers >= POLICYDB_VERSION_AVTAB) {
2089 for (i = 0; i < p->p_types.nprim; i++) {
2090 if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2091 return POLICYDB_ERROR;
2092 }
2093 }
2094
2095 return POLICYDB_SUCCESS;
2096 }
2097