installd.cpp revision c7d1b2250e8245a7e4e144758bc3ccd33b8d6319
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 48#define DEBUG_FBE 0 49 50namespace android { 51namespace installd { 52 53// Check that installd-deps sizes match cutils sizes. 54static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch."); 55static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch."); 56 57//////////////////////// 58// Plug-in functions. // 59//////////////////////// 60 61int get_property(const char *key, char *value, const char *default_value) { 62 return property_get(key, value, default_value); 63} 64 65// Compute the output path of 66bool calculate_oat_file_path(char path[PKG_PATH_MAX], 67 const char *oat_dir, 68 const char *apk_path, 69 const char *instruction_set) { 70 char *file_name_start; 71 char *file_name_end; 72 73 file_name_start = strrchr(apk_path, '/'); 74 if (file_name_start == NULL) { 75 ALOGE("apk_path '%s' has no '/'s in it\n", apk_path); 76 return false; 77 } 78 file_name_end = strrchr(apk_path, '.'); 79 if (file_name_end < file_name_start) { 80 ALOGE("apk_path '%s' has no extension\n", apk_path); 81 return false; 82 } 83 84 // Calculate file_name 85 int file_name_len = file_name_end - file_name_start - 1; 86 char file_name[file_name_len + 1]; 87 memcpy(file_name, file_name_start + 1, file_name_len); 88 file_name[file_name_len] = '\0'; 89 90 // <apk_parent_dir>/oat/<isa>/<file_name>.odex 91 snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name); 92 return true; 93} 94 95/* 96 * Computes the odex file for the given apk_path and instruction_set. 97 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex 98 * 99 * Returns false if it failed to determine the odex file path. 100 */ 101bool calculate_odex_file_path(char path[PKG_PATH_MAX], 102 const char *apk_path, 103 const char *instruction_set) { 104 if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set) 105 + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) { 106 ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path); 107 return false; 108 } 109 110 strcpy(path, apk_path); 111 char *end = strrchr(path, '/'); 112 if (end == NULL) { 113 ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); 114 return false; 115 } 116 const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/'); 117 118 strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0 119 strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0 120 strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0 121 end = strrchr(path, '.'); 122 if (end == NULL) { 123 ALOGE("apk_path '%s' has no extension.\n", apk_path); 124 return false; 125 } 126 strcpy(end + 1, "odex"); 127 return true; 128} 129 130bool create_cache_path(char path[PKG_PATH_MAX], 131 const char *src, 132 const char *instruction_set) { 133 size_t srclen = strlen(src); 134 135 /* demand that we are an absolute path */ 136 if ((src == 0) || (src[0] != '/') || strstr(src,"..")) { 137 return false; 138 } 139 140 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX? 141 return false; 142 } 143 144 size_t dstlen = 145 android_data_dir.len + 146 strlen(DALVIK_CACHE) + 147 1 + 148 strlen(instruction_set) + 149 srclen + 150 strlen(DALVIK_CACHE_POSTFIX) + 2; 151 152 if (dstlen > PKG_PATH_MAX) { 153 return false; 154 } 155 156 sprintf(path,"%s%s/%s/%s%s", 157 android_data_dir.path, 158 DALVIK_CACHE, 159 instruction_set, 160 src + 1, /* skip the leading / */ 161 DALVIK_CACHE_POSTFIX); 162 163 char* tmp = 164 path + 165 android_data_dir.len + 166 strlen(DALVIK_CACHE) + 167 1 + 168 strlen(instruction_set) + 1; 169 170 for(; *tmp; tmp++) { 171 if (*tmp == '/') { 172 *tmp = '@'; 173 } 174 } 175 176 return true; 177} 178 179 180static char* parse_null(char* arg) { 181 if (strcmp(arg, "!") == 0) { 182 return nullptr; 183 } else { 184 return arg; 185 } 186} 187 188static int do_ping(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 189{ 190 return 0; 191} 192 193static int do_create_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 194 /* const char *uuid, const char *pkgname, userid_t userid, int flags, 195 appid_t appid, const char* seinfo */ 196 return create_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]); 197} 198 199static int do_restorecon_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 200 /* const char* uuid, const char* pkgName, userid_t userid, int flags, 201 appid_t appid, const char* seinfo */ 202 return restorecon_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]); 203} 204 205static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 206 /* const char *uuid, const char *pkgname, userid_t userid, int flags */ 207 return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); 208} 209 210static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 211 /* const char *uuid, const char *pkgname, userid_t userid, int flags */ 212 return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); 213} 214 215static int do_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 216{ 217 /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags */ 218 return dexopt(arg[0], atoi(arg[1]), arg[2], arg[3], atoi(arg[4]), 219 arg[5], atoi(arg[6])); 220} 221 222static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 223{ 224 return mark_boot_complete(arg[0] /* instruction set */); 225} 226 227static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 228{ 229 return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */ 230} 231 232static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */ 233{ 234 return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */ 235} 236 237static int do_get_app_size(char **arg, char reply[REPLY_MAX]) { 238 int64_t codesize = 0; 239 int64_t datasize = 0; 240 int64_t cachesize = 0; 241 int64_t asecsize = 0; 242 int res = 0; 243 244 /* const char *uuid, const char *pkgname, userid_t userid, int flags, 245 const char *apkpath, const char *libdirpath, const char *fwdlock_apkpath, 246 const char *asecpath, const char *instruction_set */ 247 res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4], arg[5], 248 arg[6], arg[7], arg[8], &codesize, &datasize, &cachesize, &asecsize); 249 250 /* 251 * Each int64_t can take up 22 characters printed out. Make sure it 252 * doesn't go over REPLY_MAX in the future. 253 */ 254 snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64, 255 codesize, datasize, cachesize, asecsize); 256 return res; 257} 258 259static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { 260 /* const char* from_uuid, const char *to_uuid, const char *package_name, 261 const char *data_app_name, appid_t appid, const char* seinfo */ 262 return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]); 263} 264 265static int do_mk_user_config(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 266{ 267 return make_user_config(atoi(arg[0])); /* userid */ 268} 269 270static int do_rm_user(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 271{ 272 return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */ 273} 274 275static int do_movefiles(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 276{ 277 return movefiles(); 278} 279 280static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 281{ 282 return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3])); 283} 284 285static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 286{ 287 return idmap(arg[0], arg[1], atoi(arg[2])); 288} 289 290static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 291{ 292 /* oat_dir, instruction_set */ 293 return create_oat_dir(arg[0], arg[1]); 294} 295 296static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 297{ 298 /* oat_dir */ 299 return rm_package_dir(arg[0]); 300} 301 302static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) 303{ 304 /* relative_path, from_base, to_base */ 305 return link_file(arg[0], arg[1], arg[2]); 306} 307 308struct cmdinfo { 309 const char *name; 310 unsigned numargs; 311 int (*func)(char **arg, char reply[REPLY_MAX]); 312}; 313 314struct cmdinfo cmds[] = { 315 { "ping", 0, do_ping }, 316 317 { "create_app_data", 6, do_create_app_data }, 318 { "restorecon_app_data", 6, do_restorecon_app_data }, 319 { "clear_app_data", 4, do_clear_app_data }, 320 { "destroy_app_data", 4, do_destroy_app_data }, 321 { "move_complete_app", 6, do_move_complete_app }, 322 { "get_app_size", 9, do_get_app_size }, 323 324 { "dexopt", 7, do_dexopt }, 325 { "markbootcomplete", 1, do_mark_boot_complete }, 326 { "rmdex", 2, do_rm_dex }, 327 { "freecache", 2, do_free_cache }, 328 { "movefiles", 0, do_movefiles }, 329 { "linklib", 4, do_linklib }, 330 { "mkuserconfig", 1, do_mk_user_config }, 331 { "rmuser", 2, do_rm_user }, 332 { "idmap", 3, do_idmap }, 333 { "createoatdir", 2, do_create_oat_dir }, 334 { "rmpackagedir", 1, do_rm_package_dir }, 335 { "linkfile", 3, do_link_file }, 336}; 337 338static int readx(int s, void *_buf, int count) 339{ 340 char *buf = (char *) _buf; 341 int n = 0, r; 342 if (count < 0) return -1; 343 while (n < count) { 344 r = read(s, buf + n, count - n); 345 if (r < 0) { 346 if (errno == EINTR) continue; 347 ALOGE("read error: %s\n", strerror(errno)); 348 return -1; 349 } 350 if (r == 0) { 351 ALOGE("eof\n"); 352 return -1; /* EOF */ 353 } 354 n += r; 355 } 356 return 0; 357} 358 359static int writex(int s, const void *_buf, int count) 360{ 361 const char *buf = (const char *) _buf; 362 int n = 0, r; 363 if (count < 0) return -1; 364 while (n < count) { 365 r = write(s, buf + n, count - n); 366 if (r < 0) { 367 if (errno == EINTR) continue; 368 ALOGE("write error: %s\n", strerror(errno)); 369 return -1; 370 } 371 n += r; 372 } 373 return 0; 374} 375 376 377/* Tokenize the command buffer, locate a matching command, 378 * ensure that the required number of arguments are provided, 379 * call the function(), return the result. 380 */ 381static int execute(int s, char cmd[BUFFER_MAX]) 382{ 383 char reply[REPLY_MAX]; 384 char *arg[TOKEN_MAX+1]; 385 unsigned i; 386 unsigned n = 0; 387 unsigned short count; 388 int ret = -1; 389 390 // ALOGI("execute('%s')\n", cmd); 391 392 /* default reply is "" */ 393 reply[0] = 0; 394 395 /* n is number of args (not counting arg[0]) */ 396 arg[0] = cmd; 397 while (*cmd) { 398 if (isspace(*cmd)) { 399 *cmd++ = 0; 400 n++; 401 arg[n] = cmd; 402 if (n == TOKEN_MAX) { 403 ALOGE("too many arguments\n"); 404 goto done; 405 } 406 } 407 if (*cmd) { 408 cmd++; 409 } 410 } 411 412 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { 413 if (!strcmp(cmds[i].name,arg[0])) { 414 if (n != cmds[i].numargs) { 415 ALOGE("%s requires %d arguments (%d given)\n", 416 cmds[i].name, cmds[i].numargs, n); 417 } else { 418 ret = cmds[i].func(arg + 1, reply); 419 } 420 goto done; 421 } 422 } 423 ALOGE("unsupported command '%s'\n", arg[0]); 424 425done: 426 if (reply[0]) { 427 n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply); 428 } else { 429 n = snprintf(cmd, BUFFER_MAX, "%d", ret); 430 } 431 if (n > BUFFER_MAX) n = BUFFER_MAX; 432 count = n; 433 434 // ALOGI("reply: '%s'\n", cmd); 435 if (writex(s, &count, sizeof(count))) return -1; 436 if (writex(s, cmd, count)) return -1; 437 return 0; 438} 439 440bool initialize_globals() { 441 const char* data_path = getenv("ANDROID_DATA"); 442 if (data_path == nullptr) { 443 ALOGE("Could not find ANDROID_DATA"); 444 return false; 445 } 446 const char* root_path = getenv("ANDROID_ROOT"); 447 if (root_path == nullptr) { 448 ALOGE("Could not find ANDROID_ROOT"); 449 return false; 450 } 451 452 return init_globals_from_data_and_root(data_path, root_path); 453} 454 455static int initialize_directories() { 456 int res = -1; 457 458 // Read current filesystem layout version to handle upgrade paths 459 char version_path[PATH_MAX]; 460 snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path); 461 462 int oldVersion; 463 if (fs_read_atomic_int(version_path, &oldVersion) == -1) { 464 oldVersion = 0; 465 } 466 int version = oldVersion; 467 468 // /data/user 469 char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); 470 // /data/data 471 char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); 472 // /data/user/0 473 char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0"); 474 if (!user_data_dir || !legacy_data_dir || !primary_data_dir) { 475 goto fail; 476 } 477 478 // Make the /data/user directory if necessary 479 if (access(user_data_dir, R_OK) < 0) { 480 if (mkdir(user_data_dir, 0711) < 0) { 481 goto fail; 482 } 483 if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { 484 goto fail; 485 } 486 if (chmod(user_data_dir, 0711) < 0) { 487 goto fail; 488 } 489 } 490 // Make the /data/user/0 symlink to /data/data if necessary 491 if (access(primary_data_dir, R_OK) < 0) { 492 if (symlink(legacy_data_dir, primary_data_dir)) { 493 goto fail; 494 } 495 } 496 497 if (version == 0) { 498 // Introducing multi-user, so migrate /data/media contents into /data/media/0 499 ALOGD("Upgrading /data/media for multi-user"); 500 501 // Ensure /data/media 502 if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { 503 goto fail; 504 } 505 506 // /data/media.tmp 507 char media_tmp_dir[PATH_MAX]; 508 snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path); 509 510 // Only copy when upgrade not already in progress 511 if (access(media_tmp_dir, F_OK) == -1) { 512 if (rename(android_media_dir.path, media_tmp_dir) == -1) { 513 ALOGE("Failed to move legacy media path: %s", strerror(errno)); 514 goto fail; 515 } 516 } 517 518 // Create /data/media again 519 if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { 520 goto fail; 521 } 522 523 if (selinux_android_restorecon(android_media_dir.path, 0)) { 524 goto fail; 525 } 526 527 // /data/media/0 528 char owner_media_dir[PATH_MAX]; 529 snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path); 530 531 // Move any owner data into place 532 if (access(media_tmp_dir, F_OK) == 0) { 533 if (rename(media_tmp_dir, owner_media_dir) == -1) { 534 ALOGE("Failed to move owner media path: %s", strerror(errno)); 535 goto fail; 536 } 537 } 538 539 // Ensure media directories for any existing users 540 DIR *dir; 541 struct dirent *dirent; 542 char user_media_dir[PATH_MAX]; 543 544 dir = opendir(user_data_dir); 545 if (dir != NULL) { 546 while ((dirent = readdir(dir))) { 547 if (dirent->d_type == DT_DIR) { 548 const char *name = dirent->d_name; 549 550 // skip "." and ".." 551 if (name[0] == '.') { 552 if (name[1] == 0) continue; 553 if ((name[1] == '.') && (name[2] == 0)) continue; 554 } 555 556 // /data/media/<user_id> 557 snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name); 558 if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { 559 goto fail; 560 } 561 } 562 } 563 closedir(dir); 564 } 565 566 version = 1; 567 } 568 569 // /data/media/obb 570 char media_obb_dir[PATH_MAX]; 571 snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path); 572 573 if (version == 1) { 574 // Introducing /data/media/obb for sharing OBB across users; migrate 575 // any existing OBB files from owner. 576 ALOGD("Upgrading to shared /data/media/obb"); 577 578 // /data/media/0/Android/obb 579 char owner_obb_path[PATH_MAX]; 580 snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path); 581 582 // Only move if target doesn't already exist 583 if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) { 584 if (rename(owner_obb_path, media_obb_dir) == -1) { 585 ALOGE("Failed to move OBB from owner: %s", strerror(errno)); 586 goto fail; 587 } 588 } 589 590 version = 2; 591 } 592 593 if (ensure_media_user_dirs(nullptr, 0) == -1) { 594 ALOGE("Failed to setup media for user 0"); 595 goto fail; 596 } 597 if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { 598 goto fail; 599 } 600 601 if (ensure_config_user_dirs(0) == -1) { 602 ALOGE("Failed to setup misc for user 0"); 603 goto fail; 604 } 605 606 if (version == 2) { 607 ALOGD("Upgrading to /data/misc/user directories"); 608 609 char misc_dir[PATH_MAX]; 610 snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path); 611 612 char keychain_added_dir[PATH_MAX]; 613 snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir); 614 615 char keychain_removed_dir[PATH_MAX]; 616 snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir); 617 618 DIR *dir; 619 struct dirent *dirent; 620 dir = opendir(user_data_dir); 621 if (dir != NULL) { 622 while ((dirent = readdir(dir))) { 623 const char *name = dirent->d_name; 624 625 // skip "." and ".." 626 if (name[0] == '.') { 627 if (name[1] == 0) continue; 628 if ((name[1] == '.') && (name[2] == 0)) continue; 629 } 630 631 uint32_t user_id = atoi(name); 632 633 // /data/misc/user/<user_id> 634 if (ensure_config_user_dirs(user_id) == -1) { 635 goto fail; 636 } 637 638 char misc_added_dir[PATH_MAX]; 639 snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name); 640 641 char misc_removed_dir[PATH_MAX]; 642 snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name); 643 644 uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM); 645 gid_t gid = uid; 646 if (access(keychain_added_dir, F_OK) == 0) { 647 if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) { 648 ALOGE("Some files failed to copy"); 649 } 650 } 651 if (access(keychain_removed_dir, F_OK) == 0) { 652 if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) { 653 ALOGE("Some files failed to copy"); 654 } 655 } 656 } 657 closedir(dir); 658 659 if (access(keychain_added_dir, F_OK) == 0) { 660 delete_dir_contents(keychain_added_dir, 1, 0); 661 } 662 if (access(keychain_removed_dir, F_OK) == 0) { 663 delete_dir_contents(keychain_removed_dir, 1, 0); 664 } 665 } 666 667 version = 3; 668 } 669 670 // Persist layout version if changed 671 if (version != oldVersion) { 672 if (fs_write_atomic_int(version_path, version) == -1) { 673 ALOGE("Failed to save version to %s: %s", version_path, strerror(errno)); 674 goto fail; 675 } 676 } 677 678 // Success! 679 res = 0; 680 681fail: 682 free(user_data_dir); 683 free(legacy_data_dir); 684 free(primary_data_dir); 685 return res; 686} 687 688static int log_callback(int type, const char *fmt, ...) { 689 va_list ap; 690 int priority; 691 692 switch (type) { 693 case SELINUX_WARNING: 694 priority = ANDROID_LOG_WARN; 695 break; 696 case SELINUX_INFO: 697 priority = ANDROID_LOG_INFO; 698 break; 699 default: 700 priority = ANDROID_LOG_ERROR; 701 break; 702 } 703 va_start(ap, fmt); 704 LOG_PRI_VA(priority, "SELinux", fmt, ap); 705 va_end(ap); 706 return 0; 707} 708 709static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) { 710 char buf[BUFFER_MAX]; 711 struct sockaddr addr; 712 socklen_t alen; 713 int lsocket, s; 714 int selinux_enabled = (is_selinux_enabled() > 0); 715 716 setenv("ANDROID_LOG_TAGS", "*:v", 1); 717 android::base::InitLogging(argv); 718 719 ALOGI("installd firing up\n"); 720 721 union selinux_callback cb; 722 cb.func_log = log_callback; 723 selinux_set_callback(SELINUX_CB_LOG, cb); 724 725 if (!initialize_globals()) { 726 ALOGE("Could not initialize globals; exiting.\n"); 727 exit(1); 728 } 729 730 if (initialize_directories() < 0) { 731 ALOGE("Could not create directories; exiting.\n"); 732 exit(1); 733 } 734 735 if (selinux_enabled && selinux_status_open(true) < 0) { 736 ALOGE("Could not open selinux status; exiting.\n"); 737 exit(1); 738 } 739 740 lsocket = android_get_control_socket(SOCKET_PATH); 741 if (lsocket < 0) { 742 ALOGE("Failed to get socket from environment: %s\n", strerror(errno)); 743 exit(1); 744 } 745 if (listen(lsocket, 5)) { 746 ALOGE("Listen on socket failed: %s\n", strerror(errno)); 747 exit(1); 748 } 749 fcntl(lsocket, F_SETFD, FD_CLOEXEC); 750 751 // Perform all filesystem access as system so that FBE emulation mode 752 // can block access using chmod 000. 753#if DEBUG_FBE 754 setfsuid(AID_SYSTEM); 755#endif 756 757 for (;;) { 758 alen = sizeof(addr); 759 s = accept(lsocket, &addr, &alen); 760 if (s < 0) { 761 ALOGE("Accept failed: %s\n", strerror(errno)); 762 continue; 763 } 764 fcntl(s, F_SETFD, FD_CLOEXEC); 765 766 ALOGI("new connection\n"); 767 for (;;) { 768 unsigned short count; 769 if (readx(s, &count, sizeof(count))) { 770 ALOGE("failed to read size\n"); 771 break; 772 } 773 if ((count < 1) || (count >= BUFFER_MAX)) { 774 ALOGE("invalid size %d\n", count); 775 break; 776 } 777 if (readx(s, buf, count)) { 778 ALOGE("failed to read command\n"); 779 break; 780 } 781 buf[count] = 0; 782 if (selinux_enabled && selinux_status_updated() > 0) { 783 selinux_android_seapp_context_reload(); 784 } 785 if (execute(s, buf)) break; 786 } 787 ALOGI("closing connection\n"); 788 close(s); 789 } 790 791 return 0; 792} 793 794} // namespace installd 795} // namespace android 796 797int main(const int argc, char *argv[]) { 798 return android::installd::installd_main(argc, argv); 799} 800