blob: a5ac8a4d4eacf3d7f5169fa8cfbd2f2beb7a47f9 [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 */
Mark Salyzyna5e161b2016-09-29 08:08:05 -070016#define LOG_TAG "installed"
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070017
Jeff Sharkey90aff262016-12-12 14:28:24 -070018#include <fcntl.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070019#include <stdlib.h>
20#include <string.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070021#include <sys/capability.h>
22#include <sys/file.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070023#include <sys/stat.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070024#include <sys/time.h>
25#include <sys/types.h>
26#include <sys/resource.h>
27#include <sys/wait.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070028#include <unistd.h>
29
30#include <android-base/logging.h>
31#include <android-base/stringprintf.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070032#include <android-base/strings.h>
33#include <android-base/unique_fd.h>
Calin Juravle80a21252017-01-17 14:43:25 -080034#include <cutils/fs.h>
Jeff Sharkey90aff262016-12-12 14:28:24 -070035#include <cutils/properties.h>
36#include <cutils/sched_policy.h>
Mark Salyzyn7823e122016-09-29 08:08:05 -070037#include <log/log.h> // TODO: Move everything to base/logging.
Jeff Sharkey90aff262016-12-12 14:28:24 -070038#include <private/android_filesystem_config.h>
39#include <system/thread_defs.h>
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070040
41#include "dexopt.h"
Jeff Sharkey90aff262016-12-12 14:28:24 -070042#include "installd_deps.h"
43#include "otapreopt_utils.h"
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070044#include "utils.h"
45
46using android::base::StringPrintf;
Jeff Sharkey90aff262016-12-12 14:28:24 -070047using android::base::EndsWith;
Calin Juravle1a0af3b2017-03-09 14:33:33 -080048using android::base::unique_fd;
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070049
50namespace android {
51namespace installd {
52
Calin Juravle1a0af3b2017-03-09 14:33:33 -080053static unique_fd invalid_unique_fd() {
54 return unique_fd(-1);
55}
56
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070057static const char* parse_null(const char* arg) {
58 if (strcmp(arg, "!") == 0) {
59 return nullptr;
60 } else {
61 return arg;
62 }
63}
64
Jeff Sharkey90aff262016-12-12 14:28:24 -070065static bool clear_profile(const std::string& profile) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -080066 unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
Jeff Sharkey90aff262016-12-12 14:28:24 -070067 if (ufd.get() < 0) {
68 if (errno != ENOENT) {
69 PLOG(WARNING) << "Could not open profile " << profile;
70 return false;
71 } else {
72 // Nothing to clear. That's ok.
73 return true;
74 }
75 }
76
77 if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
78 if (errno != EWOULDBLOCK) {
79 PLOG(WARNING) << "Error locking profile " << profile;
80 }
81 // This implies that the app owning this profile is running
82 // (and has acquired the lock).
83 //
84 // If we can't acquire the lock bail out since clearing is useless anyway
85 // (the app will write again to the profile).
86 //
87 // Note:
88 // This does not impact the this is not an issue for the profiling correctness.
89 // In case this is needed because of an app upgrade, profiles will still be
90 // eventually cleared by the app itself due to checksum mismatch.
91 // If this is needed because profman advised, then keeping the data around
92 // until the next run is again not an issue.
93 //
94 // If the app attempts to acquire a lock while we've held one here,
95 // it will simply skip the current write cycle.
96 return false;
97 }
98
99 bool truncated = ftruncate(ufd.get(), 0) == 0;
100 if (!truncated) {
101 PLOG(WARNING) << "Could not truncate " << profile;
102 }
103 if (flock(ufd.get(), LOCK_UN) != 0) {
104 PLOG(WARNING) << "Error unlocking profile " << profile;
105 }
106 return truncated;
107}
108
Calin Juravle76268c52017-03-09 13:19:42 -0800109bool clear_reference_profile(const std::string& pkgname) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700110 std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
111 std::string reference_profile = create_primary_profile(reference_profile_dir);
112 return clear_profile(reference_profile);
113}
114
Calin Juravle76268c52017-03-09 13:19:42 -0800115bool clear_current_profile(const std::string& pkgname, userid_t user) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700116 std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
117 std::string profile = create_primary_profile(profile_dir);
118 return clear_profile(profile);
119}
120
Calin Juravle76268c52017-03-09 13:19:42 -0800121bool clear_current_profiles(const std::string& pkgname) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700122 bool success = true;
123 std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
124 for (auto user : users) {
125 success &= clear_current_profile(pkgname, user);
126 }
127 return success;
128}
129
130static int split_count(const char *str)
131{
132 char *ctx;
133 int count = 0;
134 char buf[kPropertyValueMax];
135
136 strncpy(buf, str, sizeof(buf));
137 char *pBuf = buf;
138
139 while(strtok_r(pBuf, " ", &ctx) != NULL) {
140 count++;
141 pBuf = NULL;
142 }
143
144 return count;
145}
146
147static int split(char *buf, const char **argv)
148{
149 char *ctx;
150 int count = 0;
151 char *tok;
152 char *pBuf = buf;
153
154 while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) {
155 argv[count++] = tok;
156 pBuf = NULL;
157 }
158
159 return count;
160}
161
Jeff Sharkey90aff262016-12-12 14:28:24 -0700162static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
163 const char* input_file_name, const char* output_file_name, int swap_fd,
164 const char *instruction_set, const char* compiler_filter, bool vm_safe_mode,
165 bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
166 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
167
168 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
169 ALOGE("Instruction set %s longer than max length of %d",
170 instruction_set, MAX_INSTRUCTION_SET_LEN);
171 return;
172 }
173
174 char dex2oat_Xms_flag[kPropertyValueMax];
175 bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
176
177 char dex2oat_Xmx_flag[kPropertyValueMax];
178 bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
179
180 char dex2oat_threads_buf[kPropertyValueMax];
181 bool have_dex2oat_threads_flag = get_property(post_bootcomplete
182 ? "dalvik.vm.dex2oat-threads"
183 : "dalvik.vm.boot-dex2oat-threads",
184 dex2oat_threads_buf,
185 NULL) > 0;
186 char dex2oat_threads_arg[kPropertyValueMax + 2];
187 if (have_dex2oat_threads_flag) {
188 sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
189 }
190
191 char dex2oat_isa_features_key[kPropertyKeyMax];
192 sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
193 char dex2oat_isa_features[kPropertyValueMax];
194 bool have_dex2oat_isa_features = get_property(dex2oat_isa_features_key,
195 dex2oat_isa_features, NULL) > 0;
196
197 char dex2oat_isa_variant_key[kPropertyKeyMax];
198 sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
199 char dex2oat_isa_variant[kPropertyValueMax];
200 bool have_dex2oat_isa_variant = get_property(dex2oat_isa_variant_key,
201 dex2oat_isa_variant, NULL) > 0;
202
203 const char *dex2oat_norelocation = "-Xnorelocate";
204 bool have_dex2oat_relocation_skip_flag = false;
205
206 char dex2oat_flags[kPropertyValueMax];
207 int dex2oat_flags_count = get_property("dalvik.vm.dex2oat-flags",
208 dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
209 ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
210
211 // If we booting without the real /data, don't spend time compiling.
212 char vold_decrypt[kPropertyValueMax];
213 bool have_vold_decrypt = get_property("vold.decrypt", vold_decrypt, "") > 0;
214 bool skip_compilation = (have_vold_decrypt &&
215 (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
216 (strcmp(vold_decrypt, "1") == 0)));
217
218 bool generate_debug_info = property_get_bool("debug.generate-debug-info", false);
219
220 char app_image_format[kPropertyValueMax];
221 char image_format_arg[strlen("--image-format=") + kPropertyValueMax];
222 bool have_app_image_format =
223 image_fd >= 0 && get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
224 if (have_app_image_format) {
225 sprintf(image_format_arg, "--image-format=%s", app_image_format);
226 }
227
228 char dex2oat_large_app_threshold[kPropertyValueMax];
229 bool have_dex2oat_large_app_threshold =
230 get_property("dalvik.vm.dex2oat-very-large", dex2oat_large_app_threshold, NULL) > 0;
231 char dex2oat_large_app_threshold_arg[strlen("--very-large-app-threshold=") + kPropertyValueMax];
232 if (have_dex2oat_large_app_threshold) {
233 sprintf(dex2oat_large_app_threshold_arg,
234 "--very-large-app-threshold=%s",
235 dex2oat_large_app_threshold);
236 }
237
238 static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
239
240 static const char* RUNTIME_ARG = "--runtime-arg";
241
242 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
243
George Burgess IV36cebe772017-01-25 11:52:01 -0800244 // clang FORTIFY doesn't let us use strlen in constant array bounds, so we
245 // use arraysize instead.
246 char zip_fd_arg[arraysize("--zip-fd=") + MAX_INT_LEN];
247 char zip_location_arg[arraysize("--zip-location=") + PKG_PATH_MAX];
248 char input_vdex_fd_arg[arraysize("--input-vdex-fd=") + MAX_INT_LEN];
249 char output_vdex_fd_arg[arraysize("--output-vdex-fd=") + MAX_INT_LEN];
250 char oat_fd_arg[arraysize("--oat-fd=") + MAX_INT_LEN];
251 char oat_location_arg[arraysize("--oat-location=") + PKG_PATH_MAX];
252 char instruction_set_arg[arraysize("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
253 char instruction_set_variant_arg[arraysize("--instruction-set-variant=") + kPropertyValueMax];
254 char instruction_set_features_arg[arraysize("--instruction-set-features=") + kPropertyValueMax];
255 char dex2oat_Xms_arg[arraysize("-Xms") + kPropertyValueMax];
256 char dex2oat_Xmx_arg[arraysize("-Xmx") + kPropertyValueMax];
257 char dex2oat_compiler_filter_arg[arraysize("--compiler-filter=") + kPropertyValueMax];
Jeff Sharkey90aff262016-12-12 14:28:24 -0700258 bool have_dex2oat_swap_fd = false;
George Burgess IV36cebe772017-01-25 11:52:01 -0800259 char dex2oat_swap_fd[arraysize("--swap-fd=") + MAX_INT_LEN];
Jeff Sharkey90aff262016-12-12 14:28:24 -0700260 bool have_dex2oat_image_fd = false;
George Burgess IV36cebe772017-01-25 11:52:01 -0800261 char dex2oat_image_fd[arraysize("--app-image-fd=") + MAX_INT_LEN];
Jeff Sharkey90aff262016-12-12 14:28:24 -0700262
263 sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
264 sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
265 sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
266 sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
267 sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
268 sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
269 sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
270 sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant);
271 sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
272 if (swap_fd >= 0) {
273 have_dex2oat_swap_fd = true;
274 sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
275 }
276 if (image_fd >= 0) {
277 have_dex2oat_image_fd = true;
278 sprintf(dex2oat_image_fd, "--app-image-fd=%d", image_fd);
279 }
280
281 if (have_dex2oat_Xms_flag) {
282 sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
283 }
284 if (have_dex2oat_Xmx_flag) {
285 sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
286 }
287
288 // Compute compiler filter.
289
290 bool have_dex2oat_compiler_filter_flag;
291 if (skip_compilation) {
292 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
293 have_dex2oat_compiler_filter_flag = true;
294 have_dex2oat_relocation_skip_flag = true;
295 } else if (vm_safe_mode) {
296 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
297 have_dex2oat_compiler_filter_flag = true;
298 } else if (compiler_filter != nullptr &&
299 strlen(compiler_filter) + strlen("--compiler-filter=") <
300 arraysize(dex2oat_compiler_filter_arg)) {
301 sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
302 have_dex2oat_compiler_filter_flag = true;
303 } else {
304 char dex2oat_compiler_filter_flag[kPropertyValueMax];
305 have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
306 dex2oat_compiler_filter_flag, NULL) > 0;
307 if (have_dex2oat_compiler_filter_flag) {
308 sprintf(dex2oat_compiler_filter_arg,
309 "--compiler-filter=%s",
310 dex2oat_compiler_filter_flag);
311 }
312 }
313
314 // Check whether all apps should be compiled debuggable.
315 if (!debuggable) {
316 char prop_buf[kPropertyValueMax];
317 debuggable =
318 (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
319 (prop_buf[0] == '1');
320 }
321 char profile_arg[strlen("--profile-file-fd=") + MAX_INT_LEN];
322 if (profile_fd != -1) {
323 sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
324 }
325
326
327 ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
328
329 const char* argv[9 // program name, mandatory arguments and the final NULL
330 + (have_dex2oat_isa_variant ? 1 : 0)
331 + (have_dex2oat_isa_features ? 1 : 0)
332 + (have_dex2oat_Xms_flag ? 2 : 0)
333 + (have_dex2oat_Xmx_flag ? 2 : 0)
334 + (have_dex2oat_compiler_filter_flag ? 1 : 0)
335 + (have_dex2oat_threads_flag ? 1 : 0)
336 + (have_dex2oat_swap_fd ? 1 : 0)
337 + (have_dex2oat_image_fd ? 1 : 0)
338 + (have_dex2oat_relocation_skip_flag ? 2 : 0)
339 + (generate_debug_info ? 1 : 0)
340 + (debuggable ? 1 : 0)
341 + (have_app_image_format ? 1 : 0)
342 + dex2oat_flags_count
343 + (profile_fd == -1 ? 0 : 1)
344 + (shared_libraries != nullptr ? 4 : 0)
345 + (have_dex2oat_large_app_threshold ? 1 : 0)];
346 int i = 0;
347 argv[i++] = DEX2OAT_BIN;
348 argv[i++] = zip_fd_arg;
349 argv[i++] = zip_location_arg;
350 argv[i++] = input_vdex_fd_arg;
351 argv[i++] = output_vdex_fd_arg;
352 argv[i++] = oat_fd_arg;
353 argv[i++] = oat_location_arg;
354 argv[i++] = instruction_set_arg;
355 if (have_dex2oat_isa_variant) {
356 argv[i++] = instruction_set_variant_arg;
357 }
358 if (have_dex2oat_isa_features) {
359 argv[i++] = instruction_set_features_arg;
360 }
361 if (have_dex2oat_Xms_flag) {
362 argv[i++] = RUNTIME_ARG;
363 argv[i++] = dex2oat_Xms_arg;
364 }
365 if (have_dex2oat_Xmx_flag) {
366 argv[i++] = RUNTIME_ARG;
367 argv[i++] = dex2oat_Xmx_arg;
368 }
369 if (have_dex2oat_compiler_filter_flag) {
370 argv[i++] = dex2oat_compiler_filter_arg;
371 }
372 if (have_dex2oat_threads_flag) {
373 argv[i++] = dex2oat_threads_arg;
374 }
375 if (have_dex2oat_swap_fd) {
376 argv[i++] = dex2oat_swap_fd;
377 }
378 if (have_dex2oat_image_fd) {
379 argv[i++] = dex2oat_image_fd;
380 }
381 if (generate_debug_info) {
382 argv[i++] = "--generate-debug-info";
383 }
384 if (debuggable) {
385 argv[i++] = "--debuggable";
386 }
387 if (have_app_image_format) {
388 argv[i++] = image_format_arg;
389 }
390 if (have_dex2oat_large_app_threshold) {
391 argv[i++] = dex2oat_large_app_threshold_arg;
392 }
393 if (dex2oat_flags_count) {
394 i += split(dex2oat_flags, argv + i);
395 }
396 if (have_dex2oat_relocation_skip_flag) {
397 argv[i++] = RUNTIME_ARG;
398 argv[i++] = dex2oat_norelocation;
399 }
400 if (profile_fd != -1) {
401 argv[i++] = profile_arg;
402 }
403 if (shared_libraries != nullptr) {
404 argv[i++] = RUNTIME_ARG;
405 argv[i++] = "-classpath";
406 argv[i++] = RUNTIME_ARG;
407 argv[i++] = shared_libraries;
408 }
409 // Do not add after dex2oat_flags, they should override others for debugging.
410 argv[i] = NULL;
411
412 execv(DEX2OAT_BIN, (char * const *)argv);
413 ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
414}
415
416/*
417 * Whether dexopt should use a swap file when compiling an APK.
418 *
419 * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision
420 * itself, anyways).
421 *
422 * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true".
423 *
424 * Otherwise, return true if this is a low-mem device.
425 *
426 * Otherwise, return default value.
427 */
428static bool kAlwaysProvideSwapFile = false;
429static bool kDefaultProvideSwapFile = true;
430
431static bool ShouldUseSwapFileForDexopt() {
432 if (kAlwaysProvideSwapFile) {
433 return true;
434 }
435
436 // Check the "override" property. If it exists, return value == "true".
437 char dex2oat_prop_buf[kPropertyValueMax];
438 if (get_property("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
439 if (strcmp(dex2oat_prop_buf, "true") == 0) {
440 return true;
441 } else {
442 return false;
443 }
444 }
445
446 // Shortcut for default value. This is an implementation optimization for the process sketched
447 // above. If the default value is true, we can avoid to check whether this is a low-mem device,
448 // as low-mem is never returning false. The compiler will optimize this away if it can.
449 if (kDefaultProvideSwapFile) {
450 return true;
451 }
452
453 bool is_low_mem = property_get_bool("ro.config.low_ram", false);
454 if (is_low_mem) {
455 return true;
456 }
457
458 // Default value must be false here.
459 return kDefaultProvideSwapFile;
460}
461
Richard Uhler76cc0272016-12-08 10:46:35 +0000462static void SetDex2OatScheduling(bool set_to_bg) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700463 if (set_to_bg) {
464 if (set_sched_policy(0, SP_BACKGROUND) < 0) {
465 ALOGE("set_sched_policy failed: %s\n", strerror(errno));
466 exit(70);
467 }
468 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
469 ALOGE("setpriority failed: %s\n", strerror(errno));
470 exit(71);
471 }
472 }
473}
474
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800475static unique_fd open_profile_dir(const std::string& profile_dir) {
476 unique_fd profile_dir_fd(TEMP_FAILURE_RETRY(open(profile_dir.c_str(),
477 O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW)));
478 if (profile_dir_fd.get() < 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700479 // In a multi-user environment, these directories can be created at
480 // different points and it's possible we'll attempt to open a profile
481 // dir before it exists.
482 if (errno != ENOENT) {
483 PLOG(ERROR) << "Failed to open profile_dir: " << profile_dir;
484 }
485 }
486 return profile_dir_fd;
487}
488
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800489static unique_fd open_primary_profile_file_from_dir(const std::string& profile_dir,
490 mode_t open_mode) {
491 unique_fd profile_dir_fd = open_profile_dir(profile_dir);
492 if (profile_dir_fd.get() < 0) {
493 return invalid_unique_fd();
Jeff Sharkey90aff262016-12-12 14:28:24 -0700494 }
495
Jeff Sharkey90aff262016-12-12 14:28:24 -0700496 std::string profile_file = create_primary_profile(profile_dir);
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800497 unique_fd profile_fd(TEMP_FAILURE_RETRY(open(profile_file.c_str(),
498 open_mode | O_NOFOLLOW, 0600)));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700499 if (profile_fd == -1) {
500 // It's not an error if the profile file does not exist.
501 if (errno != ENOENT) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800502 PLOG(ERROR) << "Failed to open profile : " << profile_file;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700503 }
504 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700505 return profile_fd;
506}
507
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800508static unique_fd open_primary_profile_file(userid_t user, const std::string& pkgname) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700509 std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
510 return open_primary_profile_file_from_dir(profile_dir, O_RDONLY);
511}
512
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800513static unique_fd open_reference_profile(uid_t uid, const std::string& pkgname, bool read_write) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700514 std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
515 int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY;
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800516 unique_fd fd = open_primary_profile_file_from_dir(reference_profile_dir, flags);
517 if (fd.get() < 0) {
518 return invalid_unique_fd();
Jeff Sharkey90aff262016-12-12 14:28:24 -0700519 }
520 if (read_write) {
521 // Fix the owner.
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800522 if (fchown(fd.get(), uid, uid) < 0) {
523 return invalid_unique_fd();
Jeff Sharkey90aff262016-12-12 14:28:24 -0700524 }
525 }
526 return fd;
527}
528
Calin Juravle76268c52017-03-09 13:19:42 -0800529static void open_profile_files(uid_t uid, const std::string& pkgname,
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800530 /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700531 // Open the reference profile in read-write mode as profman might need to save the merge.
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800532 reference_profile_fd->reset(open_reference_profile(uid, pkgname, /*read_write*/ true));
533 if (reference_profile_fd->get() < 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700534 // We can't access the reference profile file.
535 return;
536 }
537
538 std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
539 for (auto user : users) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800540 unique_fd profile_fd = open_primary_profile_file(user, pkgname);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700541 // Add to the lists only if both fds are valid.
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800542 if (profile_fd.get() >= 0) {
543 profiles_fd->push_back(std::move(profile_fd));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700544 }
545 }
546}
547
548static void drop_capabilities(uid_t uid) {
549 if (setgid(uid) != 0) {
550 ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
551 exit(64);
552 }
553 if (setuid(uid) != 0) {
554 ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
555 exit(65);
556 }
557 // drop capabilities
558 struct __user_cap_header_struct capheader;
559 struct __user_cap_data_struct capdata[2];
560 memset(&capheader, 0, sizeof(capheader));
561 memset(&capdata, 0, sizeof(capdata));
562 capheader.version = _LINUX_CAPABILITY_VERSION_3;
563 if (capset(&capheader, &capdata[0]) < 0) {
564 ALOGE("capset failed: %s\n", strerror(errno));
565 exit(66);
566 }
567}
568
569static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
570static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
571static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
572static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
573static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
574
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800575static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
576 const unique_fd& reference_profile_fd) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700577 static const size_t MAX_INT_LEN = 32;
578 static const char* PROFMAN_BIN = "/system/bin/profman";
579
580 std::vector<std::string> profile_args(profiles_fd.size());
581 char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN];
582 for (size_t k = 0; k < profiles_fd.size(); k++) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800583 sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k].get());
Jeff Sharkey90aff262016-12-12 14:28:24 -0700584 profile_args[k].assign(profile_buf);
585 }
586 char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800587 sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd.get());
Jeff Sharkey90aff262016-12-12 14:28:24 -0700588
589 // program name, reference profile fd, the final NULL and the profile fds
590 const char* argv[3 + profiles_fd.size()];
591 int i = 0;
592 argv[i++] = PROFMAN_BIN;
593 argv[i++] = reference_profile_arg;
594 for (size_t k = 0; k < profile_args.size(); k++) {
595 argv[i++] = profile_args[k].c_str();
596 }
597 // Do not add after dex2oat_flags, they should override others for debugging.
598 argv[i] = NULL;
599
600 execv(PROFMAN_BIN, (char * const *)argv);
601 ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
602 exit(68); /* only get here on exec failure */
603}
604
605// Decides if profile guided compilation is needed or not based on existing profiles.
606// Returns true if there is enough information in the current profiles that worth
607// a re-compilation of the package.
608// If the return value is true all the current profiles would have been merged into
609// the reference profiles accessible with open_reference_profile().
Calin Juravle76268c52017-03-09 13:19:42 -0800610bool analyse_profiles(uid_t uid, const std::string& pkgname) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800611 std::vector<unique_fd> profiles_fd;
612 unique_fd reference_profile_fd;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700613 open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd);
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800614 if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700615 // Skip profile guided compilation because no profiles were found.
616 // Or if the reference profile info couldn't be opened.
Jeff Sharkey90aff262016-12-12 14:28:24 -0700617 return false;
618 }
619
Jeff Sharkey90aff262016-12-12 14:28:24 -0700620 pid_t pid = fork();
621 if (pid == 0) {
622 /* child -- drop privileges before continuing */
623 drop_capabilities(uid);
624 run_profman_merge(profiles_fd, reference_profile_fd);
625 exit(68); /* only get here on exec failure */
626 }
627 /* parent */
628 int return_code = wait_child(pid);
629 bool need_to_compile = false;
630 bool should_clear_current_profiles = false;
631 bool should_clear_reference_profile = false;
632 if (!WIFEXITED(return_code)) {
633 LOG(WARNING) << "profman failed for package " << pkgname << ": " << return_code;
634 } else {
635 return_code = WEXITSTATUS(return_code);
636 switch (return_code) {
637 case PROFMAN_BIN_RETURN_CODE_COMPILE:
638 need_to_compile = true;
639 should_clear_current_profiles = true;
640 should_clear_reference_profile = false;
641 break;
642 case PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION:
643 need_to_compile = false;
644 should_clear_current_profiles = false;
645 should_clear_reference_profile = false;
646 break;
647 case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
648 LOG(WARNING) << "Bad profiles for package " << pkgname;
649 need_to_compile = false;
650 should_clear_current_profiles = true;
651 should_clear_reference_profile = true;
652 break;
653 case PROFMAN_BIN_RETURN_CODE_ERROR_IO: // fall-through
654 case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
655 // Temporary IO problem (e.g. locking). Ignore but log a warning.
656 LOG(WARNING) << "IO error while reading profiles for package " << pkgname;
657 need_to_compile = false;
658 should_clear_current_profiles = false;
659 should_clear_reference_profile = false;
660 break;
661 default:
662 // Unknown return code or error. Unlink profiles.
663 LOG(WARNING) << "Unknown error code while processing profiles for package " << pkgname
664 << ": " << return_code;
665 need_to_compile = false;
666 should_clear_current_profiles = true;
667 should_clear_reference_profile = true;
668 break;
669 }
670 }
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800671
Jeff Sharkey90aff262016-12-12 14:28:24 -0700672 if (should_clear_current_profiles) {
673 clear_current_profiles(pkgname);
674 }
675 if (should_clear_reference_profile) {
676 clear_reference_profile(pkgname);
677 }
678 return need_to_compile;
679}
680
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800681static void run_profman_dump(const std::vector<unique_fd>& profile_fds,
682 const unique_fd& reference_profile_fd,
Jeff Sharkey90aff262016-12-12 14:28:24 -0700683 const std::vector<std::string>& dex_locations,
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800684 const std::vector<unique_fd>& apk_fds,
685 const unique_fd& output_fd) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700686 std::vector<std::string> profman_args;
687 static const char* PROFMAN_BIN = "/system/bin/profman";
688 profman_args.push_back(PROFMAN_BIN);
689 profman_args.push_back("--dump-only");
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800690 profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700691 if (reference_profile_fd != -1) {
692 profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d",
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800693 reference_profile_fd.get()));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700694 }
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800695 for (size_t i = 0; i < profile_fds.size(); i++) {
696 profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fds[i].get()));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700697 }
698 for (const std::string& dex_location : dex_locations) {
699 profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str()));
700 }
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800701 for (size_t i = 0; i < apk_fds.size(); i++) {
702 profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fds[i].get()));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700703 }
704 const char **argv = new const char*[profman_args.size() + 1];
705 size_t i = 0;
706 for (const std::string& profman_arg : profman_args) {
707 argv[i++] = profman_arg.c_str();
708 }
709 argv[i] = NULL;
710
711 execv(PROFMAN_BIN, (char * const *)argv);
712 ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
713 exit(68); /* only get here on exec failure */
714}
715
716static const char* get_location_from_path(const char* path) {
717 static constexpr char kLocationSeparator = '/';
718 const char *location = strrchr(path, kLocationSeparator);
719 if (location == NULL) {
720 return path;
721 } else {
722 // Skip the separator character.
723 return location + 1;
724 }
725}
726
Calin Juravle76268c52017-03-09 13:19:42 -0800727bool dump_profiles(int32_t uid, const std::string& pkgname, const char* code_paths) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800728 std::vector<unique_fd> profile_fds;
729 unique_fd reference_profile_fd;
Calin Juravle76268c52017-03-09 13:19:42 -0800730 std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname.c_str());
Jeff Sharkey90aff262016-12-12 14:28:24 -0700731
732 open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd);
733
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800734 const bool has_reference_profile = (reference_profile_fd.get() != -1);
Jeff Sharkey90aff262016-12-12 14:28:24 -0700735 const bool has_profiles = !profile_fds.empty();
736
737 if (!has_reference_profile && !has_profiles) {
Calin Juravle76268c52017-03-09 13:19:42 -0800738 LOG(ERROR) << "profman dump: no profiles to dump for " << pkgname;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700739 return false;
740 }
741
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800742 unique_fd output_fd(open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700743 if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
744 ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
745 return false;
746 }
747 std::vector<std::string> code_full_paths = base::Split(code_paths, ";");
748 std::vector<std::string> dex_locations;
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800749 std::vector<unique_fd> apk_fds;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700750 for (const std::string& code_full_path : code_full_paths) {
751 const char* full_path = code_full_path.c_str();
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800752 unique_fd apk_fd(open(full_path, O_RDONLY | O_NOFOLLOW));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700753 if (apk_fd == -1) {
754 ALOGE("installd cannot open '%s'\n", full_path);
755 return false;
756 }
757 dex_locations.push_back(get_location_from_path(full_path));
Calin Juravle1a0af3b2017-03-09 14:33:33 -0800758 apk_fds.push_back(std::move(apk_fd));
Jeff Sharkey90aff262016-12-12 14:28:24 -0700759 }
760
761 pid_t pid = fork();
762 if (pid == 0) {
763 /* child -- drop privileges before continuing */
764 drop_capabilities(uid);
765 run_profman_dump(profile_fds, reference_profile_fd, dex_locations,
766 apk_fds, output_fd);
767 exit(68); /* only get here on exec failure */
768 }
769 /* parent */
Jeff Sharkey90aff262016-12-12 14:28:24 -0700770 int return_code = wait_child(pid);
771 if (!WIFEXITED(return_code)) {
772 LOG(WARNING) << "profman failed for package " << pkgname << ": "
773 << return_code;
774 return false;
775 }
776 return true;
777}
778
779static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
780 // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
781 if (EndsWith(oat_path, ".dex")) {
782 std::string new_path = oat_path;
783 new_path.replace(new_path.length() - strlen(".dex"), strlen(".dex"), new_ext);
784 CHECK(EndsWith(new_path, new_ext.c_str()));
785 return new_path;
786 }
787
788 // An odex entry. Not that this may not be an extension, e.g., in the OTA
789 // case (where the base name will have an extension for the B artifact).
790 size_t odex_pos = oat_path.rfind(".odex");
791 if (odex_pos != std::string::npos) {
792 std::string new_path = oat_path;
793 new_path.replace(odex_pos, strlen(".odex"), new_ext);
794 CHECK_NE(new_path.find(new_ext), std::string::npos);
795 return new_path;
796 }
797
798 // Don't know how to handle this.
799 return "";
800}
801
802// Translate the given oat path to an art (app image) path. An empty string
803// denotes an error.
804static std::string create_image_filename(const std::string& oat_path) {
805 return replace_file_extension(oat_path, ".art");
806}
807
808// Translate the given oat path to a vdex path. An empty string denotes an error.
809static std::string create_vdex_filename(const std::string& oat_path) {
810 return replace_file_extension(oat_path, ".vdex");
811}
812
813static bool add_extension_to_file_name(char* file_name, const char* extension) {
814 if (strlen(file_name) + strlen(extension) + 1 > PKG_PATH_MAX) {
815 return false;
816 }
817 strcat(file_name, extension);
818 return true;
819}
820
821static int open_output_file(const char* file_name, bool recreate, int permissions) {
822 int flags = O_RDWR | O_CREAT;
823 if (recreate) {
824 if (unlink(file_name) < 0) {
825 if (errno != ENOENT) {
826 PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
827 }
828 }
829 flags |= O_EXCL;
830 }
831 return open(file_name, flags, permissions);
832}
833
Calin Juravle2289c0a2017-02-15 12:44:14 -0800834static bool set_permissions_and_ownership(
835 int fd, bool is_public, int uid, const char* path, bool is_secondary_dex) {
836 // Primary apks are owned by the system. Secondary dex files are owned by the app.
837 int owning_uid = is_secondary_dex ? uid : AID_SYSTEM;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700838 if (fchmod(fd,
839 S_IRUSR|S_IWUSR|S_IRGRP |
840 (is_public ? S_IROTH : 0)) < 0) {
841 ALOGE("installd cannot chmod '%s' during dexopt\n", path);
842 return false;
Calin Juravle2289c0a2017-02-15 12:44:14 -0800843 } else if (fchown(fd, owning_uid, uid) < 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700844 ALOGE("installd cannot chown '%s' during dexopt\n", path);
845 return false;
846 }
847 return true;
848}
849
850static bool IsOutputDalvikCache(const char* oat_dir) {
851 // InstallerConnection.java (which invokes installd) transforms Java null arguments
852 // into '!'. Play it safe by handling it both.
853 // TODO: ensure we never get null.
854 // TODO: pass a flag instead of inferring if the output is dalvik cache.
855 return oat_dir == nullptr || oat_dir[0] == '!';
856}
857
858static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
Calin Juravle80a21252017-01-17 14:43:25 -0800859 const char* oat_dir, bool is_secondary_dex, /*out*/ char* out_oat_path) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700860 // Early best-effort check whether we can fit the the path into our buffers.
861 // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
862 // without a swap file, if necessary. Reference profiles file also add an extra ".prof"
863 // extension to the cache path (5 bytes).
864 if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
865 ALOGE("apk_path too long '%s'\n", apk_path);
866 return false;
867 }
868
869 if (!IsOutputDalvikCache(oat_dir)) {
Calin Juravle80a21252017-01-17 14:43:25 -0800870 // Oat dirs for secondary dex files are already validated.
871 if (!is_secondary_dex && validate_apk_path(oat_dir)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700872 ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir);
873 return false;
874 }
875 if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) {
876 return false;
877 }
878 } else {
879 if (!create_cache_path(out_oat_path, apk_path, instruction_set)) {
880 return false;
881 }
882 }
883 return true;
884}
885
886// Helper for fd management. This is similar to a unique_fd in that it closes the file descriptor
887// on destruction. It will also run the given cleanup (unless told not to) after closing.
888//
889// Usage example:
890//
Calin Juravle7a570e82017-01-14 16:23:30 -0800891// Dex2oatFileWrapper file(open(...),
Jeff Sharkey90aff262016-12-12 14:28:24 -0700892// [name]() {
893// unlink(name.c_str());
894// });
895// // Note: care needs to be taken about name, as it needs to have a lifetime longer than the
896// wrapper if captured as a reference.
897//
898// if (file.get() == -1) {
899// // Error opening...
900// }
901//
902// ...
903// if (error) {
904// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will run
905// // and delete the file (after the fd is closed).
906// return -1;
907// }
908//
909// (Success case)
910// file.SetCleanup(false);
911// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will not run
912// // (leaving the file around; after the fd is closed).
913//
Jeff Sharkey90aff262016-12-12 14:28:24 -0700914class Dex2oatFileWrapper {
915 public:
Calin Juravle7a570e82017-01-14 16:23:30 -0800916 Dex2oatFileWrapper() : value_(-1), cleanup_(), do_cleanup_(true), auto_close_(true) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700917 }
918
Calin Juravle7a570e82017-01-14 16:23:30 -0800919 Dex2oatFileWrapper(int value, std::function<void ()> cleanup)
920 : value_(value), cleanup_(cleanup), do_cleanup_(true), auto_close_(true) {}
921
922 Dex2oatFileWrapper(Dex2oatFileWrapper&& other) {
923 value_ = other.value_;
924 cleanup_ = other.cleanup_;
925 do_cleanup_ = other.do_cleanup_;
926 auto_close_ = other.auto_close_;
927 other.release();
928 }
929
930 Dex2oatFileWrapper& operator=(Dex2oatFileWrapper&& other) {
931 value_ = other.value_;
932 cleanup_ = other.cleanup_;
933 do_cleanup_ = other.do_cleanup_;
934 auto_close_ = other.auto_close_;
935 other.release();
936 return *this;
937 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700938
939 ~Dex2oatFileWrapper() {
940 reset(-1);
941 }
942
943 int get() {
944 return value_;
945 }
946
947 void SetCleanup(bool cleanup) {
948 do_cleanup_ = cleanup;
949 }
950
951 void reset(int new_value) {
Calin Juravle7a570e82017-01-14 16:23:30 -0800952 if (auto_close_ && value_ >= 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700953 close(value_);
954 }
955 if (do_cleanup_ && cleanup_ != nullptr) {
956 cleanup_();
957 }
958
959 value_ = new_value;
960 }
961
Calin Juravle7a570e82017-01-14 16:23:30 -0800962 void reset(int new_value, std::function<void ()> new_cleanup) {
963 if (auto_close_ && value_ >= 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700964 close(value_);
965 }
966 if (do_cleanup_ && cleanup_ != nullptr) {
967 cleanup_();
968 }
969
970 value_ = new_value;
971 cleanup_ = new_cleanup;
972 }
973
Calin Juravle7a570e82017-01-14 16:23:30 -0800974 void DisableAutoClose() {
975 auto_close_ = false;
976 }
977
Jeff Sharkey90aff262016-12-12 14:28:24 -0700978 private:
Calin Juravle7a570e82017-01-14 16:23:30 -0800979 void release() {
980 value_ = -1;
981 do_cleanup_ = false;
982 cleanup_ = nullptr;
983 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700984 int value_;
Calin Juravle7a570e82017-01-14 16:23:30 -0800985 std::function<void ()> cleanup_;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700986 bool do_cleanup_;
Calin Juravle7a570e82017-01-14 16:23:30 -0800987 bool auto_close_;
Jeff Sharkey90aff262016-12-12 14:28:24 -0700988};
989
Calin Juravle7a570e82017-01-14 16:23:30 -0800990// (re)Creates the app image if needed.
991Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_guided,
Calin Juravle2289c0a2017-02-15 12:44:14 -0800992 bool is_public, int uid, bool is_secondary_dex) {
Calin Juravle7a570e82017-01-14 16:23:30 -0800993 // Use app images only if it is enabled (by a set image format) and we are compiling
994 // profile-guided (so the app image doesn't conservatively contain all classes).
Calin Juravle2289c0a2017-02-15 12:44:14 -0800995 // Note that we don't create an image for secondary dex files.
996 if (is_secondary_dex || !profile_guided) {
Calin Juravle7a570e82017-01-14 16:23:30 -0800997 return Dex2oatFileWrapper();
998 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700999
Calin Juravle7a570e82017-01-14 16:23:30 -08001000 const std::string image_path = create_image_filename(out_oat_path);
1001 if (image_path.empty()) {
1002 // Happens when the out_oat_path has an unknown extension.
1003 return Dex2oatFileWrapper();
1004 }
1005 char app_image_format[kPropertyValueMax];
1006 bool have_app_image_format =
1007 get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
1008 if (!have_app_image_format) {
1009 return Dex2oatFileWrapper();
1010 }
1011 // Recreate is true since we do not want to modify a mapped image. If the app is
1012 // already running and we modify the image file, it can cause crashes (b/27493510).
1013 Dex2oatFileWrapper wrapper_fd(
1014 open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
1015 [image_path]() { unlink(image_path.c_str()); });
1016 if (wrapper_fd.get() < 0) {
1017 // Could not create application image file. Go on since we can compile without it.
1018 LOG(ERROR) << "installd could not create '" << image_path
1019 << "' for image file during dexopt";
1020 // If we have a valid image file path but no image fd, explicitly erase the image file.
1021 if (unlink(image_path.c_str()) < 0) {
1022 if (errno != ENOENT) {
1023 PLOG(ERROR) << "Couldn't unlink image file " << image_path;
1024 }
1025 }
1026 } else if (!set_permissions_and_ownership(
Calin Juravle2289c0a2017-02-15 12:44:14 -08001027 wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001028 ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
1029 wrapper_fd.reset(-1);
1030 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001031
Calin Juravle7a570e82017-01-14 16:23:30 -08001032 return wrapper_fd;
1033}
1034
1035// Creates the dexopt swap file if necessary and return its fd.
1036// Returns -1 if there's no need for a swap or in case of errors.
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001037unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001038 if (!ShouldUseSwapFileForDexopt()) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001039 return invalid_unique_fd();
Calin Juravle7a570e82017-01-14 16:23:30 -08001040 }
1041 // Make sure there really is enough space.
1042 char swap_file_name[PKG_PATH_MAX];
1043 strcpy(swap_file_name, out_oat_path);
1044 if (!add_extension_to_file_name(swap_file_name, ".swap")) {
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001045 return invalid_unique_fd();
Calin Juravle7a570e82017-01-14 16:23:30 -08001046 }
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001047 unique_fd swap_fd(open_output_file(
Calin Juravle7a570e82017-01-14 16:23:30 -08001048 swap_file_name, /*recreate*/true, /*permissions*/0600));
1049 if (swap_fd.get() < 0) {
1050 // Could not create swap file. Optimistically go on and hope that we can compile
1051 // without it.
1052 ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
1053 } else {
1054 // Immediately unlink. We don't really want to hit flash.
1055 if (unlink(swap_file_name) < 0) {
1056 PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
1057 }
1058 }
1059 return swap_fd;
1060}
1061
1062// Opens the reference profiles if needed.
1063// Note that the reference profile might not exist so it's OK if the fd will be -1.
1064Dex2oatFileWrapper maybe_open_reference_profile(const char* pkgname, bool profile_guided,
Calin Juravle80a21252017-01-17 14:43:25 -08001065 bool is_public, int uid, bool is_secondary_dex) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001066 // Public apps should not be compiled with profile information ever. Same goes for the special
1067 // package '*' used for the system server.
Calin Juravle80a21252017-01-17 14:43:25 -08001068 // TODO(calin): add support for writing profiles for secondary dex files
1069 if (profile_guided && !is_secondary_dex && !is_public && (pkgname[0] != '*')) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001070 // Open reference profile in read only mode as dex2oat does not get write permissions.
1071 const std::string pkgname_str(pkgname);
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001072 unique_fd profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ false);
Calin Juravle7a570e82017-01-14 16:23:30 -08001073 return Dex2oatFileWrapper(
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001074 profile_fd.release(),
Calin Juravle7a570e82017-01-14 16:23:30 -08001075 [pkgname_str]() {
1076 clear_reference_profile(pkgname_str.c_str());
1077 });
1078 } else {
1079 return Dex2oatFileWrapper();
Jeff Sharkey90aff262016-12-12 14:28:24 -07001080 }
Calin Juravle7a570e82017-01-14 16:23:30 -08001081}
Jeff Sharkey90aff262016-12-12 14:28:24 -07001082
Calin Juravle7a570e82017-01-14 16:23:30 -08001083// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
1084// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
1085bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
Nicolas Geoffraya2dbefc2017-03-09 13:11:25 +00001086 const char* instruction_set, bool is_public, bool profile_guided,
1087 int uid, bool is_secondary_dex, Dex2oatFileWrapper* in_vdex_wrapper_fd,
Calin Juravle7a570e82017-01-14 16:23:30 -08001088 Dex2oatFileWrapper* out_vdex_wrapper_fd) {
1089 CHECK(in_vdex_wrapper_fd != nullptr);
1090 CHECK(out_vdex_wrapper_fd != nullptr);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001091 // Open the existing VDEX. We do this before creating the new output VDEX, which will
1092 // unlink the old one.
Richard Uhler76cc0272016-12-08 10:46:35 +00001093 char in_odex_path[PKG_PATH_MAX];
1094 int dexopt_action = abs(dexopt_needed);
1095 bool is_odex_location = dexopt_needed < 0;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001096 std::string in_vdex_path_str;
Nicolas Geoffraya2dbefc2017-03-09 13:11:25 +00001097 // Disable passing an input vdex when the compilation is profile-guided. The dexlayout
1098 // optimization in dex2oat is incompatible with it. b/35872504.
1099 if (dexopt_action != DEX2OAT_FROM_SCRATCH && !profile_guided) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001100 // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
1101 const char* path = nullptr;
1102 if (is_odex_location) {
1103 if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
1104 path = in_odex_path;
1105 } else {
1106 ALOGE("installd cannot compute input vdex location for '%s'\n", apk_path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001107 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001108 }
1109 } else {
1110 path = out_oat_path;
1111 }
1112 in_vdex_path_str = create_vdex_filename(path);
1113 if (in_vdex_path_str.empty()) {
1114 ALOGE("installd cannot compute input vdex location for '%s'\n", path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001115 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001116 }
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001117 if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
Nicolas Geoffraya2dbefc2017-03-09 13:11:25 +00001118 // When we dex2oat because of boot image change, we are going to update
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001119 // in-place the vdex file.
Calin Juravle7a570e82017-01-14 16:23:30 -08001120 in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001121 } else {
Calin Juravle7a570e82017-01-14 16:23:30 -08001122 in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001123 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001124 }
1125
1126 // Infer the name of the output VDEX and create it.
Calin Juravle7a570e82017-01-14 16:23:30 -08001127 const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001128 if (out_vdex_path_str.empty()) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001129 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001130 }
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001131
1132 // If we are compiling because the boot image is out of date, we do not
1133 // need to recreate a vdex, and can use the same existing one.
1134 if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE &&
Calin Juravle7a570e82017-01-14 16:23:30 -08001135 in_vdex_wrapper_fd->get() != -1 &&
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001136 in_vdex_path_str == out_vdex_path_str) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001137 out_vdex_wrapper_fd->reset(in_vdex_wrapper_fd->get());
1138 // Disable auto close for the in wrapper fd (it will be done when destructing the out
1139 // wrapper).
1140 in_vdex_wrapper_fd->DisableAutoClose();
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001141 } else {
Calin Juravle7a570e82017-01-14 16:23:30 -08001142 out_vdex_wrapper_fd->reset(
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001143 open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
1144 [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
Calin Juravle7a570e82017-01-14 16:23:30 -08001145 if (out_vdex_wrapper_fd->get() < 0) {
1146 ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
1147 return false;
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001148 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001149 }
Calin Juravle7a570e82017-01-14 16:23:30 -08001150 if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
Calin Juravle2289c0a2017-02-15 12:44:14 -08001151 out_vdex_path_str.c_str(), is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001152 ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
1153 return false;
1154 }
1155
1156 // If we got here we successfully opened the vdex files.
1157 return true;
1158}
1159
1160// Opens the output oat file for the given apk.
1161// If successful it stores the output path into out_oat_path and returns true.
1162Dex2oatFileWrapper open_oat_out_file(const char* apk_path, const char* oat_dir,
Calin Juravle80a21252017-01-17 14:43:25 -08001163 bool is_public, int uid, const char* instruction_set, bool is_secondary_dex,
1164 char* out_oat_path) {
1165 if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001166 return Dex2oatFileWrapper();
1167 }
1168 const std::string out_oat_path_str(out_oat_path);
1169 Dex2oatFileWrapper wrapper_fd(
1170 open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
1171 [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
1172 if (wrapper_fd.get() < 0) {
Calin Juravle80a21252017-01-17 14:43:25 -08001173 PLOG(ERROR) << "installd cannot open output during dexopt" << out_oat_path;
Calin Juravle2289c0a2017-02-15 12:44:14 -08001174 } else if (!set_permissions_and_ownership(
1175 wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001176 ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
1177 wrapper_fd.reset(-1);
1178 }
1179 return wrapper_fd;
1180}
1181
1182// Updates the access times of out_oat_path based on those from apk_path.
1183void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
1184 struct stat input_stat;
1185 memset(&input_stat, 0, sizeof(input_stat));
1186 if (stat(apk_path, &input_stat) != 0) {
1187 PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
1188 return;
1189 }
1190
1191 struct utimbuf ut;
1192 ut.actime = input_stat.st_atime;
1193 ut.modtime = input_stat.st_mtime;
1194 if (utime(out_oat_path, &ut) != 0) {
1195 PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
1196 }
1197}
1198
Calin Juravle80a21252017-01-17 14:43:25 -08001199// Runs (execv) dexoptanalyzer on the given arguments.
1200static void exec_dexoptanalyzer(const char* dex_file, const char* instruction_set,
1201 const char* compiler_filter) {
1202 static const char* DEXOPTANALYZER_BIN = "/system/bin/dexoptanalyzer";
1203 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
1204
1205 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
1206 ALOGE("Instruction set %s longer than max length of %d",
1207 instruction_set, MAX_INSTRUCTION_SET_LEN);
1208 return;
1209 }
1210
1211 char dex_file_arg[strlen("--dex-file=") + PKG_PATH_MAX];
1212 char isa_arg[strlen("--isa=") + MAX_INSTRUCTION_SET_LEN];
1213 char compiler_filter_arg[strlen("--compiler-filter=") + kPropertyValueMax];
1214
1215 sprintf(dex_file_arg, "--dex-file=%s", dex_file);
1216 sprintf(isa_arg, "--isa=%s", instruction_set);
1217 sprintf(compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
1218
1219 // program name, dex file, isa, filter, the final NULL
1220 const char* argv[5];
1221 int i = 0;
1222 argv[i++] = DEXOPTANALYZER_BIN;
1223 argv[i++] = dex_file_arg;
1224 argv[i++] = isa_arg;
1225 argv[i++] = compiler_filter_arg;
1226 argv[i] = NULL;
1227
1228 execv(DEXOPTANALYZER_BIN, (char * const *)argv);
1229 ALOGE("execv(%s) failed: %s\n", DEXOPTANALYZER_BIN, strerror(errno));
1230}
1231
1232// Prepares the oat dir for the secondary dex files.
Calin Juravlec9eab382017-01-25 01:17:17 -08001233static bool prepare_secondary_dex_oat_dir(const char* dex_path, int uid,
Calin Juravle80a21252017-01-17 14:43:25 -08001234 const char* instruction_set, std::string* oat_dir_out) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001235 std::string apk_path_str(dex_path);
Calin Juravle80a21252017-01-17 14:43:25 -08001236 unsigned long dirIndex = apk_path_str.rfind('/');
1237 if (dirIndex == std::string::npos) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001238 LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001239 return false;
1240 }
1241 std::string apk_dir = apk_path_str.substr(0, dirIndex);
1242
1243 // Assign the gid to the cache gid so that the oat file storage
1244 // is counted towards the app cache.
1245 int32_t cache_gid = multiuser_get_cache_gid(
1246 multiuser_get_user_id(uid), multiuser_get_app_id(uid));
1247 // If UID doesn't have a specific cache GID, use UID value
1248 if (cache_gid == -1) {
1249 cache_gid = uid;
1250 }
1251
1252 // Create oat file output directory.
1253 if (prepare_app_cache_dir(apk_dir, "oat", 02711, uid, cache_gid) != 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001254 LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001255 return false;
1256 }
1257
1258 char oat_dir[PKG_PATH_MAX];
1259 snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
1260 oat_dir_out->assign(oat_dir);
1261
1262 // Create oat/isa output directory.
1263 if (prepare_app_cache_dir(*oat_dir_out, instruction_set, 02711, uid, cache_gid) != 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001264 LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001265 return false;
1266 }
1267
1268 return true;
1269}
1270
1271static int constexpr DEXOPTANALYZER_BIN_EXEC_ERROR = 200;
1272
1273// Verifies the result of dexoptanalyzer executed for the apk_path.
1274// If the result is valid returns true and sets dexopt_needed_out to a valid value.
1275// Returns false for errors or unexpected result values.
Calin Juravlec9eab382017-01-25 01:17:17 -08001276static bool process_dexoptanalyzer_result(const char* dex_path, int result,
Calin Juravle80a21252017-01-17 14:43:25 -08001277 int* dexopt_needed_out) {
1278 // The result values are defined in dexoptanalyzer.
1279 switch (result) {
1280 case 0: // no_dexopt_needed
1281 *dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
1282 case 1: // dex2oat_from_scratch
1283 *dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
1284 case 5: // dex2oat_for_bootimage_odex
1285 *dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
1286 case 6: // dex2oat_for_filter_odex
1287 *dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
1288 case 7: // dex2oat_for_relocation_odex
1289 *dexopt_needed_out = -DEX2OAT_FOR_RELOCATION; return true;
1290 case 2: // dex2oat_for_bootimage_oat
1291 case 3: // dex2oat_for_filter_oat
1292 case 4: // dex2oat_for_relocation_oat
Calin Juravlec9eab382017-01-25 01:17:17 -08001293 LOG(ERROR) << "Dexoptnalyzer return the status of an oat file."
1294 << " Expected odex file status for secondary dex " << dex_path
Calin Juravle80a21252017-01-17 14:43:25 -08001295 << " : dexoptanalyzer result=" << result;
1296 return false;
1297 default:
Calin Juravlec9eab382017-01-25 01:17:17 -08001298 LOG(ERROR) << "Unexpected result for dexoptanalyzer " << dex_path
Calin Juravle80a21252017-01-17 14:43:25 -08001299 << " exec_dexoptanalyzer result=" << result;
1300 return false;
1301 }
1302}
1303
Calin Juravlec9eab382017-01-25 01:17:17 -08001304// 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 -08001305// be compiled. Returns false for errors (logged) or true if the secondary dex path was process
1306// successfully.
1307// When returning true, dexopt_needed_out is assigned a valid OatFileAsssitant::DexOptNeeded
1308// code and aot_dir_out is assigned the oat dir path where the oat file should be stored.
Calin Juravlec9eab382017-01-25 01:17:17 -08001309static bool process_secondary_dex_dexopt(const char* dex_path, const char* pkgname,
Calin Juravle80a21252017-01-17 14:43:25 -08001310 int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
1311 const char* compiler_filter, int* dexopt_needed_out, std::string* aot_dir_out) {
1312 int storage_flag;
1313
1314 if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
1315 storage_flag = FLAG_STORAGE_CE;
1316 if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1317 LOG(ERROR) << "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
1318 return false;
1319 }
1320 } else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1321 storage_flag = FLAG_STORAGE_DE;
1322 } else {
1323 LOG(ERROR) << "Secondary dex storage flag must be set";
1324 return false;
1325 }
1326
Calin Juravlec9eab382017-01-25 01:17:17 -08001327 if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
1328 LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001329 return false;
1330 }
1331
1332 // Check if the path exist. If not, there's nothing to do.
Calin Juravlec9eab382017-01-25 01:17:17 -08001333 if (access(dex_path, F_OK) != 0) {
Calin Juravle80a21252017-01-17 14:43:25 -08001334 if (errno == ENOENT) {
1335 // Secondary dex files might be deleted any time by the app.
1336 // Nothing to do if that's the case
Calin Juravlec9eab382017-01-25 01:17:17 -08001337 ALOGV("Secondary dex does not exist %s", dex_path);
Calin Juravle80a21252017-01-17 14:43:25 -08001338 return NO_DEXOPT_NEEDED;
1339 } else {
Calin Juravlec9eab382017-01-25 01:17:17 -08001340 PLOG(ERROR) << "Could not access secondary dex " << dex_path;
Calin Juravle80a21252017-01-17 14:43:25 -08001341 }
1342 }
1343
1344 // Prepare the oat directories.
Calin Juravlec9eab382017-01-25 01:17:17 -08001345 if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set, aot_dir_out)) {
Calin Juravle80a21252017-01-17 14:43:25 -08001346 return false;
1347 }
1348
1349 pid_t pid = fork();
1350 if (pid == 0) {
1351 // child -- drop privileges before continuing.
1352 drop_capabilities(uid);
1353 // Run dexoptanalyzer to get dexopt_needed code.
Calin Juravlec9eab382017-01-25 01:17:17 -08001354 exec_dexoptanalyzer(dex_path, instruction_set, compiler_filter);
Calin Juravle80a21252017-01-17 14:43:25 -08001355 exit(DEXOPTANALYZER_BIN_EXEC_ERROR);
1356 }
1357
1358 /* parent */
1359
1360 int result = wait_child(pid);
1361 if (!WIFEXITED(result)) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001362 LOG(ERROR) << "dexoptanalyzer failed for path " << dex_path << ": " << result;
Calin Juravle80a21252017-01-17 14:43:25 -08001363 return false;
1364 }
1365 result = WEXITSTATUS(result);
Calin Juravlec9eab382017-01-25 01:17:17 -08001366 bool success = process_dexoptanalyzer_result(dex_path, result, dexopt_needed_out);
Calin Juravle80a21252017-01-17 14:43:25 -08001367 // Run dexopt only if needed or forced.
1368 // Note that dexoptanalyzer is executed even if force compilation is enabled.
1369 // We ignore its valid dexopNeeded result, but still check (in process_dexoptanalyzer_result)
1370 // that we only get results for odex files (apk_dir/oat/isa/code.odex) and not
1371 // for oat files from dalvik-cache.
1372 if (success && ((dexopt_flags & DEXOPT_FORCE) != 0)) {
1373 *dexopt_needed_out = DEX2OAT_FROM_SCRATCH;
1374 }
1375
1376 return success;
1377}
1378
Calin Juravlec9eab382017-01-25 01:17:17 -08001379int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
Calin Juravle80a21252017-01-17 14:43:25 -08001380 int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
1381 const char* volume_uuid, const char* shared_libraries) {
Calin Juravle7a570e82017-01-14 16:23:30 -08001382 CHECK(pkgname != nullptr);
1383 CHECK(pkgname[0] != 0);
1384 if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
1385 LOG_FATAL("dexopt flags contains unknown fields\n");
1386 }
1387
1388 bool is_public = ((dexopt_flags & DEXOPT_PUBLIC) != 0);
1389 bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
1390 bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
1391 bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
1392 bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
Calin Juravle80a21252017-01-17 14:43:25 -08001393 bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
1394
1395 // Check if we're dealing with a secondary dex file and if we need to compile it.
1396 std::string oat_dir_str;
1397 if (is_secondary_dex) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001398 if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
Calin Juravle80a21252017-01-17 14:43:25 -08001399 instruction_set, compiler_filter, &dexopt_needed, &oat_dir_str)) {
1400 oat_dir = oat_dir_str.c_str();
1401 if (dexopt_needed == NO_DEXOPT_NEEDED) {
1402 return 0; // Nothing to do, report success.
1403 }
1404 } else {
1405 return -1; // We had an error, logged in the process method.
1406 }
1407 } else {
Calin Juravlec9eab382017-01-25 01:17:17 -08001408 // Currently these flags are only use for secondary dex files.
1409 // Verify that they are not set for primary apks.
Calin Juravle80a21252017-01-17 14:43:25 -08001410 CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0);
1411 CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0);
1412 }
Calin Juravle7a570e82017-01-14 16:23:30 -08001413
1414 // Open the input file.
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001415 unique_fd input_fd(open(dex_path, O_RDONLY, 0));
Calin Juravle7a570e82017-01-14 16:23:30 -08001416 if (input_fd.get() < 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001417 ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001418 return -1;
1419 }
1420
1421 // Create the output OAT file.
1422 char out_oat_path[PKG_PATH_MAX];
Calin Juravlec9eab382017-01-25 01:17:17 -08001423 Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid,
Calin Juravle80a21252017-01-17 14:43:25 -08001424 instruction_set, is_secondary_dex, out_oat_path);
Calin Juravle7a570e82017-01-14 16:23:30 -08001425 if (out_oat_fd.get() < 0) {
1426 return -1;
1427 }
1428
1429 // Open vdex files.
1430 Dex2oatFileWrapper in_vdex_fd;
1431 Dex2oatFileWrapper out_vdex_fd;
Nicolas Geoffraya2dbefc2017-03-09 13:11:25 +00001432 if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public,
1433 profile_guided, uid, is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001434 return -1;
1435 }
1436
1437 // Create a swap file if necessary.
Calin Juravle1a0af3b2017-03-09 14:33:33 -08001438 unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001439
Calin Juravle7a570e82017-01-14 16:23:30 -08001440 // Create the app image file if needed.
1441 Dex2oatFileWrapper image_fd =
Calin Juravle2289c0a2017-02-15 12:44:14 -08001442 maybe_open_app_image(out_oat_path, profile_guided, is_public, uid, is_secondary_dex);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001443
Calin Juravle7a570e82017-01-14 16:23:30 -08001444 // Open the reference profile if needed.
1445 Dex2oatFileWrapper reference_profile_fd =
Calin Juravle80a21252017-01-17 14:43:25 -08001446 maybe_open_reference_profile(pkgname, profile_guided, is_public, uid, is_secondary_dex);
Calin Juravle7a570e82017-01-14 16:23:30 -08001447
Calin Juravlec9eab382017-01-25 01:17:17 -08001448 ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001449
1450 pid_t pid = fork();
1451 if (pid == 0) {
1452 /* child -- drop privileges before continuing */
1453 drop_capabilities(uid);
1454
Richard Uhler76cc0272016-12-08 10:46:35 +00001455 SetDex2OatScheduling(boot_complete);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001456 if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
1457 ALOGE("flock(%s) failed: %s\n", out_oat_path, strerror(errno));
1458 _exit(67);
1459 }
1460
Richard Uhler76cc0272016-12-08 10:46:35 +00001461 // Pass dex2oat the relative path to the input file.
Calin Juravlec9eab382017-01-25 01:17:17 -08001462 const char *input_file_name = get_location_from_path(dex_path);
Richard Uhler76cc0272016-12-08 10:46:35 +00001463 run_dex2oat(input_fd.get(),
1464 out_oat_fd.get(),
1465 in_vdex_fd.get(),
Calin Juravle7a570e82017-01-14 16:23:30 -08001466 out_vdex_fd.get(),
Richard Uhler76cc0272016-12-08 10:46:35 +00001467 image_fd.get(),
1468 input_file_name,
1469 out_oat_path,
1470 swap_fd.get(),
1471 instruction_set,
1472 compiler_filter,
1473 vm_safe_mode,
1474 debuggable,
1475 boot_complete,
1476 reference_profile_fd.get(),
1477 shared_libraries);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001478 _exit(68); /* only get here on exec failure */
1479 } else {
1480 int res = wait_child(pid);
1481 if (res == 0) {
Calin Juravlec9eab382017-01-25 01:17:17 -08001482 ALOGV("DexInv: --- END '%s' (success) ---\n", dex_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001483 } else {
Calin Juravlec9eab382017-01-25 01:17:17 -08001484 ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", dex_path, res);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001485 return -1;
1486 }
1487 }
1488
Calin Juravlec9eab382017-01-25 01:17:17 -08001489 update_out_oat_access_times(dex_path, out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001490
1491 // We've been successful, don't delete output.
1492 out_oat_fd.SetCleanup(false);
Calin Juravle7a570e82017-01-14 16:23:30 -08001493 out_vdex_fd.SetCleanup(false);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001494 image_fd.SetCleanup(false);
1495 reference_profile_fd.SetCleanup(false);
1496
1497 return 0;
1498}
1499
Calin Juravlec9eab382017-01-25 01:17:17 -08001500// Try to remove the given directory. Log an error if the directory exists
1501// and is empty but could not be removed.
1502static bool rmdir_if_empty(const char* dir) {
1503 if (rmdir(dir) == 0) {
1504 return true;
1505 }
1506 if (errno == ENOENT || errno == ENOTEMPTY) {
1507 return true;
1508 }
1509 PLOG(ERROR) << "Failed to remove dir: " << dir;
1510 return false;
1511}
1512
1513// Try to unlink the given file. Log an error if the file exists and could not
1514// be unlinked.
1515static bool unlink_if_exists(const std::string& file) {
1516 if (unlink(file.c_str()) == 0) {
1517 return true;
1518 }
1519 if (errno == ENOENT) {
1520 return true;
1521
1522 }
1523 PLOG(ERROR) << "Could not unlink: " << file;
1524 return false;
1525}
1526
1527// Create the oat file structure for the secondary dex 'dex_path' and assign
1528// the individual path component to the 'out_' parameters.
1529static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa,
1530 /*out*/char* out_oat_dir, /*out*/char* out_oat_isa_dir, /*out*/char* out_oat_path) {
1531 size_t dirIndex = dex_path.rfind('/');
1532 if (dirIndex == std::string::npos) {
1533 LOG(ERROR) << "Unexpected dir structure for dex file " << dex_path;
1534 return false;
1535 }
1536 // TODO(calin): we have similar computations in at lest 3 other places
1537 // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by
1538 // use string append.
1539 std::string apk_dir = dex_path.substr(0, dirIndex);
1540 snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
1541 snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str());
1542
1543 if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
1544 /*is_secondary_dex*/ true, out_oat_path)) {
1545 LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path;
1546 return false;
1547 }
1548 return true;
1549}
1550
1551// Reconcile the secondary dex 'dex_path' and its generated oat files.
1552// Return true if all the parameters are valid and the secondary dex file was
1553// processed successfully (i.e. the dex_path either exists, or if not, its corresponding
1554// oat/vdex/art files where deleted successfully). In this case, out_secondary_dex_exists
1555// will be true if the secondary dex file still exists. If the secondary dex file does not exist,
1556// the method cleans up any previously generated compiler artifacts (oat, vdex, art).
1557// Return false if there were errors during processing. In this case
1558// out_secondary_dex_exists will be set to false.
1559bool reconcile_secondary_dex_file(const std::string& dex_path,
1560 const std::string& pkgname, int uid, const std::vector<std::string>& isas,
1561 const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
1562 /*out*/bool* out_secondary_dex_exists) {
1563 // Set out to false to start with, just in case we have validation errors.
1564 *out_secondary_dex_exists = false;
1565 if (isas.size() == 0) {
1566 LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector";
1567 return false;
1568 }
1569
1570 const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
1571 if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr,
1572 uid, storage_flag)) {
1573 LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
1574 return false;
1575 }
1576
1577 if (access(dex_path.c_str(), F_OK) == 0) {
1578 // The path exists, nothing to do. The odex files (if any) will be left untouched.
1579 *out_secondary_dex_exists = true;
1580 return true;
1581 } else if (errno != ENOENT) {
1582 PLOG(ERROR) << "Failed to check access to secondary dex " << dex_path;
1583 return false;
1584 }
1585
1586 // The secondary dex does not exist anymore. Clear any generated files.
1587 char oat_path[PKG_PATH_MAX];
1588 char oat_dir[PKG_PATH_MAX];
1589 char oat_isa_dir[PKG_PATH_MAX];
1590 bool result = true;
1591 for (size_t i = 0; i < isas.size(); i++) {
1592 if (!create_secondary_dex_oat_layout(dex_path, isas[i], oat_dir, oat_isa_dir, oat_path)) {
1593 LOG(ERROR) << "Could not create secondary odex layout: " << dex_path;
1594 result = false;
1595 continue;
1596 }
1597 result = unlink_if_exists(oat_path) && result;
1598 result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
1599 result = unlink_if_exists(create_image_filename(oat_path)) && result;
1600
1601 // Try removing the directories as well, they might be empty.
1602 result = rmdir_if_empty(oat_isa_dir) && result;
1603 result = rmdir_if_empty(oat_dir) && result;
1604 }
1605
1606 return result;
1607}
1608
Jeff Sharkey90aff262016-12-12 14:28:24 -07001609// Helper for move_ab, so that we can have common failure-case cleanup.
1610static bool unlink_and_rename(const char* from, const char* to) {
1611 // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
1612 // return a failure.
1613 struct stat s;
1614 if (stat(to, &s) == 0) {
1615 if (!S_ISREG(s.st_mode)) {
1616 LOG(ERROR) << from << " is not a regular file to replace for A/B.";
1617 return false;
1618 }
1619 if (unlink(to) != 0) {
1620 LOG(ERROR) << "Could not unlink " << to << " to move A/B.";
1621 return false;
1622 }
1623 } else {
1624 // This may be a permission problem. We could investigate the error code, but we'll just
1625 // let the rename failure do the work for us.
1626 }
1627
1628 // Try to rename "to" to "from."
1629 if (rename(from, to) != 0) {
1630 PLOG(ERROR) << "Could not rename " << from << " to " << to;
1631 return false;
1632 }
1633 return true;
1634}
1635
1636// Move/rename a B artifact (from) to an A artifact (to).
1637static bool move_ab_path(const std::string& b_path, const std::string& a_path) {
1638 // Check whether B exists.
1639 {
1640 struct stat s;
1641 if (stat(b_path.c_str(), &s) != 0) {
1642 // Silently ignore for now. The service calling this isn't smart enough to understand
1643 // lack of artifacts at the moment.
1644 return false;
1645 }
1646 if (!S_ISREG(s.st_mode)) {
1647 LOG(ERROR) << "A/B artifact " << b_path << " is not a regular file.";
1648 // Try to unlink, but swallow errors.
1649 unlink(b_path.c_str());
1650 return false;
1651 }
1652 }
1653
1654 // Rename B to A.
1655 if (!unlink_and_rename(b_path.c_str(), a_path.c_str())) {
1656 // Delete the b_path so we don't try again (or fail earlier).
1657 if (unlink(b_path.c_str()) != 0) {
1658 PLOG(ERROR) << "Could not unlink " << b_path;
1659 }
1660
1661 return false;
1662 }
1663
1664 return true;
1665}
1666
1667bool move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
1668 // Get the current slot suffix. No suffix, no A/B.
1669 std::string slot_suffix;
1670 {
1671 char buf[kPropertyValueMax];
1672 if (get_property("ro.boot.slot_suffix", buf, nullptr) <= 0) {
1673 return false;
1674 }
1675 slot_suffix = buf;
1676
1677 if (!ValidateTargetSlotSuffix(slot_suffix)) {
1678 LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
1679 return false;
1680 }
1681 }
1682
1683 // Validate other inputs.
1684 if (validate_apk_path(apk_path) != 0) {
1685 LOG(ERROR) << "Invalid apk_path: " << apk_path;
1686 return false;
1687 }
1688 if (validate_apk_path(oat_dir) != 0) {
1689 LOG(ERROR) << "Invalid oat_dir: " << oat_dir;
1690 return false;
1691 }
1692
1693 char a_path[PKG_PATH_MAX];
1694 if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
1695 return false;
1696 }
1697 const std::string a_vdex_path = create_vdex_filename(a_path);
1698 const std::string a_image_path = create_image_filename(a_path);
1699
1700 // B path = A path + slot suffix.
1701 const std::string b_path = StringPrintf("%s.%s", a_path, slot_suffix.c_str());
1702 const std::string b_vdex_path = StringPrintf("%s.%s", a_vdex_path.c_str(), slot_suffix.c_str());
1703 const std::string b_image_path = StringPrintf("%s.%s",
1704 a_image_path.c_str(),
1705 slot_suffix.c_str());
1706
1707 bool success = true;
1708 if (move_ab_path(b_path, a_path)) {
1709 if (move_ab_path(b_vdex_path, a_vdex_path)) {
1710 // Note: we can live without an app image. As such, ignore failure to move the image file.
1711 // If we decide to require the app image, or the app image being moved correctly,
1712 // then change accordingly.
1713 constexpr bool kIgnoreAppImageFailure = true;
1714
1715 if (!a_image_path.empty()) {
1716 if (!move_ab_path(b_image_path, a_image_path)) {
1717 unlink(a_image_path.c_str());
1718 if (!kIgnoreAppImageFailure) {
1719 success = false;
1720 }
1721 }
1722 }
1723 } else {
1724 // Cleanup: delete B image, ignore errors.
1725 unlink(b_image_path.c_str());
1726 success = false;
1727 }
1728 } else {
1729 // Cleanup: delete B image, ignore errors.
1730 unlink(b_vdex_path.c_str());
1731 unlink(b_image_path.c_str());
1732 success = false;
1733 }
1734 return success;
1735}
1736
1737bool delete_odex(const char* apk_path, const char* instruction_set, const char* oat_dir) {
1738 // Delete the oat/odex file.
1739 char out_path[PKG_PATH_MAX];
Calin Juravle80a21252017-01-17 14:43:25 -08001740 if (!create_oat_out_path(apk_path, instruction_set, oat_dir,
1741 /*is_secondary_dex*/ false, out_path)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001742 return false;
1743 }
1744
1745 // In case of a permission failure report the issue. Otherwise just print a warning.
1746 auto unlink_and_check = [](const char* path) -> bool {
1747 int result = unlink(path);
1748 if (result != 0) {
1749 if (errno == EACCES || errno == EPERM) {
1750 PLOG(ERROR) << "Could not unlink " << path;
1751 return false;
1752 }
1753 PLOG(WARNING) << "Could not unlink " << path;
1754 }
1755 return true;
1756 };
1757
1758 // Delete the oat/odex file.
1759 bool return_value_oat = unlink_and_check(out_path);
1760
1761 // Derive and delete the app image.
1762 bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
1763
1764 // Report success.
1765 return return_value_oat && return_value_art;
1766}
1767
Jeff Sharkey6c2c0562016-12-07 12:12:00 -07001768int dexopt(const char* const params[DEXOPT_PARAM_COUNT]) {
1769 return dexopt(params[0], // apk_path
1770 atoi(params[1]), // uid
1771 params[2], // pkgname
1772 params[3], // instruction_set
1773 atoi(params[4]), // dexopt_needed
1774 params[5], // oat_dir
1775 atoi(params[6]), // dexopt_flags
1776 params[7], // compiler_filter
1777 parse_null(params[8]), // volume_uuid
1778 parse_null(params[9])); // shared_libraries
1779 static_assert(DEXOPT_PARAM_COUNT == 10U, "Unexpected dexopt param count");
1780}
1781
1782} // namespace installd
1783} // namespace android