Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0acbc6bb authored by Calin Juravle's avatar Calin Juravle Committed by android-build-merger
Browse files

Merge "Use unique_fd instead of fd_t when managing profiles" am: 02971e33

am: 9f6666ae

Change-Id: I77f6d375afbcb85a77b640a0d47ba741c08bd406
parents d47b3c13 9f6666ae
Loading
Loading
Loading
Loading
+64 −82
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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;
@@ -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.
@@ -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));
        }
        }
    }
    }
}
}
@@ -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()];
@@ -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;
    }
    }


@@ -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);
    }
    }
@@ -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;
@@ -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) {
@@ -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();
@@ -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 << ": "
@@ -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
@@ -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());
                });
                });
@@ -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;
@@ -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 =
+0 −2
Original line number Original line Diff line number Diff line
@@ -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);