blob: c00328323edc9481723f074cc4318d4cf96d8bdf [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 Juravle42451c02017-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;
Jeff Sharkey6c2c0562016-12-07 12:12:00 -070048
49namespace android {
50namespace installd {
51
52static const char* parse_null(const char* arg) {
53 if (strcmp(arg, "!") == 0) {
54 return nullptr;
55 } else {
56 return arg;
57 }
58}
59
Jeff Sharkey90aff262016-12-12 14:28:24 -070060static bool clear_profile(const std::string& profile) {
61 base::unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
62 if (ufd.get() < 0) {
63 if (errno != ENOENT) {
64 PLOG(WARNING) << "Could not open profile " << profile;
65 return false;
66 } else {
67 // Nothing to clear. That's ok.
68 return true;
69 }
70 }
71
72 if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
73 if (errno != EWOULDBLOCK) {
74 PLOG(WARNING) << "Error locking profile " << profile;
75 }
76 // This implies that the app owning this profile is running
77 // (and has acquired the lock).
78 //
79 // If we can't acquire the lock bail out since clearing is useless anyway
80 // (the app will write again to the profile).
81 //
82 // Note:
83 // This does not impact the this is not an issue for the profiling correctness.
84 // In case this is needed because of an app upgrade, profiles will still be
85 // eventually cleared by the app itself due to checksum mismatch.
86 // If this is needed because profman advised, then keeping the data around
87 // until the next run is again not an issue.
88 //
89 // If the app attempts to acquire a lock while we've held one here,
90 // it will simply skip the current write cycle.
91 return false;
92 }
93
94 bool truncated = ftruncate(ufd.get(), 0) == 0;
95 if (!truncated) {
96 PLOG(WARNING) << "Could not truncate " << profile;
97 }
98 if (flock(ufd.get(), LOCK_UN) != 0) {
99 PLOG(WARNING) << "Error unlocking profile " << profile;
100 }
101 return truncated;
102}
103
104bool clear_reference_profile(const char* pkgname) {
105 std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
106 std::string reference_profile = create_primary_profile(reference_profile_dir);
107 return clear_profile(reference_profile);
108}
109
110bool clear_current_profile(const char* pkgname, userid_t user) {
111 std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
112 std::string profile = create_primary_profile(profile_dir);
113 return clear_profile(profile);
114}
115
116bool clear_current_profiles(const char* pkgname) {
117 bool success = true;
118 std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
119 for (auto user : users) {
120 success &= clear_current_profile(pkgname, user);
121 }
122 return success;
123}
124
125static int split_count(const char *str)
126{
127 char *ctx;
128 int count = 0;
129 char buf[kPropertyValueMax];
130
131 strncpy(buf, str, sizeof(buf));
132 char *pBuf = buf;
133
134 while(strtok_r(pBuf, " ", &ctx) != NULL) {
135 count++;
136 pBuf = NULL;
137 }
138
139 return count;
140}
141
142static int split(char *buf, const char **argv)
143{
144 char *ctx;
145 int count = 0;
146 char *tok;
147 char *pBuf = buf;
148
149 while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) {
150 argv[count++] = tok;
151 pBuf = NULL;
152 }
153
154 return count;
155}
156
Jeff Sharkey90aff262016-12-12 14:28:24 -0700157static void run_dex2oat(int zip_fd, int oat_fd, int input_vdex_fd, int output_vdex_fd, int image_fd,
158 const char* input_file_name, const char* output_file_name, int swap_fd,
159 const char *instruction_set, const char* compiler_filter, bool vm_safe_mode,
160 bool debuggable, bool post_bootcomplete, int profile_fd, const char* shared_libraries) {
161 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
162
163 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
164 ALOGE("Instruction set %s longer than max length of %d",
165 instruction_set, MAX_INSTRUCTION_SET_LEN);
166 return;
167 }
168
169 char dex2oat_Xms_flag[kPropertyValueMax];
170 bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
171
172 char dex2oat_Xmx_flag[kPropertyValueMax];
173 bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
174
175 char dex2oat_threads_buf[kPropertyValueMax];
176 bool have_dex2oat_threads_flag = get_property(post_bootcomplete
177 ? "dalvik.vm.dex2oat-threads"
178 : "dalvik.vm.boot-dex2oat-threads",
179 dex2oat_threads_buf,
180 NULL) > 0;
181 char dex2oat_threads_arg[kPropertyValueMax + 2];
182 if (have_dex2oat_threads_flag) {
183 sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
184 }
185
186 char dex2oat_isa_features_key[kPropertyKeyMax];
187 sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
188 char dex2oat_isa_features[kPropertyValueMax];
189 bool have_dex2oat_isa_features = get_property(dex2oat_isa_features_key,
190 dex2oat_isa_features, NULL) > 0;
191
192 char dex2oat_isa_variant_key[kPropertyKeyMax];
193 sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
194 char dex2oat_isa_variant[kPropertyValueMax];
195 bool have_dex2oat_isa_variant = get_property(dex2oat_isa_variant_key,
196 dex2oat_isa_variant, NULL) > 0;
197
198 const char *dex2oat_norelocation = "-Xnorelocate";
199 bool have_dex2oat_relocation_skip_flag = false;
200
201 char dex2oat_flags[kPropertyValueMax];
202 int dex2oat_flags_count = get_property("dalvik.vm.dex2oat-flags",
203 dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
204 ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
205
206 // If we booting without the real /data, don't spend time compiling.
207 char vold_decrypt[kPropertyValueMax];
208 bool have_vold_decrypt = get_property("vold.decrypt", vold_decrypt, "") > 0;
209 bool skip_compilation = (have_vold_decrypt &&
210 (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
211 (strcmp(vold_decrypt, "1") == 0)));
212
213 bool generate_debug_info = property_get_bool("debug.generate-debug-info", false);
214
215 char app_image_format[kPropertyValueMax];
216 char image_format_arg[strlen("--image-format=") + kPropertyValueMax];
217 bool have_app_image_format =
218 image_fd >= 0 && get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
219 if (have_app_image_format) {
220 sprintf(image_format_arg, "--image-format=%s", app_image_format);
221 }
222
223 char dex2oat_large_app_threshold[kPropertyValueMax];
224 bool have_dex2oat_large_app_threshold =
225 get_property("dalvik.vm.dex2oat-very-large", dex2oat_large_app_threshold, NULL) > 0;
226 char dex2oat_large_app_threshold_arg[strlen("--very-large-app-threshold=") + kPropertyValueMax];
227 if (have_dex2oat_large_app_threshold) {
228 sprintf(dex2oat_large_app_threshold_arg,
229 "--very-large-app-threshold=%s",
230 dex2oat_large_app_threshold);
231 }
232
233 static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
234
235 static const char* RUNTIME_ARG = "--runtime-arg";
236
237 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
238
239 char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
240 char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
241 char input_vdex_fd_arg[strlen("--input-vdex-fd=") + MAX_INT_LEN];
242 char output_vdex_fd_arg[strlen("--output-vdex-fd=") + MAX_INT_LEN];
243 char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
244 char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
245 char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
246 char instruction_set_variant_arg[strlen("--instruction-set-variant=") + kPropertyValueMax];
247 char instruction_set_features_arg[strlen("--instruction-set-features=") + kPropertyValueMax];
248 char dex2oat_Xms_arg[strlen("-Xms") + kPropertyValueMax];
249 char dex2oat_Xmx_arg[strlen("-Xmx") + kPropertyValueMax];
250 char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + kPropertyValueMax];
251 bool have_dex2oat_swap_fd = false;
252 char dex2oat_swap_fd[strlen("--swap-fd=") + MAX_INT_LEN];
253 bool have_dex2oat_image_fd = false;
254 char dex2oat_image_fd[strlen("--app-image-fd=") + MAX_INT_LEN];
255
256 sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
257 sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
258 sprintf(input_vdex_fd_arg, "--input-vdex-fd=%d", input_vdex_fd);
259 sprintf(output_vdex_fd_arg, "--output-vdex-fd=%d", output_vdex_fd);
260 sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
261 sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
262 sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
263 sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant);
264 sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
265 if (swap_fd >= 0) {
266 have_dex2oat_swap_fd = true;
267 sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
268 }
269 if (image_fd >= 0) {
270 have_dex2oat_image_fd = true;
271 sprintf(dex2oat_image_fd, "--app-image-fd=%d", image_fd);
272 }
273
274 if (have_dex2oat_Xms_flag) {
275 sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
276 }
277 if (have_dex2oat_Xmx_flag) {
278 sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
279 }
280
281 // Compute compiler filter.
282
283 bool have_dex2oat_compiler_filter_flag;
284 if (skip_compilation) {
285 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
286 have_dex2oat_compiler_filter_flag = true;
287 have_dex2oat_relocation_skip_flag = true;
288 } else if (vm_safe_mode) {
289 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
290 have_dex2oat_compiler_filter_flag = true;
291 } else if (compiler_filter != nullptr &&
292 strlen(compiler_filter) + strlen("--compiler-filter=") <
293 arraysize(dex2oat_compiler_filter_arg)) {
294 sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
295 have_dex2oat_compiler_filter_flag = true;
296 } else {
297 char dex2oat_compiler_filter_flag[kPropertyValueMax];
298 have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
299 dex2oat_compiler_filter_flag, NULL) > 0;
300 if (have_dex2oat_compiler_filter_flag) {
301 sprintf(dex2oat_compiler_filter_arg,
302 "--compiler-filter=%s",
303 dex2oat_compiler_filter_flag);
304 }
305 }
306
307 // Check whether all apps should be compiled debuggable.
308 if (!debuggable) {
309 char prop_buf[kPropertyValueMax];
310 debuggable =
311 (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
312 (prop_buf[0] == '1');
313 }
314 char profile_arg[strlen("--profile-file-fd=") + MAX_INT_LEN];
315 if (profile_fd != -1) {
316 sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
317 }
318
319
320 ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
321
322 const char* argv[9 // program name, mandatory arguments and the final NULL
323 + (have_dex2oat_isa_variant ? 1 : 0)
324 + (have_dex2oat_isa_features ? 1 : 0)
325 + (have_dex2oat_Xms_flag ? 2 : 0)
326 + (have_dex2oat_Xmx_flag ? 2 : 0)
327 + (have_dex2oat_compiler_filter_flag ? 1 : 0)
328 + (have_dex2oat_threads_flag ? 1 : 0)
329 + (have_dex2oat_swap_fd ? 1 : 0)
330 + (have_dex2oat_image_fd ? 1 : 0)
331 + (have_dex2oat_relocation_skip_flag ? 2 : 0)
332 + (generate_debug_info ? 1 : 0)
333 + (debuggable ? 1 : 0)
334 + (have_app_image_format ? 1 : 0)
335 + dex2oat_flags_count
336 + (profile_fd == -1 ? 0 : 1)
337 + (shared_libraries != nullptr ? 4 : 0)
338 + (have_dex2oat_large_app_threshold ? 1 : 0)];
339 int i = 0;
340 argv[i++] = DEX2OAT_BIN;
341 argv[i++] = zip_fd_arg;
342 argv[i++] = zip_location_arg;
343 argv[i++] = input_vdex_fd_arg;
344 argv[i++] = output_vdex_fd_arg;
345 argv[i++] = oat_fd_arg;
346 argv[i++] = oat_location_arg;
347 argv[i++] = instruction_set_arg;
348 if (have_dex2oat_isa_variant) {
349 argv[i++] = instruction_set_variant_arg;
350 }
351 if (have_dex2oat_isa_features) {
352 argv[i++] = instruction_set_features_arg;
353 }
354 if (have_dex2oat_Xms_flag) {
355 argv[i++] = RUNTIME_ARG;
356 argv[i++] = dex2oat_Xms_arg;
357 }
358 if (have_dex2oat_Xmx_flag) {
359 argv[i++] = RUNTIME_ARG;
360 argv[i++] = dex2oat_Xmx_arg;
361 }
362 if (have_dex2oat_compiler_filter_flag) {
363 argv[i++] = dex2oat_compiler_filter_arg;
364 }
365 if (have_dex2oat_threads_flag) {
366 argv[i++] = dex2oat_threads_arg;
367 }
368 if (have_dex2oat_swap_fd) {
369 argv[i++] = dex2oat_swap_fd;
370 }
371 if (have_dex2oat_image_fd) {
372 argv[i++] = dex2oat_image_fd;
373 }
374 if (generate_debug_info) {
375 argv[i++] = "--generate-debug-info";
376 }
377 if (debuggable) {
378 argv[i++] = "--debuggable";
379 }
380 if (have_app_image_format) {
381 argv[i++] = image_format_arg;
382 }
383 if (have_dex2oat_large_app_threshold) {
384 argv[i++] = dex2oat_large_app_threshold_arg;
385 }
386 if (dex2oat_flags_count) {
387 i += split(dex2oat_flags, argv + i);
388 }
389 if (have_dex2oat_relocation_skip_flag) {
390 argv[i++] = RUNTIME_ARG;
391 argv[i++] = dex2oat_norelocation;
392 }
393 if (profile_fd != -1) {
394 argv[i++] = profile_arg;
395 }
396 if (shared_libraries != nullptr) {
397 argv[i++] = RUNTIME_ARG;
398 argv[i++] = "-classpath";
399 argv[i++] = RUNTIME_ARG;
400 argv[i++] = shared_libraries;
401 }
402 // Do not add after dex2oat_flags, they should override others for debugging.
403 argv[i] = NULL;
404
405 execv(DEX2OAT_BIN, (char * const *)argv);
406 ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
407}
408
409/*
410 * Whether dexopt should use a swap file when compiling an APK.
411 *
412 * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision
413 * itself, anyways).
414 *
415 * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true".
416 *
417 * Otherwise, return true if this is a low-mem device.
418 *
419 * Otherwise, return default value.
420 */
421static bool kAlwaysProvideSwapFile = false;
422static bool kDefaultProvideSwapFile = true;
423
424static bool ShouldUseSwapFileForDexopt() {
425 if (kAlwaysProvideSwapFile) {
426 return true;
427 }
428
429 // Check the "override" property. If it exists, return value == "true".
430 char dex2oat_prop_buf[kPropertyValueMax];
431 if (get_property("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
432 if (strcmp(dex2oat_prop_buf, "true") == 0) {
433 return true;
434 } else {
435 return false;
436 }
437 }
438
439 // Shortcut for default value. This is an implementation optimization for the process sketched
440 // above. If the default value is true, we can avoid to check whether this is a low-mem device,
441 // as low-mem is never returning false. The compiler will optimize this away if it can.
442 if (kDefaultProvideSwapFile) {
443 return true;
444 }
445
446 bool is_low_mem = property_get_bool("ro.config.low_ram", false);
447 if (is_low_mem) {
448 return true;
449 }
450
451 // Default value must be false here.
452 return kDefaultProvideSwapFile;
453}
454
Richard Uhler76cc0272016-12-08 10:46:35 +0000455static void SetDex2OatScheduling(bool set_to_bg) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700456 if (set_to_bg) {
457 if (set_sched_policy(0, SP_BACKGROUND) < 0) {
458 ALOGE("set_sched_policy failed: %s\n", strerror(errno));
459 exit(70);
460 }
461 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
462 ALOGE("setpriority failed: %s\n", strerror(errno));
463 exit(71);
464 }
465 }
466}
467
468static void close_all_fds(const std::vector<fd_t>& fds, const char* description) {
469 for (size_t i = 0; i < fds.size(); i++) {
470 if (close(fds[i]) != 0) {
471 PLOG(WARNING) << "Failed to close fd for " << description << " at index " << i;
472 }
473 }
474}
475
476static fd_t open_profile_dir(const std::string& profile_dir) {
477 fd_t profile_dir_fd = TEMP_FAILURE_RETRY(open(profile_dir.c_str(),
478 O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW));
479 if (profile_dir_fd < 0) {
480 // In a multi-user environment, these directories can be created at
481 // different points and it's possible we'll attempt to open a profile
482 // dir before it exists.
483 if (errno != ENOENT) {
484 PLOG(ERROR) << "Failed to open profile_dir: " << profile_dir;
485 }
486 }
487 return profile_dir_fd;
488}
489
490static fd_t open_primary_profile_file_from_dir(const std::string& profile_dir, mode_t open_mode) {
491 fd_t profile_dir_fd = open_profile_dir(profile_dir);
492 if (profile_dir_fd < 0) {
493 return -1;
494 }
495
496 fd_t profile_fd = -1;
497 std::string profile_file = create_primary_profile(profile_dir);
498
499 profile_fd = TEMP_FAILURE_RETRY(open(profile_file.c_str(), open_mode | O_NOFOLLOW));
500 if (profile_fd == -1) {
501 // It's not an error if the profile file does not exist.
502 if (errno != ENOENT) {
503 PLOG(ERROR) << "Failed to lstat profile_dir: " << profile_dir;
504 }
505 }
506 // TODO(calin): use AutoCloseFD instead of closing the fd manually.
507 if (close(profile_dir_fd) != 0) {
508 PLOG(WARNING) << "Could not close profile dir " << profile_dir;
509 }
510 return profile_fd;
511}
512
513static fd_t open_primary_profile_file(userid_t user, const char* pkgname) {
514 std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
515 return open_primary_profile_file_from_dir(profile_dir, O_RDONLY);
516}
517
518static fd_t open_reference_profile(uid_t uid, const char* pkgname, bool read_write) {
519 std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
520 int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY;
521 fd_t fd = open_primary_profile_file_from_dir(reference_profile_dir, flags);
522 if (fd < 0) {
523 return -1;
524 }
525 if (read_write) {
526 // Fix the owner.
527 if (fchown(fd, uid, uid) < 0) {
528 close(fd);
529 return -1;
530 }
531 }
532 return fd;
533}
534
535static void open_profile_files(uid_t uid, const char* pkgname,
536 /*out*/ std::vector<fd_t>* profiles_fd, /*out*/ fd_t* reference_profile_fd) {
537 // Open the reference profile in read-write mode as profman might need to save the merge.
538 *reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ true);
539 if (*reference_profile_fd < 0) {
540 // We can't access the reference profile file.
541 return;
542 }
543
544 std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
545 for (auto user : users) {
546 fd_t profile_fd = open_primary_profile_file(user, pkgname);
547 // Add to the lists only if both fds are valid.
548 if (profile_fd >= 0) {
549 profiles_fd->push_back(profile_fd);
550 }
551 }
552}
553
554static void drop_capabilities(uid_t uid) {
555 if (setgid(uid) != 0) {
556 ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
557 exit(64);
558 }
559 if (setuid(uid) != 0) {
560 ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
561 exit(65);
562 }
563 // drop capabilities
564 struct __user_cap_header_struct capheader;
565 struct __user_cap_data_struct capdata[2];
566 memset(&capheader, 0, sizeof(capheader));
567 memset(&capdata, 0, sizeof(capdata));
568 capheader.version = _LINUX_CAPABILITY_VERSION_3;
569 if (capset(&capheader, &capdata[0]) < 0) {
570 ALOGE("capset failed: %s\n", strerror(errno));
571 exit(66);
572 }
573}
574
575static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
576static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
577static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
578static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
579static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
580
581static void run_profman_merge(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) {
582 static const size_t MAX_INT_LEN = 32;
583 static const char* PROFMAN_BIN = "/system/bin/profman";
584
585 std::vector<std::string> profile_args(profiles_fd.size());
586 char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN];
587 for (size_t k = 0; k < profiles_fd.size(); k++) {
588 sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k]);
589 profile_args[k].assign(profile_buf);
590 }
591 char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
592 sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd);
593
594 // program name, reference profile fd, the final NULL and the profile fds
595 const char* argv[3 + profiles_fd.size()];
596 int i = 0;
597 argv[i++] = PROFMAN_BIN;
598 argv[i++] = reference_profile_arg;
599 for (size_t k = 0; k < profile_args.size(); k++) {
600 argv[i++] = profile_args[k].c_str();
601 }
602 // Do not add after dex2oat_flags, they should override others for debugging.
603 argv[i] = NULL;
604
605 execv(PROFMAN_BIN, (char * const *)argv);
606 ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
607 exit(68); /* only get here on exec failure */
608}
609
610// Decides if profile guided compilation is needed or not based on existing profiles.
611// Returns true if there is enough information in the current profiles that worth
612// a re-compilation of the package.
613// If the return value is true all the current profiles would have been merged into
614// the reference profiles accessible with open_reference_profile().
615bool analyse_profiles(uid_t uid, const char* pkgname) {
616 std::vector<fd_t> profiles_fd;
617 fd_t reference_profile_fd = -1;
618 open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd);
619 if (profiles_fd.empty() || (reference_profile_fd == -1)) {
620 // Skip profile guided compilation because no profiles were found.
621 // Or if the reference profile info couldn't be opened.
622 close_all_fds(profiles_fd, "profiles_fd");
623 if ((reference_profile_fd != - 1) && (close(reference_profile_fd) != 0)) {
624 PLOG(WARNING) << "Failed to close fd for reference profile";
625 }
626 return false;
627 }
628
629 ALOGV("PROFMAN (MERGE): --- BEGIN '%s' ---\n", pkgname);
630
631 pid_t pid = fork();
632 if (pid == 0) {
633 /* child -- drop privileges before continuing */
634 drop_capabilities(uid);
635 run_profman_merge(profiles_fd, reference_profile_fd);
636 exit(68); /* only get here on exec failure */
637 }
638 /* parent */
639 int return_code = wait_child(pid);
640 bool need_to_compile = false;
641 bool should_clear_current_profiles = false;
642 bool should_clear_reference_profile = false;
643 if (!WIFEXITED(return_code)) {
644 LOG(WARNING) << "profman failed for package " << pkgname << ": " << return_code;
645 } else {
646 return_code = WEXITSTATUS(return_code);
647 switch (return_code) {
648 case PROFMAN_BIN_RETURN_CODE_COMPILE:
649 need_to_compile = true;
650 should_clear_current_profiles = true;
651 should_clear_reference_profile = false;
652 break;
653 case PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION:
654 need_to_compile = false;
655 should_clear_current_profiles = false;
656 should_clear_reference_profile = false;
657 break;
658 case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
659 LOG(WARNING) << "Bad profiles for package " << pkgname;
660 need_to_compile = false;
661 should_clear_current_profiles = true;
662 should_clear_reference_profile = true;
663 break;
664 case PROFMAN_BIN_RETURN_CODE_ERROR_IO: // fall-through
665 case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
666 // Temporary IO problem (e.g. locking). Ignore but log a warning.
667 LOG(WARNING) << "IO error while reading profiles for package " << pkgname;
668 need_to_compile = false;
669 should_clear_current_profiles = false;
670 should_clear_reference_profile = false;
671 break;
672 default:
673 // Unknown return code or error. Unlink profiles.
674 LOG(WARNING) << "Unknown error code while processing profiles for package " << pkgname
675 << ": " << return_code;
676 need_to_compile = false;
677 should_clear_current_profiles = true;
678 should_clear_reference_profile = true;
679 break;
680 }
681 }
682 close_all_fds(profiles_fd, "profiles_fd");
683 if (close(reference_profile_fd) != 0) {
684 PLOG(WARNING) << "Failed to close fd for reference profile";
685 }
686 if (should_clear_current_profiles) {
687 clear_current_profiles(pkgname);
688 }
689 if (should_clear_reference_profile) {
690 clear_reference_profile(pkgname);
691 }
692 return need_to_compile;
693}
694
695static void run_profman_dump(const std::vector<fd_t>& profile_fds,
696 fd_t reference_profile_fd,
697 const std::vector<std::string>& dex_locations,
698 const std::vector<fd_t>& apk_fds,
699 fd_t output_fd) {
700 std::vector<std::string> profman_args;
701 static const char* PROFMAN_BIN = "/system/bin/profman";
702 profman_args.push_back(PROFMAN_BIN);
703 profman_args.push_back("--dump-only");
704 profman_args.push_back(StringPrintf("--dump-output-to-fd=%d", output_fd));
705 if (reference_profile_fd != -1) {
706 profman_args.push_back(StringPrintf("--reference-profile-file-fd=%d",
707 reference_profile_fd));
708 }
709 for (fd_t profile_fd : profile_fds) {
710 profman_args.push_back(StringPrintf("--profile-file-fd=%d", profile_fd));
711 }
712 for (const std::string& dex_location : dex_locations) {
713 profman_args.push_back(StringPrintf("--dex-location=%s", dex_location.c_str()));
714 }
715 for (fd_t apk_fd : apk_fds) {
716 profman_args.push_back(StringPrintf("--apk-fd=%d", apk_fd));
717 }
718 const char **argv = new const char*[profman_args.size() + 1];
719 size_t i = 0;
720 for (const std::string& profman_arg : profman_args) {
721 argv[i++] = profman_arg.c_str();
722 }
723 argv[i] = NULL;
724
725 execv(PROFMAN_BIN, (char * const *)argv);
726 ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
727 exit(68); /* only get here on exec failure */
728}
729
730static const char* get_location_from_path(const char* path) {
731 static constexpr char kLocationSeparator = '/';
732 const char *location = strrchr(path, kLocationSeparator);
733 if (location == NULL) {
734 return path;
735 } else {
736 // Skip the separator character.
737 return location + 1;
738 }
739}
740
741bool dump_profiles(int32_t uid, const char* pkgname, const char* code_paths) {
742 std::vector<fd_t> profile_fds;
743 fd_t reference_profile_fd = -1;
744 std::string out_file_name = StringPrintf("/data/misc/profman/%s.txt", pkgname);
745
746 ALOGV("PROFMAN (DUMP): --- BEGIN '%s' ---\n", pkgname);
747
748 open_profile_files(uid, pkgname, &profile_fds, &reference_profile_fd);
749
750 const bool has_reference_profile = (reference_profile_fd != -1);
751 const bool has_profiles = !profile_fds.empty();
752
753 if (!has_reference_profile && !has_profiles) {
754 ALOGE("profman dump: no profiles to dump for '%s'", pkgname);
755 return false;
756 }
757
758 fd_t output_fd = open(out_file_name.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW);
759 if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
760 ALOGE("installd cannot chmod '%s' dump_profile\n", out_file_name.c_str());
761 return false;
762 }
763 std::vector<std::string> code_full_paths = base::Split(code_paths, ";");
764 std::vector<std::string> dex_locations;
765 std::vector<fd_t> apk_fds;
766 for (const std::string& code_full_path : code_full_paths) {
767 const char* full_path = code_full_path.c_str();
768 fd_t apk_fd = open(full_path, O_RDONLY | O_NOFOLLOW);
769 if (apk_fd == -1) {
770 ALOGE("installd cannot open '%s'\n", full_path);
771 return false;
772 }
773 dex_locations.push_back(get_location_from_path(full_path));
774 apk_fds.push_back(apk_fd);
775 }
776
777 pid_t pid = fork();
778 if (pid == 0) {
779 /* child -- drop privileges before continuing */
780 drop_capabilities(uid);
781 run_profman_dump(profile_fds, reference_profile_fd, dex_locations,
782 apk_fds, output_fd);
783 exit(68); /* only get here on exec failure */
784 }
785 /* parent */
786 close_all_fds(apk_fds, "apk_fds");
787 close_all_fds(profile_fds, "profile_fds");
788 if (close(reference_profile_fd) != 0) {
789 PLOG(WARNING) << "Failed to close fd for reference profile";
790 }
791 int return_code = wait_child(pid);
792 if (!WIFEXITED(return_code)) {
793 LOG(WARNING) << "profman failed for package " << pkgname << ": "
794 << return_code;
795 return false;
796 }
797 return true;
798}
799
800static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
801 // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
802 if (EndsWith(oat_path, ".dex")) {
803 std::string new_path = oat_path;
804 new_path.replace(new_path.length() - strlen(".dex"), strlen(".dex"), new_ext);
805 CHECK(EndsWith(new_path, new_ext.c_str()));
806 return new_path;
807 }
808
809 // An odex entry. Not that this may not be an extension, e.g., in the OTA
810 // case (where the base name will have an extension for the B artifact).
811 size_t odex_pos = oat_path.rfind(".odex");
812 if (odex_pos != std::string::npos) {
813 std::string new_path = oat_path;
814 new_path.replace(odex_pos, strlen(".odex"), new_ext);
815 CHECK_NE(new_path.find(new_ext), std::string::npos);
816 return new_path;
817 }
818
819 // Don't know how to handle this.
820 return "";
821}
822
823// Translate the given oat path to an art (app image) path. An empty string
824// denotes an error.
825static std::string create_image_filename(const std::string& oat_path) {
826 return replace_file_extension(oat_path, ".art");
827}
828
829// Translate the given oat path to a vdex path. An empty string denotes an error.
830static std::string create_vdex_filename(const std::string& oat_path) {
831 return replace_file_extension(oat_path, ".vdex");
832}
833
834static bool add_extension_to_file_name(char* file_name, const char* extension) {
835 if (strlen(file_name) + strlen(extension) + 1 > PKG_PATH_MAX) {
836 return false;
837 }
838 strcat(file_name, extension);
839 return true;
840}
841
842static int open_output_file(const char* file_name, bool recreate, int permissions) {
843 int flags = O_RDWR | O_CREAT;
844 if (recreate) {
845 if (unlink(file_name) < 0) {
846 if (errno != ENOENT) {
847 PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
848 }
849 }
850 flags |= O_EXCL;
851 }
852 return open(file_name, flags, permissions);
853}
854
855static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const char* path) {
856 if (fchmod(fd,
857 S_IRUSR|S_IWUSR|S_IRGRP |
858 (is_public ? S_IROTH : 0)) < 0) {
859 ALOGE("installd cannot chmod '%s' during dexopt\n", path);
860 return false;
861 } else if (fchown(fd, AID_SYSTEM, uid) < 0) {
862 ALOGE("installd cannot chown '%s' during dexopt\n", path);
863 return false;
864 }
865 return true;
866}
867
868static bool IsOutputDalvikCache(const char* oat_dir) {
869 // InstallerConnection.java (which invokes installd) transforms Java null arguments
870 // into '!'. Play it safe by handling it both.
871 // TODO: ensure we never get null.
872 // TODO: pass a flag instead of inferring if the output is dalvik cache.
873 return oat_dir == nullptr || oat_dir[0] == '!';
874}
875
876static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
Calin Juravle42451c02017-01-17 14:43:25 -0800877 const char* oat_dir, bool is_secondary_dex, /*out*/ char* out_oat_path) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700878 // Early best-effort check whether we can fit the the path into our buffers.
879 // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
880 // without a swap file, if necessary. Reference profiles file also add an extra ".prof"
881 // extension to the cache path (5 bytes).
882 if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
883 ALOGE("apk_path too long '%s'\n", apk_path);
884 return false;
885 }
886
887 if (!IsOutputDalvikCache(oat_dir)) {
Calin Juravle42451c02017-01-17 14:43:25 -0800888 // Oat dirs for secondary dex files are already validated.
889 if (!is_secondary_dex && validate_apk_path(oat_dir)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700890 ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir);
891 return false;
892 }
893 if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) {
894 return false;
895 }
896 } else {
897 if (!create_cache_path(out_oat_path, apk_path, instruction_set)) {
898 return false;
899 }
900 }
901 return true;
902}
903
904// Helper for fd management. This is similar to a unique_fd in that it closes the file descriptor
905// on destruction. It will also run the given cleanup (unless told not to) after closing.
906//
907// Usage example:
908//
Calin Juravle4a391f82017-01-14 16:23:30 -0800909// Dex2oatFileWrapper file(open(...),
Jeff Sharkey90aff262016-12-12 14:28:24 -0700910// [name]() {
911// unlink(name.c_str());
912// });
913// // Note: care needs to be taken about name, as it needs to have a lifetime longer than the
914// wrapper if captured as a reference.
915//
916// if (file.get() == -1) {
917// // Error opening...
918// }
919//
920// ...
921// if (error) {
922// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will run
923// // and delete the file (after the fd is closed).
924// return -1;
925// }
926//
927// (Success case)
928// file.SetCleanup(false);
929// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will not run
930// // (leaving the file around; after the fd is closed).
931//
Jeff Sharkey90aff262016-12-12 14:28:24 -0700932class Dex2oatFileWrapper {
933 public:
Calin Juravle4a391f82017-01-14 16:23:30 -0800934 Dex2oatFileWrapper() : value_(-1), cleanup_(), do_cleanup_(true), auto_close_(true) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700935 }
936
Calin Juravle4a391f82017-01-14 16:23:30 -0800937 Dex2oatFileWrapper(int value, std::function<void ()> cleanup)
938 : value_(value), cleanup_(cleanup), do_cleanup_(true), auto_close_(true) {}
939
940 Dex2oatFileWrapper(Dex2oatFileWrapper&& other) {
941 value_ = other.value_;
942 cleanup_ = other.cleanup_;
943 do_cleanup_ = other.do_cleanup_;
944 auto_close_ = other.auto_close_;
945 other.release();
946 }
947
948 Dex2oatFileWrapper& operator=(Dex2oatFileWrapper&& other) {
949 value_ = other.value_;
950 cleanup_ = other.cleanup_;
951 do_cleanup_ = other.do_cleanup_;
952 auto_close_ = other.auto_close_;
953 other.release();
954 return *this;
955 }
Jeff Sharkey90aff262016-12-12 14:28:24 -0700956
957 ~Dex2oatFileWrapper() {
958 reset(-1);
959 }
960
961 int get() {
962 return value_;
963 }
964
965 void SetCleanup(bool cleanup) {
966 do_cleanup_ = cleanup;
967 }
968
969 void reset(int new_value) {
Calin Juravle4a391f82017-01-14 16:23:30 -0800970 if (auto_close_ && value_ >= 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700971 close(value_);
972 }
973 if (do_cleanup_ && cleanup_ != nullptr) {
974 cleanup_();
975 }
976
977 value_ = new_value;
978 }
979
Calin Juravle4a391f82017-01-14 16:23:30 -0800980 void reset(int new_value, std::function<void ()> new_cleanup) {
981 if (auto_close_ && value_ >= 0) {
Jeff Sharkey90aff262016-12-12 14:28:24 -0700982 close(value_);
983 }
984 if (do_cleanup_ && cleanup_ != nullptr) {
985 cleanup_();
986 }
987
988 value_ = new_value;
989 cleanup_ = new_cleanup;
990 }
991
Calin Juravle4a391f82017-01-14 16:23:30 -0800992 void DisableAutoClose() {
993 auto_close_ = false;
994 }
995
Jeff Sharkey90aff262016-12-12 14:28:24 -0700996 private:
Calin Juravle4a391f82017-01-14 16:23:30 -0800997 void release() {
998 value_ = -1;
999 do_cleanup_ = false;
1000 cleanup_ = nullptr;
1001 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001002 int value_;
Calin Juravle4a391f82017-01-14 16:23:30 -08001003 std::function<void ()> cleanup_;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001004 bool do_cleanup_;
Calin Juravle4a391f82017-01-14 16:23:30 -08001005 bool auto_close_;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001006};
1007
Calin Juravle4a391f82017-01-14 16:23:30 -08001008// (re)Creates the app image if needed.
1009Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path, bool profile_guided,
1010 bool is_public, int uid) {
1011 // Use app images only if it is enabled (by a set image format) and we are compiling
1012 // profile-guided (so the app image doesn't conservatively contain all classes).
1013 if (!profile_guided) {
1014 return Dex2oatFileWrapper();
1015 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001016
Calin Juravle4a391f82017-01-14 16:23:30 -08001017 const std::string image_path = create_image_filename(out_oat_path);
1018 if (image_path.empty()) {
1019 // Happens when the out_oat_path has an unknown extension.
1020 return Dex2oatFileWrapper();
1021 }
1022 char app_image_format[kPropertyValueMax];
1023 bool have_app_image_format =
1024 get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
1025 if (!have_app_image_format) {
1026 return Dex2oatFileWrapper();
1027 }
1028 // Recreate is true since we do not want to modify a mapped image. If the app is
1029 // already running and we modify the image file, it can cause crashes (b/27493510).
1030 Dex2oatFileWrapper wrapper_fd(
1031 open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
1032 [image_path]() { unlink(image_path.c_str()); });
1033 if (wrapper_fd.get() < 0) {
1034 // Could not create application image file. Go on since we can compile without it.
1035 LOG(ERROR) << "installd could not create '" << image_path
1036 << "' for image file during dexopt";
1037 // If we have a valid image file path but no image fd, explicitly erase the image file.
1038 if (unlink(image_path.c_str()) < 0) {
1039 if (errno != ENOENT) {
1040 PLOG(ERROR) << "Couldn't unlink image file " << image_path;
1041 }
1042 }
1043 } else if (!set_permissions_and_ownership(
1044 wrapper_fd.get(), is_public, uid, image_path.c_str())) {
1045 ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
1046 wrapper_fd.reset(-1);
1047 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001048
Calin Juravle4a391f82017-01-14 16:23:30 -08001049 return wrapper_fd;
1050}
1051
1052// Creates the dexopt swap file if necessary and return its fd.
1053// Returns -1 if there's no need for a swap or in case of errors.
1054base::unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
1055 if (!ShouldUseSwapFileForDexopt()) {
1056 return base::unique_fd();
1057 }
1058 // Make sure there really is enough space.
1059 char swap_file_name[PKG_PATH_MAX];
1060 strcpy(swap_file_name, out_oat_path);
1061 if (!add_extension_to_file_name(swap_file_name, ".swap")) {
1062 return base::unique_fd();
1063 }
1064 base::unique_fd swap_fd(open_output_file(
1065 swap_file_name, /*recreate*/true, /*permissions*/0600));
1066 if (swap_fd.get() < 0) {
1067 // Could not create swap file. Optimistically go on and hope that we can compile
1068 // without it.
1069 ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
1070 } else {
1071 // Immediately unlink. We don't really want to hit flash.
1072 if (unlink(swap_file_name) < 0) {
1073 PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
1074 }
1075 }
1076 return swap_fd;
1077}
1078
1079// Opens the reference profiles if needed.
1080// Note that the reference profile might not exist so it's OK if the fd will be -1.
1081Dex2oatFileWrapper maybe_open_reference_profile(const char* pkgname, bool profile_guided,
Calin Juravle42451c02017-01-17 14:43:25 -08001082 bool is_public, int uid, bool is_secondary_dex) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001083 // Public apps should not be compiled with profile information ever. Same goes for the special
1084 // package '*' used for the system server.
Calin Juravle42451c02017-01-17 14:43:25 -08001085 // TODO(calin): add support for writing profiles for secondary dex files
1086 if (profile_guided && !is_secondary_dex && !is_public && (pkgname[0] != '*')) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001087 // Open reference profile in read only mode as dex2oat does not get write permissions.
1088 const std::string pkgname_str(pkgname);
Calin Juravle4a391f82017-01-14 16:23:30 -08001089 return Dex2oatFileWrapper(
1090 open_reference_profile(uid, pkgname, /*read_write*/ false),
1091 [pkgname_str]() {
1092 clear_reference_profile(pkgname_str.c_str());
1093 });
1094 } else {
1095 return Dex2oatFileWrapper();
Jeff Sharkey90aff262016-12-12 14:28:24 -07001096 }
Calin Juravle4a391f82017-01-14 16:23:30 -08001097}
Jeff Sharkey90aff262016-12-12 14:28:24 -07001098
Calin Juravle4a391f82017-01-14 16:23:30 -08001099// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
1100// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
1101bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
1102 const char* instruction_set, bool is_public, int uid,
1103 Dex2oatFileWrapper* in_vdex_wrapper_fd,
1104 Dex2oatFileWrapper* out_vdex_wrapper_fd) {
1105 CHECK(in_vdex_wrapper_fd != nullptr);
1106 CHECK(out_vdex_wrapper_fd != nullptr);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001107 // Open the existing VDEX. We do this before creating the new output VDEX, which will
1108 // unlink the old one.
Richard Uhler76cc0272016-12-08 10:46:35 +00001109 char in_odex_path[PKG_PATH_MAX];
1110 int dexopt_action = abs(dexopt_needed);
1111 bool is_odex_location = dexopt_needed < 0;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001112 std::string in_vdex_path_str;
Richard Uhler76cc0272016-12-08 10:46:35 +00001113 if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001114 // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
1115 const char* path = nullptr;
1116 if (is_odex_location) {
1117 if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
1118 path = in_odex_path;
1119 } else {
1120 ALOGE("installd cannot compute input vdex location for '%s'\n", apk_path);
Calin Juravle4a391f82017-01-14 16:23:30 -08001121 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001122 }
1123 } else {
1124 path = out_oat_path;
1125 }
1126 in_vdex_path_str = create_vdex_filename(path);
1127 if (in_vdex_path_str.empty()) {
1128 ALOGE("installd cannot compute input vdex location for '%s'\n", path);
Calin Juravle4a391f82017-01-14 16:23:30 -08001129 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001130 }
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001131 if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
1132 // When we dex2oat because iof boot image change, we are going to update
1133 // in-place the vdex file.
Calin Juravle4a391f82017-01-14 16:23:30 -08001134 in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001135 } else {
Calin Juravle4a391f82017-01-14 16:23:30 -08001136 in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001137 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001138 }
1139
1140 // Infer the name of the output VDEX and create it.
Calin Juravle4a391f82017-01-14 16:23:30 -08001141 const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001142 if (out_vdex_path_str.empty()) {
Calin Juravle4a391f82017-01-14 16:23:30 -08001143 return false;
Jeff Sharkey90aff262016-12-12 14:28:24 -07001144 }
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001145
1146 // If we are compiling because the boot image is out of date, we do not
1147 // need to recreate a vdex, and can use the same existing one.
1148 if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE &&
Calin Juravle4a391f82017-01-14 16:23:30 -08001149 in_vdex_wrapper_fd->get() != -1 &&
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001150 in_vdex_path_str == out_vdex_path_str) {
Calin Juravle4a391f82017-01-14 16:23:30 -08001151 out_vdex_wrapper_fd->reset(in_vdex_wrapper_fd->get());
1152 // Disable auto close for the in wrapper fd (it will be done when destructing the out
1153 // wrapper).
1154 in_vdex_wrapper_fd->DisableAutoClose();
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001155 } else {
Calin Juravle4a391f82017-01-14 16:23:30 -08001156 out_vdex_wrapper_fd->reset(
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001157 open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
1158 [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
Calin Juravle4a391f82017-01-14 16:23:30 -08001159 if (out_vdex_wrapper_fd->get() < 0) {
1160 ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
1161 return false;
Nicolas Geoffrayca122282016-12-20 15:03:56 +00001162 }
Jeff Sharkey90aff262016-12-12 14:28:24 -07001163 }
Calin Juravle4a391f82017-01-14 16:23:30 -08001164 if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
1165 out_vdex_path_str.c_str())) {
1166 ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
1167 return false;
1168 }
1169
1170 // If we got here we successfully opened the vdex files.
1171 return true;
1172}
1173
1174// Opens the output oat file for the given apk.
1175// If successful it stores the output path into out_oat_path and returns true.
1176Dex2oatFileWrapper open_oat_out_file(const char* apk_path, const char* oat_dir,
Calin Juravle42451c02017-01-17 14:43:25 -08001177 bool is_public, int uid, const char* instruction_set, bool is_secondary_dex,
1178 char* out_oat_path) {
1179 if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
Calin Juravle4a391f82017-01-14 16:23:30 -08001180 return Dex2oatFileWrapper();
1181 }
1182 const std::string out_oat_path_str(out_oat_path);
1183 Dex2oatFileWrapper wrapper_fd(
1184 open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
1185 [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
1186 if (wrapper_fd.get() < 0) {
Calin Juravle42451c02017-01-17 14:43:25 -08001187 PLOG(ERROR) << "installd cannot open output during dexopt" << out_oat_path;
Calin Juravle4a391f82017-01-14 16:23:30 -08001188 } else if (!set_permissions_and_ownership(wrapper_fd.get(), is_public, uid, out_oat_path)) {
1189 ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
1190 wrapper_fd.reset(-1);
1191 }
1192 return wrapper_fd;
1193}
1194
1195// Updates the access times of out_oat_path based on those from apk_path.
1196void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
1197 struct stat input_stat;
1198 memset(&input_stat, 0, sizeof(input_stat));
1199 if (stat(apk_path, &input_stat) != 0) {
1200 PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
1201 return;
1202 }
1203
1204 struct utimbuf ut;
1205 ut.actime = input_stat.st_atime;
1206 ut.modtime = input_stat.st_mtime;
1207 if (utime(out_oat_path, &ut) != 0) {
1208 PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
1209 }
1210}
1211
Calin Juravle42451c02017-01-17 14:43:25 -08001212// Runs (execv) dexoptanalyzer on the given arguments.
1213static void exec_dexoptanalyzer(const char* dex_file, const char* instruction_set,
1214 const char* compiler_filter) {
1215 static const char* DEXOPTANALYZER_BIN = "/system/bin/dexoptanalyzer";
1216 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
1217
1218 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
1219 ALOGE("Instruction set %s longer than max length of %d",
1220 instruction_set, MAX_INSTRUCTION_SET_LEN);
1221 return;
1222 }
1223
1224 char dex_file_arg[strlen("--dex-file=") + PKG_PATH_MAX];
1225 char isa_arg[strlen("--isa=") + MAX_INSTRUCTION_SET_LEN];
1226 char compiler_filter_arg[strlen("--compiler-filter=") + kPropertyValueMax];
1227
1228 sprintf(dex_file_arg, "--dex-file=%s", dex_file);
1229 sprintf(isa_arg, "--isa=%s", instruction_set);
1230 sprintf(compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
1231
1232 // program name, dex file, isa, filter, the final NULL
1233 const char* argv[5];
1234 int i = 0;
1235 argv[i++] = DEXOPTANALYZER_BIN;
1236 argv[i++] = dex_file_arg;
1237 argv[i++] = isa_arg;
1238 argv[i++] = compiler_filter_arg;
1239 argv[i] = NULL;
1240
1241 execv(DEXOPTANALYZER_BIN, (char * const *)argv);
1242 ALOGE("execv(%s) failed: %s\n", DEXOPTANALYZER_BIN, strerror(errno));
1243}
1244
1245// Prepares the oat dir for the secondary dex files.
1246static bool prepare_secondary_dex_oat_dir(const char* apk_path, int uid,
1247 const char* instruction_set, std::string* oat_dir_out) {
1248 std::string apk_path_str(apk_path);
1249 unsigned long dirIndex = apk_path_str.rfind('/');
1250 if (dirIndex == std::string::npos) {
1251 LOG(WARNING) << "Unexpected dir structure for secondary dex " << apk_path;
1252 return false;
1253 }
1254 std::string apk_dir = apk_path_str.substr(0, dirIndex);
1255
1256 // Assign the gid to the cache gid so that the oat file storage
1257 // is counted towards the app cache.
1258 int32_t cache_gid = multiuser_get_cache_gid(
1259 multiuser_get_user_id(uid), multiuser_get_app_id(uid));
1260 // If UID doesn't have a specific cache GID, use UID value
1261 if (cache_gid == -1) {
1262 cache_gid = uid;
1263 }
1264
1265 // Create oat file output directory.
1266 if (prepare_app_cache_dir(apk_dir, "oat", 02711, uid, cache_gid) != 0) {
1267 LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << apk_path;
1268 return false;
1269 }
1270
1271 char oat_dir[PKG_PATH_MAX];
1272 snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
1273 oat_dir_out->assign(oat_dir);
1274
1275 // Create oat/isa output directory.
1276 if (prepare_app_cache_dir(*oat_dir_out, instruction_set, 02711, uid, cache_gid) != 0) {
1277 LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << apk_path;
1278 return false;
1279 }
1280
1281 return true;
1282}
1283
1284static int constexpr DEXOPTANALYZER_BIN_EXEC_ERROR = 200;
1285
1286// Verifies the result of dexoptanalyzer executed for the apk_path.
1287// If the result is valid returns true and sets dexopt_needed_out to a valid value.
1288// Returns false for errors or unexpected result values.
1289static bool process_dexoptanalyzer_result(const char* apk_path, int result,
1290 int* dexopt_needed_out) {
1291 // The result values are defined in dexoptanalyzer.
1292 switch (result) {
1293 case 0: // no_dexopt_needed
1294 *dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
1295 case 1: // dex2oat_from_scratch
1296 *dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
1297 case 5: // dex2oat_for_bootimage_odex
1298 *dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
1299 case 6: // dex2oat_for_filter_odex
1300 *dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
1301 case 7: // dex2oat_for_relocation_odex
1302 *dexopt_needed_out = -DEX2OAT_FOR_RELOCATION; return true;
1303 case 2: // dex2oat_for_bootimage_oat
1304 case 3: // dex2oat_for_filter_oat
1305 case 4: // dex2oat_for_relocation_oat
1306 LOG(ERROR) << "Expected odex file status for secondary dex " << apk_path
1307 << " : dexoptanalyzer result=" << result;
1308 return false;
1309 default:
1310 LOG(ERROR) << "Unexpected result for dexoptanalyzer " << apk_path
1311 << " exec_dexoptanalyzer result=" << result;
1312 return false;
1313 }
1314}
1315
1316// Processes the apk_path as a secondary dex files and return true if the path dex file should
1317// be compiled. Returns false for errors (logged) or true if the secondary dex path was process
1318// successfully.
1319// When returning true, dexopt_needed_out is assigned a valid OatFileAsssitant::DexOptNeeded
1320// code and aot_dir_out is assigned the oat dir path where the oat file should be stored.
1321static bool process_secondary_dex_dexopt(const char* apk_path, const char* pkgname,
1322 int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
1323 const char* compiler_filter, int* dexopt_needed_out, std::string* aot_dir_out) {
1324 int storage_flag;
1325
1326 if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
1327 storage_flag = FLAG_STORAGE_CE;
1328 if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1329 LOG(ERROR) << "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
1330 return false;
1331 }
1332 } else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1333 storage_flag = FLAG_STORAGE_DE;
1334 } else {
1335 LOG(ERROR) << "Secondary dex storage flag must be set";
1336 return false;
1337 }
1338
1339 if (!validate_secondary_dex_path(pkgname, apk_path, volume_uuid, uid, storage_flag)) {
1340 LOG(ERROR) << "Could not validate secondary dex path " << apk_path;
1341 return false;
1342 }
1343
1344 // Check if the path exist. If not, there's nothing to do.
1345 if (access(apk_path, F_OK) != 0) {
1346 if (errno == ENOENT) {
1347 // Secondary dex files might be deleted any time by the app.
1348 // Nothing to do if that's the case
1349 ALOGV("Secondary dex does not exist %s", apk_path);
1350 return NO_DEXOPT_NEEDED;
1351 } else {
1352 PLOG(ERROR) << "Could not access secondary dex " << apk_path;
1353 }
1354 }
1355
1356 // Prepare the oat directories.
1357 if (!prepare_secondary_dex_oat_dir(apk_path, uid, instruction_set, aot_dir_out)) {
1358 return false;
1359 }
1360
1361 pid_t pid = fork();
1362 if (pid == 0) {
1363 // child -- drop privileges before continuing.
1364 drop_capabilities(uid);
1365 // Run dexoptanalyzer to get dexopt_needed code.
1366 exec_dexoptanalyzer(apk_path, instruction_set, compiler_filter);
1367 exit(DEXOPTANALYZER_BIN_EXEC_ERROR);
1368 }
1369
1370 /* parent */
1371
1372 int result = wait_child(pid);
1373 if (!WIFEXITED(result)) {
1374 LOG(ERROR) << "dexoptanalyzer failed for path " << apk_path << ": " << result;
1375 return false;
1376 }
1377 result = WEXITSTATUS(result);
1378 bool success = process_dexoptanalyzer_result(apk_path, result, dexopt_needed_out);
1379 // Run dexopt only if needed or forced.
1380 // Note that dexoptanalyzer is executed even if force compilation is enabled.
1381 // We ignore its valid dexopNeeded result, but still check (in process_dexoptanalyzer_result)
1382 // that we only get results for odex files (apk_dir/oat/isa/code.odex) and not
1383 // for oat files from dalvik-cache.
1384 if (success && ((dexopt_flags & DEXOPT_FORCE) != 0)) {
1385 *dexopt_needed_out = DEX2OAT_FROM_SCRATCH;
1386 }
1387
1388 return success;
1389}
1390
Calin Juravle4a391f82017-01-14 16:23:30 -08001391int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set,
Calin Juravle42451c02017-01-17 14:43:25 -08001392 int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
1393 const char* volume_uuid, const char* shared_libraries) {
Calin Juravle4a391f82017-01-14 16:23:30 -08001394 CHECK(pkgname != nullptr);
1395 CHECK(pkgname[0] != 0);
1396 if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
1397 LOG_FATAL("dexopt flags contains unknown fields\n");
1398 }
1399
1400 bool is_public = ((dexopt_flags & DEXOPT_PUBLIC) != 0);
1401 bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
1402 bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
1403 bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
1404 bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
Calin Juravle42451c02017-01-17 14:43:25 -08001405 bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
1406
1407 // Check if we're dealing with a secondary dex file and if we need to compile it.
1408 std::string oat_dir_str;
1409 if (is_secondary_dex) {
1410 if (process_secondary_dex_dexopt(apk_path, pkgname, dexopt_flags, volume_uuid, uid,
1411 instruction_set, compiler_filter, &dexopt_needed, &oat_dir_str)) {
1412 oat_dir = oat_dir_str.c_str();
1413 if (dexopt_needed == NO_DEXOPT_NEEDED) {
1414 return 0; // Nothing to do, report success.
1415 }
1416 } else {
1417 return -1; // We had an error, logged in the process method.
1418 }
1419 } else {
1420 // Verify that secondary dex files are not set.
1421 CHECK((dexopt_flags & DEXOPT_FORCE) == 0);
1422 CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0);
1423 CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0);
1424 }
Calin Juravle4a391f82017-01-14 16:23:30 -08001425
1426 // Open the input file.
1427 base::unique_fd input_fd(open(apk_path, O_RDONLY, 0));
1428 if (input_fd.get() < 0) {
1429 ALOGE("installd cannot open '%s' for input during dexopt\n", apk_path);
1430 return -1;
1431 }
1432
1433 // Create the output OAT file.
1434 char out_oat_path[PKG_PATH_MAX];
1435 Dex2oatFileWrapper out_oat_fd = open_oat_out_file(apk_path, oat_dir, is_public, uid,
Calin Juravle42451c02017-01-17 14:43:25 -08001436 instruction_set, is_secondary_dex, out_oat_path);
Calin Juravle4a391f82017-01-14 16:23:30 -08001437 if (out_oat_fd.get() < 0) {
1438 return -1;
1439 }
1440
1441 // Open vdex files.
1442 Dex2oatFileWrapper in_vdex_fd;
1443 Dex2oatFileWrapper out_vdex_fd;
1444 if (!open_vdex_files(apk_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
1445 &in_vdex_fd, &out_vdex_fd)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001446 return -1;
1447 }
1448
1449 // Create a swap file if necessary.
Calin Juravle4a391f82017-01-14 16:23:30 -08001450 base::unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001451
Calin Juravle4a391f82017-01-14 16:23:30 -08001452 // Create the app image file if needed.
1453 Dex2oatFileWrapper image_fd =
1454 maybe_open_app_image(out_oat_path, profile_guided, is_public, uid);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001455
Calin Juravle4a391f82017-01-14 16:23:30 -08001456 // Open the reference profile if needed.
1457 Dex2oatFileWrapper reference_profile_fd =
Calin Juravle42451c02017-01-17 14:43:25 -08001458 maybe_open_reference_profile(pkgname, profile_guided, is_public, uid, is_secondary_dex);
Calin Juravle4a391f82017-01-14 16:23:30 -08001459
1460 ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001461
1462 pid_t pid = fork();
1463 if (pid == 0) {
1464 /* child -- drop privileges before continuing */
1465 drop_capabilities(uid);
1466
Richard Uhler76cc0272016-12-08 10:46:35 +00001467 SetDex2OatScheduling(boot_complete);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001468 if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
1469 ALOGE("flock(%s) failed: %s\n", out_oat_path, strerror(errno));
1470 _exit(67);
1471 }
1472
Richard Uhler76cc0272016-12-08 10:46:35 +00001473 // Pass dex2oat the relative path to the input file.
Calin Juravle4a391f82017-01-14 16:23:30 -08001474 const char *input_file_name = get_location_from_path(apk_path);
Richard Uhler76cc0272016-12-08 10:46:35 +00001475 run_dex2oat(input_fd.get(),
1476 out_oat_fd.get(),
1477 in_vdex_fd.get(),
Calin Juravle4a391f82017-01-14 16:23:30 -08001478 out_vdex_fd.get(),
Richard Uhler76cc0272016-12-08 10:46:35 +00001479 image_fd.get(),
1480 input_file_name,
1481 out_oat_path,
1482 swap_fd.get(),
1483 instruction_set,
1484 compiler_filter,
1485 vm_safe_mode,
1486 debuggable,
1487 boot_complete,
1488 reference_profile_fd.get(),
1489 shared_libraries);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001490 _exit(68); /* only get here on exec failure */
1491 } else {
1492 int res = wait_child(pid);
1493 if (res == 0) {
Calin Juravle4a391f82017-01-14 16:23:30 -08001494 ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001495 } else {
Calin Juravle4a391f82017-01-14 16:23:30 -08001496 ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", apk_path, res);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001497 return -1;
1498 }
1499 }
1500
Calin Juravle4a391f82017-01-14 16:23:30 -08001501 update_out_oat_access_times(apk_path, out_oat_path);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001502
1503 // We've been successful, don't delete output.
1504 out_oat_fd.SetCleanup(false);
Calin Juravle4a391f82017-01-14 16:23:30 -08001505 out_vdex_fd.SetCleanup(false);
Jeff Sharkey90aff262016-12-12 14:28:24 -07001506 image_fd.SetCleanup(false);
1507 reference_profile_fd.SetCleanup(false);
1508
1509 return 0;
1510}
1511
1512// Helper for move_ab, so that we can have common failure-case cleanup.
1513static bool unlink_and_rename(const char* from, const char* to) {
1514 // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
1515 // return a failure.
1516 struct stat s;
1517 if (stat(to, &s) == 0) {
1518 if (!S_ISREG(s.st_mode)) {
1519 LOG(ERROR) << from << " is not a regular file to replace for A/B.";
1520 return false;
1521 }
1522 if (unlink(to) != 0) {
1523 LOG(ERROR) << "Could not unlink " << to << " to move A/B.";
1524 return false;
1525 }
1526 } else {
1527 // This may be a permission problem. We could investigate the error code, but we'll just
1528 // let the rename failure do the work for us.
1529 }
1530
1531 // Try to rename "to" to "from."
1532 if (rename(from, to) != 0) {
1533 PLOG(ERROR) << "Could not rename " << from << " to " << to;
1534 return false;
1535 }
1536 return true;
1537}
1538
1539// Move/rename a B artifact (from) to an A artifact (to).
1540static bool move_ab_path(const std::string& b_path, const std::string& a_path) {
1541 // Check whether B exists.
1542 {
1543 struct stat s;
1544 if (stat(b_path.c_str(), &s) != 0) {
1545 // Silently ignore for now. The service calling this isn't smart enough to understand
1546 // lack of artifacts at the moment.
1547 return false;
1548 }
1549 if (!S_ISREG(s.st_mode)) {
1550 LOG(ERROR) << "A/B artifact " << b_path << " is not a regular file.";
1551 // Try to unlink, but swallow errors.
1552 unlink(b_path.c_str());
1553 return false;
1554 }
1555 }
1556
1557 // Rename B to A.
1558 if (!unlink_and_rename(b_path.c_str(), a_path.c_str())) {
1559 // Delete the b_path so we don't try again (or fail earlier).
1560 if (unlink(b_path.c_str()) != 0) {
1561 PLOG(ERROR) << "Could not unlink " << b_path;
1562 }
1563
1564 return false;
1565 }
1566
1567 return true;
1568}
1569
1570bool move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
1571 // Get the current slot suffix. No suffix, no A/B.
1572 std::string slot_suffix;
1573 {
1574 char buf[kPropertyValueMax];
1575 if (get_property("ro.boot.slot_suffix", buf, nullptr) <= 0) {
1576 return false;
1577 }
1578 slot_suffix = buf;
1579
1580 if (!ValidateTargetSlotSuffix(slot_suffix)) {
1581 LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
1582 return false;
1583 }
1584 }
1585
1586 // Validate other inputs.
1587 if (validate_apk_path(apk_path) != 0) {
1588 LOG(ERROR) << "Invalid apk_path: " << apk_path;
1589 return false;
1590 }
1591 if (validate_apk_path(oat_dir) != 0) {
1592 LOG(ERROR) << "Invalid oat_dir: " << oat_dir;
1593 return false;
1594 }
1595
1596 char a_path[PKG_PATH_MAX];
1597 if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
1598 return false;
1599 }
1600 const std::string a_vdex_path = create_vdex_filename(a_path);
1601 const std::string a_image_path = create_image_filename(a_path);
1602
1603 // B path = A path + slot suffix.
1604 const std::string b_path = StringPrintf("%s.%s", a_path, slot_suffix.c_str());
1605 const std::string b_vdex_path = StringPrintf("%s.%s", a_vdex_path.c_str(), slot_suffix.c_str());
1606 const std::string b_image_path = StringPrintf("%s.%s",
1607 a_image_path.c_str(),
1608 slot_suffix.c_str());
1609
1610 bool success = true;
1611 if (move_ab_path(b_path, a_path)) {
1612 if (move_ab_path(b_vdex_path, a_vdex_path)) {
1613 // Note: we can live without an app image. As such, ignore failure to move the image file.
1614 // If we decide to require the app image, or the app image being moved correctly,
1615 // then change accordingly.
1616 constexpr bool kIgnoreAppImageFailure = true;
1617
1618 if (!a_image_path.empty()) {
1619 if (!move_ab_path(b_image_path, a_image_path)) {
1620 unlink(a_image_path.c_str());
1621 if (!kIgnoreAppImageFailure) {
1622 success = false;
1623 }
1624 }
1625 }
1626 } else {
1627 // Cleanup: delete B image, ignore errors.
1628 unlink(b_image_path.c_str());
1629 success = false;
1630 }
1631 } else {
1632 // Cleanup: delete B image, ignore errors.
1633 unlink(b_vdex_path.c_str());
1634 unlink(b_image_path.c_str());
1635 success = false;
1636 }
1637 return success;
1638}
1639
1640bool delete_odex(const char* apk_path, const char* instruction_set, const char* oat_dir) {
1641 // Delete the oat/odex file.
1642 char out_path[PKG_PATH_MAX];
Calin Juravle42451c02017-01-17 14:43:25 -08001643 if (!create_oat_out_path(apk_path, instruction_set, oat_dir,
1644 /*is_secondary_dex*/ false, out_path)) {
Jeff Sharkey90aff262016-12-12 14:28:24 -07001645 return false;
1646 }
1647
1648 // In case of a permission failure report the issue. Otherwise just print a warning.
1649 auto unlink_and_check = [](const char* path) -> bool {
1650 int result = unlink(path);
1651 if (result != 0) {
1652 if (errno == EACCES || errno == EPERM) {
1653 PLOG(ERROR) << "Could not unlink " << path;
1654 return false;
1655 }
1656 PLOG(WARNING) << "Could not unlink " << path;
1657 }
1658 return true;
1659 };
1660
1661 // Delete the oat/odex file.
1662 bool return_value_oat = unlink_and_check(out_path);
1663
1664 // Derive and delete the app image.
1665 bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
1666
1667 // Report success.
1668 return return_value_oat && return_value_art;
1669}
1670
Jeff Sharkey6c2c0562016-12-07 12:12:00 -07001671int dexopt(const char* const params[DEXOPT_PARAM_COUNT]) {
1672 return dexopt(params[0], // apk_path
1673 atoi(params[1]), // uid
1674 params[2], // pkgname
1675 params[3], // instruction_set
1676 atoi(params[4]), // dexopt_needed
1677 params[5], // oat_dir
1678 atoi(params[6]), // dexopt_flags
1679 params[7], // compiler_filter
1680 parse_null(params[8]), // volume_uuid
1681 parse_null(params[9])); // shared_libraries
1682 static_assert(DEXOPT_PARAM_COUNT == 10U, "Unexpected dexopt param count");
1683}
1684
1685} // namespace installd
1686} // namespace android