blob: 2b360679835277fae8e6757a67908751c0e1099e [file] [log] [blame]
Jeff Sharkey6c2c0562016-12-07 12:12:00 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Alan Stokescb27c342018-04-20 17:09:25 +010016#define LOG_TAG "installd"
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070017
Alan Stokesa25d90c2017-10-16 10:56:00 +010018#include <array>
Jeff Sharkey90aff262016-12-12 14:28:24 -070019#include <fcntl.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070020#include <stdlib.h>
21#include <string.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070022#include <sys/capability.h>
23#include <sys/file.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070024#include <sys/stat.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070025#include <sys/time.h>
26#include <sys/types.h>
27#include <sys/resource.h>
28#include <sys/wait.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070029#include <unistd.h>
30
Andreas Gampe023b2242018-02-28 16:03:25 -080031#include <iomanip>
32
Alan Stokesa25d90c2017-10-16 10:56:00 +010033#include <android-base/file.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070034#include <android-base/logging.h>
Andreas Gampe6a9cf722017-07-24 16:49:10 -070035#include <android-base/properties.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070036#include <android-base/stringprintf.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070037#include <android-base/strings.h>
38#include <android-base/unique_fd.h>
Calin Juravle80a21252017-01-17 14:43:25 -080039#include <cutils/fs.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070040#include <cutils/properties.h>
41#include <cutils/sched_policy.h>
Andreas Gampefa2dadd2018-02-28 19:52:47 -080042#include <dex2oat_return_codes.h>
Mark Salyzyn7823e122016-09-29 08:08:05 -070043#include <log/log.h> // TODO: Move everything to base/logging.
Alan Stokesa25d90c2017-10-16 10:56:00 +010044#include <openssl/sha.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070045#include <private/android_filesystem_config.h>
Suren Baghdasaryan1cc5de62019-01-25 05:29:23 +000046#include <processgroup/sched_policy.h>
Calin Juravlecb556e32017-04-04 20:22:50 -070047#include <selinux/android.h>
Nicolas Geoffrayaaad21e2019-02-25 13:31:10 +000048#include <server_configurable_flags/get_flags.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070049#include <system/thread_defs.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070050
51#include "dexopt.h"
Andreas Gampefa2dadd2018-02-28 19:52:47 -080052#include "dexopt_return_codes.h"
Victor Hsiehc9821f12020-08-07 11:32:29 -070053#include "execv_helper.h"
Jeff Sharkeyc1149c92017-09-21 14:51:09 -060054#include "globals.h"
Jeff Sharkey90aff262016-12-12 14:28:24 -070055#include "installd_deps.h"
56#include "otapreopt_utils.h"
Victor Hsiehc9821f12020-08-07 11:32:29 -070057#include "run_dex2oat.h"
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070058#include "utils.h"
59
Victor Hsieh76f19ba2020-08-10 14:37:26 -070060using android::base::Basename;
Jeff Sharkey90aff262016-12-12 14:28:24 -070061using android::base::EndsWith;
Mathieu Chartier9b2da082018-10-26 13:23:11 -070062using android::base::GetBoolProperty;
63using android::base::GetProperty;
David Brazdil4f6027a2019-03-19 11:44:21 +000064using android::base::ReadFdToString;
Alan Stokesa25d90c2017-10-16 10:56:00 +010065using android::base::ReadFully;
66using android::base::StringPrintf;
67using android::base::WriteFully;
Calin Juravle1a0af3b2017-03-09 14:33:33 -080068using android::base::unique_fd;
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070069
70namespace android {
71namespace installd {
72
Andreas Gampefa2dadd2018-02-28 19:52:47 -080073
Calin Juravle114f0812017-03-08 19:05:07 -080074// Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
75struct FreeDelete {
76 // NOTE: Deleting a const object is valid but free() takes a non-const pointer.
77 void operator()(const void* ptr) const {
78 free(const_cast<void*>(ptr));
79 }
80};
81
82// Alias for std::unique_ptr<> that uses the C function free() to delete objects.
83template <typename T>
84using UniqueCPtr = std::unique_ptr<T, FreeDelete>;
85
Calin Juravle1a0af3b2017-03-09 14:33:33 -080086static unique_fd invalid_unique_fd() {
87 return unique_fd(-1);
88}
89
Andreas Gampe6a9cf722017-07-24 16:49:10 -070090static bool is_debug_runtime() {
91 return android::base::GetProperty("persist.sys.dalvik.vm.lib.2", "") == "libartd.so";
92}
93
David Sehra3b5ab62017-10-25 14:27:29 -070094static bool is_debuggable_build() {
95 return android::base::GetBoolProperty("ro.debuggable", false);
96}
97
Jeff Sharkey90aff262016-12-12 14:28:24 -070098static bool clear_profile(const std::string& profile) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -080099 unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700100 if (ufd.get() < 0) {
101 if (errno != ENOENT) {
102 PLOG(WARNING) << "Could not open profile " << profile;
103 return false;
104 } else {
105 // Nothing to clear. That's ok.
106 return true;
107 }
108 }
109
110 if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
111 if (errno != EWOULDBLOCK) {
112 PLOG(WARNING) << "Error locking profile " << profile;
113 }
114 // This implies that the app owning this profile is running
115 // (and has acquired the lock).
116 //
117 // If we can't acquire the lock bail out since clearing is useless anyway
118 // (the app will write again to the profile).
119 //
120 // Note:
121 // This does not impact the this is not an issue for the profiling correctness.
122 // In case this is needed because of an app upgrade, profiles will still be
123 // eventually cleared by the app itself due to checksum mismatch.
124 // If this is needed because profman advised, then keeping the data around
125 // until the next run is again not an issue.
126 //
127 // If the app attempts to acquire a lock while we've held one here,
128 // it will simply skip the current write cycle.
129 return false;
130 }
131
132 bool truncated = ftruncate(ufd.get(), 0) == 0;
133 if (!truncated) {
134 PLOG(WARNING) << "Could not truncate " << profile;
135 }
136 if (flock(ufd.get(), LOCK_UN) != 0) {
137 PLOG(WARNING) << "Error unlocking profile " << profile;
138 }
139 return truncated;
140}
141
Calin Juravle114f0812017-03-08 19:05:07 -0800142// Clear the reference profile for the given location.
Calin Juravle824a64d2018-01-18 20:23:17 -0800143// The location is the profile name for primary apks or the dex path for secondary dex files.
144static bool clear_reference_profile(const std::string& package_name, const std::string& location,
145 bool is_secondary_dex) {
146 return clear_profile(create_reference_profile_path(package_name, location, is_secondary_dex));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700147}
148
Calin Juravle114f0812017-03-08 19:05:07 -0800149// Clear the reference profile for the given location.
Calin Juravle824a64d2018-01-18 20:23:17 -0800150// The location is the profile name for primary apks or the dex path for secondary dex files.
151static bool clear_current_profile(const std::string& package_name, const std::string& location,
152 userid_t user, bool is_secondary_dex) {
153 return clear_profile(create_current_profile_path(user, package_name, location,
154 is_secondary_dex));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700155}
156
Calin Juravle114f0812017-03-08 19:05:07 -0800157// Clear the reference profile for the primary apk of the given package.
Calin Juravle824a64d2018-01-18 20:23:17 -0800158// The location is the profile name for primary apks or the dex path for secondary dex files.
159bool clear_primary_reference_profile(const std::string& package_name,
160 const std::string& location) {
161 return clear_reference_profile(package_name, location, /*is_secondary_dex*/false);
Calin Juravle114f0812017-03-08 19:05:07 -0800162}
163
164// Clear all current profile for the primary apk of the given package.
Calin Juravle824a64d2018-01-18 20:23:17 -0800165// The location is the profile name for primary apks or the dex path for secondary dex files.
166bool clear_primary_current_profiles(const std::string& package_name, const std::string& location) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700167 bool success = true;
Calin Juravle114f0812017-03-08 19:05:07 -0800168 // For secondary dex files, we don't really need the user but we use it for sanity checks.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700169 std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
170 for (auto user : users) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800171 success &= clear_current_profile(package_name, location, user, /*is_secondary_dex*/false);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700172 }
173 return success;
174}
175
Calin Juravle114f0812017-03-08 19:05:07 -0800176// Clear the current profile for the primary apk of the given package and user.
Calin Juravle824a64d2018-01-18 20:23:17 -0800177bool clear_primary_current_profile(const std::string& package_name, const std::string& location,
178 userid_t user) {
179 return clear_current_profile(package_name, location, user, /*is_secondary_dex*/false);
Calin Juravle114f0812017-03-08 19:05:07 -0800180}
181
Calin Juravlef74a7372019-02-28 20:29:41 -0800182// Determines which binary we should use for execution (the debug or non-debug version).
183// e.g. dex2oatd vs dex2oat
184static const char* select_execution_binary(const char* binary, const char* debug_binary,
185 bool background_job_compile) {
186 return select_execution_binary(
187 binary,
188 debug_binary,
189 background_job_compile,
190 is_debug_runtime(),
191 (android::base::GetProperty("ro.build.version.codename", "") == "REL"),
192 is_debuggable_build());
193}
194
195// Determines which binary we should use for execution (the debug or non-debug version).
196// e.g. dex2oatd vs dex2oat
197// This is convenient method which is much easier to test because it doesn't read
198// system properties.
199const char* select_execution_binary(
200 const char* binary,
201 const char* debug_binary,
202 bool background_job_compile,
203 bool is_debug_runtime,
204 bool is_release,
205 bool is_debuggable_build) {
206 // Do not use debug binaries for release candidates (to give more soak time).
207 bool is_debug_bg_job = background_job_compile && is_debuggable_build && !is_release;
208
209 // If the runtime was requested to use libartd.so, we'll run the debug version - assuming
210 // the file is present (it may not be on images with very little space available).
211 bool useDebug = (is_debug_runtime || is_debug_bg_job) && (access(debug_binary, X_OK) == 0);
212
213 return useDebug ? debug_binary : binary;
214}
215
Nicolas Geoffrayaaad21e2019-02-25 13:31:10 +0000216// Namespace for Android Runtime flags applied during boot time.
217static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot";
218// Feature flag name for running the JIT in Zygote experiment, b/119800099.
Nicolas Geoffray5a4c4e92020-02-07 11:37:34 +0000219static const char* ENABLE_JITZYGOTE_IMAGE = "enable_apex_image";
Nicolas Geoffrayaaad21e2019-02-25 13:31:10 +0000220
Mathieu Chartiere97261e2019-10-01 15:36:01 -0700221// Phenotype property name for enabling profiling the boot class path.
222static const char* PROFILE_BOOT_CLASS_PATH = "profilebootclasspath";
223
Calin Juravlef85ddb92020-05-01 14:05:40 -0700224static bool IsBootClassPathProfilingEnable() {
225 std::string profile_boot_class_path = GetProperty("dalvik.vm.profilebootclasspath", "");
226 profile_boot_class_path =
227 server_configurable_flags::GetServerConfigurableFlag(
228 RUNTIME_NATIVE_BOOT_NAMESPACE,
229 PROFILE_BOOT_CLASS_PATH,
230 /*default_value=*/ profile_boot_class_path);
231 return profile_boot_class_path == "true";
232}
233
Jeff Sharkey90aff262016-12-12 14:28:24 -0700234/*
235 * Whether dexopt should use a swap file when compiling an APK.
236 *
237 * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision
238 * itself, anyways).
239 *
240 * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true".
241 *
242 * Otherwise, return true if this is a low-mem device.
243 *
244 * Otherwise, return default value.
245 */
246static bool kAlwaysProvideSwapFile = false;
247static bool kDefaultProvideSwapFile = true;
248
249static bool ShouldUseSwapFileForDexopt() {
250 if (kAlwaysProvideSwapFile) {
251 return true;
252 }
253
254 // Check the "override" property. If it exists, return value == "true".
Mathieu Chartier9b2da082018-10-26 13:23:11 -0700255 std::string dex2oat_prop_buf = GetProperty("dalvik.vm.dex2oat-swap", "");
256 if (!dex2oat_prop_buf.empty()) {
257 return dex2oat_prop_buf == "true";
Jeff Sharkey90aff262016-12-12 14:28:24 -0700258 }
259
260 // Shortcut for default value. This is an implementation optimization for the process sketched
261 // above. If the default value is true, we can avoid to check whether this is a low-mem device,
262 // as low-mem is never returning false. The compiler will optimize this away if it can.
263 if (kDefaultProvideSwapFile) {
264 return true;
265 }
266
Mathieu Chartier9b2da082018-10-26 13:23:11 -0700267 if (GetBoolProperty("ro.config.low_ram", false)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700268 return true;
269 }
270
271 // Default value must be false here.
272 return kDefaultProvideSwapFile;
273}
274
Richard Uhler76cc0272016-12-08 10:46:35 +0000275static void SetDex2OatScheduling(bool set_to_bg) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700276 if (set_to_bg) {
277 if (set_sched_policy(0, SP_BACKGROUND) < 0) {
Andreas Gampefa2dadd2018-02-28 19:52:47 -0800278 PLOG(ERROR) << "set_sched_policy failed";
279 exit(DexoptReturnCodes::kSetSchedPolicy);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700280 }
281 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
Andreas Gampefa2dadd2018-02-28 19:52:47 -0800282 PLOG(ERROR) << "setpriority failed";
283 exit(DexoptReturnCodes::kSetPriority);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700284 }
285 }
286}
287
Calin Juravle29591732017-11-20 17:46:19 -0800288static unique_fd create_profile(uid_t uid, const std::string& profile, int32_t flags) {
289 unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags, 0600)));
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800290 if (fd.get() < 0) {
Calin Juravle29591732017-11-20 17:46:19 -0800291 if (errno != EEXIST) {
Calin Juravle114f0812017-03-08 19:05:07 -0800292 PLOG(ERROR) << "Failed to create profile " << profile;
Calin Juravle29591732017-11-20 17:46:19 -0800293 return invalid_unique_fd();
Calin Juravle114f0812017-03-08 19:05:07 -0800294 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700295 }
Calin Juravle114f0812017-03-08 19:05:07 -0800296 // Profiles should belong to the app; make sure of that by giving ownership to
297 // the app uid. If we cannot do that, there's no point in returning the fd
298 // since dex2oat/profman will fail with SElinux denials.
299 if (fchown(fd.get(), uid, uid) < 0) {
Roland Levillain019db5b2019-03-14 14:31:59 +0000300 PLOG(ERROR) << "Could not chown profile " << profile;
Calin Juravle29591732017-11-20 17:46:19 -0800301 return invalid_unique_fd();
Calin Juravle114f0812017-03-08 19:05:07 -0800302 }
Calin Juravle29591732017-11-20 17:46:19 -0800303 return fd;
Calin Juravle114f0812017-03-08 19:05:07 -0800304}
305
Calin Juravle29591732017-11-20 17:46:19 -0800306static unique_fd open_profile(uid_t uid, const std::string& profile, int32_t flags) {
Calin Juravle114f0812017-03-08 19:05:07 -0800307 // Do not follow symlinks when opening a profile:
308 // - primary profiles should not contain symlinks in their paths
309 // - secondary dex paths should have been already resolved and validated
310 flags |= O_NOFOLLOW;
311
Calin Juravle29591732017-11-20 17:46:19 -0800312 // Check if we need to create the profile
313 // Reference profiles and snapshots are created on the fly; so they might not exist beforehand.
314 unique_fd fd;
315 if ((flags & O_CREAT) != 0) {
316 fd = create_profile(uid, profile, flags);
317 } else {
318 fd.reset(TEMP_FAILURE_RETRY(open(profile.c_str(), flags)));
319 }
320
Calin Juravle114f0812017-03-08 19:05:07 -0800321 if (fd.get() < 0) {
322 if (errno != ENOENT) {
323 // Profiles might be missing for various reasons. For example, in a
324 // multi-user environment, the profile directory for one user can be created
325 // after we start a merge. In this case the current profile for that user
326 // will not be found.
327 // Also, the secondary dex profiles might be deleted by the app at any time,
328 // so we can't we need to prepare if they are missing.
329 PLOG(ERROR) << "Failed to open profile " << profile;
330 }
331 return invalid_unique_fd();
332 }
333
Jeff Sharkey90aff262016-12-12 14:28:24 -0700334 return fd;
335}
336
Calin Juravle824a64d2018-01-18 20:23:17 -0800337static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& package_name,
338 const std::string& location, bool is_secondary_dex) {
339 std::string profile = create_current_profile_path(user, package_name, location,
340 is_secondary_dex);
Calin Juravle29591732017-11-20 17:46:19 -0800341 return open_profile(uid, profile, O_RDONLY);
Calin Juravle114f0812017-03-08 19:05:07 -0800342}
343
Calin Juravle824a64d2018-01-18 20:23:17 -0800344static unique_fd open_reference_profile(uid_t uid, const std::string& package_name,
345 const std::string& location, bool read_write, bool is_secondary_dex) {
346 std::string profile = create_reference_profile_path(package_name, location, is_secondary_dex);
Calin Juravle29591732017-11-20 17:46:19 -0800347 return open_profile(uid, profile, read_write ? (O_CREAT | O_RDWR) : O_RDONLY);
348}
349
350static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name,
Calin Juravle824a64d2018-01-18 20:23:17 -0800351 const std::string& location) {
352 std::string profile = create_snapshot_profile_path(package_name, location);
Calin Juravle29591732017-11-20 17:46:19 -0800353 return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC);
Calin Juravle114f0812017-03-08 19:05:07 -0800354}
355
Calin Juravle824a64d2018-01-18 20:23:17 -0800356static void open_profile_files(uid_t uid, const std::string& package_name,
357 const std::string& location, bool is_secondary_dex,
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800358 /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700359 // Open the reference profile in read-write mode as profman might need to save the merge.
Calin Juravle824a64d2018-01-18 20:23:17 -0800360 *reference_profile_fd = open_reference_profile(uid, package_name, location,
361 /*read_write*/ true, is_secondary_dex);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700362
Calin Juravle114f0812017-03-08 19:05:07 -0800363 // For secondary dex files, we don't really need the user but we use it for sanity checks.
364 // Note: the user owning the dex file should be the current user.
365 std::vector<userid_t> users;
366 if (is_secondary_dex){
367 users.push_back(multiuser_get_user_id(uid));
368 } else {
369 users = get_known_users(/*volume_uuid*/ nullptr);
370 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700371 for (auto user : users) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800372 unique_fd profile_fd = open_current_profile(uid, user, package_name, location,
373 is_secondary_dex);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700374 // Add to the lists only if both fds are valid.
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800375 if (profile_fd.get() >= 0) {
376 profiles_fd->push_back(std::move(profile_fd));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700377 }
378 }
379}
380
Calin Juravle76561322019-11-14 09:08:52 -0800381static constexpr int PROFMAN_BIN_RETURN_CODE_SUCCESS = 0;
382static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 1;
383static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 2;
384static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 3;
385static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 4;
386static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 5;
387static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_DIFFERENT_VERSIONS = 6;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700388
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800389class RunProfman : public ExecVHelper {
390 public:
391 void SetupArgs(const std::vector<unique_fd>& profile_fds,
392 const unique_fd& reference_profile_fd,
393 const std::vector<unique_fd>& apk_fds,
394 const std::vector<std::string>& dex_locations,
Calin Juravle78728f32019-11-08 17:55:46 -0800395 bool copy_and_update,
396 bool for_snapshot,
397 bool for_boot_image) {
Calin Juravlef74a7372019-02-28 20:29:41 -0800398
399 // TODO(calin): Assume for now we run in the bg compile job (which is in
400 // most of the invocation). With the current data flow, is not very easy or
401 // clean to discover this in RunProfman (it will require quite a messy refactoring).
402 const char* profman_bin = select_execution_binary(
403 kProfmanPath, kProfmanDebugPath, /*background_job_compile=*/ true);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700404
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800405 if (copy_and_update) {
406 CHECK_EQ(1u, profile_fds.size());
407 CHECK_EQ(1u, apk_fds.size());
Mathieu Chartier31636522018-11-09 23:53:07 +0000408 }
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800409 if (reference_profile_fd != -1) {
410 AddArg("--reference-profile-file-fd=" + std::to_string(reference_profile_fd.get()));
Mathieu Chartier31636522018-11-09 23:53:07 +0000411 }
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800412
413 for (const unique_fd& fd : profile_fds) {
414 AddArg("--profile-file-fd=" + std::to_string(fd.get()));
415 }
416
417 for (const unique_fd& fd : apk_fds) {
418 AddArg("--apk-fd=" + std::to_string(fd.get()));
419 }
420
421 for (const std::string& dex_location : dex_locations) {
422 AddArg("--dex-location=" + dex_location);
423 }
424
425 if (copy_and_update) {
426 AddArg("--copy-and-update-profile-key");
427 }
428
Calin Juravle78728f32019-11-08 17:55:46 -0800429 if (for_snapshot) {
430 AddArg("--force-merge");
431 }
432
433 if (for_boot_image) {
434 AddArg("--boot-image-merge");
435 }
436
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800437 // Do not add after dex2oat_flags, they should override others for debugging.
438 PrepareArgs(profman_bin);
Mathieu Chartier62d218d2018-11-05 09:34:24 -0800439 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700440
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800441 void SetupMerge(const std::vector<unique_fd>& profiles_fd,
442 const unique_fd& reference_profile_fd,
443 const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
Calin Juravle78728f32019-11-08 17:55:46 -0800444 const std::vector<std::string>& dex_locations = std::vector<std::string>(),
445 bool for_snapshot = false,
446 bool for_boot_image = false) {
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800447 SetupArgs(profiles_fd,
Calin Juravleb3a929d2018-12-11 14:40:00 -0800448 reference_profile_fd,
449 apk_fds,
450 dex_locations,
Calin Juravle78728f32019-11-08 17:55:46 -0800451 /*copy_and_update=*/ false,
452 for_snapshot,
453 for_boot_image);
Mathieu Chartier62d218d2018-11-05 09:34:24 -0800454 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700455
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800456 void SetupCopyAndUpdate(unique_fd&& profile_fd,
457 unique_fd&& reference_profile_fd,
458 unique_fd&& apk_fd,
459 const std::string& dex_location) {
460 // The fds need to stay open longer than the scope of the function, so put them into a local
461 // variable vector.
462 profiles_fd_.push_back(std::move(profile_fd));
463 apk_fds_.push_back(std::move(apk_fd));
464 reference_profile_fd_ = std::move(reference_profile_fd);
465 std::vector<std::string> dex_locations = {dex_location};
Calin Juravleb3a929d2018-12-11 14:40:00 -0800466 SetupArgs(profiles_fd_,
467 reference_profile_fd_,
468 apk_fds_,
469 dex_locations,
Calin Juravle78728f32019-11-08 17:55:46 -0800470 /*copy_and_update=*/true,
471 /*for_snapshot*/false,
472 /*for_boot_image*/false);
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800473 }
Calin Juravlef63d4792018-01-30 17:43:34 +0000474
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800475 void SetupDump(const std::vector<unique_fd>& profiles_fd,
476 const unique_fd& reference_profile_fd,
477 const std::vector<std::string>& dex_locations,
478 const std::vector<unique_fd>& apk_fds,
479 const unique_fd& output_fd) {
480 AddArg("--dump-only");
481 AddArg(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
Calin Juravleb3a929d2018-12-11 14:40:00 -0800482 SetupArgs(profiles_fd,
483 reference_profile_fd,
484 apk_fds,
485 dex_locations,
Calin Juravle78728f32019-11-08 17:55:46 -0800486 /*copy_and_update=*/false,
487 /*for_snapshot*/false,
488 /*for_boot_image*/false);
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800489 }
Calin Juravlef63d4792018-01-30 17:43:34 +0000490
Victor Hsiehc9821f12020-08-07 11:32:29 -0700491 using ExecVHelper::Exec; // To suppress -Wno-overloaded-virtual
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800492 void Exec() {
493 ExecVHelper::Exec(DexoptReturnCodes::kProfmanExec);
494 }
Mathieu Chartier31636522018-11-09 23:53:07 +0000495
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800496 private:
497 unique_fd reference_profile_fd_;
498 std::vector<unique_fd> profiles_fd_;
499 std::vector<unique_fd> apk_fds_;
500};
Mathieu Chartier31636522018-11-09 23:53:07 +0000501
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800502
Calin Juravlef63d4792018-01-30 17:43:34 +0000503
Jeff Sharkey90aff262016-12-12 14:28:24 -0700504// Decides if profile guided compilation is needed or not based on existing profiles.
Calin Juravle114f0812017-03-08 19:05:07 -0800505// The location is the package name for primary apks or the dex path for secondary dex files.
506// Returns true if there is enough information in the current profiles that makes it
507// worth to recompile the given location.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700508// If the return value is true all the current profiles would have been merged into
509// the reference profiles accessible with open_reference_profile().
Calin Juravle824a64d2018-01-18 20:23:17 -0800510static bool analyze_profiles(uid_t uid, const std::string& package_name,
511 const std::string& location, bool is_secondary_dex) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800512 std::vector<unique_fd> profiles_fd;
513 unique_fd reference_profile_fd;
Calin Juravle824a64d2018-01-18 20:23:17 -0800514 open_profile_files(uid, package_name, location, is_secondary_dex,
515 &profiles_fd, &reference_profile_fd);
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800516 if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700517 // Skip profile guided compilation because no profiles were found.
518 // Or if the reference profile info couldn't be opened.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700519 return false;
520 }
521
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800522 RunProfman profman_merge;
Calin Juravlef85ddb92020-05-01 14:05:40 -0700523 const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>();
524 const std::vector<std::string>& dex_locations = std::vector<std::string>();
525 profman_merge.SetupMerge(
526 profiles_fd,
527 reference_profile_fd,
528 apk_fds,
529 dex_locations,
530 /* for_snapshot= */ false,
531 IsBootClassPathProfilingEnable());
Jeff Sharkey90aff262016-12-12 14:28:24 -0700532 pid_t pid = fork();
533 if (pid == 0) {
534 /* child -- drop privileges before continuing */
535 drop_capabilities(uid);
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800536 profman_merge.Exec();
Jeff Sharkey90aff262016-12-12 14:28:24 -0700537 }
538 /* parent */
539 int return_code = wait_child(pid);
540 bool need_to_compile = false;
541 bool should_clear_current_profiles = false;
542 bool should_clear_reference_profile = false;
543 if (!WIFEXITED(return_code)) {
Calin Juravle114f0812017-03-08 19:05:07 -0800544 LOG(WARNING) << "profman failed for location " << location << ": " << return_code;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700545 } else {
546 return_code = WEXITSTATUS(return_code);
547 switch (return_code) {
548 case PROFMAN_BIN_RETURN_CODE_COMPILE:
549 need_to_compile = true;
550 should_clear_current_profiles = true;
551 should_clear_reference_profile = false;
552 break;
553 case PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION:
554 need_to_compile = false;
555 should_clear_current_profiles = false;
556 should_clear_reference_profile = false;
557 break;
558 case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
Calin Juravle114f0812017-03-08 19:05:07 -0800559 LOG(WARNING) << "Bad profiles for location " << location;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700560 need_to_compile = false;
561 should_clear_current_profiles = true;
562 should_clear_reference_profile = true;
563 break;
564 case PROFMAN_BIN_RETURN_CODE_ERROR_IO: // fall-through
565 case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
566 // Temporary IO problem (e.g. locking). Ignore but log a warning.
Calin Juravle114f0812017-03-08 19:05:07 -0800567 LOG(WARNING) << "IO error while reading profiles for location " << location;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700568 need_to_compile = false;
569 should_clear_current_profiles = false;
570 should_clear_reference_profile = false;
571 break;
Calin Juravle76561322019-11-14 09:08:52 -0800572 case PROFMAN_BIN_RETURN_CODE_ERROR_DIFFERENT_VERSIONS:
573 need_to_compile = false;
574 should_clear_current_profiles = true;
575 should_clear_reference_profile = true;
576 break;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700577 default:
578 // Unknown return code or error. Unlink profiles.
Calin Juravle78728f32019-11-08 17:55:46 -0800579 LOG(WARNING) << "Unexpected error code while processing profiles for location "
Calin Juravle114f0812017-03-08 19:05:07 -0800580 << location << ": " << return_code;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700581 need_to_compile = false;
582 should_clear_current_profiles = true;
583 should_clear_reference_profile = true;
584 break;
585 }
586 }
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800587
Jeff Sharkey90aff262016-12-12 14:28:24 -0700588 if (should_clear_current_profiles) {
Calin Juravle114f0812017-03-08 19:05:07 -0800589 if (is_secondary_dex) {
590 // For secondary dex files, the owning user is the current user.
Calin Juravle824a64d2018-01-18 20:23:17 -0800591 clear_current_profile(package_name, location, multiuser_get_user_id(uid),
592 is_secondary_dex);
Calin Juravle114f0812017-03-08 19:05:07 -0800593 } else {
Calin Juravle824a64d2018-01-18 20:23:17 -0800594 clear_primary_current_profiles(package_name, location);
Calin Juravle114f0812017-03-08 19:05:07 -0800595 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700596 }
597 if (should_clear_reference_profile) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800598 clear_reference_profile(package_name, location, is_secondary_dex);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700599 }
600 return need_to_compile;
601}
602
Calin Juravle114f0812017-03-08 19:05:07 -0800603// Decides if profile guided compilation is needed or not based on existing profiles.
604// The analysis is done for the primary apks of the given package.
605// Returns true if there is enough information in the current profiles that makes it
606// worth to recompile the package.
607// If the return value is true all the current profiles would have been merged into
608// the reference profiles accessible with open_reference_profile().
Calin Juravle824a64d2018-01-18 20:23:17 -0800609bool analyze_primary_profiles(uid_t uid, const std::string& package_name,
610 const std::string& profile_name) {
611 return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false);
Calin Juravle114f0812017-03-08 19:05:07 -0800612}
613
Calin Juravle408cd4a2018-01-20 23:34:18 -0800614bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name,
615 const std::string& code_path) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800616 std::vector<unique_fd> profile_fds;
617 unique_fd reference_profile_fd;
Calin Juravle408cd4a2018-01-20 23:34:18 -0800618 std::string out_file_name = StringPrintf("/data/misc/profman/%s-%s.txt",
619 pkgname.c_str(), profile_name.c_str());
Jeff Sharkey90aff262016-12-12 14:28:24 -0700620
Calin Juravle408cd4a2018-01-20 23:34:18 -0800621 open_profile_files(uid, pkgname, profile_name, /*is_secondary_dex*/false,
Calin Juravle114f0812017-03-08 19:05:07 -0800622 &profile_fds, &reference_profile_fd);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700623
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800624 const bool has_reference_profile = (reference_profile_fd.get() != -1);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700625 const bool has_profiles = !profile_fds.empty();
626
627 if (!has_reference_profile && !has_profiles) {
Calin Juravle76268c52017-03-09 13:19:42 -0800628 LOG(ERROR) << "profman dump: no profiles to dump for " << pkgname;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700629 return false;
630 }
631
Calin Juravle114f0812017-03-08 19:05:07 -0800632 unique_fd output_fd(open(out_file_name.c_str(),
633 O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700634 if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
Calin Juravle408cd4a2018-01-20 23:34:18 -0800635 LOG(ERROR) << "installd cannot chmod file for dump_profile" << out_file_name;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700636 return false;
637 }
Calin Juravle408cd4a2018-01-20 23:34:18 -0800638
Jeff Sharkey90aff262016-12-12 14:28:24 -0700639 std::vector<std::string> dex_locations;
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800640 std::vector<unique_fd> apk_fds;
Calin Juravle408cd4a2018-01-20 23:34:18 -0800641 unique_fd apk_fd(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW));
642 if (apk_fd == -1) {
643 PLOG(ERROR) << "installd cannot open " << code_path.c_str();
644 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700645 }
Victor Hsieh76f19ba2020-08-10 14:37:26 -0700646 dex_locations.push_back(Basename(code_path));
Calin Juravle408cd4a2018-01-20 23:34:18 -0800647 apk_fds.push_back(std::move(apk_fd));
648
Jeff Sharkey90aff262016-12-12 14:28:24 -0700649
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800650 RunProfman profman_dump;
651 profman_dump.SetupDump(profile_fds, reference_profile_fd, dex_locations, apk_fds, output_fd);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700652 pid_t pid = fork();
653 if (pid == 0) {
654 /* child -- drop privileges before continuing */
655 drop_capabilities(uid);
Mathieu Chartiercc66c442018-11-09 15:57:21 -0800656 profman_dump.Exec();
Jeff Sharkey90aff262016-12-12 14:28:24 -0700657 }
658 /* parent */
Jeff Sharkey90aff262016-12-12 14:28:24 -0700659 int return_code = wait_child(pid);
660 if (!WIFEXITED(return_code)) {
661 LOG(WARNING) << "profman failed for package " << pkgname << ": "
662 << return_code;
663 return false;
664 }
665 return true;
666}
667
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700668bool copy_system_profile(const std::string& system_profile,
Calin Juravle824a64d2018-01-18 20:23:17 -0800669 uid_t packageUid, const std::string& package_name, const std::string& profile_name) {
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700670 unique_fd in_fd(open(system_profile.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
671 unique_fd out_fd(open_reference_profile(packageUid,
Calin Juravle824a64d2018-01-18 20:23:17 -0800672 package_name,
673 profile_name,
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700674 /*read_write*/ true,
675 /*secondary*/ false));
676 if (in_fd.get() < 0) {
677 PLOG(WARNING) << "Could not open profile " << system_profile;
678 return false;
679 }
680 if (out_fd.get() < 0) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800681 PLOG(WARNING) << "Could not open profile " << package_name;
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700682 return false;
683 }
684
Mathieu Chartier78f71fe2017-06-14 13:02:26 -0700685 // As a security measure we want to write the profile information with the reduced capabilities
686 // of the package user id. So we fork and drop capabilities in the child.
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700687 pid_t pid = fork();
688 if (pid == 0) {
689 /* child -- drop privileges before continuing */
690 drop_capabilities(packageUid);
691
692 if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
693 if (errno != EWOULDBLOCK) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800694 PLOG(WARNING) << "Error locking profile " << package_name;
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700695 }
696 // This implies that the app owning this profile is running
697 // (and has acquired the lock).
698 //
699 // The app never acquires the lock for the reference profiles of primary apks.
700 // Only dex2oat from installd will do that. Since installd is single threaded
701 // we should not see this case. Nevertheless be prepared for it.
Calin Juravle824a64d2018-01-18 20:23:17 -0800702 PLOG(WARNING) << "Failed to flock " << package_name;
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700703 return false;
704 }
705
706 bool truncated = ftruncate(out_fd.get(), 0) == 0;
707 if (!truncated) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800708 PLOG(WARNING) << "Could not truncate " << package_name;
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700709 }
710
711 // Copy over data.
712 static constexpr size_t kBufferSize = 4 * 1024;
713 char buffer[kBufferSize];
714 while (true) {
715 ssize_t bytes = read(in_fd.get(), buffer, kBufferSize);
716 if (bytes == 0) {
717 break;
718 }
719 write(out_fd.get(), buffer, bytes);
720 }
721 if (flock(out_fd.get(), LOCK_UN) != 0) {
Calin Juravle824a64d2018-01-18 20:23:17 -0800722 PLOG(WARNING) << "Error unlocking profile " << package_name;
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700723 }
Mathieu Chartier78f71fe2017-06-14 13:02:26 -0700724 // Use _exit since we don't want to run the global destructors in the child.
725 // b/62597429
726 _exit(0);
Mathieu Chartierf966f2a2017-05-10 12:48:37 -0700727 }
728 /* parent */
729 int return_code = wait_child(pid);
730 return return_code == 0;
731}
732
Jeff Sharkey90aff262016-12-12 14:28:24 -0700733static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
734 // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
735 if (EndsWith(oat_path, ".dex")) {
736 std::string new_path = oat_path;
737 new_path.replace(new_path.length() - strlen(".dex"), strlen(".dex"), new_ext);
Elliott Hughes969e4f82017-12-20 12:34:09 -0800738 CHECK(EndsWith(new_path, new_ext));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700739 return new_path;
740 }
741
742 // An odex entry. Not that this may not be an extension, e.g., in the OTA
743 // case (where the base name will have an extension for the B artifact).
744 size_t odex_pos = oat_path.rfind(".odex");
745 if (odex_pos != std::string::npos) {
746 std::string new_path = oat_path;
747 new_path.replace(odex_pos, strlen(".odex"), new_ext);
748 CHECK_NE(new_path.find(new_ext), std::string::npos);
749 return new_path;
750 }
751
752 // Don't know how to handle this.
753 return "";
754}
755
756// Translate the given oat path to an art (app image) path. An empty string
757// denotes an error.
758static std::string create_image_filename(const std::string& oat_path) {
759 return replace_file_extension(oat_path, ".art");
760}
761
762// Translate the given oat path to a vdex path. An empty string denotes an error.
763static std::string create_vdex_filename(const std::string& oat_path) {
764 return replace_file_extension(oat_path, ".vdex");
765}
766
Jeff Sharkey90aff262016-12-12 14:28:24 -0700767static int open_output_file(const char* file_name, bool recreate, int permissions) {
768 int flags = O_RDWR | O_CREAT;
769 if (recreate) {
770 if (unlink(file_name) < 0) {
771 if (errno != ENOENT) {
772 PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
773 }
774 }
775 flags |= O_EXCL;
776 }
777 return open(file_name, flags, permissions);
778}
779
Calin Juravle2289c0a2017-02-15 12:44:14 -0800780static bool set_permissions_and_ownership(
781 int fd, bool is_public, int uid, const char* path, bool is_secondary_dex) {
782 // Primary apks are owned by the system. Secondary dex files are owned by the app.
783 int owning_uid = is_secondary_dex ? uid : AID_SYSTEM;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700784 if (fchmod(fd,
785 S_IRUSR|S_IWUSR|S_IRGRP |
786 (is_public ? S_IROTH : 0)) < 0) {
787 ALOGE("installd cannot chmod '%s' during dexopt\n", path);
788 return false;
Calin Juravle2289c0a2017-02-15 12:44:14 -0800789 } else if (fchown(fd, owning_uid, uid) < 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700790 ALOGE("installd cannot chown '%s' during dexopt\n", path);
791 return false;
792 }
793 return true;
794}
795
796static bool IsOutputDalvikCache(const char* oat_dir) {
797 // InstallerConnection.java (which invokes installd) transforms Java null arguments
798 // into '!'. Play it safe by handling it both.
799 // TODO: ensure we never get null.
800 // TODO: pass a flag instead of inferring if the output is dalvik cache.
801 return oat_dir == nullptr || oat_dir[0] == '!';
802}
803
Calin Juravled23dee72017-07-06 16:29:11 -0700804// Best-effort check whether we can fit the the path into our buffers.
805// Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
806// without a swap file, if necessary. Reference profiles file also add an extra ".prof"
807// extension to the cache path (5 bytes).
808// TODO(calin): move away from char* buffers and PKG_PATH_MAX.
809static bool validate_dex_path_size(const std::string& dex_path) {
810 if (dex_path.size() >= (PKG_PATH_MAX - 8)) {
811 LOG(ERROR) << "dex_path too long: " << dex_path;
812 return false;
813 }
814 return true;
815}
816
Jeff Sharkey90aff262016-12-12 14:28:24 -0700817static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
Calin Juravle80a21252017-01-17 14:43:25 -0800818 const char* oat_dir, bool is_secondary_dex, /*out*/ char* out_oat_path) {
Calin Juravled23dee72017-07-06 16:29:11 -0700819 if (!validate_dex_path_size(apk_path)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700820 return false;
821 }
822
823 if (!IsOutputDalvikCache(oat_dir)) {
Calin Juravle80a21252017-01-17 14:43:25 -0800824 // Oat dirs for secondary dex files are already validated.
825 if (!is_secondary_dex && validate_apk_path(oat_dir)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700826 ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir);
827 return false;
828 }
829 if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) {
830 return false;
831 }
832 } else {
833 if (!create_cache_path(out_oat_path, apk_path, instruction_set)) {
834 return false;
835 }
836 }
837 return true;
838}
839
840// Helper for fd management. This is similar to a unique_fd in that it closes the file descriptor
841// on destruction. It will also run the given cleanup (unless told not to) after closing.
842//
843// Usage example:
844//
Calin Juravle7a570e82017-01-14 16:23:30 -0800845// Dex2oatFileWrapper file(open(...),
Jeff Sharkey90aff262016-12-12 14:28:24 -0700846// [name]() {
847// unlink(name.c_str());
848// });
849// // Note: care needs to be taken about name, as it needs to have a lifetime longer than the
850// wrapper if captured as a reference.
851//
852// if (file.get() == -1) {
853// // Error opening...
854// }
855//
856// ...
857// if (error) {
858// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will run
859// // and delete the file (after the fd is closed).
860// return -1;
861// }
862//
863// (Success case)
864// file.SetCleanup(false);
865// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will not run
866// // (leaving the file around; after the fd is closed).
867//
Jeff Sharkey90aff262016-12-12 14:28:24 -0700868class Dex2oatFileWrapper {
869 public:
Calin Juravle7a570e82017-01-14 16:23:30 -0800870 Dex2oatFileWrapper() : value_(-1), cleanup_(), do_cleanup_(true), auto_close_(true) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700871 }
872
Calin Juravle7a570e82017-01-14 16:23:30 -0800873 Dex2oatFileWrapper(int value, std::function<void ()> cleanup)
874 : value_(value), cleanup_(cleanup), do_cleanup_(true), auto_close_(true) {}
875
876 Dex2oatFileWrapper(Dex2oatFileWrapper&& other) {
877 value_ = other.value_;
878 cleanup_ = other.cleanup_;
879 do_cleanup_ = other.do_cleanup_;
880 auto_close_ = other.auto_close_;
881 other.release();
882 }
883
884 Dex2oatFileWrapper& operator=(Dex2oatFileWrapper&& other) {
885 value_ = other.value_;
886 cleanup_ = other.cleanup_;
887 do_cleanup_ = other.do_cleanup_;
888 auto_close_ = other.auto_close_;
889 other.release();
890 return *this;
891 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700892
893 ~Dex2oatFileWrapper() {
894 reset(-1);
895 }
896
897 int get() {
898 return value_;
899 }
900
901 void SetCleanup(bool cleanup) {
902 do_cleanup_ = cleanup;
903 }
904
905 void reset(int new_value) {
Calin Juravle7a570e82017-01-14 16:23:30 -0800906 if (auto_close_ && value_ >= 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700907 close(value_);
908 }
909 if (do_cleanup_ && cleanup_ != nullptr) {
910 cleanup_();
911 }
912
913 value_ = new_value;
914 }
915
Calin Juravle7a570e82017-01-14 16:23:30 -0800916 void reset(int new_value, std::function<void ()> new_cleanup) {
917 if (auto_close_ && value_ >= 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700918 close(value_);
919 }
920 if (do_cleanup_ && cleanup_ != nullptr) {
921 cleanup_();
922 }
923
924 value_ = new_value;
925 cleanup_ = new_cleanup;
926 }
927
Calin Juravle7a570e82017-01-14 16:23:30 -0800928 void DisableAutoClose() {
929 auto_close_ = false;
930 }
931
Jeff Sharkey90aff262016-12-12 14:28:24 -0700932 private:
Calin Juravle7a570e82017-01-14 16:23:30 -0800933 void release() {
934 value_ = -1;
935 do_cleanup_ = false;
936 cleanup_ = nullptr;
937 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700938 int value_;
Calin Juravle7a570e82017-01-14 16:23:30 -0800939 std::function<void ()> cleanup_;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700940 bool do_cleanup_;
Calin Juravle7a570e82017-01-14 16:23:30 -0800941 bool auto_close_;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700942};
943
Calin Juravle7a570e82017-01-14 16:23:30 -0800944// (re)Creates the app image if needed.
Mathieu Chartier1dc3dfa2018-03-12 17:55:06 -0700945Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path,
946 bool generate_app_image, bool is_public, int uid, bool is_secondary_dex) {
Nicolas Geoffrayaa17ab42017-08-15 14:51:05 +0100947
Calin Juravle7a570e82017-01-14 16:23:30 -0800948 const std::string image_path = create_image_filename(out_oat_path);
949 if (image_path.empty()) {
950 // Happens when the out_oat_path has an unknown extension.
951 return Dex2oatFileWrapper();
952 }
Nicolas Geoffrayaa17ab42017-08-15 14:51:05 +0100953
Mathieu Chartier1dc3dfa2018-03-12 17:55:06 -0700954 // In case there is a stale image, remove it now. Ignore any error.
955 unlink(image_path.c_str());
956
957 // Not enabled, exit.
958 if (!generate_app_image) {
Nicolas Geoffrayaa17ab42017-08-15 14:51:05 +0100959 return Dex2oatFileWrapper();
960 }
Mathieu Chartier9b2da082018-10-26 13:23:11 -0700961 std::string app_image_format = GetProperty("dalvik.vm.appimageformat", "");
962 if (app_image_format.empty()) {
Calin Juravle7a570e82017-01-14 16:23:30 -0800963 return Dex2oatFileWrapper();
964 }
965 // Recreate is true since we do not want to modify a mapped image. If the app is
966 // already running and we modify the image file, it can cause crashes (b/27493510).
967 Dex2oatFileWrapper wrapper_fd(
968 open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
969 [image_path]() { unlink(image_path.c_str()); });
970 if (wrapper_fd.get() < 0) {
971 // Could not create application image file. Go on since we can compile without it.
972 LOG(ERROR) << "installd could not create '" << image_path
973 << "' for image file during dexopt";
974 // If we have a valid image file path but no image fd, explicitly erase the image file.
975 if (unlink(image_path.c_str()) < 0) {
976 if (errno != ENOENT) {
977 PLOG(ERROR) << "Couldn't unlink image file " << image_path;
978 }
979 }
980 } else if (!set_permissions_and_ownership(
Calin Juravle2289c0a2017-02-15 12:44:14 -0800981 wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -0800982 ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
983 wrapper_fd.reset(-1);
984 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700985
Calin Juravle7a570e82017-01-14 16:23:30 -0800986 return wrapper_fd;
987}
988
989// Creates the dexopt swap file if necessary and return its fd.
990// Returns -1 if there's no need for a swap or in case of errors.
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800991unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
Calin Juravle7a570e82017-01-14 16:23:30 -0800992 if (!ShouldUseSwapFileForDexopt()) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800993 return invalid_unique_fd();
Calin Juravle7a570e82017-01-14 16:23:30 -0800994 }
Jeff Sharkeyc1149c92017-09-21 14:51:09 -0600995 auto swap_file_name = std::string(out_oat_path) + ".swap";
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800996 unique_fd swap_fd(open_output_file(
Jeff Sharkeyc1149c92017-09-21 14:51:09 -0600997 swap_file_name.c_str(), /*recreate*/true, /*permissions*/0600));
Calin Juravle7a570e82017-01-14 16:23:30 -0800998 if (swap_fd.get() < 0) {
999 // Could not create swap file. Optimistically go on and hope that we can compile
1000 // without it.
Jeff Sharkeyc1149c92017-09-21 14:51:09 -06001001 ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name.c_str());
Calin Juravle7a570e82017-01-14 16:23:30 -08001002 } else {
1003 // Immediately unlink. We don't really want to hit flash.
Jeff Sharkeyc1149c92017-09-21 14:51:09 -06001004 if (unlink(swap_file_name.c_str()) < 0) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001005 PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
1006 }
1007 }
1008 return swap_fd;
1009}
1010
1011// Opens the reference profiles if needed.
1012// Note that the reference profile might not exist so it's OK if the fd will be -1.
Calin Juravle114f0812017-03-08 19:05:07 -08001013Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname,
Calin Juravlec4f6a0b2018-02-01 01:27:24 +00001014 const std::string& dex_path, const char* profile_name, bool profile_guided,
Calin Juravle824a64d2018-01-18 20:23:17 -08001015 bool is_public, int uid, bool is_secondary_dex) {
Calin Juravle5bd1c722018-02-01 17:23:54 +00001016 // If we are not profile guided compilation, or we are compiling system server
1017 // do not bother to open the profiles; we won't be using them.
1018 if (!profile_guided || (pkgname[0] == '*')) {
1019 return Dex2oatFileWrapper();
1020 }
1021
1022 // If this is a secondary dex path which is public do not open the profile.
1023 // We cannot compile public secondary dex paths with profiles. That's because
1024 // it will expose how the dex files are used by their owner.
1025 //
1026 // Note that the PackageManager is responsible to set the is_public flag for
1027 // primary apks and we do not check it here. In some cases, e.g. when
1028 // compiling with a public profile from the .dm file the PackageManager will
1029 // set is_public toghether with the profile guided compilation.
1030 if (is_secondary_dex && is_public) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001031 return Dex2oatFileWrapper();
Jeff Sharkey90aff262016-12-12 14:28:24 -07001032 }
Calin Juravle114f0812017-03-08 19:05:07 -08001033
1034 // Open reference profile in read only mode as dex2oat does not get write permissions.
Calin Juravlec4f6a0b2018-02-01 01:27:24 +00001035 std::string location;
1036 if (is_secondary_dex) {
1037 location = dex_path;
1038 } else {
1039 if (profile_name == nullptr) {
1040 // This path is taken for system server re-compilation lunched from ZygoteInit.
1041 return Dex2oatFileWrapper();
1042 } else {
1043 location = profile_name;
1044 }
1045 }
Calin Juravle824a64d2018-01-18 20:23:17 -08001046 unique_fd ufd = open_reference_profile(uid, pkgname, location, /*read_write*/false,
1047 is_secondary_dex);
1048 const auto& cleanup = [pkgname, location, is_secondary_dex]() {
1049 clear_reference_profile(pkgname, location, is_secondary_dex);
Calin Juravle114f0812017-03-08 19:05:07 -08001050 };
1051 return Dex2oatFileWrapper(ufd.release(), cleanup);
Calin Juravle7a570e82017-01-14 16:23:30 -08001052}
Jeff Sharkey90aff262016-12-12 14:28:24 -07001053
Calin Juravle7a570e82017-01-14 16:23:30 -08001054// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
1055// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001056bool open_vdex_files_for_dex2oat(const char* apk_path, const char* out_oat_path, int dexopt_needed,
Nicolas Geoffray3c95f2d2017-04-24 13:34:59 +00001057 const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
Nicolas Geoffrayb03814f2017-06-05 12:38:10 +00001058 bool profile_guided, Dex2oatFileWrapper* in_vdex_wrapper_fd,
Calin Juravle7a570e82017-01-14 16:23:30 -08001059 Dex2oatFileWrapper* out_vdex_wrapper_fd) {
1060 CHECK(in_vdex_wrapper_fd != nullptr);
1061 CHECK(out_vdex_wrapper_fd != nullptr);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001062 // Open the existing VDEX. We do this before creating the new output VDEX, which will
1063 // unlink the old one.
Richard Uhler76cc0272016-12-08 10:46:35 +00001064 char in_odex_path[PKG_PATH_MAX];
1065 int dexopt_action = abs(dexopt_needed);
1066 bool is_odex_location = dexopt_needed < 0;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001067 std::string in_vdex_path_str;
Nicolas Geoffrayb03814f2017-06-05 12:38:10 +00001068
1069 // Infer the name of the output VDEX.
1070 const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
1071 if (out_vdex_path_str.empty()) {
1072 return false;
1073 }
1074
1075 bool update_vdex_in_place = false;
Nicolas Geoffray3c95f2d2017-04-24 13:34:59 +00001076 if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001077 // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
1078 const char* path = nullptr;
1079 if (is_odex_location) {
1080 if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
1081 path = in_odex_path;
1082 } else {
1083 ALOGE("installd cannot compute input vdex location for '%s'\n", apk_path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001084 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001085 }
1086 } else {
1087 path = out_oat_path;
1088 }
1089 in_vdex_path_str = create_vdex_filename(path);
1090 if (in_vdex_path_str.empty()) {
1091 ALOGE("installd cannot compute input vdex location for '%s'\n", path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001092 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001093 }
Nicolas Geoffrayb03814f2017-06-05 12:38:10 +00001094 // We can update in place when all these conditions are met:
1095 // 1) The vdex location to write to is the same as the vdex location to read (vdex files
1096 // on /system typically cannot be updated in place).
1097 // 2) We dex2oat due to boot image change, because we then know the existing vdex file
1098 // cannot be currently used by a running process.
1099 // 3) We are not doing a profile guided compilation, because dexlayout requires two
1100 // different vdex files to operate.
1101 update_vdex_in_place =
1102 (in_vdex_path_str == out_vdex_path_str) &&
1103 (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) &&
1104 !profile_guided;
1105 if (update_vdex_in_place) {
1106 // Open the file read-write to be able to update it.
1107 in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
1108 if (in_vdex_wrapper_fd->get() == -1) {
1109 // If we failed to open the file, we cannot update it in place.
1110 update_vdex_in_place = false;
1111 }
1112 } else {
1113 in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
1114 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001115 }
1116
Nicolas Geoffrayb03814f2017-06-05 12:38:10 +00001117 // If we are updating the vdex in place, we do not need to recreate a vdex,
1118 // and can use the same existing one.
1119 if (update_vdex_in_place) {
1120 // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
1121 // have bogus stale vdex files.
1122 out_vdex_wrapper_fd->reset(
1123 in_vdex_wrapper_fd->get(),
1124 [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
1125 // Disable auto close for the in wrapper fd (it will be done when destructing the out
1126 // wrapper).
1127 in_vdex_wrapper_fd->DisableAutoClose();
1128 } else {
1129 out_vdex_wrapper_fd->reset(
1130 open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
1131 [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
1132 if (out_vdex_wrapper_fd->get() < 0) {
1133 ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
1134 return false;
1135 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001136 }
Calin Juravle7a570e82017-01-14 16:23:30 -08001137 if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
Calin Juravle2289c0a2017-02-15 12:44:14 -08001138 out_vdex_path_str.c_str(), is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001139 ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
1140 return false;
1141 }
1142
1143 // If we got here we successfully opened the vdex files.
1144 return true;
1145}
1146
1147// Opens the output oat file for the given apk.
1148// If successful it stores the output path into out_oat_path and returns true.
1149Dex2oatFileWrapper open_oat_out_file(const char* apk_path, const char* oat_dir,
Calin Juravle80a21252017-01-17 14:43:25 -08001150 bool is_public, int uid, const char* instruction_set, bool is_secondary_dex,
1151 char* out_oat_path) {
1152 if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001153 return Dex2oatFileWrapper();
1154 }
1155 const std::string out_oat_path_str(out_oat_path);
1156 Dex2oatFileWrapper wrapper_fd(
1157 open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
1158 [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
1159 if (wrapper_fd.get() < 0) {
Calin Juravle80a21252017-01-17 14:43:25 -08001160 PLOG(ERROR) << "installd cannot open output during dexopt" << out_oat_path;
Calin Juravle2289c0a2017-02-15 12:44:14 -08001161 } else if (!set_permissions_and_ownership(
1162 wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001163 ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
1164 wrapper_fd.reset(-1);
1165 }
1166 return wrapper_fd;
1167}
1168
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001169// Creates RDONLY fds for oat and vdex files, if exist.
1170// Returns false if it fails to create oat out path for the given apk path.
1171// Note that the method returns true even if the files could not be opened.
1172bool maybe_open_oat_and_vdex_file(const std::string& apk_path,
1173 const std::string& oat_dir,
1174 const std::string& instruction_set,
1175 bool is_secondary_dex,
1176 unique_fd* oat_file_fd,
1177 unique_fd* vdex_file_fd) {
1178 char oat_path[PKG_PATH_MAX];
1179 if (!create_oat_out_path(apk_path.c_str(),
1180 instruction_set.c_str(),
1181 oat_dir.c_str(),
1182 is_secondary_dex,
1183 oat_path)) {
Calin Juravle7d765462017-09-04 15:57:10 -07001184 LOG(ERROR) << "Could not create oat out path for "
1185 << apk_path << " with oat dir " << oat_dir;
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001186 return false;
1187 }
1188 oat_file_fd->reset(open(oat_path, O_RDONLY));
1189 if (oat_file_fd->get() < 0) {
1190 PLOG(INFO) << "installd cannot open oat file during dexopt" << oat_path;
1191 }
1192
1193 std::string vdex_filename = create_vdex_filename(oat_path);
1194 vdex_file_fd->reset(open(vdex_filename.c_str(), O_RDONLY));
1195 if (vdex_file_fd->get() < 0) {
1196 PLOG(INFO) << "installd cannot open vdex file during dexopt" << vdex_filename;
1197 }
1198
1199 return true;
1200}
1201
Calin Juravle7a570e82017-01-14 16:23:30 -08001202// Updates the access times of out_oat_path based on those from apk_path.
1203void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
1204 struct stat input_stat;
1205 memset(&input_stat, 0, sizeof(input_stat));
1206 if (stat(apk_path, &input_stat) != 0) {
1207 PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
1208 return;
1209 }
1210
1211 struct utimbuf ut;
1212 ut.actime = input_stat.st_atime;
1213 ut.modtime = input_stat.st_mtime;
1214 if (utime(out_oat_path, &ut) != 0) {
1215 PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
1216 }
1217}
1218
Calin Juravle80a21252017-01-17 14:43:25 -08001219// Runs (execv) dexoptanalyzer on the given arguments.
Calin Juravle114f0812017-03-08 19:05:07 -08001220// The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
1221// If this is for a profile guided compilation, profile_was_updated will tell whether or not
1222// the profile has changed.
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001223class RunDexoptAnalyzer : public ExecVHelper {
1224 public:
1225 RunDexoptAnalyzer(const std::string& dex_file,
David Brazdil4f6027a2019-03-19 11:44:21 +00001226 int vdex_fd,
1227 int oat_fd,
1228 int zip_fd,
1229 const std::string& instruction_set,
1230 const std::string& compiler_filter,
1231 bool profile_was_updated,
1232 bool downgrade,
1233 const char* class_loader_context,
1234 const std::string& class_loader_context_fds) {
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001235 CHECK_GE(zip_fd, 0);
Calin Juravlef74a7372019-02-28 20:29:41 -08001236
1237 // We always run the analyzer in the background job.
1238 const char* dexoptanalyzer_bin = select_execution_binary(
1239 kDexoptanalyzerPath, kDexoptanalyzerDebugPath, /*background_job_compile=*/ true);
Calin Juravle80a21252017-01-17 14:43:25 -08001240
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001241 std::string dex_file_arg = "--dex-file=" + dex_file;
1242 std::string oat_fd_arg = "--oat-fd=" + std::to_string(oat_fd);
1243 std::string vdex_fd_arg = "--vdex-fd=" + std::to_string(vdex_fd);
1244 std::string zip_fd_arg = "--zip-fd=" + std::to_string(zip_fd);
1245 std::string isa_arg = "--isa=" + instruction_set;
1246 std::string compiler_filter_arg = "--compiler-filter=" + compiler_filter;
1247 const char* assume_profile_changed = "--assume-profile-changed";
1248 const char* downgrade_flag = "--downgrade";
1249 std::string class_loader_context_arg = "--class-loader-context=";
1250 if (class_loader_context != nullptr) {
1251 class_loader_context_arg += class_loader_context;
1252 }
David Brazdil4f6027a2019-03-19 11:44:21 +00001253 std::string class_loader_context_fds_arg = "--class-loader-context-fds=";
1254 if (!class_loader_context_fds.empty()) {
1255 class_loader_context_fds_arg += class_loader_context_fds;
1256 }
Mathieu Chartier31636522018-11-09 23:53:07 +00001257
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001258 // program name, dex file, isa, filter
1259 AddArg(dex_file_arg);
1260 AddArg(isa_arg);
1261 AddArg(compiler_filter_arg);
1262 if (oat_fd >= 0) {
1263 AddArg(oat_fd_arg);
1264 }
1265 if (vdex_fd >= 0) {
1266 AddArg(vdex_fd_arg);
1267 }
Greg Kaiser8042c372019-03-26 06:23:19 -07001268 AddArg(zip_fd_arg);
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001269 if (profile_was_updated) {
1270 AddArg(assume_profile_changed);
1271 }
1272 if (downgrade) {
1273 AddArg(downgrade_flag);
1274 }
1275 if (class_loader_context != nullptr) {
Greg Kaiser8042c372019-03-26 06:23:19 -07001276 AddArg(class_loader_context_arg);
David Brazdil4f6027a2019-03-19 11:44:21 +00001277 if (!class_loader_context_fds.empty()) {
Greg Kaiser8042c372019-03-26 06:23:19 -07001278 AddArg(class_loader_context_fds_arg);
David Brazdil4f6027a2019-03-19 11:44:21 +00001279 }
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001280 }
Mathieu Chartier31636522018-11-09 23:53:07 +00001281
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001282 PrepareArgs(dexoptanalyzer_bin);
1283 }
David Brazdil4f6027a2019-03-19 11:44:21 +00001284
1285 // Dexoptanalyzer mode which flattens the given class loader context and
1286 // prints a list of its dex files in that flattened order.
1287 RunDexoptAnalyzer(const char* class_loader_context) {
1288 CHECK(class_loader_context != nullptr);
1289
1290 // We always run the analyzer in the background job.
1291 const char* dexoptanalyzer_bin = select_execution_binary(
1292 kDexoptanalyzerPath, kDexoptanalyzerDebugPath, /*background_job_compile=*/ true);
1293
1294 AddArg("--flatten-class-loader-context");
1295 AddArg(std::string("--class-loader-context=") + class_loader_context);
1296 PrepareArgs(dexoptanalyzer_bin);
1297 }
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001298};
Calin Juravle80a21252017-01-17 14:43:25 -08001299
1300// Prepares the oat dir for the secondary dex files.
Calin Juravle114f0812017-03-08 19:05:07 -08001301static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid,
Calin Juravle7d765462017-09-04 15:57:10 -07001302 const char* instruction_set) {
Calin Juravle114f0812017-03-08 19:05:07 -08001303 unsigned long dirIndex = dex_path.rfind('/');
Calin Juravle80a21252017-01-17 14:43:25 -08001304 if (dirIndex == std::string::npos) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001305 LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001306 return false;
1307 }
Calin Juravle114f0812017-03-08 19:05:07 -08001308 std::string dex_dir = dex_path.substr(0, dirIndex);
Calin Juravle80a21252017-01-17 14:43:25 -08001309
Calin Juravle80a21252017-01-17 14:43:25 -08001310 // Create oat file output directory.
Calin Juravleebc8a792017-04-04 20:21:05 -07001311 mode_t oat_dir_mode = S_IRWXU | S_IRWXG | S_IXOTH;
1312 if (prepare_app_cache_dir(dex_dir, "oat", oat_dir_mode, uid, uid) != 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001313 LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001314 return false;
1315 }
1316
1317 char oat_dir[PKG_PATH_MAX];
Calin Juravle114f0812017-03-08 19:05:07 -08001318 snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", dex_dir.c_str());
Calin Juravle80a21252017-01-17 14:43:25 -08001319
Calin Juravle7d765462017-09-04 15:57:10 -07001320 if (prepare_app_cache_dir(oat_dir, instruction_set, oat_dir_mode, uid, uid) != 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001321 LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001322 return false;
1323 }
1324
1325 return true;
1326}
1327
Calin Juravle7d765462017-09-04 15:57:10 -07001328// Return codes for identifying the reason why dexoptanalyzer was not invoked when processing
1329// secondary dex files. This return codes are returned by the child process created for
1330// analyzing secondary dex files in process_secondary_dex_dexopt.
Calin Juravle80a21252017-01-17 14:43:25 -08001331
Andreas Gampe194fe422018-02-28 20:16:19 -08001332enum DexoptAnalyzerSkipCodes {
1333 // The dexoptanalyzer was not invoked because of validation or IO errors.
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001334 // Specific errors are encoded in the name.
1335 kSecondaryDexDexoptAnalyzerSkippedValidatePath = 200,
1336 kSecondaryDexDexoptAnalyzerSkippedOpenZip = 201,
1337 kSecondaryDexDexoptAnalyzerSkippedPrepareDir = 202,
1338 kSecondaryDexDexoptAnalyzerSkippedOpenOutput = 203,
1339 kSecondaryDexDexoptAnalyzerSkippedFailExec = 204,
Andreas Gampe194fe422018-02-28 20:16:19 -08001340 // The dexoptanalyzer was not invoked because the dex file does not exist anymore.
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001341 kSecondaryDexDexoptAnalyzerSkippedNoFile = 205,
Andreas Gampe194fe422018-02-28 20:16:19 -08001342};
Calin Juravle7d765462017-09-04 15:57:10 -07001343
1344// Verifies the result of analyzing secondary dex files from process_secondary_dex_dexopt.
Calin Juravle80a21252017-01-17 14:43:25 -08001345// If the result is valid returns true and sets dexopt_needed_out to a valid value.
1346// Returns false for errors or unexpected result values.
Calin Juravle7d765462017-09-04 15:57:10 -07001347// The result is expected to be either one of SECONDARY_DEX_* codes or a valid exit code
1348// of dexoptanalyzer.
1349static bool process_secondary_dexoptanalyzer_result(const std::string& dex_path, int result,
Andreas Gampe194fe422018-02-28 20:16:19 -08001350 int* dexopt_needed_out, std::string* error_msg) {
Calin Juravle80a21252017-01-17 14:43:25 -08001351 // The result values are defined in dexoptanalyzer.
1352 switch (result) {
Calin Juravle7d765462017-09-04 15:57:10 -07001353 case 0: // dexoptanalyzer: no_dexopt_needed
Calin Juravle80a21252017-01-17 14:43:25 -08001354 *dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
Calin Juravle7d765462017-09-04 15:57:10 -07001355 case 1: // dexoptanalyzer: dex2oat_from_scratch
Calin Juravle80a21252017-01-17 14:43:25 -08001356 *dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
Vladimir Marko1752a112018-09-03 18:15:16 +01001357 case 4: // dexoptanalyzer: dex2oat_for_bootimage_odex
Calin Juravle80a21252017-01-17 14:43:25 -08001358 *dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
Vladimir Marko1752a112018-09-03 18:15:16 +01001359 case 5: // dexoptanalyzer: dex2oat_for_filter_odex
Calin Juravle80a21252017-01-17 14:43:25 -08001360 *dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
Calin Juravle7d765462017-09-04 15:57:10 -07001361 case 2: // dexoptanalyzer: dex2oat_for_bootimage_oat
1362 case 3: // dexoptanalyzer: dex2oat_for_filter_oat
Andreas Gampe194fe422018-02-28 20:16:19 -08001363 *error_msg = StringPrintf("Dexoptanalyzer return the status of an oat file."
1364 " Expected odex file status for secondary dex %s"
1365 " : dexoptanalyzer result=%d",
1366 dex_path.c_str(),
1367 result);
Calin Juravle80a21252017-01-17 14:43:25 -08001368 return false;
Andreas Gampe194fe422018-02-28 20:16:19 -08001369 }
1370
1371 // Use a second switch for enum switch-case analysis.
1372 switch (static_cast<DexoptAnalyzerSkipCodes>(result)) {
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001373 case kSecondaryDexDexoptAnalyzerSkippedNoFile:
Calin Juravle7d765462017-09-04 15:57:10 -07001374 // If the file does not exist there's no need for dexopt.
1375 *dexopt_needed_out = NO_DEXOPT_NEEDED;
1376 return true;
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001377
1378 case kSecondaryDexDexoptAnalyzerSkippedValidatePath:
1379 *error_msg = "Dexoptanalyzer path validation failed";
1380 return false;
1381 case kSecondaryDexDexoptAnalyzerSkippedOpenZip:
1382 *error_msg = "Dexoptanalyzer open zip failed";
1383 return false;
1384 case kSecondaryDexDexoptAnalyzerSkippedPrepareDir:
1385 *error_msg = "Dexoptanalyzer dir preparation failed";
1386 return false;
1387 case kSecondaryDexDexoptAnalyzerSkippedOpenOutput:
1388 *error_msg = "Dexoptanalyzer open output failed";
1389 return false;
1390 case kSecondaryDexDexoptAnalyzerSkippedFailExec:
1391 *error_msg = "Dexoptanalyzer failed to execute";
Calin Juravle80a21252017-01-17 14:43:25 -08001392 return false;
1393 }
Andreas Gampe194fe422018-02-28 20:16:19 -08001394
1395 *error_msg = StringPrintf("Unexpected result from analyzing secondary dex %s result=%d",
1396 dex_path.c_str(),
1397 result);
1398 return false;
Calin Juravle80a21252017-01-17 14:43:25 -08001399}
1400
Calin Juravle7d765462017-09-04 15:57:10 -07001401enum SecondaryDexAccess {
1402 kSecondaryDexAccessReadOk = 0,
1403 kSecondaryDexAccessDoesNotExist = 1,
1404 kSecondaryDexAccessPermissionError = 2,
1405 kSecondaryDexAccessIOError = 3
1406};
1407
1408static SecondaryDexAccess check_secondary_dex_access(const std::string& dex_path) {
1409 // Check if the path exists and can be read. If not, there's nothing to do.
1410 if (access(dex_path.c_str(), R_OK) == 0) {
1411 return kSecondaryDexAccessReadOk;
1412 } else {
1413 if (errno == ENOENT) {
1414 LOG(INFO) << "Secondary dex does not exist: " << dex_path;
1415 return kSecondaryDexAccessDoesNotExist;
1416 } else {
1417 PLOG(ERROR) << "Could not access secondary dex " << dex_path;
1418 return errno == EACCES
1419 ? kSecondaryDexAccessPermissionError
1420 : kSecondaryDexAccessIOError;
1421 }
1422 }
1423}
1424
1425static bool is_file_public(const std::string& filename) {
1426 struct stat file_stat;
1427 if (stat(filename.c_str(), &file_stat) == 0) {
1428 return (file_stat.st_mode & S_IROTH) != 0;
1429 }
1430 return false;
1431}
1432
1433// Create the oat file structure for the secondary dex 'dex_path' and assign
1434// the individual path component to the 'out_' parameters.
1435static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa,
Andreas Gampe194fe422018-02-28 20:16:19 -08001436 char* out_oat_dir, char* out_oat_isa_dir, char* out_oat_path, std::string* error_msg) {
Calin Juravle7d765462017-09-04 15:57:10 -07001437 size_t dirIndex = dex_path.rfind('/');
1438 if (dirIndex == std::string::npos) {
Andreas Gampe194fe422018-02-28 20:16:19 -08001439 *error_msg = std::string("Unexpected dir structure for dex file ").append(dex_path);
Calin Juravle7d765462017-09-04 15:57:10 -07001440 return false;
1441 }
1442 // TODO(calin): we have similar computations in at lest 3 other places
1443 // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by
1444 // using string append.
1445 std::string apk_dir = dex_path.substr(0, dirIndex);
1446 snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
1447 snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str());
1448
1449 if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
1450 /*is_secondary_dex*/true, out_oat_path)) {
Andreas Gampe194fe422018-02-28 20:16:19 -08001451 *error_msg = std::string("Could not create oat path for secondary dex ").append(dex_path);
Calin Juravle7d765462017-09-04 15:57:10 -07001452 return false;
1453 }
1454 return true;
1455}
1456
1457// Validate that the dexopt_flags contain a valid storage flag and convert that to an installd
1458// recognized storage flags (FLAG_STORAGE_CE or FLAG_STORAGE_DE).
Andreas Gampe194fe422018-02-28 20:16:19 -08001459static bool validate_dexopt_storage_flags(int dexopt_flags,
1460 int* out_storage_flag,
1461 std::string* error_msg) {
Calin Juravle7d765462017-09-04 15:57:10 -07001462 if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
1463 *out_storage_flag = FLAG_STORAGE_CE;
1464 if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
Andreas Gampe194fe422018-02-28 20:16:19 -08001465 *error_msg = "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
Calin Juravle7d765462017-09-04 15:57:10 -07001466 return false;
1467 }
1468 } else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1469 *out_storage_flag = FLAG_STORAGE_DE;
1470 } else {
Andreas Gampe194fe422018-02-28 20:16:19 -08001471 *error_msg = "Secondary dex storage flag must be set";
Calin Juravle7d765462017-09-04 15:57:10 -07001472 return false;
1473 }
1474 return true;
1475}
1476
David Brazdil4f6027a2019-03-19 11:44:21 +00001477static bool get_class_loader_context_dex_paths(const char* class_loader_context, int uid,
1478 /* out */ std::vector<std::string>* context_dex_paths) {
1479 if (class_loader_context == nullptr) {
1480 return true;
1481 }
1482
1483 LOG(DEBUG) << "Getting dex paths for context " << class_loader_context;
1484
1485 // Pipe to get the hash result back from our child process.
1486 unique_fd pipe_read, pipe_write;
1487 if (!Pipe(&pipe_read, &pipe_write)) {
1488 PLOG(ERROR) << "Failed to create pipe";
1489 return false;
1490 }
1491
1492 pid_t pid = fork();
1493 if (pid == 0) {
1494 // child -- drop privileges before continuing.
1495 drop_capabilities(uid);
1496
1497 // Route stdout to `pipe_write`
1498 while ((dup2(pipe_write, STDOUT_FILENO) == -1) && (errno == EINTR)) {}
1499 pipe_write.reset();
1500 pipe_read.reset();
1501
1502 RunDexoptAnalyzer run_dexopt_analyzer(class_loader_context);
1503 run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
1504 }
1505
1506 /* parent */
1507 pipe_write.reset();
1508
1509 std::string str_dex_paths;
1510 if (!ReadFdToString(pipe_read, &str_dex_paths)) {
1511 PLOG(ERROR) << "Failed to read from pipe";
1512 return false;
1513 }
1514 pipe_read.reset();
1515
1516 int return_code = wait_child(pid);
1517 if (!WIFEXITED(return_code)) {
1518 PLOG(ERROR) << "Error waiting for child dexoptanalyzer process";
1519 return false;
1520 }
1521
1522 constexpr int kFlattenClassLoaderContextSuccess = 50;
1523 return_code = WEXITSTATUS(return_code);
1524 if (return_code != kFlattenClassLoaderContextSuccess) {
1525 LOG(ERROR) << "Dexoptanalyzer could not flatten class loader context, code=" << return_code;
1526 return false;
1527 }
1528
1529 if (!str_dex_paths.empty()) {
1530 *context_dex_paths = android::base::Split(str_dex_paths, ":");
1531 }
1532 return true;
1533}
1534
1535static int open_dex_paths(const std::vector<std::string>& dex_paths,
1536 /* out */ std::vector<unique_fd>* zip_fds, /* out */ std::string* error_msg) {
1537 for (const std::string& dex_path : dex_paths) {
1538 zip_fds->emplace_back(open(dex_path.c_str(), O_RDONLY));
1539 if (zip_fds->back().get() < 0) {
1540 *error_msg = StringPrintf(
1541 "installd cannot open '%s' for input during dexopt", dex_path.c_str());
1542 if (errno == ENOENT) {
1543 return kSecondaryDexDexoptAnalyzerSkippedNoFile;
1544 } else {
1545 return kSecondaryDexDexoptAnalyzerSkippedOpenZip;
1546 }
1547 }
1548 }
1549 return 0;
1550}
1551
1552static std::string join_fds(const std::vector<unique_fd>& fds) {
1553 std::stringstream ss;
1554 bool is_first = true;
1555 for (const unique_fd& fd : fds) {
1556 if (is_first) {
1557 is_first = false;
1558 } else {
1559 ss << ":";
1560 }
1561 ss << fd.get();
1562 }
1563 return ss.str();
1564}
1565
Calin Juravlec9eab382017-01-25 01:17:17 -08001566// Processes the dex_path as a secondary dex files and return true if the path dex file should
Calin Juravle80a21252017-01-17 14:43:25 -08001567// be compiled. Returns false for errors (logged) or true if the secondary dex path was process
1568// successfully.
Calin Juravleebc8a792017-04-04 20:21:05 -07001569// When returning true, the output parameters will be:
1570// - is_public_out: whether or not the oat file should not be made public
1571// - dexopt_needed_out: valid OatFileAsssitant::DexOptNeeded
1572// - oat_dir_out: the oat dir path where the oat file should be stored
Calin Juravle7d765462017-09-04 15:57:10 -07001573static bool process_secondary_dex_dexopt(const std::string& dex_path, const char* pkgname,
Calin Juravle80a21252017-01-17 14:43:25 -08001574 int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
Calin Juravleebc8a792017-04-04 20:21:05 -07001575 const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
Andreas Gampe194fe422018-02-28 20:16:19 -08001576 std::string* oat_dir_out, bool downgrade, const char* class_loader_context,
David Brazdil4f6027a2019-03-19 11:44:21 +00001577 const std::vector<std::string>& context_dex_paths, /* out */ std::string* error_msg) {
Calin Juravle7d765462017-09-04 15:57:10 -07001578 LOG(DEBUG) << "Processing secondary dex path " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001579 int storage_flag;
Andreas Gampe194fe422018-02-28 20:16:19 -08001580 if (!validate_dexopt_storage_flags(dexopt_flags, &storage_flag, error_msg)) {
1581 LOG(ERROR) << *error_msg;
Calin Juravle80a21252017-01-17 14:43:25 -08001582 return false;
1583 }
Calin Juravle7d765462017-09-04 15:57:10 -07001584 // Compute the oat dir as it's not easy to extract it from the child computation.
1585 char oat_path[PKG_PATH_MAX];
1586 char oat_dir[PKG_PATH_MAX];
1587 char oat_isa_dir[PKG_PATH_MAX];
1588 if (!create_secondary_dex_oat_layout(
Andreas Gampe194fe422018-02-28 20:16:19 -08001589 dex_path, instruction_set, oat_dir, oat_isa_dir, oat_path, error_msg)) {
1590 LOG(ERROR) << "Could not create secondary odex layout: " << *error_msg;
Calin Juravled23dee72017-07-06 16:29:11 -07001591 return false;
1592 }
Calin Juravle7d765462017-09-04 15:57:10 -07001593 oat_dir_out->assign(oat_dir);
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001594
Calin Juravle80a21252017-01-17 14:43:25 -08001595 pid_t pid = fork();
1596 if (pid == 0) {
1597 // child -- drop privileges before continuing.
1598 drop_capabilities(uid);
Calin Juravle7d765462017-09-04 15:57:10 -07001599
1600 // Validate the path structure.
1601 if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
1602 LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001603 _exit(kSecondaryDexDexoptAnalyzerSkippedValidatePath);
Calin Juravle7d765462017-09-04 15:57:10 -07001604 }
1605
1606 // Open the dex file.
1607 unique_fd zip_fd;
1608 zip_fd.reset(open(dex_path.c_str(), O_RDONLY));
1609 if (zip_fd.get() < 0) {
1610 if (errno == ENOENT) {
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001611 _exit(kSecondaryDexDexoptAnalyzerSkippedNoFile);
Calin Juravle7d765462017-09-04 15:57:10 -07001612 } else {
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001613 _exit(kSecondaryDexDexoptAnalyzerSkippedOpenZip);
Calin Juravle7d765462017-09-04 15:57:10 -07001614 }
1615 }
1616
David Brazdil4f6027a2019-03-19 11:44:21 +00001617 // Open class loader context dex files.
1618 std::vector<unique_fd> context_zip_fds;
1619 int open_dex_paths_rc = open_dex_paths(context_dex_paths, &context_zip_fds, error_msg);
1620 if (open_dex_paths_rc != 0) {
1621 _exit(open_dex_paths_rc);
1622 }
1623
Calin Juravle7d765462017-09-04 15:57:10 -07001624 // Prepare the oat directories.
1625 if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set)) {
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001626 _exit(kSecondaryDexDexoptAnalyzerSkippedPrepareDir);
Calin Juravle7d765462017-09-04 15:57:10 -07001627 }
1628
1629 // Open the vdex/oat files if any.
1630 unique_fd oat_file_fd;
1631 unique_fd vdex_file_fd;
1632 if (!maybe_open_oat_and_vdex_file(dex_path,
1633 *oat_dir_out,
1634 instruction_set,
1635 true /* is_secondary_dex */,
1636 &oat_file_fd,
1637 &vdex_file_fd)) {
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001638 _exit(kSecondaryDexDexoptAnalyzerSkippedOpenOutput);
Calin Juravle7d765462017-09-04 15:57:10 -07001639 }
1640
1641 // Analyze profiles.
Calin Juravle824a64d2018-01-18 20:23:17 -08001642 bool profile_was_updated = analyze_profiles(uid, pkgname, dex_path,
1643 /*is_secondary_dex*/true);
Calin Juravle7d765462017-09-04 15:57:10 -07001644
1645 // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return.
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001646 // Note that we do not do it before the fork since opening the files is required to happen
1647 // after forking.
1648 RunDexoptAnalyzer run_dexopt_analyzer(dex_path,
1649 vdex_file_fd.get(),
1650 oat_file_fd.get(),
1651 zip_fd.get(),
1652 instruction_set,
1653 compiler_filter, profile_was_updated,
1654 downgrade,
David Brazdil4f6027a2019-03-19 11:44:21 +00001655 class_loader_context,
1656 join_fds(context_zip_fds));
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001657 run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
Calin Juravle80a21252017-01-17 14:43:25 -08001658 }
1659
1660 /* parent */
Calin Juravle80a21252017-01-17 14:43:25 -08001661 int result = wait_child(pid);
1662 if (!WIFEXITED(result)) {
Andreas Gampe194fe422018-02-28 20:16:19 -08001663 *error_msg = StringPrintf("dexoptanalyzer failed for path %s: 0x%04x",
1664 dex_path.c_str(),
1665 result);
1666 LOG(ERROR) << *error_msg;
Calin Juravle80a21252017-01-17 14:43:25 -08001667 return false;
1668 }
1669 result = WEXITSTATUS(result);
Calin Juravle7d765462017-09-04 15:57:10 -07001670 // Check that we successfully executed dexoptanalyzer.
Andreas Gampe194fe422018-02-28 20:16:19 -08001671 bool success = process_secondary_dexoptanalyzer_result(dex_path,
1672 result,
1673 dexopt_needed_out,
1674 error_msg);
1675 if (!success) {
1676 LOG(ERROR) << *error_msg;
1677 }
Calin Juravle7d765462017-09-04 15:57:10 -07001678
1679 LOG(DEBUG) << "Processed secondary dex file " << dex_path << " result=" << result;
1680
Calin Juravle80a21252017-01-17 14:43:25 -08001681 // Run dexopt only if needed or forced.
Calin Juravle7d765462017-09-04 15:57:10 -07001682 // Note that dexoptanalyzer is executed even if force compilation is enabled (because it
1683 // makes the code simpler; force compilation is only needed during tests).
1684 if (success &&
Andreas Gampe3008bbe2018-02-28 20:24:48 -08001685 (result != kSecondaryDexDexoptAnalyzerSkippedNoFile) &&
Calin Juravle7d765462017-09-04 15:57:10 -07001686 ((dexopt_flags & DEXOPT_FORCE) != 0)) {
Calin Juravle80a21252017-01-17 14:43:25 -08001687 *dexopt_needed_out = DEX2OAT_FROM_SCRATCH;
1688 }
1689
Calin Juravle7d765462017-09-04 15:57:10 -07001690 // Check if we should make the oat file public.
1691 // Note that if the dex file is not public the compiled code cannot be made public.
1692 // It is ok to check this flag outside in the parent process.
1693 *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) && is_file_public(dex_path);
1694
Calin Juravle80a21252017-01-17 14:43:25 -08001695 return success;
1696}
1697
Andreas Gampefa2dadd2018-02-28 19:52:47 -08001698static std::string format_dexopt_error(int status, const char* dex_path) {
1699 if (WIFEXITED(status)) {
1700 int int_code = WEXITSTATUS(status);
1701 const char* code_name = get_return_code_name(static_cast<DexoptReturnCodes>(int_code));
1702 if (code_name != nullptr) {
1703 return StringPrintf("Dex2oat invocation for %s failed: %s", dex_path, code_name);
1704 }
1705 }
1706 return StringPrintf("Dex2oat invocation for %s failed with 0x%04x", dex_path, status);
Andreas Gampe023b2242018-02-28 16:03:25 -08001707}
1708
Calin Juravlec9eab382017-01-25 01:17:17 -08001709int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
Calin Juravle80a21252017-01-17 14:43:25 -08001710 int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
Calin Juravle52c45822017-07-13 22:50:21 -07001711 const char* volume_uuid, const char* class_loader_context, const char* se_info,
Calin Juravle62c5a372018-02-01 17:03:23 +00001712 bool downgrade, int target_sdk_version, const char* profile_name,
Andreas Gampe023b2242018-02-28 16:03:25 -08001713 const char* dex_metadata_path, const char* compilation_reason, std::string* error_msg) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001714 CHECK(pkgname != nullptr);
1715 CHECK(pkgname[0] != 0);
Andreas Gampe023b2242018-02-28 16:03:25 -08001716 CHECK(error_msg != nullptr);
Andreas Gamped32eec22018-02-28 16:02:51 -08001717 CHECK_EQ(dexopt_flags & ~DEXOPT_MASK, 0)
1718 << "dexopt flags contains unknown fields: " << dexopt_flags;
Calin Juravle7a570e82017-01-14 16:23:30 -08001719
Calin Juravled23dee72017-07-06 16:29:11 -07001720 if (!validate_dex_path_size(dex_path)) {
Andreas Gampe023b2242018-02-28 16:03:25 -08001721 *error_msg = StringPrintf("Failed to validate %s", dex_path);
Calin Juravle52c45822017-07-13 22:50:21 -07001722 return -1;
1723 }
1724
1725 if (class_loader_context != nullptr && strlen(class_loader_context) > PKG_PATH_MAX) {
Andreas Gampe023b2242018-02-28 16:03:25 -08001726 *error_msg = StringPrintf("Class loader context exceeds the allowed size: %s",
1727 class_loader_context);
1728 LOG(ERROR) << *error_msg;
Calin Juravle52c45822017-07-13 22:50:21 -07001729 return -1;
Calin Juravled23dee72017-07-06 16:29:11 -07001730 }
1731
Calin Juravleebc8a792017-04-04 20:21:05 -07001732 bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
Calin Juravle7a570e82017-01-14 16:23:30 -08001733 bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
1734 bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
1735 bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
Calin Juravle80a21252017-01-17 14:43:25 -08001736 bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
Andreas Gampea73a0cb2017-11-02 18:14:42 -07001737 bool background_job_compile = (dexopt_flags & DEXOPT_IDLE_BACKGROUND_JOB) != 0;
David Brazdil52249162018-02-12 18:04:59 -08001738 bool enable_hidden_api_checks = (dexopt_flags & DEXOPT_ENABLE_HIDDEN_API_CHECKS) != 0;
Mathieu Chartierf69c2f72018-03-06 13:55:58 -08001739 bool generate_compact_dex = (dexopt_flags & DEXOPT_GENERATE_COMPACT_DEX) != 0;
Mathieu Chartier1dc3dfa2018-03-12 17:55:06 -07001740 bool generate_app_image = (dexopt_flags & DEXOPT_GENERATE_APP_IMAGE) != 0;
Patrick Baumann2271b3e2020-04-14 17:03:00 -07001741 bool for_restore = (dexopt_flags & DEXOPT_FOR_RESTORE) != 0;
Calin Juravle80a21252017-01-17 14:43:25 -08001742
1743 // Check if we're dealing with a secondary dex file and if we need to compile it.
1744 std::string oat_dir_str;
David Brazdil4f6027a2019-03-19 11:44:21 +00001745 std::vector<std::string> context_dex_paths;
Calin Juravle80a21252017-01-17 14:43:25 -08001746 if (is_secondary_dex) {
David Brazdil4f6027a2019-03-19 11:44:21 +00001747 if (!get_class_loader_context_dex_paths(class_loader_context, uid, &context_dex_paths)) {
1748 *error_msg = "Failed acquiring context dex paths";
1749 return -1; // We had an error, logged in the process method.
1750 }
1751
Calin Juravlec9eab382017-01-25 01:17:17 -08001752 if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
Calin Juravleebc8a792017-04-04 20:21:05 -07001753 instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
David Brazdil4f6027a2019-03-19 11:44:21 +00001754 downgrade, class_loader_context, context_dex_paths, error_msg)) {
Calin Juravle80a21252017-01-17 14:43:25 -08001755 oat_dir = oat_dir_str.c_str();
1756 if (dexopt_needed == NO_DEXOPT_NEEDED) {
1757 return 0; // Nothing to do, report success.
1758 }
1759 } else {
Andreas Gampe194fe422018-02-28 20:16:19 -08001760 if (error_msg->empty()) { // TODO: Make this a CHECK.
1761 *error_msg = "Failed processing secondary.";
1762 }
Calin Juravle80a21252017-01-17 14:43:25 -08001763 return -1; // We had an error, logged in the process method.
1764 }
1765 } else {
David Brazdil4f6027a2019-03-19 11:44:21 +00001766 // Currently these flags are only used for secondary dex files.
Calin Juravlec9eab382017-01-25 01:17:17 -08001767 // Verify that they are not set for primary apks.
Calin Juravle80a21252017-01-17 14:43:25 -08001768 CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0);
1769 CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0);
1770 }
Calin Juravle7a570e82017-01-14 16:23:30 -08001771
1772 // Open the input file.
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001773 unique_fd input_fd(open(dex_path, O_RDONLY, 0));
Calin Juravle7a570e82017-01-14 16:23:30 -08001774 if (input_fd.get() < 0) {
Andreas Gampe023b2242018-02-28 16:03:25 -08001775 *error_msg = StringPrintf("installd cannot open '%s' for input during dexopt", dex_path);
1776 LOG(ERROR) << *error_msg;
Calin Juravle7a570e82017-01-14 16:23:30 -08001777 return -1;
1778 }
1779
David Brazdil4f6027a2019-03-19 11:44:21 +00001780 // Open class loader context dex files.
1781 std::vector<unique_fd> context_input_fds;
1782 if (open_dex_paths(context_dex_paths, &context_input_fds, error_msg) != 0) {
1783 LOG(ERROR) << *error_msg;
1784 return -1;
1785 }
1786
Calin Juravle7a570e82017-01-14 16:23:30 -08001787 // Create the output OAT file.
1788 char out_oat_path[PKG_PATH_MAX];
Calin Juravlec9eab382017-01-25 01:17:17 -08001789 Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid,
Calin Juravle80a21252017-01-17 14:43:25 -08001790 instruction_set, is_secondary_dex, out_oat_path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001791 if (out_oat_fd.get() < 0) {
Andreas Gampe023b2242018-02-28 16:03:25 -08001792 *error_msg = "Could not open out oat file.";
Calin Juravle7a570e82017-01-14 16:23:30 -08001793 return -1;
1794 }
1795
1796 // Open vdex files.
1797 Dex2oatFileWrapper in_vdex_fd;
1798 Dex2oatFileWrapper out_vdex_fd;
Shubham Ajmerab6bcd222017-10-19 10:08:03 -07001799 if (!open_vdex_files_for_dex2oat(dex_path, out_oat_path, dexopt_needed, instruction_set,
1800 is_public, uid, is_secondary_dex, profile_guided, &in_vdex_fd, &out_vdex_fd)) {
Andreas Gampe023b2242018-02-28 16:03:25 -08001801 *error_msg = "Could not open vdex files.";
Jeff Sharkey90aff262016-12-12 14:28:24 -07001802 return -1;
1803 }
1804
Calin Juravlecb556e32017-04-04 20:22:50 -07001805 // Ensure that the oat dir and the compiler artifacts of secondary dex files have the correct
1806 // selinux context (we generate them on the fly during the dexopt invocation and they don't
1807 // fully inherit their parent context).
1808 // Note that for primary apk the oat files are created before, in a separate installd
1809 // call which also does the restorecon. TODO(calin): unify the paths.
1810 if (is_secondary_dex) {
1811 if (selinux_android_restorecon_pkgdir(oat_dir, se_info, uid,
1812 SELINUX_ANDROID_RESTORECON_RECURSE)) {
Andreas Gampe023b2242018-02-28 16:03:25 -08001813 *error_msg = std::string("Failed to restorecon ").append(oat_dir);
1814 LOG(ERROR) << *error_msg;
Calin Juravlecb556e32017-04-04 20:22:50 -07001815 return -1;
1816 }
1817 }
1818
Jeff Sharkey90aff262016-12-12 14:28:24 -07001819 // Create a swap file if necessary.
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001820 unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001821
Calin Juravle7a570e82017-01-14 16:23:30 -08001822 // Open the reference profile if needed.
Calin Juravle114f0812017-03-08 19:05:07 -08001823 Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
Calin Juravle824a64d2018-01-18 20:23:17 -08001824 pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
Calin Juravle7a570e82017-01-14 16:23:30 -08001825
liulvping61907742018-08-21 09:36:52 +08001826 if (reference_profile_fd.get() == -1) {
1827 // We don't create an app image without reference profile since there is no speedup from
1828 // loading it in that case and instead will be a small overhead.
1829 generate_app_image = false;
1830 }
1831
1832 // Create the app image file if needed.
1833 Dex2oatFileWrapper image_fd = maybe_open_app_image(
1834 out_oat_path, generate_app_image, is_public, uid, is_secondary_dex);
1835
Calin Juravle62c5a372018-02-01 17:03:23 +00001836 unique_fd dex_metadata_fd;
1837 if (dex_metadata_path != nullptr) {
1838 dex_metadata_fd.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW)));
1839 if (dex_metadata_fd.get() < 0) {
1840 PLOG(ERROR) << "Failed to open dex metadata file " << dex_metadata_path;
1841 }
1842 }
1843
Victor Hsieh8948a862020-08-07 11:30:55 -07001844 std::string jitzygote_flag = server_configurable_flags::GetServerConfigurableFlag(
1845 RUNTIME_NATIVE_BOOT_NAMESPACE,
1846 ENABLE_JITZYGOTE_IMAGE,
1847 /*default_value=*/ "");
1848 bool use_jitzygote_image = jitzygote_flag == "true" || IsBootClassPathProfilingEnable();
1849
Victor Hsiehe98e6512020-08-10 15:39:22 -07001850 // Decide whether to use dex2oat64.
1851 bool use_dex2oat64 = false;
1852 // Check whether the device even supports 64-bit ABIs.
1853 if (!GetProperty("ro.product.cpu.abilist64", "").empty()) {
1854 use_dex2oat64 = GetBoolProperty("dalvik.vm.dex2oat64.enabled", false);
1855 }
1856 const char* dex2oat_bin = select_execution_binary(
1857 (use_dex2oat64 ? kDex2oat64Path : kDex2oat32Path),
1858 (use_dex2oat64 ? kDex2oatDebug64Path : kDex2oatDebug32Path),
1859 background_job_compile);
1860
Victor Hsiehc9821f12020-08-07 11:32:29 -07001861 auto execv_helper = std::make_unique<ExecVHelper>();
1862
Andreas Gampe023b2242018-02-28 16:03:25 -08001863 LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---";
Jeff Sharkey90aff262016-12-12 14:28:24 -07001864
Victor Hsiehc9821f12020-08-07 11:32:29 -07001865 RunDex2Oat runner(dex2oat_bin, execv_helper.get());
1866 runner.Initialize(input_fd.get(),
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001867 out_oat_fd.get(),
1868 in_vdex_fd.get(),
1869 out_vdex_fd.get(),
1870 image_fd.get(),
1871 dex_path,
1872 out_oat_path,
1873 swap_fd.get(),
1874 instruction_set,
1875 compiler_filter,
1876 debuggable,
1877 boot_complete,
Patrick Baumann2271b3e2020-04-14 17:03:00 -07001878 for_restore,
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001879 reference_profile_fd.get(),
1880 class_loader_context,
David Brazdil4f6027a2019-03-19 11:44:21 +00001881 join_fds(context_input_fds),
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001882 target_sdk_version,
1883 enable_hidden_api_checks,
1884 generate_compact_dex,
1885 dex_metadata_fd.get(),
Victor Hsieh8948a862020-08-07 11:30:55 -07001886 use_jitzygote_image,
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001887 compilation_reason);
1888
Jeff Sharkey90aff262016-12-12 14:28:24 -07001889 pid_t pid = fork();
1890 if (pid == 0) {
1891 /* child -- drop privileges before continuing */
1892 drop_capabilities(uid);
1893
Richard Uhler76cc0272016-12-08 10:46:35 +00001894 SetDex2OatScheduling(boot_complete);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001895 if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
Andreas Gampe023b2242018-02-28 16:03:25 -08001896 PLOG(ERROR) << "flock(" << out_oat_path << ") failed";
Andreas Gampefa2dadd2018-02-28 19:52:47 -08001897 _exit(DexoptReturnCodes::kFlock);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001898 }
1899
Mathieu Chartiercc66c442018-11-09 15:57:21 -08001900 runner.Exec(DexoptReturnCodes::kDex2oatExec);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001901 } else {
1902 int res = wait_child(pid);
1903 if (res == 0) {
Andreas Gampe023b2242018-02-28 16:03:25 -08001904 LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' (success) ---";
Jeff Sharkey90aff262016-12-12 14:28:24 -07001905 } else {
Andreas Gampe023b2242018-02-28 16:03:25 -08001906 LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' --- status=0x"
1907 << std::hex << std::setw(4) << res << ", process failed";
1908 *error_msg = format_dexopt_error(res, dex_path);
Andreas Gampe013f02e2017-03-20 18:36:54 -07001909 return res;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001910 }
1911 }
1912
Calin Juravlec9eab382017-01-25 01:17:17 -08001913 update_out_oat_access_times(dex_path, out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001914
1915 // We've been successful, don't delete output.
1916 out_oat_fd.SetCleanup(false);
Calin Juravle7a570e82017-01-14 16:23:30 -08001917 out_vdex_fd.SetCleanup(false);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001918 image_fd.SetCleanup(false);
1919 reference_profile_fd.SetCleanup(false);
1920
1921 return 0;
1922}
1923
Calin Juravlec9eab382017-01-25 01:17:17 -08001924// Try to remove the given directory. Log an error if the directory exists
1925// and is empty but could not be removed.
1926static bool rmdir_if_empty(const char* dir) {
1927 if (rmdir(dir) == 0) {
1928 return true;
1929 }
1930 if (errno == ENOENT || errno == ENOTEMPTY) {
1931 return true;
1932 }
1933 PLOG(ERROR) << "Failed to remove dir: " << dir;
1934 return false;
1935}
1936
1937// Try to unlink the given file. Log an error if the file exists and could not
1938// be unlinked.
1939static bool unlink_if_exists(const std::string& file) {
1940 if (unlink(file.c_str()) == 0) {
1941 return true;
1942 }
1943 if (errno == ENOENT) {
1944 return true;
1945
1946 }
1947 PLOG(ERROR) << "Could not unlink: " << file;
1948 return false;
1949}
1950
Calin Juravle7d765462017-09-04 15:57:10 -07001951enum ReconcileSecondaryDexResult {
1952 kReconcileSecondaryDexExists = 0,
1953 kReconcileSecondaryDexCleanedUp = 1,
1954 kReconcileSecondaryDexValidationError = 2,
1955 kReconcileSecondaryDexCleanUpError = 3,
1956 kReconcileSecondaryDexAccessIOError = 4,
1957};
Calin Juravlec9eab382017-01-25 01:17:17 -08001958
1959// Reconcile the secondary dex 'dex_path' and its generated oat files.
1960// Return true if all the parameters are valid and the secondary dex file was
1961// processed successfully (i.e. the dex_path either exists, or if not, its corresponding
1962// oat/vdex/art files where deleted successfully). In this case, out_secondary_dex_exists
1963// will be true if the secondary dex file still exists. If the secondary dex file does not exist,
1964// the method cleans up any previously generated compiler artifacts (oat, vdex, art).
1965// Return false if there were errors during processing. In this case
1966// out_secondary_dex_exists will be set to false.
1967bool reconcile_secondary_dex_file(const std::string& dex_path,
1968 const std::string& pkgname, int uid, const std::vector<std::string>& isas,
Jooyung Han9fcc4ef2020-01-23 12:45:10 +09001969 const std::optional<std::string>& volume_uuid, int storage_flag,
Calin Juravlec9eab382017-01-25 01:17:17 -08001970 /*out*/bool* out_secondary_dex_exists) {
Calin Juravle7d765462017-09-04 15:57:10 -07001971 *out_secondary_dex_exists = false; // start by assuming the file does not exist.
Calin Juravlec9eab382017-01-25 01:17:17 -08001972 if (isas.size() == 0) {
1973 LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector";
1974 return false;
1975 }
1976
Calin Juravle7d765462017-09-04 15:57:10 -07001977 if (storage_flag != FLAG_STORAGE_CE && storage_flag != FLAG_STORAGE_DE) {
1978 LOG(ERROR) << "reconcile_secondary_dex_file called with invalid storage_flag: "
1979 << storage_flag;
Calin Juravlec9eab382017-01-25 01:17:17 -08001980 return false;
1981 }
1982
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07001983 // As a security measure we want to unlink art artifacts with the reduced capabilities
1984 // of the package user id. So we fork and drop capabilities in the child.
1985 pid_t pid = fork();
1986 if (pid == 0) {
Calin Juravle7d765462017-09-04 15:57:10 -07001987 /* child -- drop privileges before continuing */
1988 drop_capabilities(uid);
1989
Jooyung Han9fcc4ef2020-01-23 12:45:10 +09001990 const char* volume_uuid_cstr = volume_uuid ? volume_uuid->c_str() : nullptr;
Greg Kaiser8042c372019-03-26 06:23:19 -07001991 if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr,
Calin Juravle7d765462017-09-04 15:57:10 -07001992 uid, storage_flag)) {
1993 LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
1994 _exit(kReconcileSecondaryDexValidationError);
1995 }
1996
1997 SecondaryDexAccess access_check = check_secondary_dex_access(dex_path);
1998 switch (access_check) {
1999 case kSecondaryDexAccessDoesNotExist:
2000 // File does not exist. Proceed with cleaning.
2001 break;
2002 case kSecondaryDexAccessReadOk: _exit(kReconcileSecondaryDexExists);
2003 case kSecondaryDexAccessIOError: _exit(kReconcileSecondaryDexAccessIOError);
2004 case kSecondaryDexAccessPermissionError: _exit(kReconcileSecondaryDexValidationError);
2005 default:
2006 LOG(ERROR) << "Unexpected result from check_secondary_dex_access: " << access_check;
2007 _exit(kReconcileSecondaryDexValidationError);
2008 }
2009
2010 // The secondary dex does not exist anymore or it's. Clear any generated files.
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002011 char oat_path[PKG_PATH_MAX];
2012 char oat_dir[PKG_PATH_MAX];
2013 char oat_isa_dir[PKG_PATH_MAX];
2014 bool result = true;
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002015 for (size_t i = 0; i < isas.size(); i++) {
Andreas Gampe194fe422018-02-28 20:16:19 -08002016 std::string error_msg;
Calin Juravle7d765462017-09-04 15:57:10 -07002017 if (!create_secondary_dex_oat_layout(
Andreas Gampe194fe422018-02-28 20:16:19 -08002018 dex_path,isas[i], oat_dir, oat_isa_dir, oat_path, &error_msg)) {
2019 LOG(ERROR) << error_msg;
Calin Juravle7d765462017-09-04 15:57:10 -07002020 _exit(kReconcileSecondaryDexValidationError);
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002021 }
Calin Juravle51314092017-05-18 15:33:05 -07002022
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002023 // Delete oat/vdex/art files.
2024 result = unlink_if_exists(oat_path) && result;
2025 result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
2026 result = unlink_if_exists(create_image_filename(oat_path)) && result;
Calin Juravlec9eab382017-01-25 01:17:17 -08002027
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002028 // Delete profiles.
2029 std::string current_profile = create_current_profile_path(
Calin Juravle824a64d2018-01-18 20:23:17 -08002030 multiuser_get_user_id(uid), pkgname, dex_path, /*is_secondary*/true);
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002031 std::string reference_profile = create_reference_profile_path(
Calin Juravle824a64d2018-01-18 20:23:17 -08002032 pkgname, dex_path, /*is_secondary*/true);
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002033 result = unlink_if_exists(current_profile) && result;
2034 result = unlink_if_exists(reference_profile) && result;
Calin Juravle51314092017-05-18 15:33:05 -07002035
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002036 // We upgraded once the location of current profile for secondary dex files.
2037 // Check for any previous left-overs and remove them as well.
2038 std::string old_current_profile = dex_path + ".prof";
2039 result = unlink_if_exists(old_current_profile);
Calin Juravle3760ad32017-07-27 16:31:55 -07002040
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002041 // Try removing the directories as well, they might be empty.
2042 result = rmdir_if_empty(oat_isa_dir) && result;
2043 result = rmdir_if_empty(oat_dir) && result;
2044 }
Calin Juravle7d765462017-09-04 15:57:10 -07002045 if (!result) {
2046 PLOG(ERROR) << "Failed to clean secondary dex artifacts for location " << dex_path;
2047 }
2048 _exit(result ? kReconcileSecondaryDexCleanedUp : kReconcileSecondaryDexAccessIOError);
Calin Juravlec9eab382017-01-25 01:17:17 -08002049 }
2050
Shubham Ajmerae6d7ad52017-08-25 13:07:44 -07002051 int return_code = wait_child(pid);
Calin Juravle7d765462017-09-04 15:57:10 -07002052 if (!WIFEXITED(return_code)) {
2053 LOG(WARNING) << "reconcile dex failed for location " << dex_path << ": " << return_code;
2054 } else {
2055 return_code = WEXITSTATUS(return_code);
2056 }
2057
2058 LOG(DEBUG) << "Reconcile secondary dex path " << dex_path << " result=" << return_code;
2059
2060 switch (return_code) {
2061 case kReconcileSecondaryDexCleanedUp:
2062 case kReconcileSecondaryDexValidationError:
2063 // If we couldn't validate assume the dex file does not exist.
2064 // This will purge the entry from the PM records.
2065 *out_secondary_dex_exists = false;
2066 return true;
2067 case kReconcileSecondaryDexExists:
2068 *out_secondary_dex_exists = true;
2069 return true;
2070 case kReconcileSecondaryDexAccessIOError:
2071 // We had an access IO error.
2072 // Return false so that we can try again.
2073 // The value of out_secondary_dex_exists does not matter in this case and by convention
2074 // is set to false.
2075 *out_secondary_dex_exists = false;
2076 return false;
2077 default:
2078 LOG(ERROR) << "Unexpected code from reconcile_secondary_dex_file: " << return_code;
2079 *out_secondary_dex_exists = false;
2080 return false;
2081 }
Calin Juravlec9eab382017-01-25 01:17:17 -08002082}
2083
Alan Stokesa25d90c2017-10-16 10:56:00 +01002084// Compute and return the hash (SHA-256) of the secondary dex file at dex_path.
2085// Returns true if all parameters are valid and the hash successfully computed and stored in
2086// out_secondary_dex_hash.
2087// Also returns true with an empty hash if the file does not currently exist or is not accessible to
2088// the app.
2089// For any other errors (e.g. if any of the parameters are invalid) returns false.
2090bool hash_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid,
Jooyung Han9fcc4ef2020-01-23 12:45:10 +09002091 const std::optional<std::string>& volume_uuid, int storage_flag,
Alan Stokesa25d90c2017-10-16 10:56:00 +01002092 std::vector<uint8_t>* out_secondary_dex_hash) {
2093 out_secondary_dex_hash->clear();
2094
Jooyung Han9fcc4ef2020-01-23 12:45:10 +09002095 const char* volume_uuid_cstr = volume_uuid ? volume_uuid->c_str() : nullptr;
Alan Stokesa25d90c2017-10-16 10:56:00 +01002096
2097 if (storage_flag != FLAG_STORAGE_CE && storage_flag != FLAG_STORAGE_DE) {
2098 LOG(ERROR) << "hash_secondary_dex_file called with invalid storage_flag: "
2099 << storage_flag;
2100 return false;
2101 }
2102
2103 // Pipe to get the hash result back from our child process.
2104 unique_fd pipe_read, pipe_write;
2105 if (!Pipe(&pipe_read, &pipe_write)) {
2106 PLOG(ERROR) << "Failed to create pipe";
2107 return false;
2108 }
2109
2110 // Fork so that actual access to the files is done in the app's own UID, to ensure we only
2111 // access data the app itself can access.
2112 pid_t pid = fork();
2113 if (pid == 0) {
2114 // child -- drop privileges before continuing
2115 drop_capabilities(uid);
2116 pipe_read.reset();
2117
2118 if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr, uid, storage_flag)) {
2119 LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
Andreas Gampefa2dadd2018-02-28 19:52:47 -08002120 _exit(DexoptReturnCodes::kHashValidatePath);
Alan Stokesa25d90c2017-10-16 10:56:00 +01002121 }
2122
2123 unique_fd fd(TEMP_FAILURE_RETRY(open(dex_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)));
2124 if (fd == -1) {
2125 if (errno == EACCES || errno == ENOENT) {
2126 // Not treated as an error.
2127 _exit(0);
2128 }
2129 PLOG(ERROR) << "Failed to open secondary dex " << dex_path;
Andreas Gampefa2dadd2018-02-28 19:52:47 -08002130 _exit(DexoptReturnCodes::kHashOpenPath);
Alan Stokesa25d90c2017-10-16 10:56:00 +01002131 }
2132
2133 SHA256_CTX ctx;
2134 SHA256_Init(&ctx);
2135
2136 std::vector<uint8_t> buffer(65536);
2137 while (true) {
2138 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
2139 if (bytes_read == 0) {
2140 break;
2141 } else if (bytes_read == -1) {
2142 PLOG(ERROR) << "Failed to read secondary dex " << dex_path;
Andreas Gampefa2dadd2018-02-28 19:52:47 -08002143 _exit(DexoptReturnCodes::kHashReadDex);
Alan Stokesa25d90c2017-10-16 10:56:00 +01002144 }
2145
2146 SHA256_Update(&ctx, buffer.data(), bytes_read);
2147 }
2148
2149 std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
2150 SHA256_Final(hash.data(), &ctx);
2151 if (!WriteFully(pipe_write, hash.data(), hash.size())) {
Andreas Gampefa2dadd2018-02-28 19:52:47 -08002152 _exit(DexoptReturnCodes::kHashWrite);
Alan Stokesa25d90c2017-10-16 10:56:00 +01002153 }
2154
2155 _exit(0);
2156 }
2157
2158 // parent
2159 pipe_write.reset();
2160
2161 out_secondary_dex_hash->resize(SHA256_DIGEST_LENGTH);
2162 if (!ReadFully(pipe_read, out_secondary_dex_hash->data(), out_secondary_dex_hash->size())) {
2163 out_secondary_dex_hash->clear();
2164 }
2165 return wait_child(pid) == 0;
2166}
2167
Jeff Sharkey90aff262016-12-12 14:28:24 -07002168// Helper for move_ab, so that we can have common failure-case cleanup.
2169static bool unlink_and_rename(const char* from, const char* to) {
2170 // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
2171 // return a failure.
2172 struct stat s;
2173 if (stat(to, &s) == 0) {
2174 if (!S_ISREG(s.st_mode)) {
2175 LOG(ERROR) << from << " is not a regular file to replace for A/B.";
2176 return false;
2177 }
2178 if (unlink(to) != 0) {
2179 LOG(ERROR) << "Could not unlink " << to << " to move A/B.";
2180 return false;
2181 }
2182 } else {
2183 // This may be a permission problem. We could investigate the error code, but we'll just
2184 // let the rename failure do the work for us.
2185 }
2186
2187 // Try to rename "to" to "from."
2188 if (rename(from, to) != 0) {
2189 PLOG(ERROR) << "Could not rename " << from << " to " << to;
2190 return false;
2191 }
2192 return true;
2193}
2194
2195// Move/rename a B artifact (from) to an A artifact (to).
2196static bool move_ab_path(const std::string& b_path, const std::string& a_path) {
2197 // Check whether B exists.
2198 {
2199 struct stat s;
2200 if (stat(b_path.c_str(), &s) != 0) {
2201 // Silently ignore for now. The service calling this isn't smart enough to understand
2202 // lack of artifacts at the moment.
2203 return false;
2204 }
2205 if (!S_ISREG(s.st_mode)) {
2206 LOG(ERROR) << "A/B artifact " << b_path << " is not a regular file.";
2207 // Try to unlink, but swallow errors.
2208 unlink(b_path.c_str());
2209 return false;
2210 }
2211 }
2212
2213 // Rename B to A.
2214 if (!unlink_and_rename(b_path.c_str(), a_path.c_str())) {
2215 // Delete the b_path so we don't try again (or fail earlier).
2216 if (unlink(b_path.c_str()) != 0) {
2217 PLOG(ERROR) << "Could not unlink " << b_path;
2218 }
2219
2220 return false;
2221 }
2222
2223 return true;
2224}
2225
2226bool move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
2227 // Get the current slot suffix. No suffix, no A/B.
Mathieu Chartier9b2da082018-10-26 13:23:11 -07002228 const std::string slot_suffix = GetProperty("ro.boot.slot_suffix", "");
2229 if (slot_suffix.empty()) {
2230 return false;
2231 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07002232
Mathieu Chartier9b2da082018-10-26 13:23:11 -07002233 if (!ValidateTargetSlotSuffix(slot_suffix)) {
2234 LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
2235 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07002236 }
2237
2238 // Validate other inputs.
2239 if (validate_apk_path(apk_path) != 0) {
2240 LOG(ERROR) << "Invalid apk_path: " << apk_path;
2241 return false;
2242 }
2243 if (validate_apk_path(oat_dir) != 0) {
2244 LOG(ERROR) << "Invalid oat_dir: " << oat_dir;
2245 return false;
2246 }
2247
2248 char a_path[PKG_PATH_MAX];
2249 if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
2250 return false;
2251 }
2252 const std::string a_vdex_path = create_vdex_filename(a_path);
2253 const std::string a_image_path = create_image_filename(a_path);
2254
2255 // B path = A path + slot suffix.
2256 const std::string b_path = StringPrintf("%s.%s", a_path, slot_suffix.c_str());
2257 const std::string b_vdex_path = StringPrintf("%s.%s", a_vdex_path.c_str(), slot_suffix.c_str());
2258 const std::string b_image_path = StringPrintf("%s.%s",
2259 a_image_path.c_str(),
2260 slot_suffix.c_str());
2261
2262 bool success = true;
2263 if (move_ab_path(b_path, a_path)) {
2264 if (move_ab_path(b_vdex_path, a_vdex_path)) {
2265 // Note: we can live without an app image. As such, ignore failure to move the image file.
2266 // If we decide to require the app image, or the app image being moved correctly,
2267 // then change accordingly.
2268 constexpr bool kIgnoreAppImageFailure = true;
2269
2270 if (!a_image_path.empty()) {
2271 if (!move_ab_path(b_image_path, a_image_path)) {
2272 unlink(a_image_path.c_str());
2273 if (!kIgnoreAppImageFailure) {
2274 success = false;
2275 }
2276 }
2277 }
2278 } else {
2279 // Cleanup: delete B image, ignore errors.
2280 unlink(b_image_path.c_str());
2281 success = false;
2282 }
2283 } else {
2284 // Cleanup: delete B image, ignore errors.
2285 unlink(b_vdex_path.c_str());
2286 unlink(b_image_path.c_str());
2287 success = false;
2288 }
2289 return success;
2290}
2291
2292bool delete_odex(const char* apk_path, const char* instruction_set, const char* oat_dir) {
2293 // Delete the oat/odex file.
2294 char out_path[PKG_PATH_MAX];
Calin Juravle80a21252017-01-17 14:43:25 -08002295 if (!create_oat_out_path(apk_path, instruction_set, oat_dir,
Calin Juravle114f0812017-03-08 19:05:07 -08002296 /*is_secondary_dex*/false, out_path)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07002297 return false;
2298 }
2299
2300 // In case of a permission failure report the issue. Otherwise just print a warning.
2301 auto unlink_and_check = [](const char* path) -> bool {
2302 int result = unlink(path);
2303 if (result != 0) {
2304 if (errno == EACCES || errno == EPERM) {
2305 PLOG(ERROR) << "Could not unlink " << path;
2306 return false;
2307 }
2308 PLOG(WARNING) << "Could not unlink " << path;
2309 }
2310 return true;
2311 };
2312
2313 // Delete the oat/odex file.
2314 bool return_value_oat = unlink_and_check(out_path);
2315
2316 // Derive and delete the app image.
2317 bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
2318
Nicolas Geoffray192fb962017-05-25 13:58:06 +01002319 // Derive and delete the vdex file.
2320 bool return_value_vdex = unlink_and_check(create_vdex_filename(out_path).c_str());
2321
Jeff Sharkey90aff262016-12-12 14:28:24 -07002322 // Report success.
Nicolas Geoffray192fb962017-05-25 13:58:06 +01002323 return return_value_oat && return_value_art && return_value_vdex;
Jeff Sharkey90aff262016-12-12 14:28:24 -07002324}
2325
Jeff Sharkeyc1149c92017-09-21 14:51:09 -06002326static bool is_absolute_path(const std::string& path) {
2327 if (path.find('/') != 0 || path.find("..") != std::string::npos) {
2328 LOG(ERROR) << "Invalid absolute path " << path;
2329 return false;
2330 } else {
2331 return true;
2332 }
2333}
2334
2335static bool is_valid_instruction_set(const std::string& instruction_set) {
2336 // TODO: add explicit whitelisting of instruction sets
2337 if (instruction_set.find('/') != std::string::npos) {
2338 LOG(ERROR) << "Invalid instruction set " << instruction_set;
2339 return false;
2340 } else {
2341 return true;
2342 }
2343}
2344
2345bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir,
2346 const char *apk_path, const char *instruction_set) {
2347 std::string oat_dir_ = oat_dir;
2348 std::string apk_path_ = apk_path;
2349 std::string instruction_set_ = instruction_set;
2350
2351 if (!is_absolute_path(oat_dir_)) return false;
2352 if (!is_absolute_path(apk_path_)) return false;
2353 if (!is_valid_instruction_set(instruction_set_)) return false;
2354
2355 std::string::size_type end = apk_path_.rfind('.');
2356 std::string::size_type start = apk_path_.rfind('/', end);
2357 if (end == std::string::npos || start == std::string::npos) {
2358 LOG(ERROR) << "Invalid apk_path " << apk_path_;
2359 return false;
2360 }
2361
2362 std::string res_ = oat_dir_ + '/' + instruction_set + '/'
2363 + apk_path_.substr(start + 1, end - start - 1) + ".odex";
2364 const char* res = res_.c_str();
2365 if (strlen(res) >= PKG_PATH_MAX) {
2366 LOG(ERROR) << "Result too large";
2367 return false;
2368 } else {
2369 strlcpy(path, res, PKG_PATH_MAX);
2370 return true;
2371 }
2372}
2373
2374bool calculate_odex_file_path_default(char path[PKG_PATH_MAX], const char *apk_path,
2375 const char *instruction_set) {
2376 std::string apk_path_ = apk_path;
2377 std::string instruction_set_ = instruction_set;
2378
2379 if (!is_absolute_path(apk_path_)) return false;
2380 if (!is_valid_instruction_set(instruction_set_)) return false;
2381
2382 std::string::size_type end = apk_path_.rfind('.');
2383 std::string::size_type start = apk_path_.rfind('/', end);
2384 if (end == std::string::npos || start == std::string::npos) {
2385 LOG(ERROR) << "Invalid apk_path " << apk_path_;
2386 return false;
2387 }
2388
2389 std::string oat_dir = apk_path_.substr(0, start + 1) + "oat";
2390 return calculate_oat_file_path_default(path, oat_dir.c_str(), apk_path, instruction_set);
2391}
2392
2393bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src,
2394 const char *instruction_set) {
2395 std::string src_ = src;
2396 std::string instruction_set_ = instruction_set;
2397
2398 if (!is_absolute_path(src_)) return false;
2399 if (!is_valid_instruction_set(instruction_set_)) return false;
2400
2401 for (auto it = src_.begin() + 1; it < src_.end(); ++it) {
2402 if (*it == '/') {
2403 *it = '@';
2404 }
2405 }
2406
2407 std::string res_ = android_data_dir + DALVIK_CACHE + '/' + instruction_set_ + src_
2408 + DALVIK_CACHE_POSTFIX;
2409 const char* res = res_.c_str();
2410 if (strlen(res) >= PKG_PATH_MAX) {
2411 LOG(ERROR) << "Result too large";
2412 return false;
2413 } else {
2414 strlcpy(path, res, PKG_PATH_MAX);
2415 return true;
2416 }
2417}
2418
Calin Juravle59f7ab82018-04-27 17:50:23 -07002419bool open_classpath_files(const std::string& classpath, std::vector<unique_fd>* apk_fds,
2420 std::vector<std::string>* dex_locations) {
Calin Juravle0d0a4922018-01-23 19:54:11 -08002421 std::vector<std::string> classpaths_elems = base::Split(classpath, ":");
2422 for (const std::string& elem : classpaths_elems) {
2423 unique_fd fd(TEMP_FAILURE_RETRY(open(elem.c_str(), O_RDONLY)));
2424 if (fd < 0) {
2425 PLOG(ERROR) << "Could not open classpath elem " << elem;
2426 return false;
2427 } else {
2428 apk_fds->push_back(std::move(fd));
Calin Juravle59f7ab82018-04-27 17:50:23 -07002429 dex_locations->push_back(elem);
Calin Juravle0d0a4922018-01-23 19:54:11 -08002430 }
2431 }
2432 return true;
2433}
2434
2435static bool create_app_profile_snapshot(int32_t app_id,
2436 const std::string& package_name,
2437 const std::string& profile_name,
2438 const std::string& classpath) {
Calin Juravle29591732017-11-20 17:46:19 -08002439 int app_shared_gid = multiuser_get_shared_gid(/*user_id*/ 0, app_id);
2440
Calin Juravle824a64d2018-01-18 20:23:17 -08002441 unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
Calin Juravle29591732017-11-20 17:46:19 -08002442 if (snapshot_fd < 0) {
2443 return false;
2444 }
2445
2446 std::vector<unique_fd> profiles_fd;
2447 unique_fd reference_profile_fd;
Calin Juravle824a64d2018-01-18 20:23:17 -08002448 open_profile_files(app_shared_gid, package_name, profile_name, /*is_secondary_dex*/ false,
2449 &profiles_fd, &reference_profile_fd);
Calin Juravle29591732017-11-20 17:46:19 -08002450 if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
2451 return false;
2452 }
2453
2454 profiles_fd.push_back(std::move(reference_profile_fd));
2455
Calin Juravle0d0a4922018-01-23 19:54:11 -08002456 // Open the class paths elements. These will be used to filter out profile data that does
2457 // not belong to the classpath during merge.
2458 std::vector<unique_fd> apk_fds;
Calin Juravle59f7ab82018-04-27 17:50:23 -07002459 std::vector<std::string> dex_locations;
2460 if (!open_classpath_files(classpath, &apk_fds, &dex_locations)) {
Calin Juravle0d0a4922018-01-23 19:54:11 -08002461 return false;
2462 }
2463
Mathieu Chartiercc66c442018-11-09 15:57:21 -08002464 RunProfman args;
Calin Juravlef85ddb92020-05-01 14:05:40 -07002465 // This is specifically a snapshot for an app, so don't use boot image profiles.
2466 args.SetupMerge(profiles_fd,
2467 snapshot_fd,
2468 apk_fds,
2469 dex_locations,
2470 /* for_snapshot= */ true,
2471 /* for_boot_image= */ false);
Calin Juravle29591732017-11-20 17:46:19 -08002472 pid_t pid = fork();
2473 if (pid == 0) {
2474 /* child -- drop privileges before continuing */
2475 drop_capabilities(app_shared_gid);
Mathieu Chartiercc66c442018-11-09 15:57:21 -08002476 args.Exec();
Calin Juravle29591732017-11-20 17:46:19 -08002477 }
2478
2479 /* parent */
2480 int return_code = wait_child(pid);
2481 if (!WIFEXITED(return_code)) {
Calin Juravle824a64d2018-01-18 20:23:17 -08002482 LOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
Calin Juravle29591732017-11-20 17:46:19 -08002483 return false;
2484 }
2485
Calin Juravle78728f32019-11-08 17:55:46 -08002486 // Verify that profman finished successfully.
2487 int profman_code = WEXITSTATUS(return_code);
2488 if (profman_code != PROFMAN_BIN_RETURN_CODE_SUCCESS) {
2489 LOG(WARNING) << "profman error for " << package_name << ":" << profile_name
2490 << ":" << profman_code;
2491 return false;
2492 }
Calin Juravle29591732017-11-20 17:46:19 -08002493 return true;
2494}
2495
Calin Juravle0d0a4922018-01-23 19:54:11 -08002496static bool create_boot_image_profile_snapshot(const std::string& package_name,
2497 const std::string& profile_name,
2498 const std::string& classpath) {
2499 // The reference profile directory for the android package might not be prepared. Do it now.
2500 const std::string ref_profile_dir =
2501 create_primary_reference_profile_package_dir_path(package_name);
2502 if (fs_prepare_dir(ref_profile_dir.c_str(), 0770, AID_SYSTEM, AID_SYSTEM) != 0) {
2503 PLOG(ERROR) << "Failed to prepare " << ref_profile_dir;
2504 return false;
2505 }
2506
Mathieu Chartiere0d64a12018-11-01 12:07:26 -07002507 // Return false for empty class path since it may otherwise return true below if profiles is
2508 // empty.
2509 if (classpath.empty()) {
2510 PLOG(ERROR) << "Class path is empty";
2511 return false;
2512 }
2513
Calin Juravle0d0a4922018-01-23 19:54:11 -08002514 // Open and create the snapshot profile.
2515 unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
2516
2517 // Collect all non empty profiles.
2518 // The collection will traverse all applications profiles and find the non empty files.
2519 // This has the potential of inspecting a large number of files and directories (depending
2520 // on the number of applications and users). So there is a slight increase in the chance
2521 // to get get occasionally I/O errors (e.g. for opening the file). When that happens do not
2522 // fail the snapshot and aggregate whatever profile we could open.
2523 //
2524 // The profile snapshot is a best effort based on available data it's ok if some data
2525 // from some apps is missing. It will be counter productive for the snapshot to fail
2526 // because we could not open or read some of the files.
2527 std::vector<std::string> profiles;
2528 if (!collect_profiles(&profiles)) {
2529 LOG(WARNING) << "There were errors while collecting the profiles for the boot image.";
2530 }
2531
2532 // If we have no profiles return early.
2533 if (profiles.empty()) {
2534 return true;
2535 }
2536
2537 // Open the classpath elements. These will be used to filter out profile data that does
2538 // not belong to the classpath during merge.
2539 std::vector<unique_fd> apk_fds;
Calin Juravle59f7ab82018-04-27 17:50:23 -07002540 std::vector<std::string> dex_locations;
2541 if (!open_classpath_files(classpath, &apk_fds, &dex_locations)) {
Calin Juravle0d0a4922018-01-23 19:54:11 -08002542 return false;
2543 }
2544
2545 // If we could not open any files from the classpath return an error.
2546 if (apk_fds.empty()) {
2547 LOG(ERROR) << "Could not open any of the classpath elements.";
2548 return false;
2549 }
2550
2551 // Aggregate the profiles in batches of kAggregationBatchSize.
2552 // We do this to avoid opening a huge a amount of files.
2553 static constexpr size_t kAggregationBatchSize = 10;
2554
Calin Juravle0d0a4922018-01-23 19:54:11 -08002555 for (size_t i = 0; i < profiles.size(); ) {
Calin Juravlea64fb512019-11-06 16:11:14 -08002556 std::vector<unique_fd> profiles_fd;
Calin Juravle0d0a4922018-01-23 19:54:11 -08002557 for (size_t k = 0; k < kAggregationBatchSize && i < profiles.size(); k++, i++) {
2558 unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY);
2559 if (fd.get() >= 0) {
2560 profiles_fd.push_back(std::move(fd));
2561 }
2562 }
Calin Juravlea64fb512019-11-06 16:11:14 -08002563
2564 // We aggregate (read & write) into the same fd multiple times in a row.
2565 // We need to reset the cursor every time to ensure we read the whole file every time.
2566 if (TEMP_FAILURE_RETRY(lseek(snapshot_fd, 0, SEEK_SET)) == static_cast<off_t>(-1)) {
2567 PLOG(ERROR) << "Cannot reset position for snapshot profile";
2568 return false;
2569 }
2570
Mathieu Chartiercc66c442018-11-09 15:57:21 -08002571 RunProfman args;
Calin Juravleb3a929d2018-12-11 14:40:00 -08002572 args.SetupMerge(profiles_fd,
2573 snapshot_fd,
2574 apk_fds,
Calin Juravle78728f32019-11-08 17:55:46 -08002575 dex_locations,
2576 /*for_snapshot=*/true,
2577 /*for_boot_image=*/true);
Calin Juravle0d0a4922018-01-23 19:54:11 -08002578 pid_t pid = fork();
2579 if (pid == 0) {
2580 /* child -- drop privileges before continuing */
2581 drop_capabilities(AID_SYSTEM);
2582
Calin Juravle59f7ab82018-04-27 17:50:23 -07002583 // The introduction of new access flags into boot jars causes them to
2584 // fail dex file verification.
Mathieu Chartiercc66c442018-11-09 15:57:21 -08002585 args.Exec();
Calin Juravle0d0a4922018-01-23 19:54:11 -08002586 }
2587
2588 /* parent */
2589 int return_code = wait_child(pid);
Calin Juravlea64fb512019-11-06 16:11:14 -08002590
Calin Juravle0d0a4922018-01-23 19:54:11 -08002591 if (!WIFEXITED(return_code)) {
2592 PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
2593 return false;
2594 }
Calin Juravlea64fb512019-11-06 16:11:14 -08002595
2596 // Verify that profman finished successfully.
2597 int profman_code = WEXITSTATUS(return_code);
Calin Juravle78728f32019-11-08 17:55:46 -08002598 if (profman_code != PROFMAN_BIN_RETURN_CODE_SUCCESS) {
2599 LOG(WARNING) << "profman error for " << package_name << ":" << profile_name
2600 << ":" << profman_code;
2601 return false;
Calin Juravlea64fb512019-11-06 16:11:14 -08002602 }
Calin Juravle0d0a4922018-01-23 19:54:11 -08002603 }
Calin Juravlea64fb512019-11-06 16:11:14 -08002604
Calin Juravle0d0a4922018-01-23 19:54:11 -08002605 return true;
2606}
2607
2608bool create_profile_snapshot(int32_t app_id, const std::string& package_name,
2609 const std::string& profile_name, const std::string& classpath) {
2610 if (app_id == -1) {
2611 return create_boot_image_profile_snapshot(package_name, profile_name, classpath);
2612 } else {
2613 return create_app_profile_snapshot(app_id, package_name, profile_name, classpath);
2614 }
2615}
2616
Calin Juravlec3b049e2018-01-18 22:32:58 -08002617bool prepare_app_profile(const std::string& package_name,
2618 userid_t user_id,
2619 appid_t app_id,
2620 const std::string& profile_name,
Calin Juravlef63d4792018-01-30 17:43:34 +00002621 const std::string& code_path,
Jooyung Han9fcc4ef2020-01-23 12:45:10 +09002622 const std::optional<std::string>& dex_metadata) {
Calin Juravlec3b049e2018-01-18 22:32:58 -08002623 // Prepare the current profile.
2624 std::string cur_profile = create_current_profile_path(user_id, package_name, profile_name,
2625 /*is_secondary_dex*/ false);
2626 uid_t uid = multiuser_get_uid(user_id, app_id);
2627 if (fs_prepare_file_strict(cur_profile.c_str(), 0600, uid, uid) != 0) {
2628 PLOG(ERROR) << "Failed to prepare " << cur_profile;
2629 return false;
2630 }
2631
2632 // Check if we need to install the profile from the dex metadata.
Jooyung Han9fcc4ef2020-01-23 12:45:10 +09002633 if (!dex_metadata) {
Calin Juravlec3b049e2018-01-18 22:32:58 -08002634 return true;
2635 }
2636
2637 // We have a dex metdata. Merge the profile into the reference profile.
2638 unique_fd ref_profile_fd = open_reference_profile(uid, package_name, profile_name,
2639 /*read_write*/ true, /*is_secondary_dex*/ false);
2640 unique_fd dex_metadata_fd(TEMP_FAILURE_RETRY(
2641 open(dex_metadata->c_str(), O_RDONLY | O_NOFOLLOW)));
Calin Juravlef63d4792018-01-30 17:43:34 +00002642 unique_fd apk_fd(TEMP_FAILURE_RETRY(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW)));
2643 if (apk_fd < 0) {
2644 PLOG(ERROR) << "Could not open code path " << code_path;
2645 return false;
2646 }
Calin Juravlec3b049e2018-01-18 22:32:58 -08002647
Mathieu Chartiercc66c442018-11-09 15:57:21 -08002648 RunProfman args;
2649 args.SetupCopyAndUpdate(std::move(dex_metadata_fd),
2650 std::move(ref_profile_fd),
2651 std::move(apk_fd),
2652 code_path);
Calin Juravlec3b049e2018-01-18 22:32:58 -08002653 pid_t pid = fork();
2654 if (pid == 0) {
2655 /* child -- drop privileges before continuing */
2656 gid_t app_shared_gid = multiuser_get_shared_gid(user_id, app_id);
2657 drop_capabilities(app_shared_gid);
2658
Calin Juravlef63d4792018-01-30 17:43:34 +00002659 // The copy and update takes ownership over the fds.
Mathieu Chartiercc66c442018-11-09 15:57:21 -08002660 args.Exec();
Calin Juravlec3b049e2018-01-18 22:32:58 -08002661 }
2662
2663 /* parent */
2664 int return_code = wait_child(pid);
2665 if (!WIFEXITED(return_code)) {
2666 PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
2667 return false;
2668 }
2669 return true;
2670}
2671
Jeff Sharkey6c2c0562016-12-07 12:12:00 -07002672} // namespace installd
2673} // namespace android