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