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