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