Loading cmds/installd/InstalldNativeService.cpp +24 −1 Original line number Original line Diff line number Diff line Loading @@ -436,7 +436,7 @@ binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::s // profiles. // profiles. int shared_app_gid = multiuser_get_shared_gid(0, appId); int shared_app_gid = multiuser_get_shared_gid(0, appId); if ((shared_app_gid != -1) && fs_prepare_dir_strict( 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); return error("Failed to prepare " + ref_profile_path); } } } } Loading Loading @@ -1833,6 +1833,29 @@ binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::stri return ok(); 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, binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t uid, const std::unique_ptr<std::string>& packageName, const std::string& instructionSet, const std::unique_ptr<std::string>& packageName, const std::string& instructionSet, int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags, int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags, Loading cmds/installd/InstalldNativeService.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -96,6 +96,11 @@ public: binder::Status clearAppProfiles(const std::string& packageName); binder::Status clearAppProfiles(const std::string& packageName); binder::Status destroyAppProfiles(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, binder::Status idmap(const std::string& targetApkPath, const std::string& overlayApkPath, int32_t uid); int32_t uid); binder::Status removeIdmap(const std::string& overlayApkPath); binder::Status removeIdmap(const std::string& overlayApkPath); Loading cmds/installd/binder/android/os/IInstalld.aidl +3 −0 Original line number Original line Diff line number Diff line Loading @@ -62,6 +62,9 @@ interface IInstalld { void clearAppProfiles(@utf8InCpp String packageName); void clearAppProfiles(@utf8InCpp String packageName); void destroyAppProfiles(@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 idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid); void removeIdmap(@utf8InCpp String overlayApkPath); void removeIdmap(@utf8InCpp String overlayApkPath); void rmPackageDir(@utf8InCpp String packageDir); void rmPackageDir(@utf8InCpp String packageDir); Loading cmds/installd/dexopt.cpp +61 −21 Original line number Original line Diff line number Diff line Loading @@ -566,14 +566,12 @@ static void SetDex2OatScheduling(bool set_to_bg) { } } } } static bool create_profile(int uid, const std::string& profile) { 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(), O_CREAT | O_NOFOLLOW, 0600))); unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags, 0600))); if (fd.get() < 0) { if (fd.get() < 0) { if (errno == EEXIST) { if (errno != EEXIST) { return true; } else { PLOG(ERROR) << "Failed to create profile " << profile; 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 // Profiles should belong to the app; make sure of that by giving ownership to Loading @@ -581,27 +579,26 @@ static bool create_profile(int uid, const std::string& profile) { // since dex2oat/profman will fail with SElinux denials. // since dex2oat/profman will fail with SElinux denials. if (fchown(fd.get(), uid, uid) < 0) { if (fchown(fd.get(), uid, uid) < 0) { PLOG(ERROR) << "Could not chwon profile " << profile; 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 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: // Do not follow symlinks when opening a profile: // - primary profiles should not contain symlinks in their paths // - primary profiles should not contain symlinks in their paths // - secondary dex paths should have been already resolved and validated // - secondary dex paths should have been already resolved and validated flags |= O_NOFOLLOW; 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 (fd.get() < 0) { if (errno != ENOENT) { if (errno != ENOENT) { // Profiles might be missing for various reasons. For example, in a // Profiles might be missing for various reasons. For example, in a Loading @@ -621,13 +618,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, static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location, bool is_secondary_dex) { bool is_secondary_dex) { std::string profile = create_current_profile_path(user, location, 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, static unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write, bool is_secondary_dex) { bool is_secondary_dex) { std::string profile = create_reference_profile_path(location, 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, static void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex, Loading Loading @@ -2396,5 +2399,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 installd } // namespace android } // namespace android cmds/installd/dexopt.h +11 −0 Original line number Original line Diff line number Diff line Loading @@ -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(). // the reference profiles accessible with open_reference_profile(). bool analyze_primary_profiles(uid_t uid, const std::string& pkgname); 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 dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths); bool copy_system_profile(const std::string& system_profile, bool copy_system_profile(const std::string& system_profile, Loading Loading
cmds/installd/InstalldNativeService.cpp +24 −1 Original line number Original line Diff line number Diff line Loading @@ -436,7 +436,7 @@ binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::s // profiles. // profiles. int shared_app_gid = multiuser_get_shared_gid(0, appId); int shared_app_gid = multiuser_get_shared_gid(0, appId); if ((shared_app_gid != -1) && fs_prepare_dir_strict( 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); return error("Failed to prepare " + ref_profile_path); } } } } Loading Loading @@ -1833,6 +1833,29 @@ binder::Status InstalldNativeService::mergeProfiles(int32_t uid, const std::stri return ok(); 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, binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t uid, const std::unique_ptr<std::string>& packageName, const std::string& instructionSet, const std::unique_ptr<std::string>& packageName, const std::string& instructionSet, int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags, int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags, Loading
cmds/installd/InstalldNativeService.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -96,6 +96,11 @@ public: binder::Status clearAppProfiles(const std::string& packageName); binder::Status clearAppProfiles(const std::string& packageName); binder::Status destroyAppProfiles(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, binder::Status idmap(const std::string& targetApkPath, const std::string& overlayApkPath, int32_t uid); int32_t uid); binder::Status removeIdmap(const std::string& overlayApkPath); binder::Status removeIdmap(const std::string& overlayApkPath); Loading
cmds/installd/binder/android/os/IInstalld.aidl +3 −0 Original line number Original line Diff line number Diff line Loading @@ -62,6 +62,9 @@ interface IInstalld { void clearAppProfiles(@utf8InCpp String packageName); void clearAppProfiles(@utf8InCpp String packageName); void destroyAppProfiles(@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 idmap(@utf8InCpp String targetApkPath, @utf8InCpp String overlayApkPath, int uid); void removeIdmap(@utf8InCpp String overlayApkPath); void removeIdmap(@utf8InCpp String overlayApkPath); void rmPackageDir(@utf8InCpp String packageDir); void rmPackageDir(@utf8InCpp String packageDir); Loading
cmds/installd/dexopt.cpp +61 −21 Original line number Original line Diff line number Diff line Loading @@ -566,14 +566,12 @@ static void SetDex2OatScheduling(bool set_to_bg) { } } } } static bool create_profile(int uid, const std::string& profile) { 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(), O_CREAT | O_NOFOLLOW, 0600))); unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags, 0600))); if (fd.get() < 0) { if (fd.get() < 0) { if (errno == EEXIST) { if (errno != EEXIST) { return true; } else { PLOG(ERROR) << "Failed to create profile " << profile; 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 // Profiles should belong to the app; make sure of that by giving ownership to Loading @@ -581,27 +579,26 @@ static bool create_profile(int uid, const std::string& profile) { // since dex2oat/profman will fail with SElinux denials. // since dex2oat/profman will fail with SElinux denials. if (fchown(fd.get(), uid, uid) < 0) { if (fchown(fd.get(), uid, uid) < 0) { PLOG(ERROR) << "Could not chwon profile " << profile; 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 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: // Do not follow symlinks when opening a profile: // - primary profiles should not contain symlinks in their paths // - primary profiles should not contain symlinks in their paths // - secondary dex paths should have been already resolved and validated // - secondary dex paths should have been already resolved and validated flags |= O_NOFOLLOW; 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 (fd.get() < 0) { if (errno != ENOENT) { if (errno != ENOENT) { // Profiles might be missing for various reasons. For example, in a // Profiles might be missing for various reasons. For example, in a Loading @@ -621,13 +618,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, static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& location, bool is_secondary_dex) { bool is_secondary_dex) { std::string profile = create_current_profile_path(user, location, 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, static unique_fd open_reference_profile(uid_t uid, const std::string& location, bool read_write, bool is_secondary_dex) { bool is_secondary_dex) { std::string profile = create_reference_profile_path(location, 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, static void open_profile_files(uid_t uid, const std::string& location, bool is_secondary_dex, Loading Loading @@ -2396,5 +2399,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 installd } // namespace android } // namespace android
cmds/installd/dexopt.h +11 −0 Original line number Original line Diff line number Diff line Loading @@ -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(). // the reference profiles accessible with open_reference_profile(). bool analyze_primary_profiles(uid_t uid, const std::string& pkgname); 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 dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths); bool copy_system_profile(const std::string& system_profile, bool copy_system_profile(const std::string& system_profile, Loading