[installd] Prepare profiles for app code paths
Implement profile preparation for individual application code paths.
The preparation is:
- create the current profile
- merge the profile from the dex metadata file (if present) into the
reference profile.
Note: currently the current profile is created as part of
InstalldNativeService::createAppData for the entire package. That logic
does not support dex metadata or individual code paths and will be removed
once the PackageManager switches over the new method.
Test: installd_dexopt_test
Bug: 30934496
Change-Id: I2aeddcda7b78017bd46838985bef5f92a79d4573
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 37f51e0..65fbdb5 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -2472,5 +2472,55 @@
return true;
}
+bool prepare_app_profile(const std::string& package_name,
+ userid_t user_id,
+ appid_t app_id,
+ const std::string& profile_name,
+ const std::string& code_path ATTRIBUTE_UNUSED,
+ const std::unique_ptr<std::string>& dex_metadata) {
+ // Prepare the current profile.
+ std::string cur_profile = create_current_profile_path(user_id, package_name, profile_name,
+ /*is_secondary_dex*/ false);
+ uid_t uid = multiuser_get_uid(user_id, app_id);
+ if (fs_prepare_file_strict(cur_profile.c_str(), 0600, uid, uid) != 0) {
+ PLOG(ERROR) << "Failed to prepare " << cur_profile;
+ return false;
+ }
+
+ // Check if we need to install the profile from the dex metadata.
+ if (dex_metadata == nullptr) {
+ return true;
+ }
+
+ // We have a dex metdata. Merge the profile into the reference profile.
+ unique_fd ref_profile_fd = open_reference_profile(uid, package_name, profile_name,
+ /*read_write*/ true, /*is_secondary_dex*/ false);
+ unique_fd dex_metadata_fd(TEMP_FAILURE_RETRY(
+ open(dex_metadata->c_str(), O_RDONLY | O_NOFOLLOW)));
+ std::vector<unique_fd> profiles_fd;
+ profiles_fd.push_back(std::move(dex_metadata_fd));
+
+ pid_t pid = fork();
+ if (pid == 0) {
+ /* child -- drop privileges before continuing */
+ gid_t app_shared_gid = multiuser_get_shared_gid(user_id, app_id);
+ drop_capabilities(app_shared_gid);
+
+ // TODO(calin): the dex metadata profile might embed different names for the
+ // same code path (e.g. YouTube.apk or base.apk, depending on how the initial
+ // profile was captured). We should pass the code path to adjust the names in the profile.
+ run_profman_merge(profiles_fd, ref_profile_fd);
+ exit(42); /* only get here on exec failure */
+ }
+
+ /* parent */
+ int return_code = wait_child(pid);
+ if (!WIFEXITED(return_code)) {
+ PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
+ return false;
+ }
+ return true;
+}
+
} // namespace installd
} // namespace android