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