diff options
| -rw-r--r-- | cmds/installd/Android.bp | 2 | ||||
| -rw-r--r-- | cmds/installd/InstalldNativeService.cpp | 12 | ||||
| -rw-r--r-- | cmds/installd/InstalldNativeService.h | 3 | ||||
| -rw-r--r-- | cmds/installd/binder/android/os/IInstalld.aidl | 2 | ||||
| -rw-r--r-- | cmds/installd/dexopt.cpp | 21 | ||||
| -rw-r--r-- | cmds/installd/utils.cpp | 23 | ||||
| -rw-r--r-- | cmds/installd/utils.h | 2 | ||||
| -rw-r--r-- | cmds/installd/view_compiler.cpp | 99 | ||||
| -rw-r--r-- | cmds/installd/view_compiler.h | 29 |
9 files changed, 172 insertions, 21 deletions
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp index 6f4e6993e9..a6f77aa086 100644 --- a/cmds/installd/Android.bp +++ b/cmds/installd/Android.bp @@ -18,6 +18,7 @@ cc_defaults { "dexopt.cpp", "globals.cpp", "utils.cpp", + "view_compiler.cpp", ":installd_aidl", ], header_libs: [ @@ -190,6 +191,7 @@ cc_binary { "globals.cpp", "otapreopt.cpp", "utils.cpp", + "view_compiler.cpp", ], header_libs: ["dex2oat_headers"], diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 2439dff54e..8a036a5c1c 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -60,6 +60,7 @@ #include "installd_deps.h" #include "otapreopt_utils.h" #include "utils.h" +#include "view_compiler.h" #include "CacheTracker.h" #include "MatchExtensionGen.h" @@ -1831,6 +1832,17 @@ binder::Status InstalldNativeService::dexopt(const std::string& apkPath, int32_t return res ? error(res, error_msg) : ok(); } +binder::Status InstalldNativeService::compileLayouts(const std::string& apkPath, + const std::string& packageName, + const std ::string& outDexFile, int uid, + bool* _aidl_return) { + const char* apk_path = apkPath.c_str(); + const char* package_name = packageName.c_str(); + const char* out_dex_file = outDexFile.c_str(); + *_aidl_return = android::installd::view_compiler(apk_path, package_name, out_dex_file, uid); + return *_aidl_return ? ok() : error("viewcompiler failed"); +} + binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) { ENFORCE_UID(AID_SYSTEM); std::lock_guard<std::recursive_mutex> lock(mLock); diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h index 367f2c1547..d482472605 100644 --- a/cmds/installd/InstalldNativeService.h +++ b/cmds/installd/InstalldNativeService.h @@ -89,6 +89,9 @@ public: const std::unique_ptr<std::string>& dexMetadataPath, const std::unique_ptr<std::string>& compilationReason); + binder::Status compileLayouts(const std::string& apkPath, const std::string& packageName, + const std::string& outDexFile, int uid, bool* _aidl_return); + binder::Status rmdex(const std::string& codePath, const std::string& instructionSet); binder::Status mergeProfiles(int32_t uid, const std::string& packageName, diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 91e20b75ae..caa0b67a4c 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -55,6 +55,8 @@ interface IInstalld { @nullable @utf8InCpp String profileName, @nullable @utf8InCpp String dexMetadataPath, @nullable @utf8InCpp String compilationReason); + boolean compileLayouts(@utf8InCpp String apkPath, @utf8InCpp String packageName, + @utf8InCpp String outDexFile, int uid); void rmdex(@utf8InCpp String codePath, @utf8InCpp String instructionSet); diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp index 07ea77b205..e3a35c71d4 100644 --- a/cmds/installd/dexopt.cpp +++ b/cmds/installd/dexopt.cpp @@ -628,27 +628,6 @@ static void open_profile_files(uid_t uid, const std::string& package_name, } } -static void drop_capabilities(uid_t uid) { - if (setgid(uid) != 0) { - PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt"; - exit(DexoptReturnCodes::kSetGid); - } - if (setuid(uid) != 0) { - PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt"; - exit(DexoptReturnCodes::kSetUid); - } - // drop capabilities - struct __user_cap_header_struct capheader; - struct __user_cap_data_struct capdata[2]; - memset(&capheader, 0, sizeof(capheader)); - memset(&capdata, 0, sizeof(capdata)); - capheader.version = _LINUX_CAPABILITY_VERSION_3; - if (capset(&capheader, &capdata[0]) < 0) { - PLOG(ERROR) << "capset failed"; - exit(DexoptReturnCodes::kCapSet); - } -} - static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0; static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1; static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2; diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp index 74ad1841a5..bbf14cb5f7 100644 --- a/cmds/installd/utils.cpp +++ b/cmds/installd/utils.cpp @@ -20,6 +20,7 @@ #include <fcntl.h> #include <fts.h> #include <stdlib.h> +#include <sys/capability.h> #include <sys/stat.h> #include <sys/wait.h> #include <sys/xattr.h> @@ -34,6 +35,7 @@ #include <log/log.h> #include <private/android_filesystem_config.h> +#include "dexopt_return_codes.h" #include "globals.h" // extern variables. #ifndef LOG_TAG @@ -1063,5 +1065,26 @@ bool collect_profiles(std::vector<std::string>* profiles_paths) { } } +void drop_capabilities(uid_t uid) { + if (setgid(uid) != 0) { + PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt"; + exit(DexoptReturnCodes::kSetGid); + } + if (setuid(uid) != 0) { + PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt"; + exit(DexoptReturnCodes::kSetUid); + } + // drop capabilities + struct __user_cap_header_struct capheader; + struct __user_cap_data_struct capdata[2]; + memset(&capheader, 0, sizeof(capheader)); + memset(&capdata, 0, sizeof(capdata)); + capheader.version = _LINUX_CAPABILITY_VERSION_3; + if (capset(&capheader, &capdata[0]) < 0) { + PLOG(ERROR) << "capset failed"; + exit(DexoptReturnCodes::kCapSet); + } +} + } // namespace installd } // namespace android diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h index d05724a8f0..206ad4158a 100644 --- a/cmds/installd/utils.h +++ b/cmds/installd/utils.h @@ -140,6 +140,8 @@ int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t ta // It returns true if there were no errors at all, and false otherwise. bool collect_profiles(std::vector<std::string>* profiles_paths); +void drop_capabilities(uid_t uid); + } // namespace installd } // namespace android diff --git a/cmds/installd/view_compiler.cpp b/cmds/installd/view_compiler.cpp new file mode 100644 index 0000000000..f1ac7178f6 --- /dev/null +++ b/cmds/installd/view_compiler.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "view_compiler.h" + +#include <string> + +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "utils.h" + +#include "android-base/logging.h" +#include "android-base/stringprintf.h" +#include "android-base/unique_fd.h" + +namespace android { +namespace installd { + +using base::unique_fd; + +bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file, + int uid) { + CHECK(apk_path != nullptr); + CHECK(package_name != nullptr); + CHECK(out_dex_file != nullptr); + + // viewcompiler won't have permission to open anything, so we have to open the files first + // and pass file descriptors. + + // Open input file + unique_fd infd{open(apk_path, 0)}; + if (infd.get() < 0) { + PLOG(ERROR) << "Could not open input file: " << apk_path; + return false; + } + + // Set up output file. viewcompiler can't open outputs by fd, but it can write to stdout, so + // we close stdout and open it towards the right output. + unique_fd outfd{open(out_dex_file, O_CREAT | O_TRUNC | O_WRONLY, 0644)}; + if (outfd.get() < 0) { + PLOG(ERROR) << "Could not open output file: " << out_dex_file; + return false; + } + if (fchmod(outfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) != 0) { + PLOG(ERROR) << "Could not change output file permissions"; + return false; + } + if (close(STDOUT_FILENO) != 0) { + PLOG(ERROR) << "Could not close stdout"; + return false; + } + if (dup2(outfd, STDOUT_FILENO) < 0) { + PLOG(ERROR) << "Could not duplicate output file descriptor"; + return false; + } + + // Prepare command line arguments for viewcompiler + std::string args[] = {"/system/bin/viewcompiler", + "--apk", + "--infd", + android::base::StringPrintf("%d", infd.get()), + "--dex", + "--package", + package_name}; + char* const argv[] = {const_cast<char*>(args[0].c_str()), const_cast<char*>(args[1].c_str()), + const_cast<char*>(args[2].c_str()), const_cast<char*>(args[3].c_str()), + const_cast<char*>(args[4].c_str()), const_cast<char*>(args[5].c_str()), + const_cast<char*>(args[6].c_str()), nullptr}; + + pid_t pid = fork(); + if (pid == 0) { + // Now that we've opened the files we need, drop privileges. + drop_capabilities(uid); + execv("/system/bin/viewcompiler", argv); + _exit(1); + } + + return wait_child(pid) == 0; +} + +} // namespace installd +} // namespace android
\ No newline at end of file diff --git a/cmds/installd/view_compiler.h b/cmds/installd/view_compiler.h new file mode 100644 index 0000000000..f7c6e57722 --- /dev/null +++ b/cmds/installd/view_compiler.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VIEW_COMPILER_H_ +#define VIEW_COMPILER_H_ + +namespace android { +namespace installd { + +bool view_compiler(const char* apk_path, const char* package_name, const char* out_dex_file, + int uid); + +} // namespace installd +} // namespace android + +#endif // VIEW_COMPILER_H_
\ No newline at end of file |