Loading cmds/installd/commands.cpp +61 −24 Original line number Diff line number Diff line Loading @@ -790,7 +790,7 @@ static void run_patchoat(int input_oat_fd, int input_vdex_fd, int out_oat_fd, in ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno)); } static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd, const char* input_file_name, const char* output_file_name, int swap_fd, const char *instruction_set, const char* compiler_filter, bool vm_safe_mode, bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) { Loading Loading @@ -874,7 +874,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN]; char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX]; char vdex_fd_arg[strlen("--vdex-fd=") + MAX_INT_LEN]; char input_vdex_fd_arg[strlen("--input-vdex-fd=") + MAX_INT_LEN]; char output_vdex_fd_arg[strlen("--output-vdex-fd=") + MAX_INT_LEN]; char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN]; char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX]; char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; Loading @@ -890,7 +891,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd); sprintf(zip_location_arg, "--zip-location=%s", input_file_name); sprintf(vdex_fd_arg, "--vdex-fd=%d", vdex_fd); sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd); sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd); sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd); sprintf(oat_location_arg, "--oat-location=%s", output_file_name); sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); Loading Loading @@ -953,7 +955,7 @@ static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name); const char* argv[8 // program name, mandatory arguments and the final NULL const char* argv[9 // program name, mandatory arguments and the final NULL + (have_dex2oat_isa_variant ? 1 : 0) + (have_dex2oat_isa_features ? 1 : 0) + (have_dex2oat_Xms_flag ? 2 : 0) Loading @@ -974,7 +976,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, argv[i++] = DEX2OAT_BIN; argv[i++] = zip_fd_arg; argv[i++] = zip_location_arg; argv[i++] = vdex_fd_arg; argv[i++] = input_vdex_fd_arg; argv[i++] = output_vdex_fd_arg; argv[i++] = oat_fd_arg; argv[i++] = oat_location_arg; argv[i++] = instruction_set_arg; Loading Loading @@ -1500,6 +1503,14 @@ static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const return true; } static bool IsOutputDalvikCache(const char* oat_dir) { // InstallerConnection.java (which invokes installd) transforms Java null arguments // into '!'. Play it safe by handling it both. // TODO: ensure we never get null. // TODO: pass a flag instead of inferring if the output is dalvik cache. return oat_dir == nullptr || oat_dir[0] == '!'; } static bool create_oat_out_path(const char* apk_path, const char* instruction_set, const char* oat_dir, /*out*/ char* out_oat_path) { // Early best-effort check whether we can fit the the path into our buffers. Loading @@ -1511,9 +1522,9 @@ static bool create_oat_out_path(const char* apk_path, const char* instruction_se return false; } if (oat_dir != NULL && oat_dir[0] != '!') { if (!IsOutputDalvikCache(oat_dir)) { if (validate_apk_path(oat_dir)) { ALOGE("invalid oat_dir '%s'\n", oat_dir); ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir); return false; } if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) { Loading Loading @@ -1702,34 +1713,59 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins return -1; } // If invoking patchoat, open the VDEX associated with the OAT too. // Create the output OAT file. const std::string out_oat_path_str(out_oat_path); Dex2oatFileWrapper<std::function<void ()>> out_oat_fd( open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644), [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); }); if (out_oat_fd.get() < 0) { ALOGE("installd cannot open '%s' for output during dexopt\n", out_oat_path); return -1; } if (!set_permissions_and_ownership(out_oat_fd.get(), is_public, uid, out_oat_path)) { return -1; } // Open the existing VDEX. We do this before creating the new output VDEX, which will // unlink the old one. base::unique_fd in_vdex_fd; std::string in_vdex_path_str; base::unique_fd input_vdex_fd; if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) { // `input_file` is the OAT file to be relocated. The VDEX has to be there as well. in_vdex_path_str = create_vdex_filename(input_file); if (in_vdex_path_str.empty()) { ALOGE("installd cannot compute input vdex location for '%s'\n", input_file); return -1; } input_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0)); if (input_vdex_fd.get() < 0) { ALOGE("installd cannot open '%s' for input during dexopt\n", in_vdex_path_str.c_str()); in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0)); if (in_vdex_fd.get() < 0) { ALOGE("installd cannot open '%s' for input during dexopt: %s\n", in_vdex_path_str.c_str(), strerror(errno)); return -1; } } // Create the output OAT file. const std::string out_oat_path_str(out_oat_path); Dex2oatFileWrapper<std::function<void ()>> out_oat_fd( open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644), [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); }); if (out_oat_fd.get() < 0) { ALOGE("installd cannot open '%s' for output during dexopt\n", out_oat_path); } else { // Open the possibly existing vdex in the `out_oat_path`. If none exist, we pass -1 // to dex2oat for input-vdex-fd. in_vdex_path_str = create_vdex_filename(out_oat_path); if (in_vdex_path_str.empty()) { ALOGE("installd cannot compute input vdex location for '%s'\n", out_oat_path); return -1; } if (!set_permissions_and_ownership(out_oat_fd.get(), is_public, uid, out_oat_path)) { in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0)); // If there is no vdex file in out_oat_path, check if we have a vdex // file next to the odex file. For other failures, we will just pass a -1 fd. if (in_vdex_fd.get() < 0 && (errno == ENOENT) && IsOutputDalvikCache(oat_dir)) { if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) { in_vdex_path_str = create_vdex_filename(std::string(in_odex_path)); if (in_vdex_path_str.empty()) { ALOGE("installd cannot compute input vdex location for '%s'\n", in_odex_path); return -1; } in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0)); } } } // Infer the name of the output VDEX and create it. const std::string out_vdex_path_str = create_vdex_filename(out_oat_path_str); Loading Loading @@ -1825,7 +1861,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) { run_patchoat(input_fd.get(), input_vdex_fd.get(), in_vdex_fd.get(), out_oat_fd.get(), out_vdex_fd.get(), input_file, Loading @@ -1839,6 +1875,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins const char *input_file_name = get_location_from_path(input_file); run_dex2oat(input_fd.get(), out_oat_fd.get(), in_vdex_fd.get(), out_vdex_fd.get(), image_fd.get(), input_file_name, Loading Loading
cmds/installd/commands.cpp +61 −24 Original line number Diff line number Diff line Loading @@ -790,7 +790,7 @@ static void run_patchoat(int input_oat_fd, int input_vdex_fd, int out_oat_fd, in ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno)); } static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd, const char* input_file_name, const char* output_file_name, int swap_fd, const char *instruction_set, const char* compiler_filter, bool vm_safe_mode, bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) { Loading Loading @@ -874,7 +874,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN]; char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX]; char vdex_fd_arg[strlen("--vdex-fd=") + MAX_INT_LEN]; char input_vdex_fd_arg[strlen("--input-vdex-fd=") + MAX_INT_LEN]; char output_vdex_fd_arg[strlen("--output-vdex-fd=") + MAX_INT_LEN]; char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN]; char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX]; char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN]; Loading @@ -890,7 +891,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd); sprintf(zip_location_arg, "--zip-location=%s", input_file_name); sprintf(vdex_fd_arg, "--vdex-fd=%d", vdex_fd); sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd); sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd); sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd); sprintf(oat_location_arg, "--oat-location=%s", output_file_name); sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set); Loading Loading @@ -953,7 +955,7 @@ static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name); const char* argv[8 // program name, mandatory arguments and the final NULL const char* argv[9 // program name, mandatory arguments and the final NULL + (have_dex2oat_isa_variant ? 1 : 0) + (have_dex2oat_isa_features ? 1 : 0) + (have_dex2oat_Xms_flag ? 2 : 0) Loading @@ -974,7 +976,8 @@ static void run_dex2oat(int zip_fd, int oat_fd, int vdex_fd, int image_fd, argv[i++] = DEX2OAT_BIN; argv[i++] = zip_fd_arg; argv[i++] = zip_location_arg; argv[i++] = vdex_fd_arg; argv[i++] = input_vdex_fd_arg; argv[i++] = output_vdex_fd_arg; argv[i++] = oat_fd_arg; argv[i++] = oat_location_arg; argv[i++] = instruction_set_arg; Loading Loading @@ -1500,6 +1503,14 @@ static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const return true; } static bool IsOutputDalvikCache(const char* oat_dir) { // InstallerConnection.java (which invokes installd) transforms Java null arguments // into '!'. Play it safe by handling it both. // TODO: ensure we never get null. // TODO: pass a flag instead of inferring if the output is dalvik cache. return oat_dir == nullptr || oat_dir[0] == '!'; } static bool create_oat_out_path(const char* apk_path, const char* instruction_set, const char* oat_dir, /*out*/ char* out_oat_path) { // Early best-effort check whether we can fit the the path into our buffers. Loading @@ -1511,9 +1522,9 @@ static bool create_oat_out_path(const char* apk_path, const char* instruction_se return false; } if (oat_dir != NULL && oat_dir[0] != '!') { if (!IsOutputDalvikCache(oat_dir)) { if (validate_apk_path(oat_dir)) { ALOGE("invalid oat_dir '%s'\n", oat_dir); ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir); return false; } if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) { Loading Loading @@ -1702,34 +1713,59 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins return -1; } // If invoking patchoat, open the VDEX associated with the OAT too. // Create the output OAT file. const std::string out_oat_path_str(out_oat_path); Dex2oatFileWrapper<std::function<void ()>> out_oat_fd( open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644), [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); }); if (out_oat_fd.get() < 0) { ALOGE("installd cannot open '%s' for output during dexopt\n", out_oat_path); return -1; } if (!set_permissions_and_ownership(out_oat_fd.get(), is_public, uid, out_oat_path)) { return -1; } // Open the existing VDEX. We do this before creating the new output VDEX, which will // unlink the old one. base::unique_fd in_vdex_fd; std::string in_vdex_path_str; base::unique_fd input_vdex_fd; if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) { // `input_file` is the OAT file to be relocated. The VDEX has to be there as well. in_vdex_path_str = create_vdex_filename(input_file); if (in_vdex_path_str.empty()) { ALOGE("installd cannot compute input vdex location for '%s'\n", input_file); return -1; } input_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0)); if (input_vdex_fd.get() < 0) { ALOGE("installd cannot open '%s' for input during dexopt\n", in_vdex_path_str.c_str()); in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0)); if (in_vdex_fd.get() < 0) { ALOGE("installd cannot open '%s' for input during dexopt: %s\n", in_vdex_path_str.c_str(), strerror(errno)); return -1; } } // Create the output OAT file. const std::string out_oat_path_str(out_oat_path); Dex2oatFileWrapper<std::function<void ()>> out_oat_fd( open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644), [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); }); if (out_oat_fd.get() < 0) { ALOGE("installd cannot open '%s' for output during dexopt\n", out_oat_path); } else { // Open the possibly existing vdex in the `out_oat_path`. If none exist, we pass -1 // to dex2oat for input-vdex-fd. in_vdex_path_str = create_vdex_filename(out_oat_path); if (in_vdex_path_str.empty()) { ALOGE("installd cannot compute input vdex location for '%s'\n", out_oat_path); return -1; } if (!set_permissions_and_ownership(out_oat_fd.get(), is_public, uid, out_oat_path)) { in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0)); // If there is no vdex file in out_oat_path, check if we have a vdex // file next to the odex file. For other failures, we will just pass a -1 fd. if (in_vdex_fd.get() < 0 && (errno == ENOENT) && IsOutputDalvikCache(oat_dir)) { if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) { in_vdex_path_str = create_vdex_filename(std::string(in_odex_path)); if (in_vdex_path_str.empty()) { ALOGE("installd cannot compute input vdex location for '%s'\n", in_odex_path); return -1; } in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0)); } } } // Infer the name of the output VDEX and create it. const std::string out_vdex_path_str = create_vdex_filename(out_oat_path_str); Loading Loading @@ -1825,7 +1861,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) { run_patchoat(input_fd.get(), input_vdex_fd.get(), in_vdex_fd.get(), out_oat_fd.get(), out_vdex_fd.get(), input_file, Loading @@ -1839,6 +1875,7 @@ int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* ins const char *input_file_name = get_location_from_path(input_file); run_dex2oat(input_fd.get(), out_oat_fd.get(), in_vdex_fd.get(), out_vdex_fd.get(), image_fd.get(), input_file_name, Loading