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 "installd.h" 18 19 #include <base/stringprintf.h> 20 #include <base/logging.h> 21 #include <cutils/sched_policy.h> 22 #include <diskusage/dirsize.h> 23 #include <logwrap/logwrap.h> 24 #include <system/thread_defs.h> 25 #include <selinux/android.h> 26 27 #include <inttypes.h> 28 #include <sys/capability.h> 29 #include <sys/file.h> 30 #include <unistd.h> 31 32 using android::base::StringPrintf; 33 34 /* Directory records that are used in execution of commands. */ 35 dir_rec_t android_data_dir; 36 dir_rec_t android_asec_dir; 37 dir_rec_t android_app_dir; 38 dir_rec_t android_app_private_dir; 39 dir_rec_t android_app_lib_dir; 40 dir_rec_t android_media_dir; 41 dir_rec_t android_mnt_expand_dir; 42 dir_rec_array_t android_system_dirs; 43 44 static const char* kCpPath = "/system/bin/cp"; 45 46 int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo) 47 { 48 if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { 49 ALOGE("invalid uid/gid: %d %d\n", uid, gid); 50 return -1; 51 } 52 53 std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname)); 54 const char* pkgdir = _pkgdir.c_str(); 55 56 if (mkdir(pkgdir, 0751) < 0) { 57 ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); 58 return -1; 59 } 60 if (chmod(pkgdir, 0751) < 0) { 61 ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 62 unlink(pkgdir); 63 return -1; 64 } 65 66 if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { 67 ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); 68 unlink(pkgdir); 69 return -errno; 70 } 71 72 if (chown(pkgdir, uid, gid) < 0) { 73 ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 74 unlink(pkgdir); 75 return -1; 76 } 77 78 return 0; 79 } 80 81 int uninstall(const char *uuid, const char *pkgname, userid_t userid) 82 { 83 std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); 84 const char* pkgdir = _pkgdir.c_str(); 85 86 remove_profile_file(pkgname); 87 88 /* delete contents AND directory, no exceptions */ 89 return delete_dir_contents(pkgdir, 1, NULL); 90 } 91 92 int renamepkg(const char *oldpkgname, const char *newpkgname) 93 { 94 char oldpkgdir[PKG_PATH_MAX]; 95 char newpkgdir[PKG_PATH_MAX]; 96 97 if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0)) 98 return -1; 99 if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0)) 100 return -1; 101 102 if (rename(oldpkgdir, newpkgdir) < 0) { 103 ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno)); 104 return -errno; 105 } 106 return 0; 107 } 108 109 int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid) 110 { 111 struct stat s; 112 113 if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { 114 ALOGE("invalid uid/gid: %d %d\n", uid, gid); 115 return -1; 116 } 117 118 std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname)); 119 const char* pkgdir = _pkgdir.c_str(); 120 121 if (stat(pkgdir, &s) < 0) return -1; 122 123 if (s.st_uid != 0 || s.st_gid != 0) { 124 ALOGE("fixing uid of non-root pkg: %s %" PRIu32 " %" PRIu32 "\n", pkgdir, s.st_uid, s.st_gid); 125 return -1; 126 } 127 128 if (chmod(pkgdir, 0751) < 0) { 129 ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 130 unlink(pkgdir); 131 return -errno; 132 } 133 if (chown(pkgdir, uid, gid) < 0) { 134 ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 135 unlink(pkgdir); 136 return -errno; 137 } 138 139 return 0; 140 } 141 142 int delete_user_data(const char *uuid, const char *pkgname, userid_t userid) 143 { 144 std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); 145 const char* pkgdir = _pkgdir.c_str(); 146 147 return delete_dir_contents(pkgdir, 0, NULL); 148 } 149 150 int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo) 151 { 152 std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname)); 153 const char* pkgdir = _pkgdir.c_str(); 154 155 if (mkdir(pkgdir, 0751) < 0) { 156 ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno)); 157 return -errno; 158 } 159 if (chmod(pkgdir, 0751) < 0) { 160 ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno)); 161 unlink(pkgdir); 162 return -errno; 163 } 164 165 if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) { 166 ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno)); 167 unlink(pkgdir); 168 return -errno; 169 } 170 171 if (chown(pkgdir, uid, uid) < 0) { 172 ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno)); 173 unlink(pkgdir); 174 return -errno; 175 } 176 177 return 0; 178 } 179 180 int copy_complete_app(const char *from_uuid, const char *to_uuid, 181 const char *package_name, const char *data_app_name, appid_t appid, 182 const char* seinfo) { 183 std::vector<userid_t> users = get_known_users(from_uuid); 184 185 // Copy app 186 { 187 std::string from(create_data_app_package_path(from_uuid, data_app_name)); 188 std::string to(create_data_app_package_path(to_uuid, data_app_name)); 189 std::string to_parent(create_data_app_path(to_uuid)); 190 191 char *argv[] = { 192 (char*) kCpPath, 193 (char*) "-F", /* delete any existing destination file first (--remove-destination) */ 194 (char*) "-p", /* preserve timestamps, ownership, and permissions */ 195 (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ 196 (char*) "-P", /* Do not follow symlinks [default] */ 197 (char*) "-d", /* don't dereference symlinks */ 198 (char*) from.c_str(), 199 (char*) to_parent.c_str() 200 }; 201 202 LOG(DEBUG) << "Copying " << from << " to " << to; 203 int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 204 205 if (rc != 0) { 206 LOG(ERROR) << "Failed copying " << from << " to " << to 207 << ": status " << rc; 208 goto fail; 209 } 210 211 if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) { 212 LOG(ERROR) << "Failed to restorecon " << to; 213 goto fail; 214 } 215 } 216 217 // Copy private data for all known users 218 for (auto user : users) { 219 std::string from(create_data_user_package_path(from_uuid, user, package_name)); 220 std::string to(create_data_user_package_path(to_uuid, user, package_name)); 221 std::string to_parent(create_data_user_path(to_uuid, user)); 222 223 // Data source may not exist for all users; that's okay 224 if (access(from.c_str(), F_OK) != 0) { 225 LOG(INFO) << "Missing source " << from; 226 continue; 227 } 228 229 std::string user_path(create_data_user_path(to_uuid, user)); 230 if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) { 231 LOG(ERROR) << "Failed to prepare user target " << user_path; 232 goto fail; 233 } 234 235 uid_t uid = multiuser_get_uid(user, appid); 236 if (make_user_data(to_uuid, package_name, uid, user, seinfo) != 0) { 237 LOG(ERROR) << "Failed to create package target " << to; 238 goto fail; 239 } 240 241 char *argv[] = { 242 (char*) kCpPath, 243 (char*) "-F", /* delete any existing destination file first (--remove-destination) */ 244 (char*) "-p", /* preserve timestamps, ownership, and permissions */ 245 (char*) "-R", /* recurse into subdirectories (DEST must be a directory) */ 246 (char*) "-P", /* Do not follow symlinks [default] */ 247 (char*) "-d", /* don't dereference symlinks */ 248 (char*) from.c_str(), 249 (char*) to_parent.c_str() 250 }; 251 252 LOG(DEBUG) << "Copying " << from << " to " << to; 253 int rc = android_fork_execvp(ARRAY_SIZE(argv), argv, NULL, false, true); 254 255 if (rc != 0) { 256 LOG(ERROR) << "Failed copying " << from << " to " << to 257 << ": status " << rc; 258 goto fail; 259 } 260 } 261 262 if (restorecon_data(to_uuid, package_name, seinfo, multiuser_get_uid(0, appid)) != 0) { 263 LOG(ERROR) << "Failed to restorecon"; 264 goto fail; 265 } 266 267 // We let the framework scan the new location and persist that before 268 // deleting the data in the old location; this ordering ensures that 269 // we can recover from things like battery pulls. 270 return 0; 271 272 fail: 273 // Nuke everything we might have already copied 274 { 275 std::string to(create_data_app_package_path(to_uuid, data_app_name)); 276 if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 277 LOG(WARNING) << "Failed to rollback " << to; 278 } 279 } 280 for (auto user : users) { 281 std::string to(create_data_user_package_path(to_uuid, user, package_name)); 282 if (delete_dir_contents(to.c_str(), 1, NULL) != 0) { 283 LOG(WARNING) << "Failed to rollback " << to; 284 } 285 } 286 return -1; 287 } 288 289 int make_user_config(userid_t userid) 290 { 291 if (ensure_config_user_dirs(userid) == -1) { 292 return -1; 293 } 294 295 return 0; 296 } 297 298 int delete_user(const char *uuid, userid_t userid) 299 { 300 int status = 0; 301 302 std::string data_path(create_data_user_path(uuid, userid)); 303 if (delete_dir_contents(data_path.c_str(), 1, NULL) != 0) { 304 status = -1; 305 } 306 307 std::string media_path(create_data_media_path(uuid, userid)); 308 if (delete_dir_contents(media_path.c_str(), 1, NULL) != 0) { 309 status = -1; 310 } 311 312 // Config paths only exist on internal storage 313 if (uuid == nullptr) { 314 char config_path[PATH_MAX]; 315 if ((create_user_config_path(config_path, userid) != 0) 316 || (delete_dir_contents(config_path, 1, NULL) != 0)) { 317 status = -1; 318 } 319 } 320 321 return status; 322 } 323 324 int delete_cache(const char *uuid, const char *pkgname, userid_t userid) 325 { 326 std::string _cachedir( 327 create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX); 328 const char* cachedir = _cachedir.c_str(); 329 330 /* delete contents, not the directory, no exceptions */ 331 return delete_dir_contents(cachedir, 0, NULL); 332 } 333 334 int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid) 335 { 336 std::string _codecachedir( 337 create_data_user_package_path(uuid, userid, pkgname) + CODE_CACHE_DIR_POSTFIX); 338 const char* codecachedir = _codecachedir.c_str(); 339 340 struct stat s; 341 342 /* it's okay if code cache is missing */ 343 if (lstat(codecachedir, &s) == -1 && errno == ENOENT) { 344 return 0; 345 } 346 347 /* delete contents, not the directory, no exceptions */ 348 return delete_dir_contents(codecachedir, 0, NULL); 349 } 350 351 /* Try to ensure free_size bytes of storage are available. 352 * Returns 0 on success. 353 * This is rather simple-minded because doing a full LRU would 354 * be potentially memory-intensive, and without atime it would 355 * also require that apps constantly modify file metadata even 356 * when just reading from the cache, which is pretty awful. 357 */ 358 int free_cache(const char *uuid, int64_t free_size) 359 { 360 cache_t* cache; 361 int64_t avail; 362 DIR *d; 363 struct dirent *de; 364 char tmpdir[PATH_MAX]; 365 char *dirpos; 366 367 std::string data_path(create_data_path(uuid)); 368 369 avail = data_disk_free(data_path); 370 if (avail < 0) return -1; 371 372 ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail); 373 if (avail >= free_size) return 0; 374 375 cache = start_cache_collection(); 376 377 // Special case for owner on internal storage 378 if (uuid == nullptr) { 379 std::string _tmpdir(create_data_user_path(nullptr, 0)); 380 add_cache_files(cache, _tmpdir.c_str(), "cache"); 381 } 382 383 // Search for other users and add any cache files from them. 384 std::string _tmpdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX); 385 strcpy(tmpdir, _tmpdir.c_str()); 386 387 dirpos = tmpdir + strlen(tmpdir); 388 d = opendir(tmpdir); 389 if (d != NULL) { 390 while ((de = readdir(d))) { 391 if (de->d_type == DT_DIR) { 392 const char *name = de->d_name; 393 /* always skip "." and ".." */ 394 if (name[0] == '.') { 395 if (name[1] == 0) continue; 396 if ((name[1] == '.') && (name[2] == 0)) continue; 397 } 398 if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) { 399 strcpy(dirpos, name); 400 //ALOGI("adding cache files from %s\n", tmpdir); 401 add_cache_files(cache, tmpdir, "cache"); 402 } else { 403 ALOGW("Path exceeds limit: %s%s", tmpdir, name); 404 } 405 } 406 } 407 closedir(d); 408 } 409 410 // Collect cache files on external storage for all users (if it is mounted as part 411 // of the internal storage). 412 strcpy(tmpdir, android_media_dir.path); 413 dirpos = tmpdir + strlen(tmpdir); 414 d = opendir(tmpdir); 415 if (d != NULL) { 416 while ((de = readdir(d))) { 417 if (de->d_type == DT_DIR) { 418 const char *name = de->d_name; 419 /* skip any dir that doesn't start with a number, so not a user */ 420 if (name[0] < '0' || name[0] > '9') { 421 continue; 422 } 423 if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) { 424 strcpy(dirpos, name); 425 if (lookup_media_dir(tmpdir, "Android") == 0 426 && lookup_media_dir(tmpdir, "data") == 0) { 427 //ALOGI("adding cache files from %s\n", tmpdir); 428 add_cache_files(cache, tmpdir, "cache"); 429 } 430 } else { 431 ALOGW("Path exceeds limit: %s%s", tmpdir, name); 432 } 433 } 434 } 435 closedir(d); 436 } 437 438 clear_cache_files(data_path, cache, free_size); 439 finish_cache_collection(cache); 440 441 return data_disk_free(data_path) >= free_size ? 0 : -1; 442 } 443 444 int move_dex(const char *src, const char *dst, const char *instruction_set) 445 { 446 char src_dex[PKG_PATH_MAX]; 447 char dst_dex[PKG_PATH_MAX]; 448 449 if (validate_apk_path(src)) { 450 ALOGE("invalid apk path '%s' (bad prefix)\n", src); 451 return -1; 452 } 453 if (validate_apk_path(dst)) { 454 ALOGE("invalid apk path '%s' (bad prefix)\n", dst); 455 return -1; 456 } 457 458 if (create_cache_path(src_dex, src, instruction_set)) return -1; 459 if (create_cache_path(dst_dex, dst, instruction_set)) return -1; 460 461 ALOGV("move %s -> %s\n", src_dex, dst_dex); 462 if (rename(src_dex, dst_dex) < 0) { 463 ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno)); 464 return -1; 465 } else { 466 return 0; 467 } 468 } 469 470 int rm_dex(const char *path, const char *instruction_set) 471 { 472 char dex_path[PKG_PATH_MAX]; 473 474 if (validate_apk_path(path) && validate_system_app_path(path)) { 475 ALOGE("invalid apk path '%s' (bad prefix)\n", path); 476 return -1; 477 } 478 479 if (create_cache_path(dex_path, path, instruction_set)) return -1; 480 481 ALOGV("unlink %s\n", dex_path); 482 if (unlink(dex_path) < 0) { 483 if (errno != ENOENT) { 484 ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno)); 485 } 486 return -1; 487 } else { 488 return 0; 489 } 490 } 491 492 int get_size(const char *uuid, const char *pkgname, int userid, const char *apkpath, 493 const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath, 494 const char *instruction_set, int64_t *_codesize, int64_t *_datasize, 495 int64_t *_cachesize, int64_t* _asecsize) 496 { 497 DIR *d; 498 int dfd; 499 struct dirent *de; 500 struct stat s; 501 char path[PKG_PATH_MAX]; 502 503 int64_t codesize = 0; 504 int64_t datasize = 0; 505 int64_t cachesize = 0; 506 int64_t asecsize = 0; 507 508 /* count the source apk as code -- but only if it's not 509 * on the /system partition and its not on the sdcard. */ 510 if (validate_system_app_path(apkpath) && 511 strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) { 512 if (stat(apkpath, &s) == 0) { 513 codesize += stat_size(&s); 514 if (S_ISDIR(s.st_mode)) { 515 d = opendir(apkpath); 516 if (d != NULL) { 517 dfd = dirfd(d); 518 codesize += calculate_dir_size(dfd); 519 closedir(d); 520 } 521 } 522 } 523 } 524 525 /* count the forward locked apk as code if it is given */ 526 if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') { 527 if (stat(fwdlock_apkpath, &s) == 0) { 528 codesize += stat_size(&s); 529 } 530 } 531 532 /* count the cached dexfile as code */ 533 if (!create_cache_path(path, apkpath, instruction_set)) { 534 if (stat(path, &s) == 0) { 535 codesize += stat_size(&s); 536 } 537 } 538 539 /* add in size of any libraries */ 540 if (libdirpath != NULL && libdirpath[0] != '!') { 541 d = opendir(libdirpath); 542 if (d != NULL) { 543 dfd = dirfd(d); 544 codesize += calculate_dir_size(dfd); 545 closedir(d); 546 } 547 } 548 549 /* compute asec size if it is given */ 550 if (asecpath != NULL && asecpath[0] != '!') { 551 if (stat(asecpath, &s) == 0) { 552 asecsize += stat_size(&s); 553 } 554 } 555 556 std::vector<userid_t> users; 557 if (userid == -1) { 558 users = get_known_users(uuid); 559 } else { 560 users.push_back(userid); 561 } 562 563 for (auto user : users) { 564 std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname)); 565 const char* pkgdir = _pkgdir.c_str(); 566 567 d = opendir(pkgdir); 568 if (d == NULL) { 569 PLOG(WARNING) << "Failed to open " << pkgdir; 570 continue; 571 } 572 dfd = dirfd(d); 573 574 /* most stuff in the pkgdir is data, except for the "cache" 575 * directory and below, which is cache, and the "lib" directory 576 * and below, which is code... 577 */ 578 while ((de = readdir(d))) { 579 const char *name = de->d_name; 580 581 if (de->d_type == DT_DIR) { 582 int subfd; 583 int64_t statsize = 0; 584 int64_t dirsize = 0; 585 /* always skip "." and ".." */ 586 if (name[0] == '.') { 587 if (name[1] == 0) continue; 588 if ((name[1] == '.') && (name[2] == 0)) continue; 589 } 590 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 591 statsize = stat_size(&s); 592 } 593 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 594 if (subfd >= 0) { 595 dirsize = calculate_dir_size(subfd); 596 } 597 if(!strcmp(name,"lib")) { 598 codesize += dirsize + statsize; 599 } else if(!strcmp(name,"cache")) { 600 cachesize += dirsize + statsize; 601 } else { 602 datasize += dirsize + statsize; 603 } 604 } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) { 605 // This is the symbolic link to the application's library 606 // code. We'll count this as code instead of data, since 607 // it is not something that the app creates. 608 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 609 codesize += stat_size(&s); 610 } 611 } else { 612 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 613 datasize += stat_size(&s); 614 } 615 } 616 } 617 closedir(d); 618 } 619 *_codesize = codesize; 620 *_datasize = datasize; 621 *_cachesize = cachesize; 622 *_asecsize = asecsize; 623 return 0; 624 } 625 626 int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) 627 { 628 char *tmp; 629 int srclen; 630 int dstlen; 631 632 srclen = strlen(src); 633 634 /* demand that we are an absolute path */ 635 if ((src == 0) || (src[0] != '/') || strstr(src,"..")) { 636 return -1; 637 } 638 639 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX? 640 return -1; 641 } 642 643 dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) + 644 strlen(instruction_set) + 645 strlen(DALVIK_CACHE_POSTFIX) + 2; 646 647 if (dstlen > PKG_PATH_MAX) { 648 return -1; 649 } 650 651 sprintf(path,"%s%s/%s%s", 652 DALVIK_CACHE_PREFIX, 653 instruction_set, 654 src + 1, /* skip the leading / */ 655 DALVIK_CACHE_POSTFIX); 656 657 for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) { 658 if (*tmp == '/') { 659 *tmp = '@'; 660 } 661 } 662 663 return 0; 664 } 665 666 static int split_count(const char *str) 667 { 668 char *ctx; 669 int count = 0; 670 char buf[PROPERTY_VALUE_MAX]; 671 672 strncpy(buf, str, sizeof(buf)); 673 char *pBuf = buf; 674 675 while(strtok_r(pBuf, " ", &ctx) != NULL) { 676 count++; 677 pBuf = NULL; 678 } 679 680 return count; 681 } 682 683 static int split(char *buf, const char **argv) 684 { 685 char *ctx; 686 int count = 0; 687 char *tok; 688 char *pBuf = buf; 689 690 while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) { 691 argv[count++] = tok; 692 pBuf = NULL; 693 } 694 695 return count; 696 } 697 698 static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name, 699 const char* output_file_name, const char *pkgname __unused, const char *instruction_set) 700 { 701 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig 702 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7; 703 704 static const char* PATCHOAT_BIN = "/system/bin/patchoat"; 705 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) { 706 ALOGE("Instruction set %s longer than max length of %d", 707 instruction_set, MAX_INSTRUCTION_SET_LEN); 708 return; 709 } 710 711 /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/ 712 char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; 713 char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN]; 714 char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN]; 715 const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art"; 716 // The caller has already gotten all the locks we need. 717 const char* no_lock_arg = "--no-lock-output"; 718 sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); 719 sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd); 720 sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd); 721 ALOGV("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n", 722 PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name); 723 724 /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */ 725 char* argv[7]; 726 argv[0] = (char*) PATCHOAT_BIN; 727 argv[1] = (char*) patched_image_location_arg; 728 argv[2] = (char*) no_lock_arg; 729 argv[3] = instruction_set_arg; 730 argv[4] = output_oat_fd_arg; 731 argv[5] = input_oat_fd_arg; 732 argv[6] = NULL; 733 734 execv(PATCHOAT_BIN, (char* const *)argv); 735 ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno)); 736 } 737 738 static bool check_boolean_property(const char* property_name, bool default_value = false) { 739 char tmp_property_value[PROPERTY_VALUE_MAX]; 740 bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0; 741 if (!have_property) { 742 return default_value; 743 } 744 return strcmp(tmp_property_value, "true") == 0; 745 } 746 747 static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name, 748 const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set, 749 bool vm_safe_mode, bool debuggable) 750 { 751 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7; 752 753 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) { 754 ALOGE("Instruction set %s longer than max length of %d", 755 instruction_set, MAX_INSTRUCTION_SET_LEN); 756 return; 757 } 758 759 char prop_buf[PROPERTY_VALUE_MAX]; 760 bool profiler = (property_get("dalvik.vm.profiler", prop_buf, "0") > 0) && (prop_buf[0] == '1'); 761 762 char dex2oat_Xms_flag[PROPERTY_VALUE_MAX]; 763 bool have_dex2oat_Xms_flag = property_get("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0; 764 765 char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX]; 766 bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0; 767 768 char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX]; 769 bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter", 770 dex2oat_compiler_filter_flag, NULL) > 0; 771 772 char dex2oat_threads_buf[PROPERTY_VALUE_MAX]; 773 bool have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads", dex2oat_threads_buf, 774 NULL) > 0; 775 char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2]; 776 if (have_dex2oat_threads_flag) { 777 sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf); 778 } 779 780 char dex2oat_isa_features_key[PROPERTY_KEY_MAX]; 781 sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set); 782 char dex2oat_isa_features[PROPERTY_VALUE_MAX]; 783 bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key, 784 dex2oat_isa_features, NULL) > 0; 785 786 char dex2oat_isa_variant_key[PROPERTY_KEY_MAX]; 787 sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set); 788 char dex2oat_isa_variant[PROPERTY_VALUE_MAX]; 789 bool have_dex2oat_isa_variant = property_get(dex2oat_isa_variant_key, 790 dex2oat_isa_variant, NULL) > 0; 791 792 const char *dex2oat_norelocation = "-Xnorelocate"; 793 bool have_dex2oat_relocation_skip_flag = false; 794 795 char dex2oat_flags[PROPERTY_VALUE_MAX]; 796 int dex2oat_flags_count = property_get("dalvik.vm.dex2oat-flags", 797 dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags); 798 ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags); 799 800 // If we booting without the real /data, don't spend time compiling. 801 char vold_decrypt[PROPERTY_VALUE_MAX]; 802 bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0; 803 bool skip_compilation = (have_vold_decrypt && 804 (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 || 805 (strcmp(vold_decrypt, "1") == 0))); 806 807 bool use_jit = check_boolean_property("debug.usejit"); 808 bool generate_debug_info = check_boolean_property("debug.generate-debug-info"); 809 810 static const char* DEX2OAT_BIN = "/system/bin/dex2oat"; 811 812 static const char* RUNTIME_ARG = "--runtime-arg"; 813 814 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig 815 816 char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN]; 817 char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX]; 818 char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN]; 819 char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX]; 820 char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; 821 char instruction_set_variant_arg[strlen("--instruction-set-variant=") + PROPERTY_VALUE_MAX]; 822 char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX]; 823 char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX]; 824 char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX]; 825 char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX]; 826 char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX]; 827 char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX]; 828 bool have_dex2oat_swap_fd = false; 829 char dex2oat_swap_fd[strlen("--swap-fd=") + MAX_INT_LEN]; 830 831 sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd); 832 sprintf(zip_location_arg, "--zip-location=%s", input_file_name); 833 sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd); 834 sprintf(oat_location_arg, "--oat-location=%s", output_file_name); 835 sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); 836 sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant); 837 sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features); 838 if (swap_fd >= 0) { 839 have_dex2oat_swap_fd = true; 840 sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd); 841 } 842 843 bool have_profile_file = false; 844 bool have_top_k_profile_threshold = false; 845 if (profiler && (strcmp(pkgname, "*") != 0)) { 846 char profile_file[PKG_PATH_MAX]; 847 snprintf(profile_file, sizeof(profile_file), "%s/%s", 848 DALVIK_CACHE_PREFIX "profiles", pkgname); 849 struct stat st; 850 if ((stat(profile_file, &st) == 0) && (st.st_size > 0)) { 851 sprintf(profile_file_arg, "--profile-file=%s", profile_file); 852 have_profile_file = true; 853 if (property_get("dalvik.vm.profile.top-k-thr", prop_buf, NULL) > 0) { 854 snprintf(top_k_profile_threshold_arg, sizeof(top_k_profile_threshold_arg), 855 "--top-k-profile-threshold=%s", prop_buf); 856 have_top_k_profile_threshold = true; 857 } 858 } 859 } 860 861 if (have_dex2oat_Xms_flag) { 862 sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag); 863 } 864 if (have_dex2oat_Xmx_flag) { 865 sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag); 866 } 867 if (skip_compilation) { 868 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none"); 869 have_dex2oat_compiler_filter_flag = true; 870 have_dex2oat_relocation_skip_flag = true; 871 } else if (vm_safe_mode) { 872 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only"); 873 have_dex2oat_compiler_filter_flag = true; 874 } else if (use_jit) { 875 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime"); 876 have_dex2oat_compiler_filter_flag = true; 877 } else if (have_dex2oat_compiler_filter_flag) { 878 sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag); 879 } 880 881 // Check whether all apps should be compiled debuggable. 882 if (!debuggable) { 883 debuggable = 884 (property_get("dalvik.vm.always_debuggable", prop_buf, "0") > 0) && 885 (prop_buf[0] == '1'); 886 } 887 888 ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name); 889 890 const char* argv[7 // program name, mandatory arguments and the final NULL 891 + (have_dex2oat_isa_variant ? 1 : 0) 892 + (have_dex2oat_isa_features ? 1 : 0) 893 + (have_profile_file ? 1 : 0) 894 + (have_top_k_profile_threshold ? 1 : 0) 895 + (have_dex2oat_Xms_flag ? 2 : 0) 896 + (have_dex2oat_Xmx_flag ? 2 : 0) 897 + (have_dex2oat_compiler_filter_flag ? 1 : 0) 898 + (have_dex2oat_threads_flag ? 1 : 0) 899 + (have_dex2oat_swap_fd ? 1 : 0) 900 + (have_dex2oat_relocation_skip_flag ? 2 : 0) 901 + (generate_debug_info ? 1 : 0) 902 + (debuggable ? 1 : 0) 903 + dex2oat_flags_count]; 904 int i = 0; 905 argv[i++] = DEX2OAT_BIN; 906 argv[i++] = zip_fd_arg; 907 argv[i++] = zip_location_arg; 908 argv[i++] = oat_fd_arg; 909 argv[i++] = oat_location_arg; 910 argv[i++] = instruction_set_arg; 911 if (have_dex2oat_isa_variant) { 912 argv[i++] = instruction_set_variant_arg; 913 } 914 if (have_dex2oat_isa_features) { 915 argv[i++] = instruction_set_features_arg; 916 } 917 if (have_profile_file) { 918 argv[i++] = profile_file_arg; 919 } 920 if (have_top_k_profile_threshold) { 921 argv[i++] = top_k_profile_threshold_arg; 922 } 923 if (have_dex2oat_Xms_flag) { 924 argv[i++] = RUNTIME_ARG; 925 argv[i++] = dex2oat_Xms_arg; 926 } 927 if (have_dex2oat_Xmx_flag) { 928 argv[i++] = RUNTIME_ARG; 929 argv[i++] = dex2oat_Xmx_arg; 930 } 931 if (have_dex2oat_compiler_filter_flag) { 932 argv[i++] = dex2oat_compiler_filter_arg; 933 } 934 if (have_dex2oat_threads_flag) { 935 argv[i++] = dex2oat_threads_arg; 936 } 937 if (have_dex2oat_swap_fd) { 938 argv[i++] = dex2oat_swap_fd; 939 } 940 if (generate_debug_info) { 941 argv[i++] = "--generate-debug-info"; 942 } 943 if (debuggable) { 944 argv[i++] = "--debuggable"; 945 } 946 if (dex2oat_flags_count) { 947 i += split(dex2oat_flags, argv + i); 948 } 949 if (have_dex2oat_relocation_skip_flag) { 950 argv[i++] = RUNTIME_ARG; 951 argv[i++] = dex2oat_norelocation; 952 } 953 // Do not add after dex2oat_flags, they should override others for debugging. 954 argv[i] = NULL; 955 956 execv(DEX2OAT_BIN, (char * const *)argv); 957 ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno)); 958 } 959 960 static int wait_child(pid_t pid) 961 { 962 int status; 963 pid_t got_pid; 964 965 while (1) { 966 got_pid = waitpid(pid, &status, 0); 967 if (got_pid == -1 && errno == EINTR) { 968 printf("waitpid interrupted, retrying\n"); 969 } else { 970 break; 971 } 972 } 973 if (got_pid != pid) { 974 ALOGW("waitpid failed: wanted %d, got %d: %s\n", 975 (int) pid, (int) got_pid, strerror(errno)); 976 return 1; 977 } 978 979 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 980 return 0; 981 } else { 982 return status; /* always nonzero */ 983 } 984 } 985 986 /* 987 * Whether dexopt should use a swap file when compiling an APK. 988 * 989 * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision 990 * itself, anyways). 991 * 992 * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true". 993 * 994 * Otherwise, return true if this is a low-mem device. 995 * 996 * Otherwise, return default value. 997 */ 998 static bool kAlwaysProvideSwapFile = false; 999 static bool kDefaultProvideSwapFile = true; 1000 1001 static bool ShouldUseSwapFileForDexopt() { 1002 if (kAlwaysProvideSwapFile) { 1003 return true; 1004 } 1005 1006 // Check the "override" property. If it exists, return value == "true". 1007 char dex2oat_prop_buf[PROPERTY_VALUE_MAX]; 1008 if (property_get("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) { 1009 if (strcmp(dex2oat_prop_buf, "true") == 0) { 1010 return true; 1011 } else { 1012 return false; 1013 } 1014 } 1015 1016 // Shortcut for default value. This is an implementation optimization for the process sketched 1017 // above. If the default value is true, we can avoid to check whether this is a low-mem device, 1018 // as low-mem is never returning false. The compiler will optimize this away if it can. 1019 if (kDefaultProvideSwapFile) { 1020 return true; 1021 } 1022 1023 bool is_low_mem = check_boolean_property("ro.config.low_ram"); 1024 if (is_low_mem) { 1025 return true; 1026 } 1027 1028 // Default value must be false here. 1029 return kDefaultProvideSwapFile; 1030 } 1031 1032 /* 1033 * Computes the odex file for the given apk_path and instruction_set. 1034 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex 1035 * 1036 * Returns false if it failed to determine the odex file path. 1037 */ 1038 static bool calculate_odex_file_path(char path[PKG_PATH_MAX], 1039 const char *apk_path, 1040 const char *instruction_set) 1041 { 1042 if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set) 1043 + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) { 1044 ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path); 1045 return false; 1046 } 1047 1048 strcpy(path, apk_path); 1049 char *end = strrchr(path, '/'); 1050 if (end == NULL) { 1051 ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path); 1052 return false; 1053 } 1054 const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/'); 1055 1056 strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0 1057 strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0 1058 strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0 1059 end = strrchr(path, '.'); 1060 if (end == NULL) { 1061 ALOGE("apk_path '%s' has no extension.\n", apk_path); 1062 return false; 1063 } 1064 strcpy(end + 1, "odex"); 1065 return true; 1066 } 1067 1068 int dexopt(const char *apk_path, uid_t uid, bool is_public, 1069 const char *pkgname, const char *instruction_set, int dexopt_needed, 1070 bool vm_safe_mode, bool debuggable, const char* oat_dir) 1071 { 1072 struct utimbuf ut; 1073 struct stat input_stat; 1074 char out_path[PKG_PATH_MAX]; 1075 char swap_file_name[PKG_PATH_MAX]; 1076 const char *input_file; 1077 char in_odex_path[PKG_PATH_MAX]; 1078 int res, input_fd=-1, out_fd=-1, swap_fd=-1; 1079 1080 // Early best-effort check whether we can fit the the path into our buffers. 1081 // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run 1082 // without a swap file, if necessary. 1083 if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) { 1084 ALOGE("apk_path too long '%s'\n", apk_path); 1085 return -1; 1086 } 1087 1088 if (oat_dir != NULL && oat_dir[0] != '!') { 1089 if (validate_apk_path(oat_dir)) { 1090 ALOGE("invalid oat_dir '%s'\n", oat_dir); 1091 return -1; 1092 } 1093 if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) { 1094 return -1; 1095 } 1096 } else { 1097 if (create_cache_path(out_path, apk_path, instruction_set)) { 1098 return -1; 1099 } 1100 } 1101 1102 switch (dexopt_needed) { 1103 case DEXOPT_DEX2OAT_NEEDED: 1104 input_file = apk_path; 1105 break; 1106 1107 case DEXOPT_PATCHOAT_NEEDED: 1108 if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) { 1109 return -1; 1110 } 1111 input_file = in_odex_path; 1112 break; 1113 1114 case DEXOPT_SELF_PATCHOAT_NEEDED: 1115 input_file = out_path; 1116 break; 1117 1118 default: 1119 ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); 1120 exit(72); 1121 } 1122 1123 memset(&input_stat, 0, sizeof(input_stat)); 1124 stat(input_file, &input_stat); 1125 1126 input_fd = open(input_file, O_RDONLY, 0); 1127 if (input_fd < 0) { 1128 ALOGE("installd cannot open '%s' for input during dexopt\n", input_file); 1129 return -1; 1130 } 1131 1132 unlink(out_path); 1133 out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644); 1134 if (out_fd < 0) { 1135 ALOGE("installd cannot open '%s' for output during dexopt\n", out_path); 1136 goto fail; 1137 } 1138 if (fchmod(out_fd, 1139 S_IRUSR|S_IWUSR|S_IRGRP | 1140 (is_public ? S_IROTH : 0)) < 0) { 1141 ALOGE("installd cannot chmod '%s' during dexopt\n", out_path); 1142 goto fail; 1143 } 1144 if (fchown(out_fd, AID_SYSTEM, uid) < 0) { 1145 ALOGE("installd cannot chown '%s' during dexopt\n", out_path); 1146 goto fail; 1147 } 1148 1149 // Create profile file if there is a package name present. 1150 if (strcmp(pkgname, "*") != 0) { 1151 create_profile_file(pkgname, uid); 1152 } 1153 1154 // Create a swap file if necessary. 1155 if (ShouldUseSwapFileForDexopt()) { 1156 // Make sure there really is enough space. 1157 size_t out_len = strlen(out_path); 1158 if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) { 1159 strcpy(swap_file_name, out_path); 1160 strcpy(swap_file_name + strlen(out_path), ".swap"); 1161 unlink(swap_file_name); 1162 swap_fd = open(swap_file_name, O_RDWR | O_CREAT | O_EXCL, 0600); 1163 if (swap_fd < 0) { 1164 // Could not create swap file. Optimistically go on and hope that we can compile 1165 // without it. 1166 ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name); 1167 } else { 1168 // Immediately unlink. We don't really want to hit flash. 1169 unlink(swap_file_name); 1170 } 1171 } else { 1172 // Swap file path is too long. Try to run without. 1173 ALOGE("installd could not create swap file for path %s during dexopt\n", out_path); 1174 } 1175 } 1176 1177 ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file); 1178 1179 pid_t pid; 1180 pid = fork(); 1181 if (pid == 0) { 1182 /* child -- drop privileges before continuing */ 1183 if (setgid(uid) != 0) { 1184 ALOGE("setgid(%d) failed in installd during dexopt\n", uid); 1185 exit(64); 1186 } 1187 if (setuid(uid) != 0) { 1188 ALOGE("setuid(%d) failed in installd during dexopt\n", uid); 1189 exit(65); 1190 } 1191 // drop capabilities 1192 struct __user_cap_header_struct capheader; 1193 struct __user_cap_data_struct capdata[2]; 1194 memset(&capheader, 0, sizeof(capheader)); 1195 memset(&capdata, 0, sizeof(capdata)); 1196 capheader.version = _LINUX_CAPABILITY_VERSION_3; 1197 if (capset(&capheader, &capdata[0]) < 0) { 1198 ALOGE("capset failed: %s\n", strerror(errno)); 1199 exit(66); 1200 } 1201 if (set_sched_policy(0, SP_BACKGROUND) < 0) { 1202 ALOGE("set_sched_policy failed: %s\n", strerror(errno)); 1203 exit(70); 1204 } 1205 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) { 1206 ALOGE("setpriority failed: %s\n", strerror(errno)); 1207 exit(71); 1208 } 1209 if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) { 1210 ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno)); 1211 exit(67); 1212 } 1213 1214 if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED 1215 || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) { 1216 run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set); 1217 } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) { 1218 const char *input_file_name = strrchr(input_file, '/'); 1219 if (input_file_name == NULL) { 1220 input_file_name = input_file; 1221 } else { 1222 input_file_name++; 1223 } 1224 run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname, 1225 instruction_set, vm_safe_mode, debuggable); 1226 } else { 1227 ALOGE("Invalid dexopt needed: %d\n", dexopt_needed); 1228 exit(73); 1229 } 1230 exit(68); /* only get here on exec failure */ 1231 } else { 1232 res = wait_child(pid); 1233 if (res == 0) { 1234 ALOGV("DexInv: --- END '%s' (success) ---\n", input_file); 1235 } else { 1236 ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res); 1237 goto fail; 1238 } 1239 } 1240 1241 ut.actime = input_stat.st_atime; 1242 ut.modtime = input_stat.st_mtime; 1243 utime(out_path, &ut); 1244 1245 close(out_fd); 1246 close(input_fd); 1247 if (swap_fd != -1) { 1248 close(swap_fd); 1249 } 1250 return 0; 1251 1252 fail: 1253 if (out_fd >= 0) { 1254 close(out_fd); 1255 unlink(out_path); 1256 } 1257 if (input_fd >= 0) { 1258 close(input_fd); 1259 } 1260 return -1; 1261 } 1262 1263 int mark_boot_complete(const char* instruction_set) 1264 { 1265 char boot_marker_path[PKG_PATH_MAX]; 1266 sprintf(boot_marker_path,"%s%s/.booting", DALVIK_CACHE_PREFIX, instruction_set); 1267 1268 ALOGV("mark_boot_complete : %s", boot_marker_path); 1269 if (unlink(boot_marker_path) != 0) { 1270 ALOGE("Unable to unlink boot marker at %s, error=%s", boot_marker_path, 1271 strerror(errno)); 1272 return -1; 1273 } 1274 1275 return 0; 1276 } 1277 1278 void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid, 1279 struct stat* statbuf) 1280 { 1281 while (path[basepos] != 0) { 1282 if (path[basepos] == '/') { 1283 path[basepos] = 0; 1284 if (lstat(path, statbuf) < 0) { 1285 ALOGV("Making directory: %s\n", path); 1286 if (mkdir(path, mode) == 0) { 1287 chown(path, uid, gid); 1288 } else { 1289 ALOGW("Unable to make directory %s: %s\n", path, strerror(errno)); 1290 } 1291 } 1292 path[basepos] = '/'; 1293 basepos++; 1294 } 1295 basepos++; 1296 } 1297 } 1298 1299 int movefileordir(char* srcpath, char* dstpath, int dstbasepos, 1300 int dstuid, int dstgid, struct stat* statbuf) 1301 { 1302 DIR *d; 1303 struct dirent *de; 1304 int res; 1305 1306 int srcend = strlen(srcpath); 1307 int dstend = strlen(dstpath); 1308 1309 if (lstat(srcpath, statbuf) < 0) { 1310 ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno)); 1311 return 1; 1312 } 1313 1314 if ((statbuf->st_mode&S_IFDIR) == 0) { 1315 mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH, 1316 dstuid, dstgid, statbuf); 1317 ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid); 1318 if (rename(srcpath, dstpath) >= 0) { 1319 if (chown(dstpath, dstuid, dstgid) < 0) { 1320 ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno)); 1321 unlink(dstpath); 1322 return 1; 1323 } 1324 } else { 1325 ALOGW("Unable to rename %s to %s: %s\n", 1326 srcpath, dstpath, strerror(errno)); 1327 return 1; 1328 } 1329 return 0; 1330 } 1331 1332 d = opendir(srcpath); 1333 if (d == NULL) { 1334 ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno)); 1335 return 1; 1336 } 1337 1338 res = 0; 1339 1340 while ((de = readdir(d))) { 1341 const char *name = de->d_name; 1342 /* always skip "." and ".." */ 1343 if (name[0] == '.') { 1344 if (name[1] == 0) continue; 1345 if ((name[1] == '.') && (name[2] == 0)) continue; 1346 } 1347 1348 if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) { 1349 ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name); 1350 continue; 1351 } 1352 1353 if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) { 1354 ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name); 1355 continue; 1356 } 1357 1358 srcpath[srcend] = dstpath[dstend] = '/'; 1359 strcpy(srcpath+srcend+1, name); 1360 strcpy(dstpath+dstend+1, name); 1361 1362 if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) { 1363 res = 1; 1364 } 1365 1366 // Note: we will be leaving empty directories behind in srcpath, 1367 // but that is okay, the package manager will be erasing all of the 1368 // data associated with .apks that disappear. 1369 1370 srcpath[srcend] = dstpath[dstend] = 0; 1371 } 1372 1373 closedir(d); 1374 return res; 1375 } 1376 1377 int movefiles() 1378 { 1379 DIR *d; 1380 int dfd, subfd; 1381 struct dirent *de; 1382 struct stat s; 1383 char buf[PKG_PATH_MAX+1]; 1384 int bufp, bufe, bufi, readlen; 1385 1386 char srcpkg[PKG_NAME_MAX]; 1387 char dstpkg[PKG_NAME_MAX]; 1388 char srcpath[PKG_PATH_MAX]; 1389 char dstpath[PKG_PATH_MAX]; 1390 int dstuid=-1, dstgid=-1; 1391 int hasspace; 1392 1393 d = opendir(UPDATE_COMMANDS_DIR_PREFIX); 1394 if (d == NULL) { 1395 goto done; 1396 } 1397 dfd = dirfd(d); 1398 1399 /* Iterate through all files in the directory, executing the 1400 * file movements requested there-in. 1401 */ 1402 while ((de = readdir(d))) { 1403 const char *name = de->d_name; 1404 1405 if (de->d_type == DT_DIR) { 1406 continue; 1407 } else { 1408 subfd = openat(dfd, name, O_RDONLY); 1409 if (subfd < 0) { 1410 ALOGW("Unable to open update commands at %s%s\n", 1411 UPDATE_COMMANDS_DIR_PREFIX, name); 1412 continue; 1413 } 1414 1415 bufp = 0; 1416 bufe = 0; 1417 buf[PKG_PATH_MAX] = 0; 1418 srcpkg[0] = dstpkg[0] = 0; 1419 while (1) { 1420 bufi = bufp; 1421 while (bufi < bufe && buf[bufi] != '\n') { 1422 bufi++; 1423 } 1424 if (bufi < bufe) { 1425 buf[bufi] = 0; 1426 ALOGV("Processing line: %s\n", buf+bufp); 1427 hasspace = 0; 1428 while (bufp < bufi && isspace(buf[bufp])) { 1429 hasspace = 1; 1430 bufp++; 1431 } 1432 if (buf[bufp] == '#' || bufp == bufi) { 1433 // skip comments and empty lines. 1434 } else if (hasspace) { 1435 if (dstpkg[0] == 0) { 1436 ALOGW("Path before package line in %s%s: %s\n", 1437 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 1438 } else if (srcpkg[0] == 0) { 1439 // Skip -- source package no longer exists. 1440 } else { 1441 ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg); 1442 if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) && 1443 !create_move_path(dstpath, dstpkg, buf+bufp, 0)) { 1444 movefileordir(srcpath, dstpath, 1445 strlen(dstpath)-strlen(buf+bufp), 1446 dstuid, dstgid, &s); 1447 } 1448 } 1449 } else { 1450 char* div = strchr(buf+bufp, ':'); 1451 if (div == NULL) { 1452 ALOGW("Bad package spec in %s%s; no ':' sep: %s\n", 1453 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 1454 } else { 1455 *div = 0; 1456 div++; 1457 if (strlen(buf+bufp) < PKG_NAME_MAX) { 1458 strcpy(dstpkg, buf+bufp); 1459 } else { 1460 srcpkg[0] = dstpkg[0] = 0; 1461 ALOGW("Package name too long in %s%s: %s\n", 1462 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp); 1463 } 1464 if (strlen(div) < PKG_NAME_MAX) { 1465 strcpy(srcpkg, div); 1466 } else { 1467 srcpkg[0] = dstpkg[0] = 0; 1468 ALOGW("Package name too long in %s%s: %s\n", 1469 UPDATE_COMMANDS_DIR_PREFIX, name, div); 1470 } 1471 if (srcpkg[0] != 0) { 1472 if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) { 1473 if (lstat(srcpath, &s) < 0) { 1474 // Package no longer exists -- skip. 1475 srcpkg[0] = 0; 1476 } 1477 } else { 1478 srcpkg[0] = 0; 1479 ALOGW("Can't create path %s in %s%s\n", 1480 div, UPDATE_COMMANDS_DIR_PREFIX, name); 1481 } 1482 if (srcpkg[0] != 0) { 1483 if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) { 1484 if (lstat(dstpath, &s) == 0) { 1485 dstuid = s.st_uid; 1486 dstgid = s.st_gid; 1487 } else { 1488 // Destination package doesn't 1489 // exist... due to original-package, 1490 // this is normal, so don't be 1491 // noisy about it. 1492 srcpkg[0] = 0; 1493 } 1494 } else { 1495 srcpkg[0] = 0; 1496 ALOGW("Can't create path %s in %s%s\n", 1497 div, UPDATE_COMMANDS_DIR_PREFIX, name); 1498 } 1499 } 1500 ALOGV("Transfering from %s to %s: uid=%d\n", 1501 srcpkg, dstpkg, dstuid); 1502 } 1503 } 1504 } 1505 bufp = bufi+1; 1506 } else { 1507 if (bufp == 0) { 1508 if (bufp < bufe) { 1509 ALOGW("Line too long in %s%s, skipping: %s\n", 1510 UPDATE_COMMANDS_DIR_PREFIX, name, buf); 1511 } 1512 } else if (bufp < bufe) { 1513 memcpy(buf, buf+bufp, bufe-bufp); 1514 bufe -= bufp; 1515 bufp = 0; 1516 } 1517 readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe); 1518 if (readlen < 0) { 1519 ALOGW("Failure reading update commands in %s%s: %s\n", 1520 UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno)); 1521 break; 1522 } else if (readlen == 0) { 1523 break; 1524 } 1525 bufe += readlen; 1526 buf[bufe] = 0; 1527 ALOGV("Read buf: %s\n", buf); 1528 } 1529 } 1530 close(subfd); 1531 } 1532 } 1533 closedir(d); 1534 done: 1535 return 0; 1536 } 1537 1538 int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId) 1539 { 1540 struct stat s, libStat; 1541 int rc = 0; 1542 1543 std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname)); 1544 std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX); 1545 1546 const char* pkgdir = _pkgdir.c_str(); 1547 const char* libsymlink = _libsymlink.c_str(); 1548 1549 if (stat(pkgdir, &s) < 0) return -1; 1550 1551 if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) { 1552 ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno)); 1553 return -1; 1554 } 1555 1556 if (chmod(pkgdir, 0700) < 0) { 1557 ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno)); 1558 rc = -1; 1559 goto out; 1560 } 1561 1562 if (lstat(libsymlink, &libStat) < 0) { 1563 if (errno != ENOENT) { 1564 ALOGE("couldn't stat lib dir: %s\n", strerror(errno)); 1565 rc = -1; 1566 goto out; 1567 } 1568 } else { 1569 if (S_ISDIR(libStat.st_mode)) { 1570 if (delete_dir_contents(libsymlink, 1, NULL) < 0) { 1571 rc = -1; 1572 goto out; 1573 } 1574 } else if (S_ISLNK(libStat.st_mode)) { 1575 if (unlink(libsymlink) < 0) { 1576 ALOGE("couldn't unlink lib dir: %s\n", strerror(errno)); 1577 rc = -1; 1578 goto out; 1579 } 1580 } 1581 } 1582 1583 if (symlink(asecLibDir, libsymlink) < 0) { 1584 ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir, 1585 strerror(errno)); 1586 rc = -errno; 1587 goto out; 1588 } 1589 1590 out: 1591 if (chmod(pkgdir, s.st_mode) < 0) { 1592 ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno)); 1593 rc = -errno; 1594 } 1595 1596 if (chown(pkgdir, s.st_uid, s.st_gid) < 0) { 1597 ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno)); 1598 return -errno; 1599 } 1600 1601 return rc; 1602 } 1603 1604 static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd) 1605 { 1606 static const char *IDMAP_BIN = "/system/bin/idmap"; 1607 static const size_t MAX_INT_LEN = 32; 1608 char idmap_str[MAX_INT_LEN]; 1609 1610 snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd); 1611 1612 execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL); 1613 ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno)); 1614 } 1615 1616 // Transform string /a/b/c.apk to (prefix)/a@b (at) c.apk@(suffix) 1617 // eg /a/b/c.apk to /data/resource-cache/a@b (at) c.apk@idmap 1618 static int flatten_path(const char *prefix, const char *suffix, 1619 const char *overlay_path, char *idmap_path, size_t N) 1620 { 1621 if (overlay_path == NULL || idmap_path == NULL) { 1622 return -1; 1623 } 1624 const size_t len_overlay_path = strlen(overlay_path); 1625 // will access overlay_path + 1 further below; requires absolute path 1626 if (len_overlay_path < 2 || *overlay_path != '/') { 1627 return -1; 1628 } 1629 const size_t len_idmap_root = strlen(prefix); 1630 const size_t len_suffix = strlen(suffix); 1631 if (SIZE_MAX - len_idmap_root < len_overlay_path || 1632 SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) { 1633 // additions below would cause overflow 1634 return -1; 1635 } 1636 if (N < len_idmap_root + len_overlay_path + len_suffix) { 1637 return -1; 1638 } 1639 memset(idmap_path, 0, N); 1640 snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix); 1641 char *ch = idmap_path + len_idmap_root; 1642 while (*ch != '\0') { 1643 if (*ch == '/') { 1644 *ch = '@'; 1645 } 1646 ++ch; 1647 } 1648 return 0; 1649 } 1650 1651 int idmap(const char *target_apk, const char *overlay_apk, uid_t uid) 1652 { 1653 ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid); 1654 1655 int idmap_fd = -1; 1656 char idmap_path[PATH_MAX]; 1657 1658 if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk, 1659 idmap_path, sizeof(idmap_path)) == -1) { 1660 ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk); 1661 goto fail; 1662 } 1663 1664 unlink(idmap_path); 1665 idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644); 1666 if (idmap_fd < 0) { 1667 ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno)); 1668 goto fail; 1669 } 1670 if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) { 1671 ALOGE("idmap cannot chown '%s'\n", idmap_path); 1672 goto fail; 1673 } 1674 if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) { 1675 ALOGE("idmap cannot chmod '%s'\n", idmap_path); 1676 goto fail; 1677 } 1678 1679 pid_t pid; 1680 pid = fork(); 1681 if (pid == 0) { 1682 /* child -- drop privileges before continuing */ 1683 if (setgid(uid) != 0) { 1684 ALOGE("setgid(%d) failed during idmap\n", uid); 1685 exit(1); 1686 } 1687 if (setuid(uid) != 0) { 1688 ALOGE("setuid(%d) failed during idmap\n", uid); 1689 exit(1); 1690 } 1691 if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) { 1692 ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno)); 1693 exit(1); 1694 } 1695 1696 run_idmap(target_apk, overlay_apk, idmap_fd); 1697 exit(1); /* only if exec call to idmap failed */ 1698 } else { 1699 int status = wait_child(pid); 1700 if (status != 0) { 1701 ALOGE("idmap failed, status=0x%04x\n", status); 1702 goto fail; 1703 } 1704 } 1705 1706 close(idmap_fd); 1707 return 0; 1708 fail: 1709 if (idmap_fd >= 0) { 1710 close(idmap_fd); 1711 unlink(idmap_path); 1712 } 1713 return -1; 1714 } 1715 1716 int restorecon_data(const char* uuid, const char* pkgName, 1717 const char* seinfo, uid_t uid) 1718 { 1719 struct dirent *entry; 1720 DIR *d; 1721 struct stat s; 1722 int ret = 0; 1723 1724 // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here. 1725 unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE; 1726 1727 if (!pkgName || !seinfo) { 1728 ALOGE("Package name or seinfo tag is null when trying to restorecon."); 1729 return -1; 1730 } 1731 1732 // Special case for owner on internal storage 1733 if (uuid == nullptr) { 1734 std::string path(create_data_user_package_path(nullptr, 0, pkgName)); 1735 1736 if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) { 1737 PLOG(ERROR) << "restorecon failed for " << path; 1738 ret |= -1; 1739 } 1740 } 1741 1742 // Relabel package directory for all secondary users. 1743 std::string userdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX); 1744 d = opendir(userdir.c_str()); 1745 if (d == NULL) { 1746 return -1; 1747 } 1748 1749 while ((entry = readdir(d))) { 1750 if (entry->d_type != DT_DIR) { 1751 continue; 1752 } 1753 1754 const char *user = entry->d_name; 1755 // Ignore "." and ".." 1756 if (!strcmp(user, ".") || !strcmp(user, "..")) { 1757 continue; 1758 } 1759 1760 // user directories start with a number 1761 if (user[0] < '0' || user[0] > '9') { 1762 ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user); 1763 continue; 1764 } 1765 1766 std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName)); 1767 if (stat(pkgdir.c_str(), &s) < 0) { 1768 continue; 1769 } 1770 1771 if (selinux_android_restorecon_pkgdir(pkgdir.c_str(), seinfo, s.st_uid, flags) < 0) { 1772 PLOG(ERROR) << "restorecon failed for " << pkgdir; 1773 ret |= -1; 1774 } 1775 } 1776 1777 closedir(d); 1778 return ret; 1779 } 1780 1781 int create_oat_dir(const char* oat_dir, const char* instruction_set) 1782 { 1783 char oat_instr_dir[PKG_PATH_MAX]; 1784 1785 if (validate_apk_path(oat_dir)) { 1786 ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir); 1787 return -1; 1788 } 1789 if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { 1790 return -1; 1791 } 1792 if (selinux_android_restorecon(oat_dir, 0)) { 1793 ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno)); 1794 return -1; 1795 } 1796 snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set); 1797 if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) { 1798 return -1; 1799 } 1800 return 0; 1801 } 1802 1803 int rm_package_dir(const char* apk_path) 1804 { 1805 if (validate_apk_path(apk_path)) { 1806 ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path); 1807 return -1; 1808 } 1809 return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */); 1810 } 1811 1812 int link_file(const char* relative_path, const char* from_base, const char* to_base) { 1813 char from_path[PKG_PATH_MAX]; 1814 char to_path[PKG_PATH_MAX]; 1815 snprintf(from_path, PKG_PATH_MAX, "%s/%s", from_base, relative_path); 1816 snprintf(to_path, PKG_PATH_MAX, "%s/%s", to_base, relative_path); 1817 1818 if (validate_apk_path_subdirs(from_path)) { 1819 ALOGE("invalid app data sub-path '%s' (bad prefix)\n", from_path); 1820 return -1; 1821 } 1822 1823 if (validate_apk_path_subdirs(to_path)) { 1824 ALOGE("invalid app data sub-path '%s' (bad prefix)\n", to_path); 1825 return -1; 1826 } 1827 1828 const int ret = link(from_path, to_path); 1829 if (ret < 0) { 1830 ALOGE("link(%s, %s) failed : %s", from_path, to_path, strerror(errno)); 1831 return -1; 1832 } 1833 1834 return 0; 1835 } 1836 1837 int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, 1838 const char *instruction_set) { 1839 char *file_name_start; 1840 char *file_name_end; 1841 1842 file_name_start = strrchr(apk_path, '/'); 1843 if (file_name_start == NULL) { 1844 ALOGE("apk_path '%s' has no '/'s in it\n", apk_path); 1845 return -1; 1846 } 1847 file_name_end = strrchr(apk_path, '.'); 1848 if (file_name_end < file_name_start) { 1849 ALOGE("apk_path '%s' has no extension\n", apk_path); 1850 return -1; 1851 } 1852 1853 // Calculate file_name 1854 int file_name_len = file_name_end - file_name_start - 1; 1855 char file_name[file_name_len + 1]; 1856 memcpy(file_name, file_name_start + 1, file_name_len); 1857 file_name[file_name_len] = '\0'; 1858 1859 // <apk_parent_dir>/oat/<isa>/<file_name>.odex 1860 snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name); 1861 return 0; 1862 } 1863