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

Commit 98ad260f authored by Calin Juravle's avatar Calin Juravle Committed by Gerrit Code Review
Browse files

Merge "Add snapshotProfile APIs to installd"

parents 8a213534 29591736
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -436,7 +436,7 @@ binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::s
            // profiles.
            int shared_app_gid = multiuser_get_shared_gid(0, appId);
            if ((shared_app_gid != -1) && fs_prepare_dir_strict(
                    ref_profile_path.c_str(), 0700, shared_app_gid, shared_app_gid) != 0) {
                    ref_profile_path.c_str(), 0701, shared_app_gid, shared_app_gid) != 0) {
                return error("Failed to prepare " + ref_profile_path);
            }
        }
@@ -1833,6 +1833,29 @@ binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::stri
    return ok();
}

binder::Status InstalldNativeService::snapshotProfile(int32_t appId, const std::string& packageName,
        const std::string& codePath, bool* _aidl_return) {
    ENFORCE_UID(AID_SYSTEM);
    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    std::lock_guard<std::recursive_mutex> lock(mLock);

    *_aidl_return = snapshot_profile(appId, packageName, codePath);
    return ok();
}

binder::Status InstalldNativeService::destroyProfileSnapshot(const std::string& packageName,
        const std::string& codePath) {
    ENFORCE_UID(AID_SYSTEM);
    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
    std::lock_guard<std::recursive_mutex> lock(mLock);

    std::string snapshot = create_snapshot_profile_path(packageName, codePath);
    if ((unlink(snapshot.c_str()) != 0) && (errno != ENOENT)) {
        return error("Failed to destroy profile snapshot for " + packageName + ":" + codePath);
    }
    return ok();
}

binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t uid,
        const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
        int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
+5 −0
Original line number Diff line number Diff line
@@ -96,6 +96,11 @@ public:
    binder::Status clearAppProfiles(const std::string& packageName);
    binder::Status destroyAppProfiles(const std::string& packageName);

    binder::Status snapshotProfile(int32_t appId, const std::string& packageName,
            const std::string& codePath, bool* _aidl_return);
    binder::Status destroyProfileSnapshot(const std::string& packageName,
            const std::string& codePath);

    binder::Status idmap(const std::string& targetApkPath, const std::string& overlayApkPath,
            int32_t uid);
    binder::Status removeIdmap(const std::string& overlayApkPath);
+3 −0
Original line number Diff line number Diff line
@@ -62,6 +62,9 @@ interface IInstalld {
    void clearAppProfiles(@utf8InCpp String packageName);
    void destroyAppProfiles(@utf8InCpp String packageName);

    boolean snapshotProfile(int appId, @utf8InCpp String packageName, @utf8InCpp String codePath);
    void destroyProfileSnapshot(@utf8InCpp String packageName, @utf8InCpp String codePath);

    void idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid);
    void removeIdmap(@utf8InCpp String overlayApkPath);
    void rmPackageDir(@utf8InCpp String packageDir);
+61 −21
Original line number Diff line number Diff line
@@ -561,14 +561,12 @@ static void SetDex2OatScheduling(bool set_to_bg) {
    }
}

static bool create_profile(int uid, const std::string& profile) {
    unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), O_CREAT | O_NOFOLLOW, 0600)));
static unique_fd create_profile(uid_t uid, const std::string& profile, int32_t flags) {
    unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags, 0600)));
    if (fd.get() < 0) {
        if (errno == EEXIST) {
            return true;
        } else {
        if (errno != EEXIST) {
            PLOG(ERROR) << "Failed to create profile " << profile;
            return false;
            return invalid_unique_fd();
        }
    }
    // Profiles should belong to the app; make sure of that by giving ownership to
@@ -576,27 +574,26 @@ static bool create_profile(int uid, const std::string& profile) {
    // since dex2oat/profman will fail with SElinux denials.
    if (fchown(fd.get(), uid, uid) < 0) {
        PLOG(ERROR) << "Could not chwon profile " << profile;
        return false;
    }
    return true;
}

static unique_fd open_profile(int uid, const std::string& profile, bool read_write) {
    // Check if we need to open the profile for a read-write operation. If so, we
    // might need to create the profile since the file might not be there. Reference
    // profiles are created on the fly so they might not exist beforehand.
    if (read_write) {
        if (!create_profile(uid, profile)) {
        return invalid_unique_fd();
    }
    return fd;
}
    int flags = read_write ? O_RDWR : O_RDONLY;

static unique_fd open_profile(uid_t uid, const std::string& profile, int32_t flags) {
    // Do not follow symlinks when opening a profile:
    //   - primary profiles should not contain symlinks in their paths
    //   - secondary dex paths should have been already resolved and validated
    flags |= O_NOFOLLOW;

    unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags)));
    // Check if we need to create the profile
    // Reference profiles and snapshots are created on the fly; so they might not exist beforehand.
    unique_fd fd;
    if ((flags & O_CREAT) != 0) {
        fd = create_profile(uid, profile, flags);
    } else {
        fd.reset(TEMP_FAILURE_RETRY(open(profile.c_str(), flags)));
    }

    if (fd.get() < 0) {
        if (errno != ENOENT) {
            // Profiles might be missing for various reasons. For example, in a
@@ -616,13 +613,19 @@ static unique_fd open_profile(int uid, const std::string& profile, bool read_wri
static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location,
        bool is_secondary_dex) {
    std::string profile = create_current_profile_path(user, location, is_secondary_dex);
    return open_profile(uid, profile, /*read_write*/false);
    return open_profile(uid, profile, O_RDONLY);
}

static unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write,
        bool is_secondary_dex) {
    std::string profile = create_reference_profile_path(location, is_secondary_dex);
    return open_profile(uid, profile, read_write);
    return open_profile(uid, profile, read_write ? (O_CREAT | O_RDWR) : O_RDONLY);
}

static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name,
        const std::string& code_path) {
    std::string profile = create_snapshot_profile_path(package_name, code_path);
    return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC);
}

static void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex,
@@ -2307,5 +2310,42 @@ bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src,
    }
}

bool snapshot_profile(int32_t app_id, const std::string& package_name,
        const std::string& code_path) {
    int app_shared_gid = multiuser_get_shared_gid(/*user_id*/ 0, app_id);

    unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, code_path);
    if (snapshot_fd < 0) {
        return false;
    }

    std::vector<unique_fd> profiles_fd;
    unique_fd reference_profile_fd;
    open_profile_files(app_shared_gid, package_name, /*is_secondary_dex*/ false, &profiles_fd,
            &reference_profile_fd);
    if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
        return false;
    }

    profiles_fd.push_back(std::move(reference_profile_fd));

    pid_t pid = fork();
    if (pid == 0) {
        /* child -- drop privileges before continuing */
        drop_capabilities(app_shared_gid);
        run_profman_merge(profiles_fd, snapshot_fd);
        exit(42);   /* only get here on exec failure */
    }

    /* parent */
    int return_code = wait_child(pid);
    if (!WIFEXITED(return_code)) {
        LOG(WARNING) << "profman failed for " << package_name << ":" << code_path;
        return false;
    }

    return true;
}

}  // namespace installd
}  // namespace android
+11 −0
Original line number Diff line number Diff line
@@ -50,6 +50,17 @@ bool move_ab(const char* apk_path, const char* instruction_set, const char* outp
// the reference profiles accessible with open_reference_profile().
bool analyze_primary_profiles(uid_t uid, const std::string& pkgname);

// Create a snapshot of the profile information for the given package and code path.
// The profile snapshot is the aggregation of all existing profiles (all current user
// profiles & the reference profile) and is meant to capture the all the profile information
// without performing a merge into the reference profile which might impact future dex2oat
// compilations.
// The snapshot is created next to the reference profile of the package and the
// ownership is assigned to AID_SYSTEM.
// The snapshot location is reference_profile_location.snapshot. If a snapshot is already
// there, it will be truncated and overwritten.
bool snapshot_profile(int32_t app_id, const std::string& package, const std::string& code_path);

bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths);

bool copy_system_profile(const std::string& system_profile,
Loading