1 #include <sys/types.h> 2 #include <unistd.h> 3 #include <string.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <stdbool.h> 7 #include <ctype.h> 8 #include <errno.h> 9 #include <pwd.h> 10 #include <grp.h> 11 #include <sys/mman.h> 12 #include <sys/mount.h> 13 #include <sys/types.h> 14 #include <sys/stat.h> 15 #include <sys/xattr.h> 16 #include <fcntl.h> 17 #include <fts.h> 18 #include <selinux/selinux.h> 19 #include <selinux/context.h> 20 #include <selinux/android.h> 21 #include <selinux/label.h> 22 #include <selinux/avc.h> 23 #include <openssl/sha.h> 24 #include <private/android_filesystem_config.h> 25 #include <log/log.h> 26 #include "policy.h" 27 #include "callbacks.h" 28 #include "selinux_internal.h" 29 #include "label_internal.h" 30 #include <fnmatch.h> 31 #include <limits.h> 32 #include <sys/vfs.h> 33 #include <linux/magic.h> 34 #include <libgen.h> 35 #include <packagelistparser/packagelistparser.h> 36 37 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 38 #include <sys/_system_properties.h> 39 40 /* 41 * XXX Where should this configuration file be located? 42 * Needs to be accessible by zygote and installd when 43 * setting credentials for app processes and setting permissions 44 * on app data directories. 45 */ 46 static char const * const seapp_contexts_file[] = { 47 "/seapp_contexts", 48 "/data/security/current/seapp_contexts", 49 NULL }; 50 51 static const struct selinux_opt seopts[] = { 52 { SELABEL_OPT_PATH, "/file_contexts.bin" }, 53 { SELABEL_OPT_PATH, "/data/security/current/file_contexts.bin" }, 54 { 0, NULL } }; 55 56 static const char *const sepolicy_file[] = { 57 "/sepolicy", 58 "/data/security/current/sepolicy", 59 NULL }; 60 61 static const struct selinux_opt seopts_prop[] = { 62 { SELABEL_OPT_PATH, "/property_contexts" }, 63 { SELABEL_OPT_PATH, "/data/security/current/property_contexts" }, 64 { 0, NULL } 65 }; 66 67 static const struct selinux_opt seopts_service[] = { 68 { SELABEL_OPT_PATH, "/service_contexts" }, 69 { SELABEL_OPT_PATH, "/data/security/current/service_contexts" }, 70 { 0, NULL } 71 }; 72 73 enum levelFrom { 74 LEVELFROM_NONE, 75 LEVELFROM_APP, 76 LEVELFROM_USER, 77 LEVELFROM_ALL 78 }; 79 80 #define POLICY_OVERRIDE_VERSION "/data/security/current/selinux_version" 81 #define POLICY_BASE_VERSION "/selinux_version" 82 static int policy_index = 0; 83 84 static void set_policy_index(void) 85 { 86 int fd_base = -1, fd_override = -1; 87 struct stat sb_base; 88 struct stat sb_override; 89 void *map_base, *map_override; 90 91 policy_index = 0; 92 93 fd_base = open(POLICY_BASE_VERSION, O_RDONLY | O_NOFOLLOW); 94 if (fd_base < 0) 95 return; 96 97 if (fstat(fd_base, &sb_base) < 0) 98 goto close_base; 99 100 fd_override = open(POLICY_OVERRIDE_VERSION, O_RDONLY | O_NOFOLLOW); 101 if (fd_override < 0) 102 goto close_base; 103 104 if (fstat(fd_override, &sb_override) < 0) 105 goto close_override; 106 107 if (sb_base.st_size != sb_override.st_size) 108 goto close_override; 109 110 map_base = mmap(NULL, sb_base.st_size, PROT_READ, MAP_PRIVATE, fd_base, 0); 111 if (map_base == MAP_FAILED) 112 goto close_override; 113 114 map_override = mmap(NULL, sb_override.st_size, PROT_READ, MAP_PRIVATE, fd_override, 0); 115 if (map_override == MAP_FAILED) 116 goto unmap_base; 117 118 if (memcmp(map_base, map_override, sb_base.st_size) != 0) 119 goto unmap_override; 120 121 if (access(sepolicy_file[1], R_OK) != 0) 122 goto unmap_override; 123 124 if (access(seopts[1].value, R_OK) != 0) 125 goto unmap_override; 126 127 if (access(seopts_prop[1].value, R_OK) != 0) 128 goto unmap_override; 129 130 if (access(seopts_service[1].value, R_OK) != 0) 131 goto unmap_override; 132 133 if (access(seapp_contexts_file[1], R_OK) != 0) 134 goto unmap_override; 135 136 policy_index = 1; 137 138 unmap_override: 139 munmap(map_override, sb_override.st_size); 140 unmap_base: 141 munmap(map_base, sb_base.st_size); 142 close_override: 143 close(fd_override); 144 close_base: 145 close(fd_base); 146 return; 147 } 148 149 #if DEBUG 150 static char const * const levelFromName[] = { 151 "none", 152 "app", 153 "user", 154 "all" 155 }; 156 #endif 157 158 struct prefix_str { 159 size_t len; 160 char *str; 161 char is_prefix; 162 }; 163 164 static void free_prefix_str(struct prefix_str *p) 165 { 166 if (!p) 167 return; 168 free(p->str); 169 } 170 171 struct seapp_context { 172 /* input selectors */ 173 bool isSystemServer; 174 bool isAutoPlayAppSet; 175 bool isAutoPlayApp; 176 bool isOwnerSet; 177 bool isOwner; 178 struct prefix_str user; 179 char *seinfo; 180 struct prefix_str name; 181 struct prefix_str path; 182 bool isPrivAppSet; 183 bool isPrivApp; 184 /* outputs */ 185 char *domain; 186 char *type; 187 char *level; 188 enum levelFrom levelFrom; 189 }; 190 191 static void free_seapp_context(struct seapp_context *s) 192 { 193 if (!s) 194 return; 195 196 free_prefix_str(&s->user); 197 free(s->seinfo); 198 free_prefix_str(&s->name); 199 free_prefix_str(&s->path); 200 free(s->domain); 201 free(s->type); 202 free(s->level); 203 } 204 205 static bool seapp_contexts_dup = false; 206 207 static int seapp_context_cmp(const void *A, const void *B) 208 { 209 const struct seapp_context *const *sp1 = (const struct seapp_context *const *) A; 210 const struct seapp_context *const *sp2 = (const struct seapp_context *const *) B; 211 const struct seapp_context *s1 = *sp1, *s2 = *sp2; 212 bool dup; 213 214 /* Give precedence to isSystemServer=true. */ 215 if (s1->isSystemServer != s2->isSystemServer) 216 return (s1->isSystemServer ? -1 : 1); 217 218 /* Give precedence to a specified isAutoPlayApp= over an 219 * unspecified isAutoPlayApp=. */ 220 if (s1->isAutoPlayAppSet != s2->isAutoPlayAppSet) 221 return (s1->isAutoPlayAppSet ? -1 : 1); 222 223 224 /* Give precedence to a specified isOwner= over an unspecified isOwner=. */ 225 if (s1->isOwnerSet != s2->isOwnerSet) 226 return (s1->isOwnerSet ? -1 : 1); 227 228 /* Give precedence to a specified user= over an unspecified user=. */ 229 if (s1->user.str && !s2->user.str) 230 return -1; 231 if (!s1->user.str && s2->user.str) 232 return 1; 233 234 if (s1->user.str) { 235 /* Give precedence to a fixed user= string over a prefix. */ 236 if (s1->user.is_prefix != s2->user.is_prefix) 237 return (s2->user.is_prefix ? -1 : 1); 238 239 /* Give precedence to a longer prefix over a shorter prefix. */ 240 if (s1->user.is_prefix && s1->user.len != s2->user.len) 241 return (s1->user.len > s2->user.len) ? -1 : 1; 242 } 243 244 /* Give precedence to a specified seinfo= over an unspecified seinfo=. */ 245 if (s1->seinfo && !s2->seinfo) 246 return -1; 247 if (!s1->seinfo && s2->seinfo) 248 return 1; 249 250 /* Give precedence to a specified name= over an unspecified name=. */ 251 if (s1->name.str && !s2->name.str) 252 return -1; 253 if (!s1->name.str && s2->name.str) 254 return 1; 255 256 if (s1->name.str) { 257 /* Give precedence to a fixed name= string over a prefix. */ 258 if (s1->name.is_prefix != s2->name.is_prefix) 259 return (s2->name.is_prefix ? -1 : 1); 260 261 /* Give precedence to a longer prefix over a shorter prefix. */ 262 if (s1->name.is_prefix && s1->name.len != s2->name.len) 263 return (s1->name.len > s2->name.len) ? -1 : 1; 264 } 265 266 /* Give precedence to a specified path= over an unspecified path=. */ 267 if (s1->path.str && !s2->path.str) 268 return -1; 269 if (!s1->path.str && s2->path.str) 270 return 1; 271 272 if (s1->path.str) { 273 /* Give precedence to a fixed path= string over a prefix. */ 274 if (s1->path.is_prefix != s2->path.is_prefix) 275 return (s2->path.is_prefix ? -1 : 1); 276 277 /* Give precedence to a longer prefix over a shorter prefix. */ 278 if (s1->path.is_prefix && s1->path.len != s2->path.len) 279 return (s1->path.len > s2->path.len) ? -1 : 1; 280 } 281 282 /* Give precedence to a specified isPrivApp= over an unspecified isPrivApp=. */ 283 if (s1->isPrivAppSet != s2->isPrivAppSet) 284 return (s1->isPrivAppSet ? -1 : 1); 285 286 /* 287 * Check for a duplicated entry on the input selectors. 288 * We already compared isSystemServer, isOwnerSet, and isOwner above. 289 * We also have already checked that both entries specify the same 290 * string fields, so if s1 has a non-NULL string, then so does s2. 291 */ 292 dup = (!s1->user.str || !strcmp(s1->user.str, s2->user.str)) && 293 (!s1->seinfo || !strcmp(s1->seinfo, s2->seinfo)) && 294 (!s1->name.str || !strcmp(s1->name.str, s2->name.str)) && 295 (!s1->path.str || !strcmp(s1->path.str, s2->path.str)); 296 if (dup) { 297 seapp_contexts_dup = true; 298 selinux_log(SELINUX_ERROR, "seapp_contexts: Duplicated entry\n"); 299 if (s1->user.str) 300 selinux_log(SELINUX_ERROR, " user=%s\n", s1->user.str); 301 if (s1->seinfo) 302 selinux_log(SELINUX_ERROR, " seinfo=%s\n", s1->seinfo); 303 if (s1->name.str) 304 selinux_log(SELINUX_ERROR, " name=%s\n", s1->name.str); 305 if (s1->path.str) 306 selinux_log(SELINUX_ERROR, " path=%s\n", s1->path.str); 307 } 308 309 /* Anything else has equal precedence. */ 310 return 0; 311 } 312 313 static struct seapp_context **seapp_contexts = NULL; 314 static int nspec = 0; 315 316 static void free_seapp_contexts(void) 317 { 318 int n; 319 320 if (!seapp_contexts) 321 return; 322 323 for (n = 0; n < nspec; n++) 324 free_seapp_context(seapp_contexts[n]); 325 326 free(seapp_contexts); 327 seapp_contexts = NULL; 328 nspec = 0; 329 } 330 331 int selinux_android_seapp_context_reload(void) 332 { 333 FILE *fp = NULL; 334 char line_buf[BUFSIZ]; 335 char *token; 336 unsigned lineno; 337 struct seapp_context *cur; 338 char *p, *name = NULL, *value = NULL, *saveptr; 339 size_t len; 340 int n, ret; 341 342 set_policy_index(); 343 344 fp = fopen(seapp_contexts_file[policy_index], "r"); 345 if (!fp) { 346 selinux_log(SELINUX_ERROR, "%s: could not open any seapp_contexts file", __FUNCTION__); 347 return -1; 348 } 349 350 free_seapp_contexts(); 351 352 nspec = 0; 353 while (fgets(line_buf, sizeof line_buf - 1, fp)) { 354 p = line_buf; 355 while (isspace(*p)) 356 p++; 357 if (*p == '#' || *p == 0) 358 continue; 359 nspec++; 360 } 361 362 seapp_contexts = (struct seapp_context **) calloc(nspec, sizeof(struct seapp_context *)); 363 if (!seapp_contexts) 364 goto oom; 365 366 rewind(fp); 367 nspec = 0; 368 lineno = 1; 369 while (fgets(line_buf, sizeof line_buf - 1, fp)) { 370 len = strlen(line_buf); 371 if (line_buf[len - 1] == '\n') 372 line_buf[len - 1] = 0; 373 p = line_buf; 374 while (isspace(*p)) 375 p++; 376 if (*p == '#' || *p == 0) 377 continue; 378 379 cur = (struct seapp_context *) calloc(1, sizeof(struct seapp_context)); 380 if (!cur) 381 goto oom; 382 383 token = strtok_r(p, " \t", &saveptr); 384 if (!token) { 385 free_seapp_context(cur); 386 goto err; 387 } 388 389 while (1) { 390 name = token; 391 value = strchr(name, '='); 392 if (!value) { 393 free_seapp_context(cur); 394 goto err; 395 } 396 *value++ = 0; 397 398 if (!strcasecmp(name, "isSystemServer")) { 399 if (!strcasecmp(value, "true")) 400 cur->isSystemServer = true; 401 else if (!strcasecmp(value, "false")) 402 cur->isSystemServer = false; 403 else { 404 free_seapp_context(cur); 405 goto err; 406 } 407 } else if (!strcasecmp(name, "isAutoPlayApp")) { 408 cur->isAutoPlayAppSet = true; 409 if (!strcasecmp(value, "true")) 410 cur->isAutoPlayApp = true; 411 else if (!strcasecmp(value, "false")) 412 cur->isAutoPlayApp = false; 413 else { 414 free_seapp_context(cur); 415 goto err; 416 } 417 } else if (!strcasecmp(name, "isOwner")) { 418 cur->isOwnerSet = true; 419 if (!strcasecmp(value, "true")) 420 cur->isOwner = true; 421 else if (!strcasecmp(value, "false")) 422 cur->isOwner = false; 423 else { 424 free_seapp_context(cur); 425 goto err; 426 } 427 } else if (!strcasecmp(name, "user")) { 428 if (cur->user.str) { 429 free_seapp_context(cur); 430 goto err; 431 } 432 cur->user.str = strdup(value); 433 if (!cur->user.str) { 434 free_seapp_context(cur); 435 goto oom; 436 } 437 cur->user.len = strlen(cur->user.str); 438 if (cur->user.str[cur->user.len-1] == '*') 439 cur->user.is_prefix = 1; 440 } else if (!strcasecmp(name, "seinfo")) { 441 if (cur->seinfo) { 442 free_seapp_context(cur); 443 goto err; 444 } 445 cur->seinfo = strdup(value); 446 if (!cur->seinfo) { 447 free_seapp_context(cur); 448 goto oom; 449 } 450 if (strstr(value, ":")) { 451 free_seapp_context(cur); 452 goto err; 453 } 454 } else if (!strcasecmp(name, "name")) { 455 if (cur->name.str) { 456 free_seapp_context(cur); 457 goto err; 458 } 459 cur->name.str = strdup(value); 460 if (!cur->name.str) { 461 free_seapp_context(cur); 462 goto oom; 463 } 464 cur->name.len = strlen(cur->name.str); 465 if (cur->name.str[cur->name.len-1] == '*') 466 cur->name.is_prefix = 1; 467 } else if (!strcasecmp(name, "domain")) { 468 if (cur->domain) { 469 free_seapp_context(cur); 470 goto err; 471 } 472 cur->domain = strdup(value); 473 if (!cur->domain) { 474 free_seapp_context(cur); 475 goto oom; 476 } 477 } else if (!strcasecmp(name, "type")) { 478 if (cur->type) { 479 free_seapp_context(cur); 480 goto err; 481 } 482 cur->type = strdup(value); 483 if (!cur->type) { 484 free_seapp_context(cur); 485 goto oom; 486 } 487 } else if (!strcasecmp(name, "levelFromUid")) { 488 if (cur->levelFrom) { 489 free_seapp_context(cur); 490 goto err; 491 } 492 if (!strcasecmp(value, "true")) 493 cur->levelFrom = LEVELFROM_APP; 494 else if (!strcasecmp(value, "false")) 495 cur->levelFrom = LEVELFROM_NONE; 496 else { 497 free_seapp_context(cur); 498 goto err; 499 } 500 } else if (!strcasecmp(name, "levelFrom")) { 501 if (cur->levelFrom) { 502 free_seapp_context(cur); 503 goto err; 504 } 505 if (!strcasecmp(value, "none")) 506 cur->levelFrom = LEVELFROM_NONE; 507 else if (!strcasecmp(value, "app")) 508 cur->levelFrom = LEVELFROM_APP; 509 else if (!strcasecmp(value, "user")) 510 cur->levelFrom = LEVELFROM_USER; 511 else if (!strcasecmp(value, "all")) 512 cur->levelFrom = LEVELFROM_ALL; 513 else { 514 free_seapp_context(cur); 515 goto err; 516 } 517 } else if (!strcasecmp(name, "level")) { 518 if (cur->level) { 519 free_seapp_context(cur); 520 goto err; 521 } 522 cur->level = strdup(value); 523 if (!cur->level) { 524 free_seapp_context(cur); 525 goto oom; 526 } 527 } else if (!strcasecmp(name, "path")) { 528 if (cur->path.str) { 529 free_seapp_context(cur); 530 goto err; 531 } 532 cur->path.str = strdup(value); 533 if (!cur->path.str) { 534 free_seapp_context(cur); 535 goto oom; 536 } 537 cur->path.len = strlen(cur->path.str); 538 if (cur->path.str[cur->path.len-1] == '*') 539 cur->path.is_prefix = 1; 540 } else if (!strcasecmp(name, "isPrivApp")) { 541 cur->isPrivAppSet = true; 542 if (!strcasecmp(value, "true")) 543 cur->isPrivApp = true; 544 else if (!strcasecmp(value, "false")) 545 cur->isPrivApp = false; 546 else { 547 free_seapp_context(cur); 548 goto err; 549 } 550 } else { 551 free_seapp_context(cur); 552 goto err; 553 } 554 555 token = strtok_r(NULL, " \t", &saveptr); 556 if (!token) 557 break; 558 } 559 560 if (cur->name.str && 561 (!cur->seinfo || !strcmp(cur->seinfo, "default"))) { 562 selinux_log(SELINUX_ERROR, "%s: No specific seinfo value specified with name=\"%s\", on line %u: insecure configuration!\n", 563 seapp_contexts_file[policy_index], cur->name.str, lineno); 564 free_seapp_context(cur); 565 goto err; 566 } 567 568 seapp_contexts[nspec] = cur; 569 nspec++; 570 lineno++; 571 } 572 573 qsort(seapp_contexts, nspec, sizeof(struct seapp_context *), 574 seapp_context_cmp); 575 576 if (seapp_contexts_dup) 577 goto err; 578 579 #if DEBUG 580 { 581 int i; 582 for (i = 0; i < nspec; i++) { 583 cur = seapp_contexts[i]; 584 selinux_log(SELINUX_INFO, "%s: isSystemServer=%s isAutoPlayApp=%s isOwner=%s user=%s seinfo=%s " 585 "name=%s path=%s isPrivApp=%s -> domain=%s type=%s level=%s levelFrom=%s", 586 __FUNCTION__, 587 cur->isSystemServer ? "true" : "false", 588 cur->isAutoPlayAppSet ? (cur->isAutoPlayApp ? "true" : "false") : "null", 589 cur->isOwnerSet ? (cur->isOwner ? "true" : "false") : "null", 590 cur->user.str, 591 cur->seinfo, cur->name.str, cur->path.str, 592 cur->isPrivAppSet ? (cur->isPrivApp ? "true" : "false") : "null", 593 cur->domain, cur->type, cur->level, 594 levelFromName[cur->levelFrom]); 595 } 596 } 597 #endif 598 599 ret = 0; 600 601 out: 602 fclose(fp); 603 return ret; 604 605 err: 606 selinux_log(SELINUX_ERROR, "%s: Invalid entry on line %u\n", 607 seapp_contexts_file[policy_index], lineno); 608 free_seapp_contexts(); 609 ret = -1; 610 goto out; 611 oom: 612 selinux_log(SELINUX_ERROR, 613 "%s: Out of memory\n", __FUNCTION__); 614 free_seapp_contexts(); 615 ret = -1; 616 goto out; 617 } 618 619 620 static void seapp_context_init(void) 621 { 622 selinux_android_seapp_context_reload(); 623 } 624 625 static pthread_once_t once = PTHREAD_ONCE_INIT; 626 627 /* 628 * Max id that can be mapped to category set uniquely 629 * using the current scheme. 630 */ 631 #define CAT_MAPPING_MAX_ID (0x1<<16) 632 633 enum seapp_kind { 634 SEAPP_TYPE, 635 SEAPP_DOMAIN 636 }; 637 638 #define PRIVILEGED_APP_STR ":privapp" 639 #define AUTOPLAY_APP_STR ":autoplayapp" 640 641 static int seinfo_parse(char *dest, const char *src, size_t size) 642 { 643 size_t len; 644 char *p; 645 646 if ((p = strchr(src, ':')) != NULL) 647 len = p - src; 648 else 649 len = strlen(src); 650 651 if (len > size - 1) 652 return -1; 653 654 strncpy(dest, src, len); 655 dest[len] = '\0'; 656 657 return 0; 658 } 659 660 static int seapp_context_lookup(enum seapp_kind kind, 661 uid_t uid, 662 bool isSystemServer, 663 const char *seinfo, 664 const char *pkgname, 665 const char *path, 666 context_t ctx) 667 { 668 bool isOwner; 669 const char *username = NULL; 670 struct seapp_context *cur = NULL; 671 int i; 672 size_t n; 673 uid_t userid; 674 uid_t appid; 675 bool isPrivApp = false; 676 bool isAutoPlayApp = false; 677 char parsedseinfo[BUFSIZ]; 678 679 __selinux_once(once, seapp_context_init); 680 681 if (seinfo) { 682 if (seinfo_parse(parsedseinfo, seinfo, BUFSIZ)) 683 goto err; 684 isPrivApp = strstr(seinfo, PRIVILEGED_APP_STR) ? true : false; 685 isAutoPlayApp = strstr(seinfo, AUTOPLAY_APP_STR) ? true : false; 686 seinfo = parsedseinfo; 687 } 688 689 userid = uid / AID_USER; 690 isOwner = (userid == 0); 691 appid = uid % AID_USER; 692 if (appid < AID_APP) { 693 for (n = 0; n < android_id_count; n++) { 694 if (android_ids[n].aid == appid) { 695 username = android_ids[n].name; 696 break; 697 } 698 } 699 if (!username) 700 goto err; 701 } else if (appid < AID_ISOLATED_START) { 702 username = "_app"; 703 appid -= AID_APP; 704 } else { 705 username = "_isolated"; 706 appid -= AID_ISOLATED_START; 707 } 708 709 if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID) 710 goto err; 711 712 for (i = 0; i < nspec; i++) { 713 cur = seapp_contexts[i]; 714 715 if (cur->isSystemServer != isSystemServer) 716 continue; 717 718 if (cur->isAutoPlayAppSet && cur->isAutoPlayApp != isAutoPlayApp) 719 continue; 720 721 if (cur->isOwnerSet && cur->isOwner != isOwner) 722 continue; 723 724 if (cur->user.str) { 725 if (cur->user.is_prefix) { 726 if (strncasecmp(username, cur->user.str, cur->user.len-1)) 727 continue; 728 } else { 729 if (strcasecmp(username, cur->user.str)) 730 continue; 731 } 732 } 733 734 if (cur->seinfo) { 735 if (!seinfo || strcasecmp(seinfo, cur->seinfo)) 736 continue; 737 } 738 739 if (cur->name.str) { 740 if(!pkgname) 741 continue; 742 743 if (cur->name.is_prefix) { 744 if (strncasecmp(pkgname, cur->name.str, cur->name.len-1)) 745 continue; 746 } else { 747 if (strcasecmp(pkgname, cur->name.str)) 748 continue; 749 } 750 } 751 752 if (cur->isPrivAppSet && cur->isPrivApp != isPrivApp) 753 continue; 754 755 if (cur->path.str) { 756 if (!path) 757 continue; 758 759 if (cur->path.is_prefix) { 760 if (strncmp(path, cur->path.str, cur->path.len-1)) 761 continue; 762 } else { 763 if (strcmp(path, cur->path.str)) 764 continue; 765 } 766 } 767 768 if (kind == SEAPP_TYPE && !cur->type) 769 continue; 770 else if (kind == SEAPP_DOMAIN && !cur->domain) 771 continue; 772 773 if (kind == SEAPP_TYPE) { 774 if (context_type_set(ctx, cur->type)) 775 goto oom; 776 } else if (kind == SEAPP_DOMAIN) { 777 if (context_type_set(ctx, cur->domain)) 778 goto oom; 779 } 780 781 if (cur->levelFrom != LEVELFROM_NONE) { 782 char level[255]; 783 switch (cur->levelFrom) { 784 case LEVELFROM_APP: 785 snprintf(level, sizeof level, "s0:c%u,c%u", 786 appid & 0xff, 787 256 + (appid>>8 & 0xff)); 788 break; 789 case LEVELFROM_USER: 790 snprintf(level, sizeof level, "s0:c%u,c%u", 791 512 + (userid & 0xff), 792 768 + (userid>>8 & 0xff)); 793 break; 794 case LEVELFROM_ALL: 795 snprintf(level, sizeof level, "s0:c%u,c%u,c%u,c%u", 796 appid & 0xff, 797 256 + (appid>>8 & 0xff), 798 512 + (userid & 0xff), 799 768 + (userid>>8 & 0xff)); 800 break; 801 default: 802 goto err; 803 } 804 if (context_range_set(ctx, level)) 805 goto oom; 806 } else if (cur->level) { 807 if (context_range_set(ctx, cur->level)) 808 goto oom; 809 } 810 811 break; 812 } 813 814 if (kind == SEAPP_DOMAIN && i == nspec) { 815 /* 816 * No match. 817 * Fail to prevent staying in the zygote's context. 818 */ 819 selinux_log(SELINUX_ERROR, 820 "%s: No match for app with uid %d, seinfo %s, name %s\n", 821 __FUNCTION__, uid, seinfo, pkgname); 822 823 if (security_getenforce() == 1) 824 goto err; 825 } 826 827 return 0; 828 err: 829 return -1; 830 oom: 831 return -2; 832 } 833 834 int selinux_android_setfilecon(const char *pkgdir, 835 const char *pkgname, 836 const char *seinfo, 837 uid_t uid) 838 { 839 char *orig_ctx_str = NULL; 840 char *ctx_str = NULL; 841 context_t ctx = NULL; 842 int rc = -1; 843 844 if (is_selinux_enabled() <= 0) 845 return 0; 846 847 rc = getfilecon(pkgdir, &ctx_str); 848 if (rc < 0) 849 goto err; 850 851 ctx = context_new(ctx_str); 852 orig_ctx_str = ctx_str; 853 if (!ctx) 854 goto oom; 855 856 rc = seapp_context_lookup(SEAPP_TYPE, uid, 0, seinfo, pkgname, NULL, ctx); 857 if (rc == -1) 858 goto err; 859 else if (rc == -2) 860 goto oom; 861 862 ctx_str = context_str(ctx); 863 if (!ctx_str) 864 goto oom; 865 866 rc = security_check_context(ctx_str); 867 if (rc < 0) 868 goto err; 869 870 if (strcmp(ctx_str, orig_ctx_str)) { 871 rc = setfilecon(pkgdir, ctx_str); 872 if (rc < 0) 873 goto err; 874 } 875 876 rc = 0; 877 out: 878 freecon(orig_ctx_str); 879 context_free(ctx); 880 return rc; 881 err: 882 selinux_log(SELINUX_ERROR, "%s: Error setting context for pkgdir %s, uid %d: %s\n", 883 __FUNCTION__, pkgdir, uid, strerror(errno)); 884 rc = -1; 885 goto out; 886 oom: 887 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 888 rc = -1; 889 goto out; 890 } 891 892 int selinux_android_setcon(const char *con) 893 { 894 int ret = setcon(con); 895 if (ret) 896 return ret; 897 /* 898 System properties must be reinitialized after setcon() otherwise the 899 previous property files will be leaked since mmap()'ed regions are not 900 closed as a result of setcon(). 901 */ 902 return __system_properties_init(); 903 } 904 905 int selinux_android_setcontext(uid_t uid, 906 bool isSystemServer, 907 const char *seinfo, 908 const char *pkgname) 909 { 910 char *orig_ctx_str = NULL, *ctx_str; 911 context_t ctx = NULL; 912 int rc = -1; 913 914 if (is_selinux_enabled() <= 0) 915 return 0; 916 917 rc = getcon(&ctx_str); 918 if (rc) 919 goto err; 920 921 ctx = context_new(ctx_str); 922 orig_ctx_str = ctx_str; 923 if (!ctx) 924 goto oom; 925 926 rc = seapp_context_lookup(SEAPP_DOMAIN, uid, isSystemServer, seinfo, pkgname, NULL, ctx); 927 if (rc == -1) 928 goto err; 929 else if (rc == -2) 930 goto oom; 931 932 ctx_str = context_str(ctx); 933 if (!ctx_str) 934 goto oom; 935 936 rc = security_check_context(ctx_str); 937 if (rc < 0) 938 goto err; 939 940 if (strcmp(ctx_str, orig_ctx_str)) { 941 rc = selinux_android_setcon(ctx_str); 942 if (rc < 0) 943 goto err; 944 } 945 946 rc = 0; 947 out: 948 freecon(orig_ctx_str); 949 context_free(ctx); 950 avc_netlink_close(); 951 return rc; 952 err: 953 if (isSystemServer) 954 selinux_log(SELINUX_ERROR, 955 "%s: Error setting context for system server: %s\n", 956 __FUNCTION__, strerror(errno)); 957 else 958 selinux_log(SELINUX_ERROR, 959 "%s: Error setting context for app with uid %d, seinfo %s: %s\n", 960 __FUNCTION__, uid, seinfo, strerror(errno)); 961 962 rc = -1; 963 goto out; 964 oom: 965 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 966 rc = -1; 967 goto out; 968 } 969 970 static struct selabel_handle *fc_sehandle = NULL; 971 #define FC_DIGEST_SIZE SHA_DIGEST_LENGTH 972 static uint8_t fc_digest[FC_DIGEST_SIZE]; 973 974 static bool compute_contexts_hash(const struct selinux_opt opts[], uint8_t c_digest[]) 975 { 976 int fd; 977 struct stat sb; 978 void *map; 979 980 fd = open(opts[policy_index].value, O_CLOEXEC | O_RDONLY | O_NOFOLLOW); 981 if (fd < 0) { 982 selinux_log(SELINUX_ERROR, "SELinux: Could not open %s: %s\n", 983 opts[policy_index].value, strerror(errno)); 984 return false; 985 } 986 if (fstat(fd, &sb) < 0) { 987 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n", 988 opts[policy_index].value, strerror(errno)); 989 close(fd); 990 return false; 991 } 992 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 993 if (map == MAP_FAILED) { 994 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n", 995 opts[policy_index].value, strerror(errno)); 996 close(fd); 997 return false; 998 } 999 SHA1(map, sb.st_size, c_digest); 1000 munmap(map, sb.st_size); 1001 close(fd); 1002 1003 return true; 1004 } 1005 1006 static void file_context_init(void) 1007 { 1008 if (!fc_sehandle) 1009 fc_sehandle = selinux_android_file_context_handle(); 1010 } 1011 1012 1013 1014 static pthread_once_t fc_once = PTHREAD_ONCE_INIT; 1015 1016 #define PKGTAB_SIZE 256 1017 static struct pkg_info *pkgTab[PKGTAB_SIZE]; 1018 1019 static unsigned int pkghash(const char *pkgname) 1020 { 1021 unsigned int h = 7; 1022 for (; *pkgname; pkgname++) { 1023 h = h * 31 + *pkgname; 1024 } 1025 return h & (PKGTAB_SIZE - 1); 1026 } 1027 1028 static bool pkg_parse_callback(pkg_info *info, void *userdata) { 1029 1030 (void) userdata; 1031 1032 unsigned int hash = pkghash(info->name); 1033 if (pkgTab[hash]) 1034 info->private_data = pkgTab[hash]; 1035 pkgTab[hash] = info; 1036 return true; 1037 } 1038 1039 static void package_info_init(void) 1040 { 1041 1042 bool rc = packagelist_parse(pkg_parse_callback, NULL); 1043 if (!rc) { 1044 selinux_log(SELINUX_ERROR, "SELinux: Could NOT parse package list\n"); 1045 return; 1046 } 1047 1048 #if DEBUG 1049 { 1050 unsigned int hash, buckets, entries, chainlen, longestchain; 1051 struct pkg_info *info = NULL; 1052 1053 buckets = entries = longestchain = 0; 1054 for (hash = 0; hash < PKGTAB_SIZE; hash++) { 1055 if (pkgTab[hash]) { 1056 buckets++; 1057 chainlen = 0; 1058 for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) { 1059 chainlen++; 1060 selinux_log(SELINUX_INFO, "%s: name=%s uid=%u debuggable=%s dataDir=%s seinfo=%s\n", 1061 __FUNCTION__, 1062 info->name, info->uid, info->debuggable ? "true" : "false", info->data_dir, info->seinfo); 1063 } 1064 entries += chainlen; 1065 if (longestchain < chainlen) 1066 longestchain = chainlen; 1067 } 1068 } 1069 selinux_log(SELINUX_INFO, "SELinux: %d pkg entries and %d/%d buckets used, longest chain %d\n", entries, buckets, PKGTAB_SIZE, longestchain); 1070 } 1071 #endif 1072 1073 } 1074 1075 static pthread_once_t pkg_once = PTHREAD_ONCE_INIT; 1076 1077 struct pkg_info *package_info_lookup(const char *name) 1078 { 1079 struct pkg_info *info; 1080 unsigned int hash; 1081 1082 __selinux_once(pkg_once, package_info_init); 1083 1084 hash = pkghash(name); 1085 for (info = pkgTab[hash]; info; info = (pkg_info *)info->private_data) { 1086 if (!strcmp(name, info->name)) 1087 return info; 1088 } 1089 return NULL; 1090 } 1091 1092 /* The contents of these paths are encrypted on FBE devices until user 1093 * credentials are presented (filenames inside are mangled), so we need 1094 * to delay restorecon of those until vold explicitly requests it. */ 1095 // NOTE: these paths need to be kept in sync with vold 1096 #define DATA_SYSTEM_CE_PREFIX "/data/system_ce/" 1097 #define DATA_MISC_CE_PREFIX "/data/misc_ce/" 1098 1099 /* The path prefixes of package data directories. */ 1100 #define DATA_DATA_PATH "/data/data" 1101 #define DATA_USER_PATH "/data/user" 1102 #define DATA_USER_DE_PATH "/data/user_de" 1103 #define EXPAND_USER_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user" 1104 #define EXPAND_USER_DE_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?/user_de" 1105 #define DATA_DATA_PREFIX DATA_DATA_PATH "/" 1106 #define DATA_USER_PREFIX DATA_USER_PATH "/" 1107 #define DATA_USER_DE_PREFIX DATA_USER_DE_PATH "/" 1108 1109 static int pkgdir_selabel_lookup(const char *pathname, 1110 const char *seinfo, 1111 uid_t uid, 1112 char **secontextp) 1113 { 1114 char *pkgname = NULL, *end = NULL; 1115 struct pkg_info *info = NULL; 1116 char *secontext = *secontextp; 1117 context_t ctx = NULL; 1118 int rc = 0; 1119 1120 /* Skip directory prefix before package name. */ 1121 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) { 1122 pathname += sizeof(DATA_DATA_PREFIX) - 1; 1123 } else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) { 1124 pathname += sizeof(DATA_USER_PREFIX) - 1; 1125 while (isdigit(*pathname)) 1126 pathname++; 1127 if (*pathname == '/') 1128 pathname++; 1129 else 1130 return 0; 1131 } else if (!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1)) { 1132 pathname += sizeof(DATA_USER_DE_PREFIX) - 1; 1133 while (isdigit(*pathname)) 1134 pathname++; 1135 if (*pathname == '/') 1136 pathname++; 1137 else 1138 return 0; 1139 } else if (!fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) { 1140 pathname += sizeof(EXPAND_USER_PATH); 1141 while (isdigit(*pathname)) 1142 pathname++; 1143 if (*pathname == '/') 1144 pathname++; 1145 else 1146 return 0; 1147 } else if (!fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) { 1148 pathname += sizeof(EXPAND_USER_DE_PATH); 1149 while (isdigit(*pathname)) 1150 pathname++; 1151 if (*pathname == '/') 1152 pathname++; 1153 else 1154 return 0; 1155 } else 1156 return 0; 1157 1158 if (!(*pathname)) 1159 return 0; 1160 1161 pkgname = strdup(pathname); 1162 if (!pkgname) 1163 return -1; 1164 1165 for (end = pkgname; *end && *end != '/'; end++) 1166 ; 1167 pathname = end; 1168 if (*end) 1169 pathname++; 1170 *end = '\0'; 1171 1172 if (!seinfo) { 1173 info = package_info_lookup(pkgname); 1174 if (!info) { 1175 selinux_log(SELINUX_WARNING, "SELinux: Could not look up information for package %s, cannot restorecon %s.\n", 1176 pkgname, pathname); 1177 free(pkgname); 1178 return -1; 1179 } 1180 } 1181 1182 ctx = context_new(secontext); 1183 if (!ctx) 1184 goto err; 1185 1186 rc = seapp_context_lookup(SEAPP_TYPE, info ? info->uid : uid, 0, 1187 info ? info->seinfo : seinfo, info ? info->name : pkgname, pathname, ctx); 1188 if (rc < 0) 1189 goto err; 1190 1191 secontext = context_str(ctx); 1192 if (!secontext) 1193 goto err; 1194 1195 if (!strcmp(secontext, *secontextp)) 1196 goto out; 1197 1198 rc = security_check_context(secontext); 1199 if (rc < 0) 1200 goto err; 1201 1202 freecon(*secontextp); 1203 *secontextp = strdup(secontext); 1204 if (!(*secontextp)) 1205 goto err; 1206 1207 rc = 0; 1208 1209 out: 1210 free(pkgname); 1211 context_free(ctx); 1212 return rc; 1213 err: 1214 selinux_log(SELINUX_ERROR, "%s: Error looking up context for path %s, pkgname %s, seinfo %s, uid %u: %s\n", 1215 __FUNCTION__, pathname, pkgname, info->seinfo, info->uid, strerror(errno)); 1216 rc = -1; 1217 goto out; 1218 } 1219 1220 #define RESTORECON_LAST "security.restorecon_last" 1221 1222 static int restorecon_sb(const char *pathname, const struct stat *sb, 1223 bool nochange, bool verbose, 1224 const char *seinfo, uid_t uid) 1225 { 1226 char *secontext = NULL; 1227 char *oldsecontext = NULL; 1228 int rc = 0; 1229 1230 if (selabel_lookup(fc_sehandle, &secontext, pathname, sb->st_mode) < 0) 1231 return 0; /* no match, but not an error */ 1232 1233 if (lgetfilecon(pathname, &oldsecontext) < 0) 1234 goto err; 1235 1236 /* 1237 * For subdirectories of /data/data or /data/user, we ignore selabel_lookup() 1238 * and use pkgdir_selabel_lookup() instead. Files within those directories 1239 * have different labeling rules, based off of /seapp_contexts, and 1240 * installd is responsible for managing these labels instead of init. 1241 */ 1242 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) || 1243 !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) || 1244 !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) || 1245 !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) || 1246 !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) { 1247 if (pkgdir_selabel_lookup(pathname, seinfo, uid, &secontext) < 0) 1248 goto err; 1249 } 1250 1251 if (strcmp(oldsecontext, secontext) != 0) { 1252 if (verbose) 1253 selinux_log(SELINUX_INFO, 1254 "SELinux: Relabeling %s from %s to %s.\n", pathname, oldsecontext, secontext); 1255 if (!nochange) { 1256 if (lsetfilecon(pathname, secontext) < 0) 1257 goto err; 1258 } 1259 } 1260 1261 rc = 0; 1262 1263 out: 1264 freecon(oldsecontext); 1265 freecon(secontext); 1266 return rc; 1267 1268 err: 1269 selinux_log(SELINUX_ERROR, 1270 "SELinux: Could not set context for %s: %s\n", 1271 pathname, strerror(errno)); 1272 rc = -1; 1273 goto out; 1274 } 1275 1276 #define SYS_PATH "/sys" 1277 #define SYS_PREFIX SYS_PATH "/" 1278 1279 static int selinux_android_restorecon_common(const char* pathname_orig, 1280 const char *seinfo, 1281 uid_t uid, 1282 unsigned int flags) 1283 { 1284 bool nochange = (flags & SELINUX_ANDROID_RESTORECON_NOCHANGE) ? true : false; 1285 bool verbose = (flags & SELINUX_ANDROID_RESTORECON_VERBOSE) ? true : false; 1286 bool recurse = (flags & SELINUX_ANDROID_RESTORECON_RECURSE) ? true : false; 1287 bool force = (flags & SELINUX_ANDROID_RESTORECON_FORCE) ? true : false; 1288 bool datadata = (flags & SELINUX_ANDROID_RESTORECON_DATADATA) ? true : false; 1289 bool skipce = (flags & SELINUX_ANDROID_RESTORECON_SKIPCE) ? true : false; 1290 bool issys; 1291 bool setrestoreconlast = true; 1292 struct stat sb; 1293 struct statfs sfsb; 1294 FTS *fts; 1295 FTSENT *ftsent; 1296 char *pathname = NULL, *pathdnamer = NULL, *pathdname, *pathbname; 1297 char * paths[2] = { NULL , NULL }; 1298 int ftsflags = FTS_NOCHDIR | FTS_XDEV | FTS_PHYSICAL; 1299 int error, sverrno; 1300 char xattr_value[FC_DIGEST_SIZE]; 1301 ssize_t size; 1302 1303 if (is_selinux_enabled() <= 0) 1304 return 0; 1305 1306 __selinux_once(fc_once, file_context_init); 1307 1308 if (!fc_sehandle) 1309 return 0; 1310 1311 /* 1312 * Convert passed-in pathname to canonical pathname by resolving realpath of 1313 * containing dir, then appending last component name. 1314 */ 1315 pathbname = basename(pathname_orig); 1316 if (!strcmp(pathbname, "/") || !strcmp(pathbname, ".") || !strcmp(pathbname, "..")) { 1317 pathname = realpath(pathname_orig, NULL); 1318 if (!pathname) 1319 goto realpatherr; 1320 } else { 1321 pathdname = dirname(pathname_orig); 1322 pathdnamer = realpath(pathdname, NULL); 1323 if (!pathdnamer) 1324 goto realpatherr; 1325 if (!strcmp(pathdnamer, "/")) 1326 error = asprintf(&pathname, "/%s", pathbname); 1327 else 1328 error = asprintf(&pathname, "%s/%s", pathdnamer, pathbname); 1329 if (error < 0) 1330 goto oom; 1331 } 1332 1333 paths[0] = pathname; 1334 issys = (!strcmp(pathname, SYS_PATH) 1335 || !strncmp(pathname, SYS_PREFIX, sizeof(SYS_PREFIX)-1)) ? true : false; 1336 1337 if (!recurse) { 1338 if (lstat(pathname, &sb) < 0) { 1339 error = -1; 1340 goto cleanup; 1341 } 1342 1343 error = restorecon_sb(pathname, &sb, nochange, verbose, seinfo, uid); 1344 goto cleanup; 1345 } 1346 1347 /* 1348 * Ignore restorecon_last on /data/data or /data/user 1349 * since their labeling is based on seapp_contexts and seinfo 1350 * assignments rather than file_contexts and is managed by 1351 * installd rather than init. 1352 */ 1353 if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) || 1354 !strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) || 1355 !strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) || 1356 !fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME) || 1357 !fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) 1358 setrestoreconlast = false; 1359 1360 /* Also ignore on /sys since it is regenerated on each boot regardless. */ 1361 if (issys) 1362 setrestoreconlast = false; 1363 1364 /* Ignore files on in-memory filesystems */ 1365 if (statfs(pathname, &sfsb) == 0) { 1366 if (sfsb.f_type == RAMFS_MAGIC || sfsb.f_type == TMPFS_MAGIC) 1367 setrestoreconlast = false; 1368 } 1369 1370 if (setrestoreconlast) { 1371 size = getxattr(pathname, RESTORECON_LAST, xattr_value, sizeof fc_digest); 1372 if (!force && size == sizeof fc_digest && memcmp(fc_digest, xattr_value, sizeof fc_digest) == 0) { 1373 selinux_log(SELINUX_INFO, 1374 "SELinux: Skipping restorecon_recursive(%s)\n", 1375 pathname); 1376 error = 0; 1377 goto cleanup; 1378 } 1379 } 1380 1381 fts = fts_open(paths, ftsflags, NULL); 1382 if (!fts) { 1383 error = -1; 1384 goto cleanup; 1385 } 1386 1387 error = 0; 1388 while ((ftsent = fts_read(fts)) != NULL) { 1389 switch (ftsent->fts_info) { 1390 case FTS_DC: 1391 selinux_log(SELINUX_ERROR, 1392 "SELinux: Directory cycle on %s.\n", ftsent->fts_path); 1393 errno = ELOOP; 1394 error = -1; 1395 goto out; 1396 case FTS_DP: 1397 continue; 1398 case FTS_DNR: 1399 selinux_log(SELINUX_ERROR, 1400 "SELinux: Could not read %s: %s.\n", ftsent->fts_path, strerror(errno)); 1401 fts_set(fts, ftsent, FTS_SKIP); 1402 continue; 1403 case FTS_NS: 1404 selinux_log(SELINUX_ERROR, 1405 "SELinux: Could not stat %s: %s.\n", ftsent->fts_path, strerror(errno)); 1406 fts_set(fts, ftsent, FTS_SKIP); 1407 continue; 1408 case FTS_ERR: 1409 selinux_log(SELINUX_ERROR, 1410 "SELinux: Error on %s: %s.\n", ftsent->fts_path, strerror(errno)); 1411 fts_set(fts, ftsent, FTS_SKIP); 1412 continue; 1413 case FTS_D: 1414 if (issys && !selabel_partial_match(fc_sehandle, ftsent->fts_path)) { 1415 fts_set(fts, ftsent, FTS_SKIP); 1416 continue; 1417 } 1418 1419 if (skipce && 1420 (!strncmp(ftsent->fts_path, DATA_SYSTEM_CE_PREFIX, sizeof(DATA_SYSTEM_CE_PREFIX)-1) || 1421 !strncmp(ftsent->fts_path, DATA_MISC_CE_PREFIX, sizeof(DATA_MISC_CE_PREFIX)-1))) { 1422 // Don't label anything below this directory. 1423 fts_set(fts, ftsent, FTS_SKIP); 1424 // but fall through and make sure we label the directory itself 1425 } 1426 1427 if (!datadata && 1428 (!strcmp(ftsent->fts_path, DATA_DATA_PATH) || 1429 !strncmp(ftsent->fts_path, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) || 1430 !strncmp(ftsent->fts_path, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) || 1431 !fnmatch(EXPAND_USER_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME) || 1432 !fnmatch(EXPAND_USER_DE_PATH, ftsent->fts_path, FNM_LEADING_DIR|FNM_PATHNAME))) { 1433 // Don't label anything below this directory. 1434 fts_set(fts, ftsent, FTS_SKIP); 1435 // but fall through and make sure we label the directory itself 1436 } 1437 /* fall through */ 1438 default: 1439 error |= restorecon_sb(ftsent->fts_path, ftsent->fts_statp, nochange, verbose, seinfo, uid); 1440 break; 1441 } 1442 } 1443 1444 // Labeling successful. Mark the top level directory as completed. 1445 if (setrestoreconlast && !nochange && !error) 1446 setxattr(pathname, RESTORECON_LAST, fc_digest, sizeof fc_digest, 0); 1447 1448 out: 1449 sverrno = errno; 1450 (void) fts_close(fts); 1451 errno = sverrno; 1452 cleanup: 1453 free(pathdnamer); 1454 free(pathname); 1455 return error; 1456 oom: 1457 sverrno = errno; 1458 selinux_log(SELINUX_ERROR, "%s: Out of memory\n", __FUNCTION__); 1459 errno = sverrno; 1460 error = -1; 1461 goto cleanup; 1462 realpatherr: 1463 sverrno = errno; 1464 selinux_log(SELINUX_ERROR, "SELinux: Could not get canonical path for %s restorecon: %s.\n", 1465 pathname_orig, strerror(errno)); 1466 errno = sverrno; 1467 error = -1; 1468 goto cleanup; 1469 } 1470 1471 int selinux_android_restorecon(const char *file, unsigned int flags) 1472 { 1473 return selinux_android_restorecon_common(file, NULL, -1, flags); 1474 } 1475 1476 int selinux_android_restorecon_pkgdir(const char *pkgdir, 1477 const char *seinfo, 1478 uid_t uid, 1479 unsigned int flags) 1480 { 1481 return selinux_android_restorecon_common(pkgdir, seinfo, uid, flags | SELINUX_ANDROID_RESTORECON_DATADATA); 1482 } 1483 1484 struct selabel_handle* selinux_android_file_context_handle(void) 1485 { 1486 char *path = NULL; 1487 struct selabel_handle *sehandle; 1488 struct selinux_opt fc_opts[] = { 1489 { SELABEL_OPT_PATH, path }, 1490 { SELABEL_OPT_BASEONLY, (char *)1 } 1491 }; 1492 1493 set_policy_index(); 1494 fc_opts[0].value = seopts[policy_index].value; 1495 1496 sehandle = selabel_open(SELABEL_CTX_FILE, fc_opts, 2); 1497 1498 if (!sehandle) { 1499 selinux_log(SELINUX_ERROR, "%s: Error getting file context handle (%s)\n", 1500 __FUNCTION__, strerror(errno)); 1501 return NULL; 1502 } 1503 if (!compute_contexts_hash(seopts, fc_digest)) { 1504 selabel_close(sehandle); 1505 return NULL; 1506 } 1507 selinux_log(SELINUX_INFO, "SELinux: Loaded file_contexts contexts from %s.\n", 1508 fc_opts[0].value); 1509 1510 return sehandle; 1511 } 1512 1513 struct selabel_handle* selinux_android_prop_context_handle(void) 1514 { 1515 struct selabel_handle* sehandle; 1516 1517 set_policy_index(); 1518 sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP, 1519 &seopts_prop[policy_index], 1); 1520 if (!sehandle) { 1521 selinux_log(SELINUX_ERROR, "%s: Error getting property context handle (%s)\n", 1522 __FUNCTION__, strerror(errno)); 1523 return NULL; 1524 } 1525 selinux_log(SELINUX_INFO, "SELinux: Loaded property_contexts from %s.\n", 1526 seopts_prop[policy_index].value); 1527 1528 return sehandle; 1529 } 1530 1531 struct selabel_handle* selinux_android_service_context_handle(void) 1532 { 1533 struct selabel_handle* sehandle; 1534 1535 set_policy_index(); 1536 sehandle = selabel_open(SELABEL_CTX_ANDROID_PROP, 1537 &seopts_service[policy_index], 1); 1538 1539 if (!sehandle) { 1540 selinux_log(SELINUX_ERROR, "%s: Error getting service context handle (%s)\n", 1541 __FUNCTION__, strerror(errno)); 1542 return NULL; 1543 } 1544 selinux_log(SELINUX_INFO, "SELinux: Loaded service_contexts from %s.\n", 1545 seopts_service[policy_index].value); 1546 1547 return sehandle; 1548 } 1549 1550 void selinux_android_set_sehandle(const struct selabel_handle *hndl) 1551 { 1552 fc_sehandle = (struct selabel_handle *) hndl; 1553 } 1554 1555 static int selinux_android_load_policy_helper(bool reload) 1556 { 1557 int fd = -1, rc; 1558 struct stat sb; 1559 void *map = NULL; 1560 int old_policy_index = policy_index; 1561 1562 /* 1563 * If reloading policy and there is no /data policy or 1564 * that /data policy has the wrong version and our prior 1565 * load was from the / policy, then just return. 1566 * There is no point in reloading policy from / a second time. 1567 */ 1568 set_policy_index(); 1569 if (reload && !policy_index && !old_policy_index) 1570 return 0; 1571 1572 fd = open(sepolicy_file[policy_index], O_RDONLY | O_NOFOLLOW); 1573 if (fd < 0) { 1574 selinux_log(SELINUX_ERROR, "SELinux: Could not open sepolicy: %s\n", 1575 strerror(errno)); 1576 return -1; 1577 } 1578 if (fstat(fd, &sb) < 0) { 1579 selinux_log(SELINUX_ERROR, "SELinux: Could not stat %s: %s\n", 1580 sepolicy_file[policy_index], strerror(errno)); 1581 close(fd); 1582 return -1; 1583 } 1584 map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 1585 if (map == MAP_FAILED) { 1586 selinux_log(SELINUX_ERROR, "SELinux: Could not map %s: %s\n", 1587 sepolicy_file[policy_index], strerror(errno)); 1588 close(fd); 1589 return -1; 1590 } 1591 1592 rc = security_load_policy(map, sb.st_size); 1593 if (rc < 0) { 1594 selinux_log(SELINUX_ERROR, "SELinux: Could not load policy: %s\n", 1595 strerror(errno)); 1596 munmap(map, sb.st_size); 1597 close(fd); 1598 return -1; 1599 } 1600 1601 munmap(map, sb.st_size); 1602 close(fd); 1603 selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file[policy_index]); 1604 1605 return 0; 1606 } 1607 1608 int selinux_android_reload_policy(void) 1609 { 1610 return selinux_android_load_policy_helper(true); 1611 } 1612 1613 int selinux_android_load_policy(void) 1614 { 1615 const char *mnt = SELINUXMNT; 1616 int rc; 1617 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL); 1618 if (rc < 0) { 1619 if (errno == ENODEV) { 1620 /* SELinux not enabled in kernel */ 1621 return -1; 1622 } 1623 if (errno == ENOENT) { 1624 /* Fall back to legacy mountpoint. */ 1625 mnt = OLDSELINUXMNT; 1626 rc = mkdir(mnt, 0755); 1627 if (rc == -1 && errno != EEXIST) { 1628 selinux_log(SELINUX_ERROR,"SELinux: Could not mkdir: %s\n", 1629 strerror(errno)); 1630 return -1; 1631 } 1632 rc = mount(SELINUXFS, mnt, SELINUXFS, 0, NULL); 1633 } 1634 } 1635 if (rc < 0) { 1636 selinux_log(SELINUX_ERROR,"SELinux: Could not mount selinuxfs: %s\n", 1637 strerror(errno)); 1638 return -1; 1639 } 1640 set_selinuxmnt(mnt); 1641 1642 return selinux_android_load_policy_helper(false); 1643 } 1644 1645 int selinux_log_callback(int type, const char *fmt, ...) 1646 { 1647 va_list ap; 1648 int priority; 1649 char *strp; 1650 1651 switch(type) { 1652 case SELINUX_WARNING: 1653 priority = ANDROID_LOG_WARN; 1654 break; 1655 case SELINUX_INFO: 1656 priority = ANDROID_LOG_INFO; 1657 break; 1658 default: 1659 priority = ANDROID_LOG_ERROR; 1660 break; 1661 } 1662 1663 va_start(ap, fmt); 1664 if (vasprintf(&strp, fmt, ap) != -1) { 1665 LOG_PRI(priority, "SELinux", "%s", strp); 1666 LOG_EVENT_STRING(AUDITD_LOG_TAG, strp); 1667 free(strp); 1668 } 1669 va_end(ap); 1670 return 0; 1671 } 1672