Loading cmds/installd/commands.cpp +108 −3 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <unistd.h> #include <unistd.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/unique_fd.h> #include <android-base/unique_fd.h> #include <cutils/fs.h> #include <cutils/fs.h> Loading Loading @@ -1085,7 +1086,7 @@ static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4; static void run_profman(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) { static void run_profman_merge(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) { static const size_t MAX_INT_LEN = 32; static const size_t MAX_INT_LEN = 32; static const char* PROFMAN_BIN = "/system/bin/profman"; static const char* PROFMAN_BIN = "/system/bin/profman"; Loading Loading @@ -1133,13 +1134,13 @@ static bool analyse_profiles(uid_t uid, const char* pkgname) { return false; return false; } } ALOGV("PROFMAN: --- BEGIN '%s' ---\n", pkgname); ALOGV("PROFMAN (MERGE): --- BEGIN '%s' ---\n", pkgname); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ drop_capabilities(uid); drop_capabilities(uid); run_profman(profiles_fd, reference_profile_fd); run_profman_merge(profiles_fd, reference_profile_fd); exit(68); /* only get here on exec failure */ exit(68); /* only get here on exec failure */ } } /* parent */ /* parent */ Loading Loading @@ -1199,6 +1200,110 @@ static bool analyse_profiles(uid_t uid, const char* pkgname) { return need_to_compile; return need_to_compile; } } static void run_profman_dump(const std::vector<fd_t>& profile_fds, fd_t reference_profile_fd, const std::vector<std::string>& code_locations, const std::vector<fd_t>& code_location_fds, fd_t output_fd) { static const char* PROFMAN_BIN = "/system/bin/profman"; const bool has_reference_profile = (reference_profile_fd != -1); // program name // --dump-only // --dump-output-to-fd=<output_fd> // (optionally, --reference-profile-file-fd=<reference_profile_fd>) const size_t fixed_args = (has_reference_profile ? 4 : 3); // Fixed arguments, profiles, code paths, code path fds, and final NULL. const size_t argc = fixed_args + profile_fds.size() + code_locations.size() + code_location_fds.size() + 1; const char **argv = new const char*[argc]; int i = 0; argv[i++] = PROFMAN_BIN; argv[i++] = "--dump-only"; std::string dump_output = StringPrintf("--dump-output-to-fd=%d", output_fd); argv[i++] = dump_output.c_str(); if (has_reference_profile) { std::string reference = StringPrintf("--reference-profile-file-fd=%d", reference_profile_fd); argv[i++] = reference.c_str(); } for (fd_t profile_fd : profile_fds) { std::string profile_arg = StringPrintf("--profile-file-fd=%d", profile_fd); argv[i++] = strdup(profile_arg.c_str()); } for (const std::string& code_location : code_locations) { std::string path_str = StringPrintf("--code-location=%s", code_location.c_str()); argv[i++] = strdup(path_str.c_str()); } for (fd_t code_location_fd : code_location_fds) { std::string fd_str = StringPrintf("--code-location-fd=%d", code_location_fd); argv[i++] = strdup(fd_str.c_str()); } argv[i] = NULL; assert(i == argc - 1); execv(PROFMAN_BIN, (char * const *)argv); ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno)); exit(68); /* only get here on exec failure */ } // Dumps the contents of a profile file, using pkgname's dex files for pretty // printing the result. bool dump_profile(uid_t uid, const char* pkgname, const char* code_path_string) { std::vector<fd_t> profile_fds; fd_t reference_profile_fd = -1; std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname); ALOGV("PROFMAN (DUMP): --- BEGIN '%s' ---\n", pkgname); open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd); const bool has_reference_profile = (reference_profile_fd != -1); const bool has_profiles = !profile_fds.empty(); if (!has_reference_profile && !has_profiles) { ALOGE("profman dump: no profiles to dump for '%s'", pkgname); return false; } fd_t output_fd = open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW); if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str()); return false; } std::vector<std::string> code_locations = base::Split(code_path_string, ";"); std::vector<fd_t> code_location_fds; for (const std::string& code_location : code_locations) { fd_t code_location_fd = open(code_location.c_str(), O_RDONLY | O_NOFOLLOW); if (code_location_fd == -1) { ALOGE("installd cannot open '%s'\n", code_location.c_str()); return false; } code_location_fds.push_back(code_location_fd); } pid_t pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ drop_capabilities(uid); run_profman_dump(profile_fds, reference_profile_fd, code_locations, code_location_fds, output_fd); exit(68); /* only get here on exec failure */ } /* parent */ close_all_fds(code_location_fds, "code_location_fds"); close_all_fds(profile_fds, "profile_fds"); if (close(reference_profile_fd) != 0) { PLOG(WARNING) << "Failed to close fd for reference profile"; } int return_code = wait_child(pid); if (!WIFEXITED(return_code)) { LOG(WARNING) << "profman failed for package " << pkgname << ": " << return_code; return false; } return true; } static void trim_extension(char* path) { static void trim_extension(char* path) { // Trim the extension. // Trim the extension. int pos = strlen(path); int pos = strlen(path); Loading cmds/installd/commands.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -54,6 +54,8 @@ int free_cache(const char *uuid, int64_t free_size); bool merge_profiles(uid_t uid, const char *pkgname); bool merge_profiles(uid_t uid, const char *pkgname); bool dump_profile(uid_t uid, const char *pkgname, const char *dex_files); int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set, int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set, int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter, int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter, const char* volume_uuid, const char* shared_libraries); const char* volume_uuid, const char* shared_libraries); Loading cmds/installd/installd.cpp +14 −0 Original line number Original line Diff line number Diff line Loading @@ -282,6 +282,19 @@ static int do_merge_profiles(char **arg, char reply[REPLY_MAX]) return 0; return 0; } } static int do_dump_profiles(char **arg, char reply[REPLY_MAX]) { uid_t uid = static_cast<uid_t>(atoi(arg[0])); const char* pkgname = arg[1]; const char* dex_files = arg[2]; if (dump_profile(uid, pkgname, dex_files)) { strncpy(reply, "true", REPLY_MAX); } else { strncpy(reply, "false", REPLY_MAX); } return 0; } static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { { return mark_boot_complete(arg[0] /* instruction set */); return mark_boot_complete(arg[0] /* instruction set */); Loading Loading @@ -428,6 +441,7 @@ struct cmdinfo cmds[] = { { "linkfile", 3, do_link_file }, { "linkfile", 3, do_link_file }, { "move_ab", 3, do_move_ab }, { "move_ab", 3, do_move_ab }, { "merge_profiles", 2, do_merge_profiles }, { "merge_profiles", 2, do_merge_profiles }, { "dump_profiles", 3, do_dump_profiles }, }; }; static int readx(int s, void *_buf, int count) static int readx(int s, void *_buf, int count) Loading Loading
cmds/installd/commands.cpp +108 −3 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <unistd.h> #include <unistd.h> #include <android-base/stringprintf.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/logging.h> #include <android-base/logging.h> #include <android-base/unique_fd.h> #include <android-base/unique_fd.h> #include <cutils/fs.h> #include <cutils/fs.h> Loading Loading @@ -1085,7 +1086,7 @@ static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4; static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4; static void run_profman(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) { static void run_profman_merge(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) { static const size_t MAX_INT_LEN = 32; static const size_t MAX_INT_LEN = 32; static const char* PROFMAN_BIN = "/system/bin/profman"; static const char* PROFMAN_BIN = "/system/bin/profman"; Loading Loading @@ -1133,13 +1134,13 @@ static bool analyse_profiles(uid_t uid, const char* pkgname) { return false; return false; } } ALOGV("PROFMAN: --- BEGIN '%s' ---\n", pkgname); ALOGV("PROFMAN (MERGE): --- BEGIN '%s' ---\n", pkgname); pid_t pid = fork(); pid_t pid = fork(); if (pid == 0) { if (pid == 0) { /* child -- drop privileges before continuing */ /* child -- drop privileges before continuing */ drop_capabilities(uid); drop_capabilities(uid); run_profman(profiles_fd, reference_profile_fd); run_profman_merge(profiles_fd, reference_profile_fd); exit(68); /* only get here on exec failure */ exit(68); /* only get here on exec failure */ } } /* parent */ /* parent */ Loading Loading @@ -1199,6 +1200,110 @@ static bool analyse_profiles(uid_t uid, const char* pkgname) { return need_to_compile; return need_to_compile; } } static void run_profman_dump(const std::vector<fd_t>& profile_fds, fd_t reference_profile_fd, const std::vector<std::string>& code_locations, const std::vector<fd_t>& code_location_fds, fd_t output_fd) { static const char* PROFMAN_BIN = "/system/bin/profman"; const bool has_reference_profile = (reference_profile_fd != -1); // program name // --dump-only // --dump-output-to-fd=<output_fd> // (optionally, --reference-profile-file-fd=<reference_profile_fd>) const size_t fixed_args = (has_reference_profile ? 4 : 3); // Fixed arguments, profiles, code paths, code path fds, and final NULL. const size_t argc = fixed_args + profile_fds.size() + code_locations.size() + code_location_fds.size() + 1; const char **argv = new const char*[argc]; int i = 0; argv[i++] = PROFMAN_BIN; argv[i++] = "--dump-only"; std::string dump_output = StringPrintf("--dump-output-to-fd=%d", output_fd); argv[i++] = dump_output.c_str(); if (has_reference_profile) { std::string reference = StringPrintf("--reference-profile-file-fd=%d", reference_profile_fd); argv[i++] = reference.c_str(); } for (fd_t profile_fd : profile_fds) { std::string profile_arg = StringPrintf("--profile-file-fd=%d", profile_fd); argv[i++] = strdup(profile_arg.c_str()); } for (const std::string& code_location : code_locations) { std::string path_str = StringPrintf("--code-location=%s", code_location.c_str()); argv[i++] = strdup(path_str.c_str()); } for (fd_t code_location_fd : code_location_fds) { std::string fd_str = StringPrintf("--code-location-fd=%d", code_location_fd); argv[i++] = strdup(fd_str.c_str()); } argv[i] = NULL; assert(i == argc - 1); execv(PROFMAN_BIN, (char * const *)argv); ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno)); exit(68); /* only get here on exec failure */ } // Dumps the contents of a profile file, using pkgname's dex files for pretty // printing the result. bool dump_profile(uid_t uid, const char* pkgname, const char* code_path_string) { std::vector<fd_t> profile_fds; fd_t reference_profile_fd = -1; std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname); ALOGV("PROFMAN (DUMP): --- BEGIN '%s' ---\n", pkgname); open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd); const bool has_reference_profile = (reference_profile_fd != -1); const bool has_profiles = !profile_fds.empty(); if (!has_reference_profile && !has_profiles) { ALOGE("profman dump: no profiles to dump for '%s'", pkgname); return false; } fd_t output_fd = open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW); if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str()); return false; } std::vector<std::string> code_locations = base::Split(code_path_string, ";"); std::vector<fd_t> code_location_fds; for (const std::string& code_location : code_locations) { fd_t code_location_fd = open(code_location.c_str(), O_RDONLY | O_NOFOLLOW); if (code_location_fd == -1) { ALOGE("installd cannot open '%s'\n", code_location.c_str()); return false; } code_location_fds.push_back(code_location_fd); } pid_t pid = fork(); if (pid == 0) { /* child -- drop privileges before continuing */ drop_capabilities(uid); run_profman_dump(profile_fds, reference_profile_fd, code_locations, code_location_fds, output_fd); exit(68); /* only get here on exec failure */ } /* parent */ close_all_fds(code_location_fds, "code_location_fds"); close_all_fds(profile_fds, "profile_fds"); if (close(reference_profile_fd) != 0) { PLOG(WARNING) << "Failed to close fd for reference profile"; } int return_code = wait_child(pid); if (!WIFEXITED(return_code)) { LOG(WARNING) << "profman failed for package " << pkgname << ": " << return_code; return false; } return true; } static void trim_extension(char* path) { static void trim_extension(char* path) { // Trim the extension. // Trim the extension. int pos = strlen(path); int pos = strlen(path); Loading
cmds/installd/commands.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -54,6 +54,8 @@ int free_cache(const char *uuid, int64_t free_size); bool merge_profiles(uid_t uid, const char *pkgname); bool merge_profiles(uid_t uid, const char *pkgname); bool dump_profile(uid_t uid, const char *pkgname, const char *dex_files); int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set, int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set, int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter, int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter, const char* volume_uuid, const char* shared_libraries); const char* volume_uuid, const char* shared_libraries); Loading
cmds/installd/installd.cpp +14 −0 Original line number Original line Diff line number Diff line Loading @@ -282,6 +282,19 @@ static int do_merge_profiles(char **arg, char reply[REPLY_MAX]) return 0; return 0; } } static int do_dump_profiles(char **arg, char reply[REPLY_MAX]) { uid_t uid = static_cast<uid_t>(atoi(arg[0])); const char* pkgname = arg[1]; const char* dex_files = arg[2]; if (dump_profile(uid, pkgname, dex_files)) { strncpy(reply, "true", REPLY_MAX); } else { strncpy(reply, "false", REPLY_MAX); } return 0; } static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) { { return mark_boot_complete(arg[0] /* instruction set */); return mark_boot_complete(arg[0] /* instruction set */); Loading Loading @@ -428,6 +441,7 @@ struct cmdinfo cmds[] = { { "linkfile", 3, do_link_file }, { "linkfile", 3, do_link_file }, { "move_ab", 3, do_move_ab }, { "move_ab", 3, do_move_ab }, { "merge_profiles", 2, do_merge_profiles }, { "merge_profiles", 2, do_merge_profiles }, { "dump_profiles", 3, do_dump_profiles }, }; }; static int readx(int s, void *_buf, int count) static int readx(int s, void *_buf, int count) Loading