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