Loading cmds/installd/dexopt.cpp +64 −82 Original line number Original line Diff line number Diff line Loading @@ -45,10 +45,15 @@ using android::base::StringPrintf; using android::base::StringPrintf; using android::base::EndsWith; using android::base::EndsWith; using android::base::unique_fd; namespace android { namespace android { namespace installd { namespace installd { static unique_fd invalid_unique_fd() { return unique_fd(-1); } static const char* parse_null(const char* arg) { static const char* parse_null(const char* arg) { if (strcmp(arg, "!") == 0) { if (strcmp(arg, "!") == 0) { return nullptr; return nullptr; Loading @@ -58,7 +63,7 @@ static const char* parse_null(const char* arg) { } } static bool clear_profile(const std::string& profile) { static bool clear_profile(const std::string& profile) { base::unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC)); unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC)); if (ufd.get() < 0) { if (ufd.get() < 0) { if (errno != ENOENT) { if (errno != ENOENT) { PLOG(WARNING) << "Could not open profile " << profile; PLOG(WARNING) << "Could not open profile " << profile; Loading Loading @@ -467,18 +472,10 @@ static void SetDex2OatScheduling(bool set_to_bg) { } } } } static void close_all_fds(const std::vector<fd_t>& fds, const char* description) { static unique_fd open_profile_dir(const std::string& profile_dir) { for (size_t i = 0; i < fds.size(); i++) { unique_fd profile_dir_fd(TEMP_FAILURE_RETRY(open(profile_dir.c_str(), if (close(fds[i]) != 0) { O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW))); PLOG(WARNING) << "Failed to close fd for " << description << " at index " << i; if (profile_dir_fd.get() < 0) { } } } static fd_t open_profile_dir(const std::string& profile_dir) { fd_t profile_dir_fd = TEMP_FAILURE_RETRY(open(profile_dir.c_str(), O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW)); if (profile_dir_fd < 0) { // In a multi-user environment, these directories can be created at // In a multi-user environment, these directories can be created at // different points and it's possible we'll attempt to open a profile // different points and it's possible we'll attempt to open a profile // dir before it exists. // dir before it exists. Loading @@ -489,66 +486,61 @@ static fd_t open_profile_dir(const std::string& profile_dir) { return profile_dir_fd; return profile_dir_fd; } } static fd_t open_primary_profile_file_from_dir(const std::string& profile_dir, mode_t open_mode) { static unique_fd open_primary_profile_file_from_dir(const std::string& profile_dir, fd_t profile_dir_fd = open_profile_dir(profile_dir); mode_t open_mode) { if (profile_dir_fd < 0) { unique_fd profile_dir_fd = open_profile_dir(profile_dir); return -1; if (profile_dir_fd.get() < 0) { return invalid_unique_fd(); } } fd_t profile_fd = -1; std::string profile_file = create_primary_profile(profile_dir); std::string profile_file = create_primary_profile(profile_dir); unique_fd profile_fd(TEMP_FAILURE_RETRY(open(profile_file.c_str(), profile_fd = TEMP_FAILURE_RETRY(open(profile_file.c_str(), open_mode | O_NOFOLLOW, 0600)); open_mode | O_NOFOLLOW, 0600))); if (profile_fd == -1) { if (profile_fd == -1) { // It's not an error if the profile file does not exist. // It's not an error if the profile file does not exist. if (errno != ENOENT) { if (errno != ENOENT) { PLOG(ERROR) << "Failed to lstat profile_dir: " << profile_dir; PLOG(ERROR) << "Failed to open profile : " << profile_file; } } } } // TODO(calin): use AutoCloseFD instead of closing the fd manually. if (close(profile_dir_fd) != 0) { PLOG(WARNING) << "Could not close profile dir " << profile_dir; } return profile_fd; return profile_fd; } } static fd_t open_primary_profile_file(userid_t user, const std::string& pkgname) { static unique_fd open_primary_profile_file(userid_t user, const std::string& pkgname) { std::string profile_dir = create_data_user_profile_package_path(user, pkgname); std::string profile_dir = create_data_user_profile_package_path(user, pkgname); return open_primary_profile_file_from_dir(profile_dir, O_RDONLY); return open_primary_profile_file_from_dir(profile_dir, O_RDONLY); } } static fd_t open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) { static unique_fd open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) { std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname); std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname); int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY; int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY; fd_t fd = open_primary_profile_file_from_dir(reference_profile_dir, flags); unique_fd fd = open_primary_profile_file_from_dir(reference_profile_dir, flags); if (fd < 0) { if (fd.get() < 0) { return -1; return invalid_unique_fd(); } } if (read_write) { if (read_write) { // Fix the owner. // Fix the owner. if (fchown(fd, uid, uid) < 0) { if (fchown(fd.get(), uid, uid) < 0) { close(fd); return invalid_unique_fd(); return -1; } } } } return fd; return fd; } } static void open_profile_files(uid_t uid, const std::string& pkgname, static void open_profile_files(uid_t uid, const std::string& pkgname, /*out*/ std::vector<fd_t>* profiles_fd, /*out*/ fd_t* reference_profile_fd) { /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) { // Open the reference profile in read-write mode as profman might need to save the merge. // Open the reference profile in read-write mode as profman might need to save the merge. *reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ true); reference_profile_fd->reset(open_reference_profile(uid, pkgname, /*read_write*/ true)); if (*reference_profile_fd < 0) { if (reference_profile_fd->get() < 0) { // We can't access the reference profile file. // We can't access the reference profile file. return; return; } } std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr); std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr); for (auto user : users) { for (auto user : users) { fd_t profile_fd = open_primary_profile_file(user, pkgname); unique_fd profile_fd = open_primary_profile_file(user, pkgname); // Add to the lists only if both fds are valid. // Add to the lists only if both fds are valid. if (profile_fd >= 0) { if (profile_fd.get() >= 0) { profiles_fd->push_back(profile_fd); profiles_fd->push_back(std::move(profile_fd)); } } } } } } Loading Loading @@ -580,18 +572,19 @@ 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_merge(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) { static void run_profman_merge(const std::vector<unique_fd>& profiles_fd, const unique_fd& 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"; std::vector<std::string> profile_args(profiles_fd.size()); std::vector<std::string> profile_args(profiles_fd.size()); char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN]; char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN]; for (size_t k = 0; k < profiles_fd.size(); k++) { for (size_t k = 0; k < profiles_fd.size(); k++) { sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k]); sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k].get()); profile_args[k].assign(profile_buf); profile_args[k].assign(profile_buf); } } char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN]; char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN]; sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd); sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd.get()); // program name, reference profile fd, the final NULL and the profile fds // program name, reference profile fd, the final NULL and the profile fds const char* argv[3 + profiles_fd.size()]; const char* argv[3 + profiles_fd.size()]; Loading @@ -615,16 +608,12 @@ static void run_profman_merge(const std::vector<fd_t>& profiles_fd, fd_t referen // If the return value is true all the current profiles would have been merged into // If the return value is true all the current profiles would have been merged into // the reference profiles accessible with open_reference_profile(). // the reference profiles accessible with open_reference_profile(). bool analyse_profiles(uid_t uid, const std::string& pkgname) { bool analyse_profiles(uid_t uid, const std::string& pkgname) { std::vector<fd_t> profiles_fd; std::vector<unique_fd> profiles_fd; fd_t reference_profile_fd = -1; unique_fd reference_profile_fd; open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd); open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd); if (profiles_fd.empty() || (reference_profile_fd == -1)) { if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) { // Skip profile guided compilation because no profiles were found. // Skip profile guided compilation because no profiles were found. // Or if the reference profile info couldn't be opened. // Or if the reference profile info couldn't be opened. close_all_fds(profiles_fd, "profiles_fd"); if ((reference_profile_fd != - 1) && (close(reference_profile_fd) != 0)) { PLOG(WARNING) << "Failed to close fd for reference profile"; } return false; return false; } } Loading Loading @@ -679,10 +668,7 @@ bool analyse_profiles(uid_t uid, const std::string& pkgname) { break; break; } } } } close_all_fds(profiles_fd, "profiles_fd"); if (close(reference_profile_fd) != 0) { PLOG(WARNING) << "Failed to close fd for reference profile"; } if (should_clear_current_profiles) { if (should_clear_current_profiles) { clear_current_profiles(pkgname); clear_current_profiles(pkgname); } } Loading @@ -692,28 +678,28 @@ bool analyse_profiles(uid_t uid, const std::string& pkgname) { return need_to_compile; return need_to_compile; } } static void run_profman_dump(const std::vector<fd_t>& profile_fds, static void run_profman_dump(const std::vector<unique_fd>& profile_fds, fd_t reference_profile_fd, const unique_fd& reference_profile_fd, const std::vector<std::string>& dex_locations, const std::vector<std::string>& dex_locations, const std::vector<fd_t>& apk_fds, const std::vector<unique_fd>& apk_fds, fd_t output_fd) { const unique_fd& output_fd) { std::vector<std::string> profman_args; std::vector<std::string> profman_args; static const char* PROFMAN_BIN = "/system/bin/profman"; static const char* PROFMAN_BIN = "/system/bin/profman"; profman_args.push_back(PROFMAN_BIN); profman_args.push_back(PROFMAN_BIN); profman_args.push_back("--dump-only"); profman_args.push_back("--dump-only"); profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd)); profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get())); if (reference_profile_fd != -1) { if (reference_profile_fd != -1) { profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d", profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d", reference_profile_fd)); reference_profile_fd.get())); } } for (fd_t profile_fd : profile_fds) { for (size_t i = 0; i < profile_fds.size(); i++) { profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fd)); profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get())); } } for (const std::string& dex_location : dex_locations) { for (const std::string& dex_location : dex_locations) { profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str())); profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str())); } } for (fd_t apk_fd : apk_fds) { for (size_t i = 0; i < apk_fds.size(); i++) { profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fd)); profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get())); } } const char **argv = new const char*[profman_args.size() + 1]; const char **argv = new const char*[profman_args.size() + 1]; size_t i = 0; size_t i = 0; Loading @@ -739,13 +725,13 @@ static const char* get_location_from_path(const char* path) { } } bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) { bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) { std::vector<fd_t> profile_fds; std::vector<unique_fd> profile_fds; fd_t reference_profile_fd = -1; unique_fd reference_profile_fd; std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str()); std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str()); open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd); open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd); const bool has_reference_profile = (reference_profile_fd != -1); const bool has_reference_profile = (reference_profile_fd.get() != -1); const bool has_profiles = !profile_fds.empty(); const bool has_profiles = !profile_fds.empty(); if (!has_reference_profile && !has_profiles) { if (!has_reference_profile && !has_profiles) { Loading @@ -753,23 +739,23 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat return false; return false; } } fd_t output_fd = open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644); unique_fd output_fd(open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644)); if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { 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()); ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str()); return false; return false; } } std::vector<std::string> code_full_paths = base::Split(code_paths, ";"); std::vector<std::string> code_full_paths = base::Split(code_paths, ";"); std::vector<std::string> dex_locations; std::vector<std::string> dex_locations; std::vector<fd_t> apk_fds; std::vector<unique_fd> apk_fds; for (const std::string& code_full_path : code_full_paths) { for (const std::string& code_full_path : code_full_paths) { const char* full_path = code_full_path.c_str(); const char* full_path = code_full_path.c_str(); fd_t apk_fd = open(full_path, O_RDONLY | O_NOFOLLOW); unique_fd apk_fd(open(full_path, O_RDONLY | O_NOFOLLOW)); if (apk_fd == -1) { if (apk_fd == -1) { ALOGE("installd cannot open '%s'\n", full_path); ALOGE("installd cannot open '%s'\n", full_path); return false; return false; } } dex_locations.push_back(get_location_from_path(full_path)); dex_locations.push_back(get_location_from_path(full_path)); apk_fds.push_back(apk_fd); apk_fds.push_back(std::move(apk_fd)); } } pid_t pid = fork(); pid_t pid = fork(); Loading @@ -781,11 +767,6 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat exit(68); /* only get here on exec failure */ exit(68); /* only get here on exec failure */ } } /* parent */ /* parent */ close_all_fds(apk_fds, "apk_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); int return_code = wait_child(pid); if (!WIFEXITED(return_code)) { if (!WIFEXITED(return_code)) { LOG(WARNING) << "profman failed for package " << pkgname << ": " LOG(WARNING) << "profman failed for package " << pkgname << ": " Loading Loading @@ -1053,17 +1034,17 @@ Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_g // Creates the dexopt swap file if necessary and return its fd. // Creates the dexopt swap file if necessary and return its fd. // Returns -1 if there's no need for a swap or in case of errors. // Returns -1 if there's no need for a swap or in case of errors. base::unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) { unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) { if (!ShouldUseSwapFileForDexopt()) { if (!ShouldUseSwapFileForDexopt()) { return base::unique_fd(); return invalid_unique_fd(); } } // Make sure there really is enough space. // Make sure there really is enough space. char swap_file_name[PKG_PATH_MAX]; char swap_file_name[PKG_PATH_MAX]; strcpy(swap_file_name, out_oat_path); strcpy(swap_file_name, out_oat_path); if (!add_extension_to_file_name(swap_file_name, ".swap")) { if (!add_extension_to_file_name(swap_file_name, ".swap")) { return base::unique_fd(); return invalid_unique_fd(); } } base::unique_fd swap_fd(open_output_file( unique_fd swap_fd(open_output_file( swap_file_name, /*recreate*/true, /*permissions*/0600)); swap_file_name, /*recreate*/true, /*permissions*/0600)); if (swap_fd.get() < 0) { if (swap_fd.get() < 0) { // Could not create swap file. Optimistically go on and hope that we can compile // Could not create swap file. Optimistically go on and hope that we can compile Loading @@ -1088,8 +1069,9 @@ Dex2oatFileWrapper maybe_open_reference_profile(const char* pkgname, bool profil if (profile_guided && !is_secondary_dex && !is_public && (pkgname[0] != '*')) { if (profile_guided && !is_secondary_dex && !is_public && (pkgname[0] != '*')) { // Open reference profile in read only mode as dex2oat does not get write permissions. // Open reference profile in read only mode as dex2oat does not get write permissions. const std::string pkgname_str(pkgname); const std::string pkgname_str(pkgname); unique_fd profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ false); return Dex2oatFileWrapper( return Dex2oatFileWrapper( open_reference_profile(uid, pkgname, /*read_write*/ false), profile_fd.release(), [pkgname_str]() { [pkgname_str]() { clear_reference_profile(pkgname_str.c_str()); clear_reference_profile(pkgname_str.c_str()); }); }); Loading Loading @@ -1430,7 +1412,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins } } // Open the input file. // Open the input file. base::unique_fd input_fd(open(dex_path, O_RDONLY, 0)); unique_fd input_fd(open(dex_path, O_RDONLY, 0)); if (input_fd.get() < 0) { if (input_fd.get() < 0) { ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path); ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path); return -1; return -1; Loading @@ -1453,7 +1435,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins } } // Create a swap file if necessary. // Create a swap file if necessary. base::unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path); unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path); // Create the app image file if needed. // Create the app image file if needed. Dex2oatFileWrapper image_fd = Dex2oatFileWrapper image_fd = Loading cmds/installd/dexopt.h +0 −2 Original line number Original line Diff line number Diff line Loading @@ -32,8 +32,6 @@ static constexpr int DEX2OAT_FOR_FILTER = 3; static constexpr int DEX2OAT_FOR_RELOCATION = 4; static constexpr int DEX2OAT_FOR_RELOCATION = 4; static constexpr int PATCHOAT_FOR_RELOCATION = 5; static constexpr int PATCHOAT_FOR_RELOCATION = 5; typedef int fd_t; bool clear_reference_profile(const std::string& pkgname); bool clear_reference_profile(const std::string& pkgname); bool clear_current_profile(const std::string& pkgname, userid_t user); bool clear_current_profile(const std::string& pkgname, userid_t user); bool clear_current_profiles(const std::string& pkgname); bool clear_current_profiles(const std::string& pkgname); Loading Loading
cmds/installd/dexopt.cpp +64 −82 Original line number Original line Diff line number Diff line Loading @@ -45,10 +45,15 @@ using android::base::StringPrintf; using android::base::StringPrintf; using android::base::EndsWith; using android::base::EndsWith; using android::base::unique_fd; namespace android { namespace android { namespace installd { namespace installd { static unique_fd invalid_unique_fd() { return unique_fd(-1); } static const char* parse_null(const char* arg) { static const char* parse_null(const char* arg) { if (strcmp(arg, "!") == 0) { if (strcmp(arg, "!") == 0) { return nullptr; return nullptr; Loading @@ -58,7 +63,7 @@ static const char* parse_null(const char* arg) { } } static bool clear_profile(const std::string& profile) { static bool clear_profile(const std::string& profile) { base::unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC)); unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC)); if (ufd.get() < 0) { if (ufd.get() < 0) { if (errno != ENOENT) { if (errno != ENOENT) { PLOG(WARNING) << "Could not open profile " << profile; PLOG(WARNING) << "Could not open profile " << profile; Loading Loading @@ -467,18 +472,10 @@ static void SetDex2OatScheduling(bool set_to_bg) { } } } } static void close_all_fds(const std::vector<fd_t>& fds, const char* description) { static unique_fd open_profile_dir(const std::string& profile_dir) { for (size_t i = 0; i < fds.size(); i++) { unique_fd profile_dir_fd(TEMP_FAILURE_RETRY(open(profile_dir.c_str(), if (close(fds[i]) != 0) { O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW))); PLOG(WARNING) << "Failed to close fd for " << description << " at index " << i; if (profile_dir_fd.get() < 0) { } } } static fd_t open_profile_dir(const std::string& profile_dir) { fd_t profile_dir_fd = TEMP_FAILURE_RETRY(open(profile_dir.c_str(), O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW)); if (profile_dir_fd < 0) { // In a multi-user environment, these directories can be created at // In a multi-user environment, these directories can be created at // different points and it's possible we'll attempt to open a profile // different points and it's possible we'll attempt to open a profile // dir before it exists. // dir before it exists. Loading @@ -489,66 +486,61 @@ static fd_t open_profile_dir(const std::string& profile_dir) { return profile_dir_fd; return profile_dir_fd; } } static fd_t open_primary_profile_file_from_dir(const std::string& profile_dir, mode_t open_mode) { static unique_fd open_primary_profile_file_from_dir(const std::string& profile_dir, fd_t profile_dir_fd = open_profile_dir(profile_dir); mode_t open_mode) { if (profile_dir_fd < 0) { unique_fd profile_dir_fd = open_profile_dir(profile_dir); return -1; if (profile_dir_fd.get() < 0) { return invalid_unique_fd(); } } fd_t profile_fd = -1; std::string profile_file = create_primary_profile(profile_dir); std::string profile_file = create_primary_profile(profile_dir); unique_fd profile_fd(TEMP_FAILURE_RETRY(open(profile_file.c_str(), profile_fd = TEMP_FAILURE_RETRY(open(profile_file.c_str(), open_mode | O_NOFOLLOW, 0600)); open_mode | O_NOFOLLOW, 0600))); if (profile_fd == -1) { if (profile_fd == -1) { // It's not an error if the profile file does not exist. // It's not an error if the profile file does not exist. if (errno != ENOENT) { if (errno != ENOENT) { PLOG(ERROR) << "Failed to lstat profile_dir: " << profile_dir; PLOG(ERROR) << "Failed to open profile : " << profile_file; } } } } // TODO(calin): use AutoCloseFD instead of closing the fd manually. if (close(profile_dir_fd) != 0) { PLOG(WARNING) << "Could not close profile dir " << profile_dir; } return profile_fd; return profile_fd; } } static fd_t open_primary_profile_file(userid_t user, const std::string& pkgname) { static unique_fd open_primary_profile_file(userid_t user, const std::string& pkgname) { std::string profile_dir = create_data_user_profile_package_path(user, pkgname); std::string profile_dir = create_data_user_profile_package_path(user, pkgname); return open_primary_profile_file_from_dir(profile_dir, O_RDONLY); return open_primary_profile_file_from_dir(profile_dir, O_RDONLY); } } static fd_t open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) { static unique_fd open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) { std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname); std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname); int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY; int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY; fd_t fd = open_primary_profile_file_from_dir(reference_profile_dir, flags); unique_fd fd = open_primary_profile_file_from_dir(reference_profile_dir, flags); if (fd < 0) { if (fd.get() < 0) { return -1; return invalid_unique_fd(); } } if (read_write) { if (read_write) { // Fix the owner. // Fix the owner. if (fchown(fd, uid, uid) < 0) { if (fchown(fd.get(), uid, uid) < 0) { close(fd); return invalid_unique_fd(); return -1; } } } } return fd; return fd; } } static void open_profile_files(uid_t uid, const std::string& pkgname, static void open_profile_files(uid_t uid, const std::string& pkgname, /*out*/ std::vector<fd_t>* profiles_fd, /*out*/ fd_t* reference_profile_fd) { /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) { // Open the reference profile in read-write mode as profman might need to save the merge. // Open the reference profile in read-write mode as profman might need to save the merge. *reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ true); reference_profile_fd->reset(open_reference_profile(uid, pkgname, /*read_write*/ true)); if (*reference_profile_fd < 0) { if (reference_profile_fd->get() < 0) { // We can't access the reference profile file. // We can't access the reference profile file. return; return; } } std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr); std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr); for (auto user : users) { for (auto user : users) { fd_t profile_fd = open_primary_profile_file(user, pkgname); unique_fd profile_fd = open_primary_profile_file(user, pkgname); // Add to the lists only if both fds are valid. // Add to the lists only if both fds are valid. if (profile_fd >= 0) { if (profile_fd.get() >= 0) { profiles_fd->push_back(profile_fd); profiles_fd->push_back(std::move(profile_fd)); } } } } } } Loading Loading @@ -580,18 +572,19 @@ 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_merge(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) { static void run_profman_merge(const std::vector<unique_fd>& profiles_fd, const unique_fd& 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"; std::vector<std::string> profile_args(profiles_fd.size()); std::vector<std::string> profile_args(profiles_fd.size()); char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN]; char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN]; for (size_t k = 0; k < profiles_fd.size(); k++) { for (size_t k = 0; k < profiles_fd.size(); k++) { sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k]); sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k].get()); profile_args[k].assign(profile_buf); profile_args[k].assign(profile_buf); } } char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN]; char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN]; sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd); sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd.get()); // program name, reference profile fd, the final NULL and the profile fds // program name, reference profile fd, the final NULL and the profile fds const char* argv[3 + profiles_fd.size()]; const char* argv[3 + profiles_fd.size()]; Loading @@ -615,16 +608,12 @@ static void run_profman_merge(const std::vector<fd_t>& profiles_fd, fd_t referen // If the return value is true all the current profiles would have been merged into // If the return value is true all the current profiles would have been merged into // the reference profiles accessible with open_reference_profile(). // the reference profiles accessible with open_reference_profile(). bool analyse_profiles(uid_t uid, const std::string& pkgname) { bool analyse_profiles(uid_t uid, const std::string& pkgname) { std::vector<fd_t> profiles_fd; std::vector<unique_fd> profiles_fd; fd_t reference_profile_fd = -1; unique_fd reference_profile_fd; open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd); open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd); if (profiles_fd.empty() || (reference_profile_fd == -1)) { if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) { // Skip profile guided compilation because no profiles were found. // Skip profile guided compilation because no profiles were found. // Or if the reference profile info couldn't be opened. // Or if the reference profile info couldn't be opened. close_all_fds(profiles_fd, "profiles_fd"); if ((reference_profile_fd != - 1) && (close(reference_profile_fd) != 0)) { PLOG(WARNING) << "Failed to close fd for reference profile"; } return false; return false; } } Loading Loading @@ -679,10 +668,7 @@ bool analyse_profiles(uid_t uid, const std::string& pkgname) { break; break; } } } } close_all_fds(profiles_fd, "profiles_fd"); if (close(reference_profile_fd) != 0) { PLOG(WARNING) << "Failed to close fd for reference profile"; } if (should_clear_current_profiles) { if (should_clear_current_profiles) { clear_current_profiles(pkgname); clear_current_profiles(pkgname); } } Loading @@ -692,28 +678,28 @@ bool analyse_profiles(uid_t uid, const std::string& pkgname) { return need_to_compile; return need_to_compile; } } static void run_profman_dump(const std::vector<fd_t>& profile_fds, static void run_profman_dump(const std::vector<unique_fd>& profile_fds, fd_t reference_profile_fd, const unique_fd& reference_profile_fd, const std::vector<std::string>& dex_locations, const std::vector<std::string>& dex_locations, const std::vector<fd_t>& apk_fds, const std::vector<unique_fd>& apk_fds, fd_t output_fd) { const unique_fd& output_fd) { std::vector<std::string> profman_args; std::vector<std::string> profman_args; static const char* PROFMAN_BIN = "/system/bin/profman"; static const char* PROFMAN_BIN = "/system/bin/profman"; profman_args.push_back(PROFMAN_BIN); profman_args.push_back(PROFMAN_BIN); profman_args.push_back("--dump-only"); profman_args.push_back("--dump-only"); profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd)); profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get())); if (reference_profile_fd != -1) { if (reference_profile_fd != -1) { profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d", profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d", reference_profile_fd)); reference_profile_fd.get())); } } for (fd_t profile_fd : profile_fds) { for (size_t i = 0; i < profile_fds.size(); i++) { profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fd)); profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get())); } } for (const std::string& dex_location : dex_locations) { for (const std::string& dex_location : dex_locations) { profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str())); profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str())); } } for (fd_t apk_fd : apk_fds) { for (size_t i = 0; i < apk_fds.size(); i++) { profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fd)); profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get())); } } const char **argv = new const char*[profman_args.size() + 1]; const char **argv = new const char*[profman_args.size() + 1]; size_t i = 0; size_t i = 0; Loading @@ -739,13 +725,13 @@ static const char* get_location_from_path(const char* path) { } } bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) { bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) { std::vector<fd_t> profile_fds; std::vector<unique_fd> profile_fds; fd_t reference_profile_fd = -1; unique_fd reference_profile_fd; std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str()); std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str()); open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd); open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd); const bool has_reference_profile = (reference_profile_fd != -1); const bool has_reference_profile = (reference_profile_fd.get() != -1); const bool has_profiles = !profile_fds.empty(); const bool has_profiles = !profile_fds.empty(); if (!has_reference_profile && !has_profiles) { if (!has_reference_profile && !has_profiles) { Loading @@ -753,23 +739,23 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat return false; return false; } } fd_t output_fd = open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644); unique_fd output_fd(open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644)); if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { 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()); ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str()); return false; return false; } } std::vector<std::string> code_full_paths = base::Split(code_paths, ";"); std::vector<std::string> code_full_paths = base::Split(code_paths, ";"); std::vector<std::string> dex_locations; std::vector<std::string> dex_locations; std::vector<fd_t> apk_fds; std::vector<unique_fd> apk_fds; for (const std::string& code_full_path : code_full_paths) { for (const std::string& code_full_path : code_full_paths) { const char* full_path = code_full_path.c_str(); const char* full_path = code_full_path.c_str(); fd_t apk_fd = open(full_path, O_RDONLY | O_NOFOLLOW); unique_fd apk_fd(open(full_path, O_RDONLY | O_NOFOLLOW)); if (apk_fd == -1) { if (apk_fd == -1) { ALOGE("installd cannot open '%s'\n", full_path); ALOGE("installd cannot open '%s'\n", full_path); return false; return false; } } dex_locations.push_back(get_location_from_path(full_path)); dex_locations.push_back(get_location_from_path(full_path)); apk_fds.push_back(apk_fd); apk_fds.push_back(std::move(apk_fd)); } } pid_t pid = fork(); pid_t pid = fork(); Loading @@ -781,11 +767,6 @@ bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_pat exit(68); /* only get here on exec failure */ exit(68); /* only get here on exec failure */ } } /* parent */ /* parent */ close_all_fds(apk_fds, "apk_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); int return_code = wait_child(pid); if (!WIFEXITED(return_code)) { if (!WIFEXITED(return_code)) { LOG(WARNING) << "profman failed for package " << pkgname << ": " LOG(WARNING) << "profman failed for package " << pkgname << ": " Loading Loading @@ -1053,17 +1034,17 @@ Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_g // Creates the dexopt swap file if necessary and return its fd. // Creates the dexopt swap file if necessary and return its fd. // Returns -1 if there's no need for a swap or in case of errors. // Returns -1 if there's no need for a swap or in case of errors. base::unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) { unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) { if (!ShouldUseSwapFileForDexopt()) { if (!ShouldUseSwapFileForDexopt()) { return base::unique_fd(); return invalid_unique_fd(); } } // Make sure there really is enough space. // Make sure there really is enough space. char swap_file_name[PKG_PATH_MAX]; char swap_file_name[PKG_PATH_MAX]; strcpy(swap_file_name, out_oat_path); strcpy(swap_file_name, out_oat_path); if (!add_extension_to_file_name(swap_file_name, ".swap")) { if (!add_extension_to_file_name(swap_file_name, ".swap")) { return base::unique_fd(); return invalid_unique_fd(); } } base::unique_fd swap_fd(open_output_file( unique_fd swap_fd(open_output_file( swap_file_name, /*recreate*/true, /*permissions*/0600)); swap_file_name, /*recreate*/true, /*permissions*/0600)); if (swap_fd.get() < 0) { if (swap_fd.get() < 0) { // Could not create swap file. Optimistically go on and hope that we can compile // Could not create swap file. Optimistically go on and hope that we can compile Loading @@ -1088,8 +1069,9 @@ Dex2oatFileWrapper maybe_open_reference_profile(const char* pkgname, bool profil if (profile_guided && !is_secondary_dex && !is_public && (pkgname[0] != '*')) { if (profile_guided && !is_secondary_dex && !is_public && (pkgname[0] != '*')) { // Open reference profile in read only mode as dex2oat does not get write permissions. // Open reference profile in read only mode as dex2oat does not get write permissions. const std::string pkgname_str(pkgname); const std::string pkgname_str(pkgname); unique_fd profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ false); return Dex2oatFileWrapper( return Dex2oatFileWrapper( open_reference_profile(uid, pkgname, /*read_write*/ false), profile_fd.release(), [pkgname_str]() { [pkgname_str]() { clear_reference_profile(pkgname_str.c_str()); clear_reference_profile(pkgname_str.c_str()); }); }); Loading Loading @@ -1430,7 +1412,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins } } // Open the input file. // Open the input file. base::unique_fd input_fd(open(dex_path, O_RDONLY, 0)); unique_fd input_fd(open(dex_path, O_RDONLY, 0)); if (input_fd.get() < 0) { if (input_fd.get() < 0) { ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path); ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path); return -1; return -1; Loading @@ -1453,7 +1435,7 @@ int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* ins } } // Create a swap file if necessary. // Create a swap file if necessary. base::unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path); unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path); // Create the app image file if needed. // Create the app image file if needed. Dex2oatFileWrapper image_fd = Dex2oatFileWrapper image_fd = Loading
cmds/installd/dexopt.h +0 −2 Original line number Original line Diff line number Diff line Loading @@ -32,8 +32,6 @@ static constexpr int DEX2OAT_FOR_FILTER = 3; static constexpr int DEX2OAT_FOR_RELOCATION = 4; static constexpr int DEX2OAT_FOR_RELOCATION = 4; static constexpr int PATCHOAT_FOR_RELOCATION = 5; static constexpr int PATCHOAT_FOR_RELOCATION = 5; typedef int fd_t; bool clear_reference_profile(const std::string& pkgname); bool clear_reference_profile(const std::string& pkgname); bool clear_current_profile(const std::string& pkgname, userid_t user); bool clear_current_profile(const std::string& pkgname, userid_t user); bool clear_current_profiles(const std::string& pkgname); bool clear_current_profiles(const std::string& pkgname); Loading