installd.cpp revision 0274c977e3b10b52936fd5b2eb464857f0ca6358
1/* 2** Copyright 2008, The Android Open Source Project 3** 4** Licensed under the Apache License, Version 2.0 (the "License"); 5** you may not use this file except in compliance with the License. 6** You may obtain a copy of the License at 7** 8** http://www.apache.org/licenses/LICENSE-2.0 9** 10** Unless required by applicable law or agreed to in writing, software 11** distributed under the License is distributed on an "AS IS" BASIS, 12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13** See the License for the specific language governing permissions and 14** limitations under the License. 15*/ 16 17#include <fcntl.h> 18#include <selinux/android.h> 19#include <selinux/avc.h> 20#include <sys/capability.h> 21#include <sys/fsuid.h> 22#include <sys/prctl.h> 23#include <sys/socket.h> 24#include <sys/stat.h> 25 26#include <android-base/logging.h> 27#include <cutils/fs.h> 28#include <cutils/log.h> // TODO: Move everything to base::logging. 29#include <cutils/properties.h> 30#include <cutils/sockets.h> 31#include <private/android_filesystem_config.h> 32 33#include <commands.h> 34#include <globals.h> 35#include <installd_constants.h> 36#include <installd_deps.h> // Need to fill in requirements of commands. 37#include <utils.h> 38 39#ifndef LOG_TAG 40#define LOG_TAG "installd" 41#endif 42#define SOCKET_PATH "installd" 43 44#define BUFFER_MAX 1024 /* input buffer for commands */ 45#define TOKEN_MAX 16 /* max number of arguments in buffer */ 46#define REPLY_MAX 256 /* largest reply allowed */ 47 48namespace android { 49namespace installd { 50 51// Check that installd-deps sizes match cutils sizes. 52static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch."); 53static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch."); 54 55//////////////////////// 56// Plug-in functions. // 57//////////////////////// 58 59int get_property(const char *key, char *value, const char *default_value) { 60 return property_get(key, value, default_value); 61} 62 63// Compute the output path of 64bool calculate_oat_file_path(char path[PKG_PATH_MAX], 65 const char *oat_dir, 66 const char *apk_path, 67 const char *instruction_set) { 68 const char *file_name_start; 69 const char *file_name_end; 70 71 file_name_start = strrchr(apk_path, '/'); 72 if (file_name_start == NULL) { 73 ALOGE("apk_path '%s' has no '/'s in it\n", apk_path); 74 return false; 75 } 76 file_name_end = strrchr(apk_path, '.'); 77 if (file_name_end < file_name_start) { 78 ALOGE("apk_path '%s' has no extension\n", apk_path); 79 return false; 80 } 81 82 // Calculate file_name 83 int file_name_len = file_name_end - file_name_start - 1; 84 char file_name[file_name_len + 1]; 85 memcpy(file_name, file_name_start + 1, file_name_len); 86 file_name[file_name_len] = '\0'; 87 88 // <apk_parent_dir>/oat/<isa>/<file_name>.odex 89 snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name); 90 return true; 91} 92 93/* 94 * Computes the odex file for the given apk_path and instruction_set. 95 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex 96 * 97 * Returns false if it failed to determine the odex file path. 98 */ 99bool calculate_odex_file_path(char path[PKG_PATH_MAX], 100 const char *apk_path, 101 const char *instruction_set) { 102 if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set) 103 + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) { 104 ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path); 105 return false; 106 } 107 108 strcpy(path, apk_path); 109 char *end = strrchr(path, '/'); 110 if (end == NULL) { 111 ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); 112 return false; 113 } 114 const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/'); 115 116 strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0 117 strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0 118 strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0 119 end = strrchr(path, '.'); 120 if (end == NULL) { 121 ALOGE("apk_path '%s' has no extension.\n", apk_path); 122 return false; 123 } 124 strcpy(end + 1, "odex"); 125 return true; 126} 127 128bool create_cache_path(char path[PKG_PATH_MAX], 129 const char *src, 130 const char *instruction_set) { 131 /* demand that we are an absolute path */ 132 if ((src == nullptr) || (src[0] != '/') || strstr(src,"..")) { 133 return false; 134 } 135 136 size_t srclen = strlen(src); 137 138 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX? 139 return false; 140 } 141 142 size_t dstlen = 143 android_data_dir.len + 144 strlen(DALVIK_CACHE) + 145 1 + 146 strlen(instruction_set) + 147 srclen + 148 strlen(DALVIK_CACHE_POSTFIX) + 2; 149 150 if (dstlen > PKG_PATH_MAX) { 151 return false; 152 } 153 154 sprintf(path,"%s%s/%s/%s", 155 android_data_dir.path, 156 DALVIK_CACHE, 157 instruction_set, 158 src + 1 /* skip the leading / */); 159 160 char* tmp = 161 path + 162 android_data_dir.len + 163 strlen(DALVIK_CACHE) + 164 1 + 165 strlen(instruction_set) + 1; 166 167 for(; *tmp; tmp++) { 168 if (*tmp == '/') { 169 *tmp = '@'; 170 } 171 } 172 173 strcat(path, DALVIK_CACHE_POSTFIX); 174 return true; 175} 176 177 178static char* parse_null(char* arg) { 179 if (strcmp(arg, "!") == 0) { 180 return nullptr; 181 } else { 182 return arg; 183 } 184} 185 186static int do_ping(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 187{ 188 return 0; 189} 190 191static int do_restorecon_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 192 /* const char* uuid, const char* pkgName, userid_t userid, int flags, 193 appid_t appid, const char* seinfo */ 194 return restorecon_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]); 195} 196 197static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 198 /* const char *uuid, const char *pkgname, userid_t userid, int flags */ 199 return migrate_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); 200} 201 202static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 203 /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */ 204 return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4])); 205} 206 207static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 208 /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */ 209 return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4])); 210} 211 212// We use otapreopt_chroot to get into the chroot. 213static constexpr const char* kOtaPreopt = "/system/bin/otapreopt_chroot"; 214 215static int do_ota_dexopt(const char* args[DEXOPT_PARAM_COUNT], 216 char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 217 // Time to fork and run otapreopt. 218 219 // Check that the tool exists. 220 struct stat s; 221 if (stat(kOtaPreopt, &s) != 0) { 222 LOG(ERROR) << "Otapreopt chroot tool not found."; 223 return -1; 224 } 225 226 pid_t pid = fork(); 227 if (pid == 0) { 228 const char* argv[1 + DEXOPT_PARAM_COUNT + 1]; 229 argv[0] = kOtaPreopt; 230 231 for (size_t i = 0; i < DEXOPT_PARAM_COUNT; ++i) { 232 argv[i + 1] = args[i]; 233 } 234 235 argv[DEXOPT_PARAM_COUNT + 1] = nullptr; 236 237 execv(argv[0], (char * const *)argv); 238 PLOG(ERROR) << "execv(OTAPREOPT_CHROOT) failed"; 239 exit(99); 240 } else { 241 int res = wait_child(pid); 242 if (res == 0) { 243 ALOGV("DexInv: --- END OTAPREOPT (success) ---\n"); 244 } else { 245 ALOGE("DexInv: --- END OTAPREOPT --- status=0x%04x, process failed\n", res); 246 } 247 return res; 248 } 249} 250 251static int do_regular_dexopt(const char* args[DEXOPT_PARAM_COUNT], 252 char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 253 return dexopt(args); 254} 255 256using DexoptFn = int (*)(const char* args[DEXOPT_PARAM_COUNT], 257 char reply[REPLY_MAX]); 258 259static int do_dexopt(char **arg, char reply[REPLY_MAX]) 260{ 261 const char* args[DEXOPT_PARAM_COUNT]; 262 for (size_t i = 0; i < DEXOPT_PARAM_COUNT; ++i) { 263 CHECK(arg[i] != nullptr); 264 args[i] = arg[i]; 265 } 266 267 int dexopt_flags = atoi(arg[6]); 268 DexoptFn dexopt_fn; 269 if ((dexopt_flags & DEXOPT_OTA) != 0) { 270 dexopt_fn = do_ota_dexopt; 271 } else { 272 dexopt_fn = do_regular_dexopt; 273 } 274 return dexopt_fn(args, reply); 275} 276 277static int do_merge_profiles(char **arg, char reply[REPLY_MAX]) 278{ 279 uid_t uid = static_cast<uid_t>(atoi(arg[0])); 280 const char* pkgname = arg[1]; 281 if (merge_profiles(uid, pkgname)) { 282 strncpy(reply, "true", REPLY_MAX); 283 } else { 284 strncpy(reply, "false", REPLY_MAX); 285 } 286 return 0; 287} 288 289static int do_dump_profiles(char **arg, char reply[REPLY_MAX]) 290{ 291 uid_t uid = static_cast<uid_t>(atoi(arg[0])); 292 const char* pkgname = arg[1]; 293 const char* dex_files = arg[2]; 294 if (dump_profile(uid, pkgname, dex_files)) { 295 strncpy(reply, "true", REPLY_MAX); 296 } else { 297 strncpy(reply, "false", REPLY_MAX); 298 } 299 return 0; 300} 301 302static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 303{ 304 return mark_boot_complete(arg[0] /* instruction set */); 305} 306 307static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 308{ 309 return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */ 310} 311 312static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */ 313{ 314 return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */ 315} 316 317static int do_get_app_size(char **arg, char reply[REPLY_MAX]) { 318 int64_t codesize = 0; 319 int64_t datasize = 0; 320 int64_t cachesize = 0; 321 int64_t asecsize = 0; 322 int res = 0; 323 324 /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode, 325 const char* code_path */ 326 res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]), 327 arg[5], &codesize, &datasize, &cachesize, &asecsize); 328 329 /* 330 * Each int64_t can take up 22 characters printed out. Make sure it 331 * doesn't go over REPLY_MAX in the future. 332 */ 333 snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64, 334 codesize, datasize, cachesize, asecsize); 335 return res; 336} 337 338static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) { 339 ino_t inode = 0; 340 int res = 0; 341 342 /* const char *uuid, const char *pkgname, int userid, int flags */ 343 res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode); 344 345 snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode); 346 return res; 347} 348 349static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 350{ 351 /* const char *uuid, userid_t userid, int user_serial, int flags */ 352 return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3])); 353} 354 355static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 356{ 357 /* const char *uuid, userid_t userid, int flags */ 358 return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2])); 359} 360 361static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 362{ 363 return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3])); 364} 365 366static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 367{ 368 return idmap(arg[0], arg[1], atoi(arg[2])); 369} 370 371static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 372{ 373 /* oat_dir, instruction_set */ 374 return create_oat_dir(arg[0], arg[1]); 375} 376 377static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 378{ 379 /* oat_dir */ 380 return rm_package_dir(arg[0]); 381} 382 383static int do_clear_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 384{ 385 /* package_name */ 386 return clear_app_profiles(arg[0]); 387} 388 389static int do_destroy_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 390{ 391 /* package_name */ 392 return destroy_app_profiles(arg[0]); 393} 394 395static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 396{ 397 /* relative_path, from_base, to_base */ 398 return link_file(arg[0], arg[1], arg[2]); 399} 400 401static int do_move_ab(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 402 // apk_path, instruction_set, oat_dir 403 return move_ab(arg[0], arg[1], arg[2]); 404} 405 406static int do_delete_odex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 407 // apk_path, instruction_set, oat_dir 408 return delete_odex(arg[0], arg[1], arg[2]) ? 0 : -1; 409} 410 411struct cmdinfo { 412 const char *name; 413 unsigned numargs; 414 int (*func)(char **arg, char reply[REPLY_MAX]); 415}; 416 417struct cmdinfo cmds[] = { 418 { "ping", 0, do_ping }, 419 420 { "restorecon_app_data", 6, do_restorecon_app_data }, 421 { "migrate_app_data", 4, do_migrate_app_data }, 422 { "clear_app_data", 5, do_clear_app_data }, 423 { "destroy_app_data", 5, do_destroy_app_data }, 424 { "get_app_size", 6, do_get_app_size }, 425 { "get_app_data_inode", 4, do_get_app_data_inode }, 426 427 { "create_user_data", 4, do_create_user_data }, 428 { "destroy_user_data", 3, do_destroy_user_data }, 429 430 { "dexopt", 10, do_dexopt }, 431 { "markbootcomplete", 1, do_mark_boot_complete }, 432 { "rmdex", 2, do_rm_dex }, 433 { "freecache", 2, do_free_cache }, 434 { "linklib", 4, do_linklib }, 435 { "idmap", 3, do_idmap }, 436 { "createoatdir", 2, do_create_oat_dir }, 437 { "rmpackagedir", 1, do_rm_package_dir }, 438 { "clear_app_profiles", 1, do_clear_app_profiles }, 439 { "destroy_app_profiles", 1, do_destroy_app_profiles }, 440 { "linkfile", 3, do_link_file }, 441 { "move_ab", 3, do_move_ab }, 442 { "merge_profiles", 2, do_merge_profiles }, 443 { "dump_profiles", 3, do_dump_profiles }, 444 { "delete_odex", 3, do_delete_odex }, 445}; 446 447static int readx(int s, void *_buf, int count) 448{ 449 char *buf = (char *) _buf; 450 int n = 0, r; 451 if (count < 0) return -1; 452 while (n < count) { 453 r = read(s, buf + n, count - n); 454 if (r < 0) { 455 if (errno == EINTR) continue; 456 ALOGE("read error: %s\n", strerror(errno)); 457 return -1; 458 } 459 if (r == 0) { 460 ALOGE("eof\n"); 461 return -1; /* EOF */ 462 } 463 n += r; 464 } 465 return 0; 466} 467 468static int writex(int s, const void *_buf, int count) 469{ 470 const char *buf = (const char *) _buf; 471 int n = 0, r; 472 if (count < 0) return -1; 473 while (n < count) { 474 r = write(s, buf + n, count - n); 475 if (r < 0) { 476 if (errno == EINTR) continue; 477 ALOGE("write error: %s\n", strerror(errno)); 478 return -1; 479 } 480 n += r; 481 } 482 return 0; 483} 484 485 486/* Tokenize the command buffer, locate a matching command, 487 * ensure that the required number of arguments are provided, 488 * call the function(), return the result. 489 */ 490static int execute(int s, char cmd[BUFFER_MAX]) 491{ 492 char reply[REPLY_MAX]; 493 char *arg[TOKEN_MAX+1]; 494 unsigned i; 495 unsigned n = 0; 496 unsigned short count; 497 int ret = -1; 498 499 // ALOGI("execute('%s')\n", cmd); 500 501 /* default reply is "" */ 502 reply[0] = 0; 503 504 /* n is number of args (not counting arg[0]) */ 505 arg[0] = cmd; 506 while (*cmd) { 507 if (isspace(*cmd)) { 508 *cmd++ = 0; 509 n++; 510 arg[n] = cmd; 511 if (n == TOKEN_MAX) { 512 ALOGE("too many arguments\n"); 513 goto done; 514 } 515 } 516 if (*cmd) { 517 cmd++; 518 } 519 } 520 521 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { 522 if (!strcmp(cmds[i].name,arg[0])) { 523 if (n != cmds[i].numargs) { 524 ALOGE("%s requires %d arguments (%d given)\n", 525 cmds[i].name, cmds[i].numargs, n); 526 } else { 527 ret = cmds[i].func(arg + 1, reply); 528 } 529 goto done; 530 } 531 } 532 ALOGE("unsupported command '%s'\n", arg[0]); 533 534done: 535 if (reply[0]) { 536 n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply); 537 } else { 538 n = snprintf(cmd, BUFFER_MAX, "%d", ret); 539 } 540 if (n > BUFFER_MAX) n = BUFFER_MAX; 541 count = n; 542 543 // ALOGI("reply: '%s'\n", cmd); 544 if (writex(s, &count, sizeof(count))) return -1; 545 if (writex(s, cmd, count)) return -1; 546 return 0; 547} 548 549static bool initialize_globals() { 550 const char* data_path = getenv("ANDROID_DATA"); 551 if (data_path == nullptr) { 552 ALOGE("Could not find ANDROID_DATA"); 553 return false; 554 } 555 const char* root_path = getenv("ANDROID_ROOT"); 556 if (root_path == nullptr) { 557 ALOGE("Could not find ANDROID_ROOT"); 558 return false; 559 } 560 561 return init_globals_from_data_and_root(data_path, root_path); 562} 563 564static int initialize_directories() { 565 int res = -1; 566 567 // Read current filesystem layout version to handle upgrade paths 568 char version_path[PATH_MAX]; 569 snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path); 570 571 int oldVersion; 572 if (fs_read_atomic_int(version_path, &oldVersion) == -1) { 573 oldVersion = 0; 574 } 575 int version = oldVersion; 576 577 if (version < 2) { 578 SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported"); 579 version = 2; 580 } 581 582 if (ensure_config_user_dirs(0) == -1) { 583 ALOGE("Failed to setup misc for user 0"); 584 goto fail; 585 } 586 587 if (version == 2) { 588 ALOGD("Upgrading to /data/misc/user directories"); 589 590 char misc_dir[PATH_MAX]; 591 snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path); 592 593 char keychain_added_dir[PATH_MAX]; 594 snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir); 595 596 char keychain_removed_dir[PATH_MAX]; 597 snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir); 598 599 DIR *dir; 600 struct dirent *dirent; 601 dir = opendir("/data/user"); 602 if (dir != NULL) { 603 while ((dirent = readdir(dir))) { 604 const char *name = dirent->d_name; 605 606 // skip "." and ".." 607 if (name[0] == '.') { 608 if (name[1] == 0) continue; 609 if ((name[1] == '.') && (name[2] == 0)) continue; 610 } 611 612 uint32_t user_id = atoi(name); 613 614 // /data/misc/user/<user_id> 615 if (ensure_config_user_dirs(user_id) == -1) { 616 goto fail; 617 } 618 619 char misc_added_dir[PATH_MAX]; 620 snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name); 621 622 char misc_removed_dir[PATH_MAX]; 623 snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name); 624 625 uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM); 626 gid_t gid = uid; 627 if (access(keychain_added_dir, F_OK) == 0) { 628 if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) { 629 ALOGE("Some files failed to copy"); 630 } 631 } 632 if (access(keychain_removed_dir, F_OK) == 0) { 633 if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) { 634 ALOGE("Some files failed to copy"); 635 } 636 } 637 } 638 closedir(dir); 639 640 if (access(keychain_added_dir, F_OK) == 0) { 641 delete_dir_contents(keychain_added_dir, 1, 0); 642 } 643 if (access(keychain_removed_dir, F_OK) == 0) { 644 delete_dir_contents(keychain_removed_dir, 1, 0); 645 } 646 } 647 648 version = 3; 649 } 650 651 // Persist layout version if changed 652 if (version != oldVersion) { 653 if (fs_write_atomic_int(version_path, version) == -1) { 654 ALOGE("Failed to save version to %s: %s", version_path, strerror(errno)); 655 goto fail; 656 } 657 } 658 659 // Success! 660 res = 0; 661 662fail: 663 return res; 664} 665 666static int log_callback(int type, const char *fmt, ...) { 667 va_list ap; 668 int priority; 669 670 switch (type) { 671 case SELINUX_WARNING: 672 priority = ANDROID_LOG_WARN; 673 break; 674 case SELINUX_INFO: 675 priority = ANDROID_LOG_INFO; 676 break; 677 default: 678 priority = ANDROID_LOG_ERROR; 679 break; 680 } 681 va_start(ap, fmt); 682 LOG_PRI_VA(priority, "SELinux", fmt, ap); 683 va_end(ap); 684 return 0; 685} 686 687static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) { 688 char buf[BUFFER_MAX]; 689 struct sockaddr addr; 690 socklen_t alen; 691 int lsocket, s, ret; 692 int selinux_enabled = (is_selinux_enabled() > 0); 693 694 setenv("ANDROID_LOG_TAGS", "*:v", 1); 695 android::base::InitLogging(argv); 696 697 ALOGI("installd firing up\n"); 698 699 union selinux_callback cb; 700 cb.func_log = log_callback; 701 selinux_set_callback(SELINUX_CB_LOG, cb); 702 703 if (!initialize_globals()) { 704 ALOGE("Could not initialize globals; exiting.\n"); 705 exit(1); 706 } 707 708 if (initialize_directories() < 0) { 709 ALOGE("Could not create directories; exiting.\n"); 710 exit(1); 711 } 712 713 if (selinux_enabled && selinux_status_open(true) < 0) { 714 ALOGE("Could not open selinux status; exiting.\n"); 715 exit(1); 716 } 717 718 if ((ret = InstalldNativeService::start()) != android::OK) { 719 ALOGE("Unable to start InstalldNativeService: %d", ret); 720 exit(1); 721 } 722 723 lsocket = android_get_control_socket(SOCKET_PATH); 724 if (lsocket < 0) { 725 ALOGE("Failed to get socket from environment: %s\n", strerror(errno)); 726 exit(1); 727 } 728 if (listen(lsocket, 5)) { 729 ALOGE("Listen on socket failed: %s\n", strerror(errno)); 730 exit(1); 731 } 732 fcntl(lsocket, F_SETFD, FD_CLOEXEC); 733 734 for (;;) { 735 alen = sizeof(addr); 736 s = accept(lsocket, &addr, &alen); 737 if (s < 0) { 738 ALOGE("Accept failed: %s\n", strerror(errno)); 739 continue; 740 } 741 fcntl(s, F_SETFD, FD_CLOEXEC); 742 743 ALOGI("new connection\n"); 744 for (;;) { 745 unsigned short count; 746 if (readx(s, &count, sizeof(count))) { 747 ALOGE("failed to read size\n"); 748 break; 749 } 750 if ((count < 1) || (count >= BUFFER_MAX)) { 751 ALOGE("invalid size %d\n", count); 752 break; 753 } 754 if (readx(s, buf, count)) { 755 ALOGE("failed to read command\n"); 756 break; 757 } 758 buf[count] = 0; 759 if (selinux_enabled && selinux_status_updated() > 0) { 760 selinux_android_seapp_context_reload(); 761 } 762 if (execute(s, buf)) break; 763 } 764 ALOGI("closing connection\n"); 765 close(s); 766 } 767 768 return 0; 769} 770 771} // namespace installd 772} // namespace android 773 774int main(const int argc, char *argv[]) { 775 return android::installd::installd_main(argc, argv); 776} 777