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