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 items = 0;
1749 buf[items++] = cpu_to_le32(avrule->specified);
1750 buf[items++] = cpu_to_le32(avrule->flags);
1751 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1752 if (items2 != items)
1753 return POLICYDB_ERROR;
1754
1755 if (type_set_write(&avrule->stypes, fp))
1756 return POLICYDB_ERROR;
1757
1758 if (type_set_write(&avrule->ttypes, fp))
1759 return POLICYDB_ERROR;
1760
1761 cur = avrule->perms;
1762 len = 0;
1763 while (cur) {
1764 len++;
1765 cur = cur->next;
1766 }
1767 items = 0;
1768 buf[items++] = cpu_to_le32(len);
1769 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1770 if (items2 != items)
1771 return POLICYDB_ERROR;
1772 cur = avrule->perms;
1773 while (cur) {
1774 items = 0;
1775 buf[items++] = cpu_to_le32(cur->tclass);
1776 buf[items++] = cpu_to_le32(cur->data);
1777 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
1778 if (items2 != items)
1779 return POLICYDB_ERROR;
1780
1781 cur = cur->next;
1782 }
1783
1784 if (avrule->specified & AVRULE_XPERMS) {
1785 size_t nel = ARRAY_SIZE(avrule->xperms->perms);
1786 uint32_t buf32[nel];
1787 uint8_t buf8;
1788 unsigned int i;
1789
1790 if (p->policyvers < MOD_POLICYDB_VERSION_XPERMS_IOCTL) {
1791 ERR(fp->handle,
1792 "module policy version %u does not support ioctl"
1793 " extended permissions rules and one was specified",
1794 p->policyvers);
1795 return POLICYDB_ERROR;
1796 }
1797
1798 if (p->target_platform != SEPOL_TARGET_SELINUX) {
1799 ERR(fp->handle,
1800 "Target platform %s does not support ioctl"
1801 " extended permissions rules and one was specified",
1802 policydb_target_strings[p->target_platform]);
1803 return POLICYDB_ERROR;
1804 }
1805
1806 buf8 = avrule->xperms->specified;
1807 items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1808 if (items != 1)
1809 return POLICYDB_ERROR;
1810 buf8 = avrule->xperms->driver;
1811 items = put_entry(&buf8, sizeof(uint8_t),1,fp);
1812 if (items != 1)
1813 return POLICYDB_ERROR;
1814 for (i = 0; i < nel; i++)
1815 buf32[i] = cpu_to_le32(avrule->xperms->perms[i]);
1816 items = put_entry(buf32, sizeof(uint32_t), nel, fp);
1817 if (items != nel)
1818 return POLICYDB_ERROR;
1819 }
1820
1821 return POLICYDB_SUCCESS;
1822 }
1823
avrule_write_list(policydb_t * p,avrule_t * avrules,struct policy_file * fp)1824 static int avrule_write_list(policydb_t *p, avrule_t * avrules,
1825 struct policy_file *fp)
1826 {
1827 uint32_t buf[32], len;
1828 avrule_t *avrule;
1829
1830 avrule = avrules;
1831 len = 0;
1832 while (avrule) {
1833 len++;
1834 avrule = avrule->next;
1835 }
1836
1837 buf[0] = cpu_to_le32(len);
1838 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1)
1839 return POLICYDB_ERROR;
1840
1841 avrule = avrules;
1842 while (avrule) {
1843 if (avrule_write(p, avrule, fp))
1844 return POLICYDB_ERROR;
1845 avrule = avrule->next;
1846 }
1847
1848 return POLICYDB_SUCCESS;
1849 }
1850
only_process(ebitmap_t * in,struct policydb * p)1851 static int only_process(ebitmap_t *in, struct policydb *p)
1852 {
1853 unsigned int i, value;
1854 ebitmap_node_t *node;
1855
1856 if (!p->process_class)
1857 return 0;
1858
1859 value = p->process_class - 1;
1860
1861 ebitmap_for_each_positive_bit(in, node, i) {
1862 if (i != value)
1863 return 0;
1864 }
1865 return 1;
1866 }
1867
role_trans_rule_write(policydb_t * p,role_trans_rule_t * t,struct policy_file * fp)1868 static int role_trans_rule_write(policydb_t *p, role_trans_rule_t * t,
1869 struct policy_file *fp)
1870 {
1871 int nel = 0;
1872 size_t items;
1873 uint32_t buf[1];
1874 role_trans_rule_t *tr;
1875 int warned = 0;
1876 int new_role = p->policyvers >= MOD_POLICYDB_VERSION_ROLETRANS;
1877
1878 for (tr = t; tr; tr = tr->next)
1879 if (new_role || only_process(&tr->classes, p))
1880 nel++;
1881
1882 buf[0] = cpu_to_le32(nel);
1883 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1884 if (items != 1)
1885 return POLICYDB_ERROR;
1886 for (tr = t; tr; tr = tr->next) {
1887 if (!new_role && !only_process(&tr->classes, p)) {
1888 if (!warned)
1889 WARN(fp->handle, "Discarding role_transition "
1890 "rules for security classes other than "
1891 "\"process\"");
1892 warned = 1;
1893 continue;
1894 }
1895 if (role_set_write(&tr->roles, fp))
1896 return POLICYDB_ERROR;
1897 if (type_set_write(&tr->types, fp))
1898 return POLICYDB_ERROR;
1899 if (new_role)
1900 if (ebitmap_write(&tr->classes, fp))
1901 return POLICYDB_ERROR;
1902 buf[0] = cpu_to_le32(tr->new_role);
1903 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1904 if (items != 1)
1905 return POLICYDB_ERROR;
1906 }
1907 return POLICYDB_SUCCESS;
1908 }
1909
role_allow_rule_write(role_allow_rule_t * r,struct policy_file * fp)1910 static int role_allow_rule_write(role_allow_rule_t * r, struct policy_file *fp)
1911 {
1912 int nel = 0;
1913 size_t items;
1914 uint32_t buf[1];
1915 role_allow_rule_t *ra;
1916
1917 for (ra = r; ra; ra = ra->next)
1918 nel++;
1919 buf[0] = cpu_to_le32(nel);
1920 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1921 if (items != 1)
1922 return POLICYDB_ERROR;
1923 for (ra = r; ra; ra = ra->next) {
1924 if (role_set_write(&ra->roles, fp))
1925 return POLICYDB_ERROR;
1926 if (role_set_write(&ra->new_roles, fp))
1927 return POLICYDB_ERROR;
1928 }
1929 return POLICYDB_SUCCESS;
1930 }
1931
filename_trans_rule_write(filename_trans_rule_t * t,struct policy_file * fp)1932 static int filename_trans_rule_write(filename_trans_rule_t * t, struct policy_file *fp)
1933 {
1934 int nel = 0;
1935 size_t items;
1936 uint32_t buf[2], len;
1937 filename_trans_rule_t *ftr;
1938
1939 for (ftr = t; ftr; ftr = ftr->next)
1940 nel++;
1941
1942 buf[0] = cpu_to_le32(nel);
1943 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1944 if (items != 1)
1945 return POLICYDB_ERROR;
1946
1947 for (ftr = t; ftr; ftr = ftr->next) {
1948 len = strlen(ftr->name);
1949 buf[0] = cpu_to_le32(len);
1950 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1951 if (items != 1)
1952 return POLICYDB_ERROR;
1953
1954 items = put_entry(ftr->name, sizeof(char), len, fp);
1955 if (items != len)
1956 return POLICYDB_ERROR;
1957
1958 if (type_set_write(&ftr->stypes, fp))
1959 return POLICYDB_ERROR;
1960 if (type_set_write(&ftr->ttypes, fp))
1961 return POLICYDB_ERROR;
1962
1963 buf[0] = cpu_to_le32(ftr->tclass);
1964 buf[1] = cpu_to_le32(ftr->otype);
1965
1966 items = put_entry(buf, sizeof(uint32_t), 2, fp);
1967 if (items != 2)
1968 return POLICYDB_ERROR;
1969 }
1970 return POLICYDB_SUCCESS;
1971 }
1972
range_trans_rule_write(range_trans_rule_t * t,struct policy_file * fp)1973 static int range_trans_rule_write(range_trans_rule_t * t,
1974 struct policy_file *fp)
1975 {
1976 int nel = 0;
1977 size_t items;
1978 uint32_t buf[1];
1979 range_trans_rule_t *rt;
1980
1981 for (rt = t; rt; rt = rt->next)
1982 nel++;
1983 buf[0] = cpu_to_le32(nel);
1984 items = put_entry(buf, sizeof(uint32_t), 1, fp);
1985 if (items != 1)
1986 return POLICYDB_ERROR;
1987 for (rt = t; rt; rt = rt->next) {
1988 if (type_set_write(&rt->stypes, fp))
1989 return POLICYDB_ERROR;
1990 if (type_set_write(&rt->ttypes, fp))
1991 return POLICYDB_ERROR;
1992 if (ebitmap_write(&rt->tclasses, fp))
1993 return POLICYDB_ERROR;
1994 if (mls_write_semantic_range_helper(&rt->trange, fp))
1995 return POLICYDB_ERROR;
1996 }
1997 return POLICYDB_SUCCESS;
1998 }
1999
scope_index_write(scope_index_t * scope_index,unsigned int num_scope_syms,struct policy_file * fp)2000 static int scope_index_write(scope_index_t * scope_index,
2001 unsigned int num_scope_syms,
2002 struct policy_file *fp)
2003 {
2004 unsigned int i;
2005 uint32_t buf[1];
2006 for (i = 0; i < num_scope_syms; i++) {
2007 if (ebitmap_write(scope_index->scope + i, fp) == -1) {
2008 return POLICYDB_ERROR;
2009 }
2010 }
2011 buf[0] = cpu_to_le32(scope_index->class_perms_len);
2012 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2013 return POLICYDB_ERROR;
2014 }
2015 for (i = 0; i < scope_index->class_perms_len; i++) {
2016 if (ebitmap_write(scope_index->class_perms_map + i, fp) == -1) {
2017 return POLICYDB_ERROR;
2018 }
2019 }
2020 return POLICYDB_SUCCESS;
2021 }
2022
avrule_decl_write(avrule_decl_t * decl,int num_scope_syms,policydb_t * p,struct policy_file * fp)2023 static int avrule_decl_write(avrule_decl_t * decl, int num_scope_syms,
2024 policydb_t * p, struct policy_file *fp)
2025 {
2026 struct policy_data pd;
2027 uint32_t buf[2];
2028 int i;
2029 buf[0] = cpu_to_le32(decl->decl_id);
2030 buf[1] = cpu_to_le32(decl->enabled);
2031 if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2032 return POLICYDB_ERROR;
2033 }
2034 if (cond_write_list(p, decl->cond_list, fp) == -1 ||
2035 avrule_write_list(p, decl->avrules, fp) == -1 ||
2036 role_trans_rule_write(p, decl->role_tr_rules, fp) == -1 ||
2037 role_allow_rule_write(decl->role_allow_rules, fp) == -1) {
2038 return POLICYDB_ERROR;
2039 }
2040
2041 if (p->policyvers >= MOD_POLICYDB_VERSION_FILENAME_TRANS &&
2042 filename_trans_rule_write(decl->filename_trans_rules, fp))
2043 return POLICYDB_ERROR;
2044
2045 if (p->policyvers >= MOD_POLICYDB_VERSION_RANGETRANS &&
2046 range_trans_rule_write(decl->range_tr_rules, fp) == -1) {
2047 return POLICYDB_ERROR;
2048 }
2049 if (scope_index_write(&decl->required, num_scope_syms, fp) == -1 ||
2050 scope_index_write(&decl->declared, num_scope_syms, fp) == -1) {
2051 return POLICYDB_ERROR;
2052 }
2053 pd.fp = fp;
2054 pd.p = p;
2055 for (i = 0; i < num_scope_syms; i++) {
2056 buf[0] = cpu_to_le32(decl->symtab[i].nprim);
2057 buf[1] = cpu_to_le32(decl->symtab[i].table->nel);
2058 if (put_entry(buf, sizeof(uint32_t), 2, fp) != 2) {
2059 return POLICYDB_ERROR;
2060 }
2061 if (hashtab_map(decl->symtab[i].table, write_f[i], &pd)) {
2062 return POLICYDB_ERROR;
2063 }
2064 }
2065 return POLICYDB_SUCCESS;
2066 }
2067
avrule_block_write(avrule_block_t * block,int num_scope_syms,policydb_t * p,struct policy_file * fp)2068 static int avrule_block_write(avrule_block_t * block, int num_scope_syms,
2069 policydb_t * p, struct policy_file *fp)
2070 {
2071 /* first write a count of the total number of blocks */
2072 uint32_t buf[1], num_blocks = 0;
2073 avrule_block_t *cur;
2074 for (cur = block; cur != NULL; cur = cur->next) {
2075 num_blocks++;
2076 }
2077 buf[0] = cpu_to_le32(num_blocks);
2078 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2079 return POLICYDB_ERROR;
2080 }
2081
2082 /* now write each block */
2083 for (cur = block; cur != NULL; cur = cur->next) {
2084 uint32_t num_decls = 0;
2085 avrule_decl_t *decl;
2086 /* write a count of number of branches */
2087 for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2088 num_decls++;
2089 }
2090 buf[0] = cpu_to_le32(num_decls);
2091 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2092 return POLICYDB_ERROR;
2093 }
2094 for (decl = cur->branch_list; decl != NULL; decl = decl->next) {
2095 if (avrule_decl_write(decl, num_scope_syms, p, fp) ==
2096 -1) {
2097 return POLICYDB_ERROR;
2098 }
2099 }
2100 }
2101 return POLICYDB_SUCCESS;
2102 }
2103
scope_write(hashtab_key_t key,hashtab_datum_t datum,void * ptr)2104 static int scope_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr)
2105 {
2106 scope_datum_t *scope = (scope_datum_t *) datum;
2107 struct policy_data *pd = ptr;
2108 struct policy_file *fp = pd->fp;
2109 uint32_t static_buf[32], *dyn_buf = NULL, *buf;
2110 size_t key_len = strlen(key);
2111 unsigned int items = 2 + scope->decl_ids_len, i;
2112 int rc;
2113
2114 buf = static_buf;
2115 if (items >= (sizeof(static_buf) / 4)) {
2116 /* too many things required, so dynamically create a
2117 * buffer. this would have been easier with C99's
2118 * dynamic arrays... */
2119 rc = POLICYDB_ERROR;
2120 dyn_buf = malloc(items * sizeof(*dyn_buf));
2121 if (!dyn_buf)
2122 goto err;
2123 buf = dyn_buf;
2124 }
2125 buf[0] = cpu_to_le32(key_len);
2126
2127 rc = POLICYDB_ERROR;
2128 if (put_entry(buf, sizeof(*buf), 1, fp) != 1 ||
2129 put_entry(key, 1, key_len, fp) != key_len)
2130 goto err;
2131 buf[0] = cpu_to_le32(scope->scope);
2132 buf[1] = cpu_to_le32(scope->decl_ids_len);
2133
2134 for (i = 0; i < scope->decl_ids_len; i++)
2135 buf[2 + i] = cpu_to_le32(scope->decl_ids[i]);
2136
2137 rc = POLICYDB_ERROR;
2138 if (put_entry(buf, sizeof(*buf), items, fp) != items)
2139 goto err;
2140 rc = POLICYDB_SUCCESS;
2141 err:
2142 free(dyn_buf);
2143 return rc;
2144 }
2145
type_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2146 static int type_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2147 hashtab_datum_t datum, void *args)
2148 {
2149 type_datum_t *typdatum = datum;
2150 uint32_t *p_nel = args;
2151
2152 if (typdatum->flavor == TYPE_ATTRIB) {
2153 /* uncount attribute from total number of types */
2154 (*p_nel)--;
2155 }
2156 return 0;
2157 }
2158
role_attr_uncount(hashtab_key_t key,hashtab_datum_t datum,void * args)2159 static int role_attr_uncount(hashtab_key_t key __attribute__ ((unused)),
2160 hashtab_datum_t datum, void *args)
2161 {
2162 role_datum_t *role = datum;
2163 uint32_t *p_nel = args;
2164
2165 if (role->flavor == ROLE_ATTRIB) {
2166 /* uncount attribute from total number of roles */
2167 (*p_nel)--;
2168 }
2169 return 0;
2170 }
2171
2172 /*
2173 * Write the configuration data in a policy database
2174 * structure to a policy database binary representation
2175 * file.
2176 */
policydb_write(policydb_t * p,struct policy_file * fp)2177 int policydb_write(policydb_t * p, struct policy_file *fp)
2178 {
2179 unsigned int i, num_syms;
2180 uint32_t buf[32], config;
2181 size_t items, items2, len;
2182 const struct policydb_compat_info *info;
2183 struct policy_data pd;
2184 const char *policydb_str;
2185
2186 if (p->unsupported_format)
2187 return POLICYDB_UNSUPPORTED;
2188
2189 pd.fp = fp;
2190 pd.p = p;
2191
2192 config = 0;
2193 if (p->mls) {
2194 if ((p->policyvers < POLICYDB_VERSION_MLS &&
2195 p->policy_type == POLICY_KERN) ||
2196 (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2197 p->policy_type == POLICY_BASE) ||
2198 (p->policyvers < MOD_POLICYDB_VERSION_MLS &&
2199 p->policy_type == POLICY_MOD)) {
2200 ERR(fp->handle, "policy version %d cannot support MLS",
2201 p->policyvers);
2202 return POLICYDB_ERROR;
2203 }
2204 config |= POLICYDB_CONFIG_MLS;
2205 }
2206
2207 config |= (POLICYDB_CONFIG_UNKNOWN_MASK & p->handle_unknown);
2208
2209 /* Write the magic number and string identifiers. */
2210 items = 0;
2211 if (p->policy_type == POLICY_KERN) {
2212 buf[items++] = cpu_to_le32(POLICYDB_MAGIC);
2213 len = strlen(policydb_target_strings[p->target_platform]);
2214 policydb_str = policydb_target_strings[p->target_platform];
2215 } else {
2216 buf[items++] = cpu_to_le32(POLICYDB_MOD_MAGIC);
2217 len = strlen(POLICYDB_MOD_STRING);
2218 policydb_str = POLICYDB_MOD_STRING;
2219 }
2220 buf[items++] = cpu_to_le32(len);
2221 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2222 if (items != items2)
2223 return POLICYDB_ERROR;
2224 items = put_entry(policydb_str, 1, len, fp);
2225 if (items != len)
2226 return POLICYDB_ERROR;
2227
2228 /* Write the version, config, and table sizes. */
2229 items = 0;
2230 info = policydb_lookup_compat(p->policyvers, p->policy_type,
2231 p->target_platform);
2232 if (!info) {
2233 ERR(fp->handle, "compatibility lookup failed for policy "
2234 "version %d", p->policyvers);
2235 return POLICYDB_ERROR;
2236 }
2237
2238 if (p->policy_type != POLICY_KERN) {
2239 buf[items++] = cpu_to_le32(p->policy_type);
2240 }
2241 buf[items++] = cpu_to_le32(p->policyvers);
2242 buf[items++] = cpu_to_le32(config);
2243 buf[items++] = cpu_to_le32(info->sym_num);
2244 buf[items++] = cpu_to_le32(info->ocon_num);
2245
2246 items2 = put_entry(buf, sizeof(uint32_t), items, fp);
2247 if (items != items2)
2248 return POLICYDB_ERROR;
2249
2250 if (p->policy_type == POLICY_MOD) {
2251 /* Write module name and version */
2252 len = strlen(p->name);
2253 buf[0] = cpu_to_le32(len);
2254 items = put_entry(buf, sizeof(uint32_t), 1, fp);
2255 if (items != 1)
2256 return POLICYDB_ERROR;
2257 items = put_entry(p->name, 1, len, fp);
2258 if (items != len)
2259 return POLICYDB_ERROR;
2260 len = strlen(p->version);
2261 buf[0] = cpu_to_le32(len);
2262 items = put_entry(buf, sizeof(uint32_t), 1, fp);
2263 if (items != 1)
2264 return POLICYDB_ERROR;
2265 items = put_entry(p->version, 1, len, fp);
2266 if (items != len)
2267 return POLICYDB_ERROR;
2268 }
2269
2270 if ((p->policyvers >= POLICYDB_VERSION_POLCAP &&
2271 p->policy_type == POLICY_KERN) ||
2272 (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2273 p->policy_type == POLICY_BASE) ||
2274 (p->policyvers >= MOD_POLICYDB_VERSION_POLCAP &&
2275 p->policy_type == POLICY_MOD)) {
2276 if (ebitmap_write(&p->policycaps, fp) == -1)
2277 return POLICYDB_ERROR;
2278 }
2279
2280 if (p->policyvers < POLICYDB_VERSION_PERMISSIVE &&
2281 p->policy_type == POLICY_KERN) {
2282 ebitmap_node_t *tnode;
2283
2284 ebitmap_for_each_positive_bit(&p->permissive_map, tnode, i) {
2285 WARN(fp->handle, "Warning! Policy version %d cannot "
2286 "support permissive types, but some were defined",
2287 p->policyvers);
2288 break;
2289 }
2290 }
2291
2292 if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
2293 p->policy_type == POLICY_KERN) {
2294 if (ebitmap_write(&p->permissive_map, fp) == -1)
2295 return POLICYDB_ERROR;
2296 }
2297
2298 num_syms = info->sym_num;
2299 for (i = 0; i < num_syms; i++) {
2300 buf[0] = cpu_to_le32(p->symtab[i].nprim);
2301 buf[1] = p->symtab[i].table->nel;
2302
2303 /*
2304 * A special case when writing type/attribute symbol table.
2305 * The kernel policy version less than 24 does not support
2306 * to load entries of attribute, so we have to re-calculate
2307 * the actual number of types except for attributes.
2308 */
2309 if (i == SYM_TYPES &&
2310 p->policyvers < POLICYDB_VERSION_BOUNDARY &&
2311 p->policy_type == POLICY_KERN) {
2312 hashtab_map(p->symtab[i].table, type_attr_uncount, &buf[1]);
2313 }
2314
2315 /*
2316 * Another special case when writing role/attribute symbol
2317 * table, role attributes are redundant for policy.X, or
2318 * when the pp's version is not big enough. So deduct
2319 * their numbers from p_roles.table->nel.
2320 */
2321 if ((i == SYM_ROLES) &&
2322 ((p->policy_type == POLICY_KERN) ||
2323 (p->policy_type != POLICY_KERN &&
2324 p->policyvers < MOD_POLICYDB_VERSION_ROLEATTRIB)))
2325 (void)hashtab_map(p->symtab[i].table, role_attr_uncount, &buf[1]);
2326
2327 buf[1] = cpu_to_le32(buf[1]);
2328 items = put_entry(buf, sizeof(uint32_t), 2, fp);
2329 if (items != 2)
2330 return POLICYDB_ERROR;
2331 if (hashtab_map(p->symtab[i].table, write_f[i], &pd))
2332 return POLICYDB_ERROR;
2333 }
2334
2335 if (p->policy_type == POLICY_KERN) {
2336 if (avtab_write(p, &p->te_avtab, fp))
2337 return POLICYDB_ERROR;
2338 if (p->policyvers < POLICYDB_VERSION_BOOL) {
2339 if (p->p_bools.nprim)
2340 WARN(fp->handle, "Discarding "
2341 "booleans and conditional rules");
2342 } else {
2343 if (cond_write_list(p, p->cond_list, fp))
2344 return POLICYDB_ERROR;
2345 }
2346 if (role_trans_write(p, fp))
2347 return POLICYDB_ERROR;
2348 if (role_allow_write(p->role_allow, fp))
2349 return POLICYDB_ERROR;
2350 if (p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS) {
2351 if (filename_trans_write(p, fp))
2352 return POLICYDB_ERROR;
2353 } else {
2354 if (p->filename_trans)
2355 WARN(fp->handle, "Discarding filename type transition rules");
2356 }
2357 } else {
2358 if (avrule_block_write(p->global, num_syms, p, fp) == -1) {
2359 return POLICYDB_ERROR;
2360 }
2361
2362 for (i = 0; i < num_syms; i++) {
2363 buf[0] = cpu_to_le32(p->scope[i].table->nel);
2364 if (put_entry(buf, sizeof(uint32_t), 1, fp) != 1) {
2365 return POLICYDB_ERROR;
2366 }
2367 if (hashtab_map(p->scope[i].table, scope_write, &pd))
2368 return POLICYDB_ERROR;
2369 }
2370 }
2371
2372 if (ocontext_write(info, p, fp) == -1 || genfs_write(p, fp) == -1) {
2373 return POLICYDB_ERROR;
2374 }
2375
2376 if ((p->policyvers >= POLICYDB_VERSION_MLS
2377 && p->policy_type == POLICY_KERN)
2378 || (p->policyvers >= MOD_POLICYDB_VERSION_MLS
2379 && p->policyvers < MOD_POLICYDB_VERSION_RANGETRANS
2380 && p->policy_type == POLICY_BASE)) {
2381 if (range_write(p, fp)) {
2382 return POLICYDB_ERROR;
2383 }
2384 }
2385
2386 if (p->policy_type == POLICY_KERN
2387 && p->policyvers >= POLICYDB_VERSION_AVTAB) {
2388 for (i = 0; i < p->p_types.nprim; i++) {
2389 if (ebitmap_write(&p->type_attr_map[i], fp) == -1)
2390 return POLICYDB_ERROR;
2391 }
2392 }
2393
2394 return POLICYDB_SUCCESS;
2395 }
2396