1/* Author: Karl MacMillan <kmacmillan@tresys.com> 2 * Jason Tang <jtang@tresys.com> 3 * Chris PeBenito <cpebenito@tresys.com> 4 * 5 * Copyright (C) 2004-2005 Tresys Technology, LLC 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "policydb_internal.h" 23#include "module_internal.h" 24#include <sepol/policydb/link.h> 25#include <sepol/policydb/expand.h> 26#include <sepol/policydb/module.h> 27#include "debug.h" 28#include "private.h" 29 30#include <stdio.h> 31#include <stdlib.h> 32#include <limits.h> 33#include <inttypes.h> 34 35#define SEPOL_PACKAGE_SECTION_FC 0xf97cff90 36#define SEPOL_PACKAGE_SECTION_SEUSER 0x97cff91 37#define SEPOL_PACKAGE_SECTION_USER_EXTRA 0x97cff92 38#define SEPOL_PACKAGE_SECTION_NETFILTER 0x97cff93 39 40static int policy_file_seek(struct policy_file *fp, size_t offset) 41{ 42 switch (fp->type) { 43 case PF_USE_STDIO: 44 if (offset > LONG_MAX) { 45 errno = EFAULT; 46 return -1; 47 } 48 return fseek(fp->fp, (long)offset, SEEK_SET); 49 case PF_USE_MEMORY: 50 if (offset > fp->size) { 51 errno = EFAULT; 52 return -1; 53 } 54 fp->data -= fp->size - fp->len; 55 fp->data += offset; 56 fp->len = fp->size - offset; 57 return 0; 58 default: 59 return 0; 60 } 61} 62 63static int policy_file_length(struct policy_file *fp, size_t *out) 64{ 65 long prev_offset, end_offset; 66 int rc; 67 switch (fp->type) { 68 case PF_USE_STDIO: 69 prev_offset = ftell(fp->fp); 70 if (prev_offset < 0) 71 return prev_offset; 72 rc = fseek(fp->fp, 0L, SEEK_END); 73 if (rc < 0) 74 return rc; 75 end_offset = ftell(fp->fp); 76 if (end_offset < 0) 77 return end_offset; 78 rc = fseek(fp->fp, prev_offset, SEEK_SET); 79 if (rc < 0) 80 return rc; 81 *out = end_offset; 82 break; 83 case PF_USE_MEMORY: 84 *out = fp->size; 85 break; 86 default: 87 *out = 0; 88 break; 89 } 90 return 0; 91} 92 93static int module_package_init(sepol_module_package_t * p) 94{ 95 memset(p, 0, sizeof(sepol_module_package_t)); 96 if (sepol_policydb_create(&p->policy)) 97 return -1; 98 99 p->version = 1; 100 return 0; 101} 102 103static int set_char(char **field, char *data, size_t len) 104{ 105 if (*field) { 106 free(*field); 107 *field = NULL; 108 } 109 if (len) { 110 *field = malloc(len); 111 if (!*field) 112 return -1; 113 memcpy(*field, data, len); 114 } 115 return 0; 116} 117 118int sepol_module_package_create(sepol_module_package_t ** p) 119{ 120 int rc; 121 122 *p = calloc(1, sizeof(sepol_module_package_t)); 123 if (!(*p)) 124 return -1; 125 126 rc = module_package_init(*p); 127 if (rc < 0) { 128 free(*p); 129 *p = NULL; 130 } 131 132 return rc; 133} 134 135 136/* Deallocates all memory associated with a module package, including 137 * the pointer itself. Does nothing if p is NULL. 138 */ 139void sepol_module_package_free(sepol_module_package_t * p) 140{ 141 if (p == NULL) 142 return; 143 144 sepol_policydb_free(p->policy); 145 free(p->file_contexts); 146 free(p->seusers); 147 free(p->user_extra); 148 free(p->netfilter_contexts); 149 free(p); 150} 151 152 153char *sepol_module_package_get_file_contexts(sepol_module_package_t * p) 154{ 155 return p->file_contexts; 156} 157 158size_t sepol_module_package_get_file_contexts_len(sepol_module_package_t * p) 159{ 160 return p->file_contexts_len; 161} 162 163char *sepol_module_package_get_seusers(sepol_module_package_t * p) 164{ 165 return p->seusers; 166} 167 168size_t sepol_module_package_get_seusers_len(sepol_module_package_t * p) 169{ 170 return p->seusers_len; 171} 172 173char *sepol_module_package_get_user_extra(sepol_module_package_t * p) 174{ 175 return p->user_extra; 176} 177 178size_t sepol_module_package_get_user_extra_len(sepol_module_package_t * p) 179{ 180 return p->user_extra_len; 181} 182 183char *sepol_module_package_get_netfilter_contexts(sepol_module_package_t * p) 184{ 185 return p->netfilter_contexts; 186} 187 188size_t sepol_module_package_get_netfilter_contexts_len(sepol_module_package_t * 189 p) 190{ 191 return p->netfilter_contexts_len; 192} 193 194int sepol_module_package_set_file_contexts(sepol_module_package_t * p, 195 char *data, size_t len) 196{ 197 if (set_char(&p->file_contexts, data, len)) 198 return -1; 199 200 p->file_contexts_len = len; 201 return 0; 202} 203 204int sepol_module_package_set_seusers(sepol_module_package_t * p, 205 char *data, size_t len) 206{ 207 if (set_char(&p->seusers, data, len)) 208 return -1; 209 210 p->seusers_len = len; 211 return 0; 212} 213 214int sepol_module_package_set_user_extra(sepol_module_package_t * p, 215 char *data, size_t len) 216{ 217 if (set_char(&p->user_extra, data, len)) 218 return -1; 219 220 p->user_extra_len = len; 221 return 0; 222} 223 224int sepol_module_package_set_netfilter_contexts(sepol_module_package_t * p, 225 char *data, size_t len) 226{ 227 if (set_char(&p->netfilter_contexts, data, len)) 228 return -1; 229 230 p->netfilter_contexts_len = len; 231 return 0; 232} 233 234sepol_policydb_t *sepol_module_package_get_policy(sepol_module_package_t * p) 235{ 236 return p->policy; 237} 238 239/* Append each of the file contexts from each module to the base 240 * policy's file context. 'base_context' will be reallocated to a 241 * larger size (and thus it is an in/out reference 242 * variable). 'base_fc_len' is the length of base's file context; it 243 * too is a reference variable. Return 0 on success, -1 if out of 244 * memory. */ 245static int link_file_contexts(sepol_module_package_t * base, 246 sepol_module_package_t ** modules, 247 int num_modules) 248{ 249 size_t fc_len; 250 int i; 251 char *s; 252 253 fc_len = base->file_contexts_len; 254 for (i = 0; i < num_modules; i++) { 255 fc_len += modules[i]->file_contexts_len; 256 } 257 258 if ((s = (char *)realloc(base->file_contexts, fc_len)) == NULL) { 259 return -1; 260 } 261 base->file_contexts = s; 262 for (i = 0; i < num_modules; i++) { 263 memcpy(base->file_contexts + base->file_contexts_len, 264 modules[i]->file_contexts, 265 modules[i]->file_contexts_len); 266 base->file_contexts_len += modules[i]->file_contexts_len; 267 } 268 return 0; 269} 270 271/* Append each of the netfilter contexts from each module to the base 272 * policy's netfilter context. 'base_context' will be reallocated to a 273 * larger size (and thus it is an in/out reference 274 * variable). 'base_nc_len' is the length of base's netfilter contexts; it 275 * too is a reference variable. Return 0 on success, -1 if out of 276 * memory. */ 277static int link_netfilter_contexts(sepol_module_package_t * base, 278 sepol_module_package_t ** modules, 279 int num_modules) 280{ 281 size_t base_nc_len; 282 int i; 283 char *base_context; 284 285 base_nc_len = base->netfilter_contexts_len; 286 for (i = 0; i < num_modules; i++) { 287 base_nc_len += modules[i]->netfilter_contexts_len; 288 } 289 290 if ((base_context = 291 (char *)realloc(base->netfilter_contexts, base_nc_len)) == NULL) { 292 return -1; 293 } 294 base->netfilter_contexts = base_context; 295 for (i = 0; i < num_modules; i++) { 296 if (modules[i]->netfilter_contexts_len > 0) { 297 memcpy(base->netfilter_contexts + base->netfilter_contexts_len, 298 modules[i]->netfilter_contexts, 299 modules[i]->netfilter_contexts_len); 300 base->netfilter_contexts_len += 301 modules[i]->netfilter_contexts_len; 302 } 303 304 } 305 return 0; 306} 307 308/* Links the module packages into the base. Returns 0 on success, -1 309 * if a requirement was not met, or -2 for all other errors. */ 310int sepol_link_packages(sepol_handle_t * handle, 311 sepol_module_package_t * base, 312 sepol_module_package_t ** modules, int num_modules, 313 int verbose) 314{ 315 policydb_t **mod_pols = NULL; 316 int i, retval; 317 318 if ((mod_pols = calloc(num_modules, sizeof(*mod_pols))) == NULL) { 319 ERR(handle, "Out of memory!"); 320 return -2; 321 } 322 for (i = 0; i < num_modules; i++) { 323 mod_pols[i] = &modules[i]->policy->p; 324 } 325 326 retval = link_modules(handle, &base->policy->p, mod_pols, num_modules, 327 verbose); 328 free(mod_pols); 329 if (retval == -3) { 330 return -1; 331 } else if (retval < 0) { 332 return -2; 333 } 334 335 if (link_file_contexts(base, modules, num_modules) == -1) { 336 ERR(handle, "Out of memory!"); 337 return -2; 338 } 339 340 if (link_netfilter_contexts(base, modules, num_modules) == -1) { 341 ERR(handle, "Out of memory!"); 342 return -2; 343 } 344 345 return 0; 346} 347 348/* buf must be large enough - no checks are performed */ 349#define _read_helper_bufsize BUFSIZ 350static int read_helper(char *buf, struct policy_file *file, uint32_t bytes) 351{ 352 uint32_t offset, nel, read_len; 353 int rc; 354 355 offset = 0; 356 nel = bytes; 357 358 while (nel) { 359 if (nel < _read_helper_bufsize) 360 read_len = nel; 361 else 362 read_len = _read_helper_bufsize; 363 rc = next_entry(&buf[offset], file, read_len); 364 if (rc < 0) 365 return -1; 366 offset += read_len; 367 nel -= read_len; 368 } 369 return 0; 370} 371 372#define MAXSECTIONS 100 373 374/* Get the section offsets from a package file, offsets will be malloc'd to 375 * the appropriate size and the caller must free() them */ 376static int module_package_read_offsets(sepol_module_package_t * mod, 377 struct policy_file *file, 378 size_t ** offsets, uint32_t * sections) 379{ 380 uint32_t *buf = NULL, nsec; 381 unsigned i; 382 size_t *off = NULL; 383 int rc; 384 385 buf = malloc(sizeof(uint32_t)*3); 386 if (!buf) { 387 ERR(file->handle, "out of memory"); 388 goto err; 389 } 390 391 rc = next_entry(buf, file, sizeof(uint32_t) * 3); 392 if (rc < 0) { 393 ERR(file->handle, "module package header truncated"); 394 goto err; 395 } 396 if (le32_to_cpu(buf[0]) != SEPOL_MODULE_PACKAGE_MAGIC) { 397 ERR(file->handle, 398 "wrong magic number for module package: expected %#08x, got %#08x", 399 SEPOL_MODULE_PACKAGE_MAGIC, le32_to_cpu(buf[0])); 400 goto err; 401 } 402 403 mod->version = le32_to_cpu(buf[1]); 404 nsec = *sections = le32_to_cpu(buf[2]); 405 406 if (nsec > MAXSECTIONS) { 407 ERR(file->handle, "too many sections (%u) in module package", 408 nsec); 409 goto err; 410 } 411 412 off = (size_t *) calloc(nsec + 1, sizeof(size_t)); 413 if (!off) { 414 ERR(file->handle, "out of memory"); 415 goto err; 416 } 417 418 free(buf); 419 buf = calloc(nsec, sizeof(uint32_t)); 420 if (!buf) { 421 ERR(file->handle, "out of memory"); 422 goto err; 423 } 424 rc = next_entry(buf, file, sizeof(uint32_t) * nsec); 425 if (rc < 0) { 426 ERR(file->handle, "module package offset array truncated"); 427 goto err; 428 } 429 430 for (i = 0; i < nsec; i++) { 431 off[i] = le32_to_cpu(buf[i]); 432 if (i && off[i] < off[i - 1]) { 433 ERR(file->handle, "offsets are not increasing (at %u, " 434 "offset %zu -> %zu", i, off[i - 1], 435 off[i]); 436 goto err; 437 } 438 } 439 440 rc = policy_file_length(file, &off[nsec]); 441 if (rc < 0) 442 goto err; 443 444 if (nsec && off[nsec] < off[nsec-1]) { 445 ERR(file->handle, "offset greater than file size (at %u, " 446 "offset %zu -> %zu", nsec, off[nsec - 1], 447 off[nsec]); 448 goto err; 449 } 450 *offsets = off; 451 free(buf); 452 return 0; 453 454err: 455 free(buf); 456 free(off); 457 return -1; 458} 459 460/* Flags for which sections have been seen during parsing of module package. */ 461#define SEEN_MOD 1 462#define SEEN_FC 2 463#define SEEN_SEUSER 4 464#define SEEN_USER_EXTRA 8 465#define SEEN_NETFILTER 16 466 467int sepol_module_package_read(sepol_module_package_t * mod, 468 struct sepol_policy_file *spf, int verbose) 469{ 470 struct policy_file *file = &spf->pf; 471 uint32_t buf[1], nsec; 472 size_t *offsets, len; 473 int rc; 474 unsigned i, seen = 0; 475 476 if (module_package_read_offsets(mod, file, &offsets, &nsec)) 477 return -1; 478 479 /* we know the section offsets, seek to them and read in the data */ 480 481 for (i = 0; i < nsec; i++) { 482 483 if (policy_file_seek(file, offsets[i])) { 484 ERR(file->handle, "error seeking to offset %zu for " 485 "module package section %u", offsets[i], i); 486 goto cleanup; 487 } 488 489 len = offsets[i + 1] - offsets[i]; 490 491 if (len < sizeof(uint32_t)) { 492 ERR(file->handle, "module package section %u " 493 "has too small length %zu", i, len); 494 goto cleanup; 495 } 496 497 /* read the magic number, so that we know which function to call */ 498 rc = next_entry(buf, file, sizeof(uint32_t)); 499 if (rc < 0) { 500 ERR(file->handle, 501 "module package section %u truncated, lacks magic number", 502 i); 503 goto cleanup; 504 } 505 506 switch (le32_to_cpu(buf[0])) { 507 case SEPOL_PACKAGE_SECTION_FC: 508 if (seen & SEEN_FC) { 509 ERR(file->handle, 510 "found multiple file contexts sections in module package (at section %u)", 511 i); 512 goto cleanup; 513 } 514 515 mod->file_contexts_len = len - sizeof(uint32_t); 516 mod->file_contexts = 517 (char *)malloc(mod->file_contexts_len); 518 if (!mod->file_contexts) { 519 ERR(file->handle, "out of memory"); 520 goto cleanup; 521 } 522 if (read_helper 523 (mod->file_contexts, file, 524 mod->file_contexts_len)) { 525 ERR(file->handle, 526 "invalid file contexts section at section %u", 527 i); 528 free(mod->file_contexts); 529 mod->file_contexts = NULL; 530 goto cleanup; 531 } 532 seen |= SEEN_FC; 533 break; 534 case SEPOL_PACKAGE_SECTION_SEUSER: 535 if (seen & SEEN_SEUSER) { 536 ERR(file->handle, 537 "found multiple seuser sections in module package (at section %u)", 538 i); 539 goto cleanup; 540 } 541 542 mod->seusers_len = len - sizeof(uint32_t); 543 mod->seusers = (char *)malloc(mod->seusers_len); 544 if (!mod->seusers) { 545 ERR(file->handle, "out of memory"); 546 goto cleanup; 547 } 548 if (read_helper(mod->seusers, file, mod->seusers_len)) { 549 ERR(file->handle, 550 "invalid seuser section at section %u", i); 551 free(mod->seusers); 552 mod->seusers = NULL; 553 goto cleanup; 554 } 555 seen |= SEEN_SEUSER; 556 break; 557 case SEPOL_PACKAGE_SECTION_USER_EXTRA: 558 if (seen & SEEN_USER_EXTRA) { 559 ERR(file->handle, 560 "found multiple user_extra sections in module package (at section %u)", 561 i); 562 goto cleanup; 563 } 564 565 mod->user_extra_len = len - sizeof(uint32_t); 566 mod->user_extra = (char *)malloc(mod->user_extra_len); 567 if (!mod->user_extra) { 568 ERR(file->handle, "out of memory"); 569 goto cleanup; 570 } 571 if (read_helper 572 (mod->user_extra, file, mod->user_extra_len)) { 573 ERR(file->handle, 574 "invalid user_extra section at section %u", 575 i); 576 free(mod->user_extra); 577 mod->user_extra = NULL; 578 goto cleanup; 579 } 580 seen |= SEEN_USER_EXTRA; 581 break; 582 case SEPOL_PACKAGE_SECTION_NETFILTER: 583 if (seen & SEEN_NETFILTER) { 584 ERR(file->handle, 585 "found multiple netfilter contexts sections in module package (at section %u)", 586 i); 587 goto cleanup; 588 } 589 590 mod->netfilter_contexts_len = len - sizeof(uint32_t); 591 mod->netfilter_contexts = 592 (char *)malloc(mod->netfilter_contexts_len); 593 if (!mod->netfilter_contexts) { 594 ERR(file->handle, "out of memory"); 595 goto cleanup; 596 } 597 if (read_helper 598 (mod->netfilter_contexts, file, 599 mod->netfilter_contexts_len)) { 600 ERR(file->handle, 601 "invalid netfilter contexts section at section %u", 602 i); 603 free(mod->netfilter_contexts); 604 mod->netfilter_contexts = NULL; 605 goto cleanup; 606 } 607 seen |= SEEN_NETFILTER; 608 break; 609 case POLICYDB_MOD_MAGIC: 610 if (seen & SEEN_MOD) { 611 ERR(file->handle, 612 "found multiple module sections in module package (at section %u)", 613 i); 614 goto cleanup; 615 } 616 617 /* seek back to where the magic number was */ 618 if (policy_file_seek(file, offsets[i])) 619 goto cleanup; 620 621 rc = policydb_read(&mod->policy->p, file, verbose); 622 if (rc < 0) { 623 ERR(file->handle, 624 "invalid module in module package (at section %u)", 625 i); 626 goto cleanup; 627 } 628 seen |= SEEN_MOD; 629 break; 630 default: 631 /* unknown section, ignore */ 632 ERR(file->handle, 633 "unknown magic number at section %u, offset: %zx, number: %x ", 634 i, offsets[i], le32_to_cpu(buf[0])); 635 break; 636 } 637 } 638 639 if ((seen & SEEN_MOD) == 0) { 640 ERR(file->handle, "missing module in module package"); 641 goto cleanup; 642 } 643 644 free(offsets); 645 return 0; 646 647 cleanup: 648 free(offsets); 649 return -1; 650} 651 652int sepol_module_package_info(struct sepol_policy_file *spf, int *type, 653 char **name, char **version) 654{ 655 struct policy_file *file = &spf->pf; 656 sepol_module_package_t *mod = NULL; 657 uint32_t buf[5], len, nsec; 658 size_t *offsets = NULL; 659 unsigned i, seen = 0; 660 char *id; 661 int rc; 662 663 if (sepol_module_package_create(&mod)) 664 return -1; 665 666 if (module_package_read_offsets(mod, file, &offsets, &nsec)) { 667 goto cleanup; 668 } 669 670 for (i = 0; i < nsec; i++) { 671 672 if (policy_file_seek(file, offsets[i])) { 673 ERR(file->handle, "error seeking to offset " 674 "%zu for module package section %u", offsets[i], i); 675 goto cleanup; 676 } 677 678 len = offsets[i + 1] - offsets[i]; 679 680 if (len < sizeof(uint32_t)) { 681 ERR(file->handle, 682 "module package section %u has too small length %u", 683 i, len); 684 goto cleanup; 685 } 686 687 /* read the magic number, so that we know which function to call */ 688 rc = next_entry(buf, file, sizeof(uint32_t) * 2); 689 if (rc < 0) { 690 ERR(file->handle, 691 "module package section %u truncated, lacks magic number", 692 i); 693 goto cleanup; 694 } 695 696 switch (le32_to_cpu(buf[0])) { 697 case SEPOL_PACKAGE_SECTION_FC: 698 /* skip file contexts */ 699 if (seen & SEEN_FC) { 700 ERR(file->handle, 701 "found multiple file contexts sections in module package (at section %u)", 702 i); 703 goto cleanup; 704 } 705 seen |= SEEN_FC; 706 break; 707 case SEPOL_PACKAGE_SECTION_SEUSER: 708 /* skip seuser */ 709 if (seen & SEEN_SEUSER) { 710 ERR(file->handle, 711 "found seuser sections in module package (at section %u)", 712 i); 713 goto cleanup; 714 } 715 seen |= SEEN_SEUSER; 716 break; 717 case SEPOL_PACKAGE_SECTION_USER_EXTRA: 718 /* skip user_extra */ 719 if (seen & SEEN_USER_EXTRA) { 720 ERR(file->handle, 721 "found user_extra sections in module package (at section %u)", 722 i); 723 goto cleanup; 724 } 725 seen |= SEEN_USER_EXTRA; 726 break; 727 case SEPOL_PACKAGE_SECTION_NETFILTER: 728 /* skip netfilter contexts */ 729 if (seen & SEEN_NETFILTER) { 730 ERR(file->handle, 731 "found multiple netfilter contexts sections in module package (at section %u)", 732 i); 733 goto cleanup; 734 } 735 seen |= SEEN_NETFILTER; 736 break; 737 case POLICYDB_MOD_MAGIC: 738 if (seen & SEEN_MOD) { 739 ERR(file->handle, 740 "found multiple module sections in module package (at section %u)", 741 i); 742 goto cleanup; 743 } 744 len = le32_to_cpu(buf[1]); 745 if (len != strlen(POLICYDB_MOD_STRING)) { 746 ERR(file->handle, 747 "module string length is wrong (at section %u)", 748 i); 749 goto cleanup; 750 } 751 752 /* skip id */ 753 id = malloc(len + 1); 754 if (!id) { 755 ERR(file->handle, 756 "out of memory (at section %u)", 757 i); 758 goto cleanup; 759 } 760 rc = next_entry(id, file, len); 761 free(id); 762 if (rc < 0) { 763 ERR(file->handle, 764 "cannot get module string (at section %u)", 765 i); 766 goto cleanup; 767 } 768 769 rc = next_entry(buf, file, sizeof(uint32_t) * 5); 770 if (rc < 0) { 771 ERR(file->handle, 772 "cannot get module header (at section %u)", 773 i); 774 goto cleanup; 775 } 776 777 *type = le32_to_cpu(buf[0]); 778 /* if base - we're done */ 779 if (*type == POLICY_BASE) { 780 *name = NULL; 781 *version = NULL; 782 seen |= SEEN_MOD; 783 break; 784 } else if (*type != POLICY_MOD) { 785 ERR(file->handle, 786 "module has invalid type %d (at section %u)", 787 *type, i); 788 goto cleanup; 789 } 790 791 /* read the name and version */ 792 rc = next_entry(buf, file, sizeof(uint32_t)); 793 if (rc < 0) { 794 ERR(file->handle, 795 "cannot get module name len (at section %u)", 796 i); 797 goto cleanup; 798 } 799 800 len = le32_to_cpu(buf[0]); 801 if (str_read(name, file, len)) { 802 ERR(file->handle, 803 "cannot read module name (at section %u): %m", 804 i); 805 goto cleanup; 806 } 807 808 rc = next_entry(buf, file, sizeof(uint32_t)); 809 if (rc < 0) { 810 ERR(file->handle, 811 "cannot get module version len (at section %u)", 812 i); 813 goto cleanup; 814 } 815 len = le32_to_cpu(buf[0]); 816 if (str_read(version, file, len)) { 817 ERR(file->handle, 818 "cannot read module version (at section %u): %m", 819 i); 820 goto cleanup; 821 } 822 seen |= SEEN_MOD; 823 break; 824 default: 825 break; 826 } 827 828 } 829 830 if ((seen & SEEN_MOD) == 0) { 831 ERR(file->handle, "missing module in module package"); 832 goto cleanup; 833 } 834 835 sepol_module_package_free(mod); 836 free(offsets); 837 return 0; 838 839 cleanup: 840 sepol_module_package_free(mod); 841 free(offsets); 842 return -1; 843} 844 845static int write_helper(char *data, size_t len, struct policy_file *file) 846{ 847 int idx = 0; 848 size_t len2; 849 850 while (len) { 851 if (len > BUFSIZ) 852 len2 = BUFSIZ; 853 else 854 len2 = len; 855 856 if (put_entry(&data[idx], 1, len2, file) != len2) { 857 return -1; 858 } 859 len -= len2; 860 idx += len2; 861 } 862 return 0; 863} 864 865int sepol_module_package_write(sepol_module_package_t * p, 866 struct sepol_policy_file *spf) 867{ 868 struct policy_file *file = &spf->pf; 869 policy_file_t polfile; 870 uint32_t buf[5], offsets[5], len, nsec = 0; 871 int i; 872 873 if (p->policy) { 874 /* compute policy length */ 875 policy_file_init(&polfile); 876 polfile.type = PF_LEN; 877 polfile.handle = file->handle; 878 if (policydb_write(&p->policy->p, &polfile)) 879 return -1; 880 len = polfile.len; 881 if (!polfile.len) 882 return -1; 883 nsec++; 884 885 } else { 886 /* We don't support writing a package without a module at this point */ 887 return -1; 888 } 889 890 /* seusers and user_extra only supported in base at the moment */ 891 if ((p->seusers || p->user_extra) 892 && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) { 893 ERR(file->handle, 894 "seuser and user_extra sections only supported in base"); 895 return -1; 896 } 897 898 if (p->file_contexts) 899 nsec++; 900 901 if (p->seusers) 902 nsec++; 903 904 if (p->user_extra) 905 nsec++; 906 907 if (p->netfilter_contexts) 908 nsec++; 909 910 buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC); 911 buf[1] = cpu_to_le32(p->version); 912 buf[2] = cpu_to_le32(nsec); 913 if (put_entry(buf, sizeof(uint32_t), 3, file) != 3) 914 return -1; 915 916 /* calculate offsets */ 917 offsets[0] = (nsec + 3) * sizeof(uint32_t); 918 buf[0] = cpu_to_le32(offsets[0]); 919 920 i = 1; 921 if (p->file_contexts) { 922 offsets[i] = offsets[i - 1] + len; 923 buf[i] = cpu_to_le32(offsets[i]); 924 /* add a uint32_t to compensate for the magic number */ 925 len = p->file_contexts_len + sizeof(uint32_t); 926 i++; 927 } 928 if (p->seusers) { 929 offsets[i] = offsets[i - 1] + len; 930 buf[i] = cpu_to_le32(offsets[i]); 931 len = p->seusers_len + sizeof(uint32_t); 932 i++; 933 } 934 if (p->user_extra) { 935 offsets[i] = offsets[i - 1] + len; 936 buf[i] = cpu_to_le32(offsets[i]); 937 len = p->user_extra_len + sizeof(uint32_t); 938 i++; 939 } 940 if (p->netfilter_contexts) { 941 offsets[i] = offsets[i - 1] + len; 942 buf[i] = cpu_to_le32(offsets[i]); 943 len = p->netfilter_contexts_len + sizeof(uint32_t); 944 i++; 945 } 946 if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec) 947 return -1; 948 949 /* write sections */ 950 951 if (policydb_write(&p->policy->p, file)) 952 return -1; 953 954 if (p->file_contexts) { 955 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC); 956 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) 957 return -1; 958 if (write_helper(p->file_contexts, p->file_contexts_len, file)) 959 return -1; 960 } 961 if (p->seusers) { 962 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER); 963 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) 964 return -1; 965 if (write_helper(p->seusers, p->seusers_len, file)) 966 return -1; 967 968 } 969 if (p->user_extra) { 970 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA); 971 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) 972 return -1; 973 if (write_helper(p->user_extra, p->user_extra_len, file)) 974 return -1; 975 } 976 if (p->netfilter_contexts) { 977 buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_NETFILTER); 978 if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) 979 return -1; 980 if (write_helper 981 (p->netfilter_contexts, p->netfilter_contexts_len, file)) 982 return -1; 983 } 984 return 0; 985} 986 987int sepol_link_modules(sepol_handle_t * handle, 988 sepol_policydb_t * base, 989 sepol_policydb_t ** modules, size_t len, int verbose) 990{ 991 return link_modules(handle, &base->p, (policydb_t **) modules, len, 992 verbose); 993} 994 995int sepol_expand_module(sepol_handle_t * handle, 996 sepol_policydb_t * base, 997 sepol_policydb_t * out, int verbose, int check) 998{ 999 return expand_module(handle, &base->p, &out->p, verbose, check); 1000} 1001