1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdarg.h> 4 #include <string.h> 5 #include <sys/types.h> 6 #include <unistd.h> 7 8 #include <arpa/inet.h> 9 #include <netinet/in.h> 10 #ifndef IPPROTO_DCCP 11 #define IPPROTO_DCCP 33 12 #endif 13 #ifndef IPPROTO_SCTP 14 #define IPPROTO_SCTP 132 15 #endif 16 17 #include <sepol/policydb/ebitmap.h> 18 #include <sepol/policydb/hashtab.h> 19 #include <sepol/policydb/symtab.h> 20 21 #include "kernel_to_common.h" 22 23 24 void sepol_log_err(const char *fmt, ...) 25 { 26 va_list argptr; 27 va_start(argptr, fmt); 28 if (vfprintf(stderr, fmt, argptr) < 0) { 29 _exit(EXIT_FAILURE); 30 } 31 va_end(argptr); 32 if (fprintf(stderr, "\n") < 0) { 33 _exit(EXIT_FAILURE); 34 } 35 } 36 37 void sepol_indent(FILE *out, int indent) 38 { 39 if (fprintf(out, "%*s", indent * 4, "") < 0) { 40 sepol_log_err("Failed to write to output"); 41 } 42 } 43 44 void sepol_printf(FILE *out, const char *fmt, ...) 45 { 46 va_list argptr; 47 va_start(argptr, fmt); 48 if (vfprintf(out, fmt, argptr) < 0) { 49 sepol_log_err("Failed to write to output"); 50 } 51 va_end(argptr); 52 } 53 54 __attribute__ ((format(printf, 1, 0))) 55 static char *create_str_helper(const char *fmt, int num, va_list vargs) 56 { 57 va_list vargs2; 58 char *str = NULL; 59 char *s; 60 size_t len; 61 int i, rc; 62 63 va_copy(vargs2, vargs); 64 65 len = strlen(fmt) + 1; /* +1 for '\0' */ 66 67 for (i=0; i<num; i++) { 68 s = va_arg(vargs, char *); 69 len += strlen(s) - 2; /* -2 for each %s in fmt */ 70 } 71 72 str = malloc(len); 73 if (!str) { 74 sepol_log_err("Out of memory"); 75 goto exit; 76 } 77 78 rc = vsnprintf(str, len, fmt, vargs2); 79 if (rc < 0 || rc >= (int)len) { 80 goto exit; 81 } 82 83 va_end(vargs2); 84 85 return str; 86 87 exit: 88 free(str); 89 va_end(vargs2); 90 return NULL; 91 } 92 93 char *create_str(const char *fmt, int num, ...) 94 { 95 char *str = NULL; 96 va_list vargs; 97 98 va_start(vargs, num); 99 str = create_str_helper(fmt, num, vargs); 100 va_end(vargs); 101 102 return str; 103 } 104 105 int strs_init(struct strs **strs, size_t size) 106 { 107 struct strs *new; 108 109 *strs = NULL; 110 111 new = malloc(sizeof(struct strs)); 112 if (!new) { 113 sepol_log_err("Out of memory"); 114 return -1; 115 } 116 117 new->list = calloc(sizeof(char *), size); 118 if (!new->list) { 119 sepol_log_err("Out of memory"); 120 free(new); 121 return -1; 122 } 123 124 new->num = 0; 125 new->size = size; 126 127 *strs = new; 128 129 return 0; 130 } 131 132 void strs_destroy(struct strs **strs) 133 { 134 if (!strs || !*strs) { 135 return; 136 } 137 138 free((*strs)->list); 139 (*strs)->list = NULL; 140 (*strs)->num = 0; 141 (*strs)->size = 0; 142 free(*strs); 143 *strs = NULL; 144 } 145 146 void strs_free_all(struct strs *strs) 147 { 148 if (!strs) { 149 return; 150 } 151 152 while (strs->num > 0) { 153 strs->num--; 154 free(strs->list[strs->num]); 155 } 156 } 157 158 int strs_add(struct strs *strs, char *s) 159 { 160 if (strs->num + 1 > strs->size) { 161 char **new; 162 unsigned i = strs->size; 163 strs->size *= 2; 164 new = realloc(strs->list, sizeof(char *)*strs->size); 165 if (!new) { 166 sepol_log_err("Out of memory"); 167 return -1; 168 } 169 strs->list = new; 170 memset(&strs->list[i], 0, sizeof(char *)*(strs->size-i)); 171 } 172 173 strs->list[strs->num] = s; 174 strs->num++; 175 176 return 0; 177 } 178 179 int strs_create_and_add(struct strs *strs, const char *fmt, int num, ...) 180 { 181 char *str; 182 va_list vargs; 183 int rc; 184 185 va_start(vargs, num); 186 str = create_str_helper(fmt, num, vargs); 187 va_end(vargs); 188 189 if (!str) { 190 rc = -1; 191 goto exit; 192 } 193 194 rc = strs_add(strs, str); 195 if (rc != 0) { 196 free(str); 197 goto exit; 198 } 199 200 return 0; 201 202 exit: 203 return rc; 204 } 205 206 char *strs_remove_last(struct strs *strs) 207 { 208 if (strs->num == 0) { 209 return NULL; 210 } 211 strs->num--; 212 return strs->list[strs->num]; 213 } 214 215 int strs_add_at_index(struct strs *strs, char *s, unsigned index) 216 { 217 if (index >= strs->size) { 218 char **new; 219 unsigned i = strs->size; 220 while (index >= strs->size) { 221 strs->size *= 2; 222 } 223 new = realloc(strs->list, sizeof(char *)*strs->size); 224 if (!new) { 225 sepol_log_err("Out of memory"); 226 return -1; 227 } 228 strs->list = new; 229 memset(&strs->list[i], 0, sizeof(char *)*(strs->size - i)); 230 } 231 232 strs->list[index] = s; 233 if (index >= strs->num) { 234 strs->num = index+1; 235 } 236 237 return 0; 238 } 239 240 char *strs_read_at_index(struct strs *strs, unsigned index) 241 { 242 if (index >= strs->num) { 243 return NULL; 244 } 245 246 return strs->list[index]; 247 } 248 249 static int strs_cmp(const void *a, const void *b) 250 { 251 char *const *aa = a; 252 char *const *bb = b; 253 return strcmp(*aa,*bb); 254 } 255 256 void strs_sort(struct strs *strs) 257 { 258 if (strs->num == 0) { 259 return; 260 } 261 qsort(strs->list, strs->num, sizeof(char *), strs_cmp); 262 } 263 264 unsigned strs_num_items(struct strs *strs) 265 { 266 return strs->num; 267 } 268 269 size_t strs_len_items(struct strs *strs) 270 { 271 unsigned i; 272 size_t len = 0; 273 274 for (i=0; i<strs->num; i++) { 275 if (!strs->list[i]) continue; 276 len += strlen(strs->list[i]); 277 } 278 279 return len; 280 } 281 282 char *strs_to_str(struct strs *strs) 283 { 284 char *str = NULL; 285 size_t len = 0; 286 char *p; 287 unsigned i; 288 int rc; 289 290 if (strs->num == 0) { 291 goto exit; 292 } 293 294 /* strs->num added because either ' ' or '\0' follows each item */ 295 len = strs_len_items(strs) + strs->num; 296 str = malloc(len); 297 if (!str) { 298 sepol_log_err("Out of memory"); 299 goto exit; 300 } 301 302 p = str; 303 for (i=0; i<strs->num; i++) { 304 if (!strs->list[i]) continue; 305 len = strlen(strs->list[i]); 306 rc = snprintf(p, len+1, "%s", strs->list[i]); 307 if (rc < 0 || rc > (int)len) { 308 free(str); 309 str = NULL; 310 goto exit; 311 } 312 p += len; 313 if (i < strs->num - 1) { 314 *p++ = ' '; 315 } 316 } 317 318 *p = '\0'; 319 320 exit: 321 return str; 322 } 323 324 void strs_write_each(struct strs *strs, FILE *out) 325 { 326 unsigned i; 327 328 for (i=0; i<strs->num; i++) { 329 if (!strs->list[i]) { 330 continue; 331 } 332 sepol_printf(out, "%s\n",strs->list[i]); 333 } 334 } 335 336 void strs_write_each_indented(struct strs *strs, FILE *out, int indent) 337 { 338 unsigned i; 339 340 for (i=0; i<strs->num; i++) { 341 if (!strs->list[i]) { 342 continue; 343 } 344 sepol_indent(out, indent); 345 sepol_printf(out, "%s\n",strs->list[i]); 346 } 347 } 348 349 int hashtab_ordered_to_strs(char *key, void *data, void *args) 350 { 351 struct strs *strs = (struct strs *)args; 352 symtab_datum_t *datum = data; 353 354 return strs_add_at_index(strs, key, datum->value-1); 355 } 356 357 int ebitmap_to_strs(struct ebitmap *map, struct strs *strs, char **val_to_name) 358 { 359 struct ebitmap_node *node; 360 uint32_t i; 361 int rc; 362 363 ebitmap_for_each_bit(map, node, i) { 364 if (!ebitmap_get_bit(map, i)) continue; 365 366 rc = strs_add(strs, val_to_name[i]); 367 if (rc != 0) { 368 return -1; 369 } 370 } 371 372 return 0; 373 } 374 375 char *ebitmap_to_str(struct ebitmap *map, char **val_to_name, int sort) 376 { 377 struct strs *strs; 378 char *str = NULL; 379 int rc; 380 381 rc = strs_init(&strs, 32); 382 if (rc != 0) { 383 goto exit; 384 } 385 386 rc = ebitmap_to_strs(map, strs, val_to_name); 387 if (rc != 0) { 388 goto exit; 389 } 390 391 if (sort) { 392 strs_sort(strs); 393 } 394 395 str = strs_to_str(strs); 396 397 exit: 398 strs_destroy(&strs); 399 400 return str; 401 } 402 403 int strs_stack_init(struct strs **stack) 404 { 405 return strs_init(stack, STACK_SIZE); 406 } 407 408 void strs_stack_destroy(struct strs **stack) 409 { 410 return strs_destroy(stack); 411 } 412 413 int strs_stack_push(struct strs *stack, char *s) 414 { 415 return strs_add(stack, s); 416 } 417 418 char *strs_stack_pop(struct strs *stack) 419 { 420 return strs_remove_last(stack); 421 } 422 423 int strs_stack_empty(struct strs *stack) 424 { 425 return strs_num_items(stack) == 0; 426 } 427 428 static int compare_ranges(uint64_t l1, uint64_t h1, uint64_t l2, uint64_t h2) 429 { 430 uint64_t d1, d2; 431 432 d1 = h1-l1; 433 d2 = h2-l2; 434 435 if (d1 < d2) { 436 return -1; 437 } else if (d1 > d2) { 438 return 1; 439 } else { 440 if (l1 < l2) { 441 return -1; 442 } else if (l1 > l2) { 443 return 1; 444 } 445 } 446 447 return 0; 448 } 449 450 static int fsuse_data_cmp(const void *a, const void *b) 451 { 452 struct ocontext *const *aa = a; 453 struct ocontext *const *bb = b; 454 455 if ((*aa)->v.behavior != (*bb)->v.behavior) { 456 if ((*aa)->v.behavior < (*bb)->v.behavior) { 457 return -1; 458 } else { 459 return 1; 460 } 461 } 462 463 return strcmp((*aa)->u.name, (*bb)->u.name); 464 } 465 466 static int portcon_data_cmp(const void *a, const void *b) 467 { 468 struct ocontext *const *aa = a; 469 struct ocontext *const *bb = b; 470 int rc; 471 472 rc = compare_ranges((*aa)->u.port.low_port, (*aa)->u.port.high_port, 473 (*bb)->u.port.low_port, (*bb)->u.port.high_port); 474 if (rc == 0) { 475 if ((*aa)->u.port.protocol == (*bb)->u.port.protocol) { 476 rc = 0; 477 } else if ((*aa)->u.port.protocol == IPPROTO_TCP) { 478 rc = -1; 479 } else { 480 rc = 1; 481 } 482 } 483 484 return rc; 485 } 486 487 static int netif_data_cmp(const void *a, const void *b) 488 { 489 struct ocontext *const *aa = a; 490 struct ocontext *const *bb = b; 491 492 return strcmp((*aa)->u.name, (*bb)->u.name); 493 } 494 495 static int node_data_cmp(const void *a, const void *b) 496 { 497 struct ocontext *const *aa = a; 498 struct ocontext *const *bb = b; 499 int rc; 500 501 rc = memcmp(&(*aa)->u.node.mask, &(*bb)->u.node.mask, sizeof((*aa)->u.node.mask)); 502 if (rc > 0) { 503 return -1; 504 } else if (rc < 0) { 505 return 1; 506 } 507 508 return memcmp(&(*aa)->u.node.addr, &(*bb)->u.node.addr, sizeof((*aa)->u.node.addr)); 509 } 510 511 static int node6_data_cmp(const void *a, const void *b) 512 { 513 struct ocontext *const *aa = a; 514 struct ocontext *const *bb = b; 515 int rc; 516 517 rc = memcmp(&(*aa)->u.node6.mask, &(*bb)->u.node6.mask, sizeof((*aa)->u.node6.mask)); 518 if (rc > 0) { 519 return -1; 520 } else if (rc < 0) { 521 return 1; 522 } 523 524 return memcmp(&(*aa)->u.node6.addr, &(*bb)->u.node6.addr, sizeof((*aa)->u.node6.addr)); 525 } 526 527 static int ibpkey_data_cmp(const void *a, const void *b) 528 { 529 int rc; 530 struct ocontext *const *aa = a; 531 struct ocontext *const *bb = b; 532 533 rc = (*aa)->u.ibpkey.subnet_prefix - (*bb)->u.ibpkey.subnet_prefix; 534 if (rc) 535 return rc; 536 537 return compare_ranges((*aa)->u.ibpkey.low_pkey, (*aa)->u.ibpkey.high_pkey, 538 (*bb)->u.ibpkey.low_pkey, (*bb)->u.ibpkey.high_pkey); 539 } 540 541 static int ibendport_data_cmp(const void *a, const void *b) 542 { 543 int rc; 544 struct ocontext *const *aa = a; 545 struct ocontext *const *bb = b; 546 547 rc = strcmp((*aa)->u.ibendport.dev_name, (*bb)->u.ibendport.dev_name); 548 if (rc) 549 return rc; 550 551 return (*aa)->u.ibendport.port - (*bb)->u.ibendport.port; 552 } 553 554 static int pirq_data_cmp(const void *a, const void *b) 555 { 556 struct ocontext *const *aa = a; 557 struct ocontext *const *bb = b; 558 559 if ((*aa)->u.pirq < (*bb)->u.pirq) { 560 return -1; 561 } else if ((*aa)->u.pirq > (*bb)->u.pirq) { 562 return 1; 563 } 564 565 return 0; 566 } 567 568 static int ioport_data_cmp(const void *a, const void *b) 569 { 570 struct ocontext *const *aa = a; 571 struct ocontext *const *bb = b; 572 573 return compare_ranges((*aa)->u.ioport.low_ioport, (*aa)->u.ioport.high_ioport, 574 (*bb)->u.ioport.low_ioport, (*bb)->u.ioport.high_ioport); 575 } 576 577 static int iomem_data_cmp(const void *a, const void *b) 578 { 579 struct ocontext *const *aa = a; 580 struct ocontext *const *bb = b; 581 582 return compare_ranges((*aa)->u.iomem.low_iomem, (*aa)->u.iomem.high_iomem, 583 (*bb)->u.iomem.low_iomem, (*bb)->u.iomem.high_iomem); 584 } 585 586 static int pcid_data_cmp(const void *a, const void *b) 587 { 588 struct ocontext *const *aa = a; 589 struct ocontext *const *bb = b; 590 591 if ((*aa)->u.device < (*bb)->u.device) { 592 return -1; 593 } else if ((*aa)->u.device > (*bb)->u.device) { 594 return 1; 595 } 596 597 return 0; 598 } 599 600 static int dtree_data_cmp(const void *a, const void *b) 601 { 602 struct ocontext *const *aa = a; 603 struct ocontext *const *bb = b; 604 605 return strcmp((*aa)->u.name, (*bb)->u.name); 606 } 607 608 static int sort_ocontext_data(struct ocontext **ocons, int (*cmp)(const void *, const void *)) 609 { 610 struct ocontext *ocon; 611 struct ocontext **data; 612 unsigned i, num; 613 614 num = 0; 615 for (ocon = *ocons; ocon != NULL; ocon = ocon->next) { 616 num++; 617 } 618 619 if (num == 0) { 620 return 0; 621 } 622 623 data = calloc(sizeof(*data), num); 624 if (!data) { 625 sepol_log_err("Out of memory\n"); 626 return -1; 627 } 628 629 i = 0; 630 for (ocon = *ocons; ocon != NULL; ocon = ocon->next) { 631 data[i] = ocon; 632 i++; 633 } 634 635 qsort(data, num, sizeof(*data), cmp); 636 637 *ocons = data[0]; 638 for (i=1; i < num; i++) { 639 data[i-1]->next = data[i]; 640 } 641 data[num-1]->next = NULL; 642 643 free(data); 644 645 return 0; 646 } 647 648 int sort_ocontexts(struct policydb *pdb) 649 { 650 int rc = 0; 651 652 if (pdb->target_platform == SEPOL_TARGET_SELINUX) { 653 rc = sort_ocontext_data(&pdb->ocontexts[5], fsuse_data_cmp); 654 if (rc != 0) { 655 goto exit; 656 } 657 658 rc = sort_ocontext_data(&pdb->ocontexts[2], portcon_data_cmp); 659 if (rc != 0) { 660 goto exit; 661 } 662 663 rc = sort_ocontext_data(&pdb->ocontexts[3], netif_data_cmp); 664 if (rc != 0) { 665 goto exit; 666 } 667 668 rc = sort_ocontext_data(&pdb->ocontexts[4], node_data_cmp); 669 if (rc != 0) { 670 goto exit; 671 } 672 673 rc = sort_ocontext_data(&pdb->ocontexts[6], node6_data_cmp); 674 if (rc != 0) { 675 goto exit; 676 } 677 678 rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBPKEY], ibpkey_data_cmp); 679 if (rc != 0) { 680 goto exit; 681 } 682 683 rc = sort_ocontext_data(&pdb->ocontexts[OCON_IBENDPORT], ibendport_data_cmp); 684 if (rc != 0) { 685 goto exit; 686 } 687 } else if (pdb->target_platform == SEPOL_TARGET_XEN) { 688 rc = sort_ocontext_data(&pdb->ocontexts[1], pirq_data_cmp); 689 if (rc != 0) { 690 goto exit; 691 } 692 693 rc = sort_ocontext_data(&pdb->ocontexts[2], ioport_data_cmp); 694 if (rc != 0) { 695 goto exit; 696 } 697 698 rc = sort_ocontext_data(&pdb->ocontexts[3], iomem_data_cmp); 699 if (rc != 0) { 700 goto exit; 701 } 702 703 rc = sort_ocontext_data(&pdb->ocontexts[4], pcid_data_cmp); 704 if (rc != 0) { 705 goto exit; 706 } 707 708 rc = sort_ocontext_data(&pdb->ocontexts[5], dtree_data_cmp); 709 if (rc != 0) { 710 goto exit; 711 } 712 } 713 714 exit: 715 if (rc != 0) { 716 sepol_log_err("Error sorting ocontexts\n"); 717 } 718 719 return rc; 720 } 721