• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
16 #define LOG_TAG "installd"
17 
18 #include <array>
19 #include <fcntl.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/capability.h>
23 #include <sys/file.h>
24 #include <sys/stat.h>
25 #include <sys/time.h>
26 #include <sys/types.h>
27 #include <sys/resource.h>
28 #include <sys/wait.h>
29 #include <unistd.h>
30 
31 #include <iomanip>
32 
33 #include <android-base/file.h>
34 #include <android-base/logging.h>
35 #include <android-base/properties.h>
36 #include <android-base/stringprintf.h>
37 #include <android-base/strings.h>
38 #include <android-base/unique_fd.h>
39 #include <cutils/fs.h>
40 #include <cutils/properties.h>
41 #include <cutils/sched_policy.h>
42 #include <dex2oat_return_codes.h>
43 #include <log/log.h>               // TODO: Move everything to base/logging.
44 #include <openssl/sha.h>
45 #include <private/android_filesystem_config.h>
46 #include <processgroup/sched_policy.h>
47 #include <selinux/android.h>
48 #include <server_configurable_flags/get_flags.h>
49 #include <system/thread_defs.h>
50 
51 #include "dexopt.h"
52 #include "dexopt_return_codes.h"
53 #include "globals.h"
54 #include "installd_deps.h"
55 #include "otapreopt_utils.h"
56 #include "utils.h"
57 
58 using android::base::EndsWith;
59 using android::base::GetBoolProperty;
60 using android::base::GetProperty;
61 using android::base::ReadFdToString;
62 using android::base::ReadFully;
63 using android::base::StringPrintf;
64 using android::base::WriteFully;
65 using android::base::unique_fd;
66 
67 namespace android {
68 namespace installd {
69 
70 // Should minidebug info be included in compiled artifacts? Even if this value is
71 // "true," usage might still be conditional to other constraints, e.g., system
72 // property overrides.
73 static constexpr bool kEnableMinidebugInfo = true;
74 
75 static constexpr const char* kMinidebugInfoSystemProperty = "dalvik.vm.dex2oat-minidebuginfo";
76 static constexpr bool kMinidebugInfoSystemPropertyDefault = false;
77 static constexpr const char* kMinidebugDex2oatFlag = "--generate-mini-debug-info";
78 static constexpr const char* kDisableCompactDexFlag = "--compact-dex-level=none";
79 
80 
81 // Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
82 struct FreeDelete {
83   // NOTE: Deleting a const object is valid but free() takes a non-const pointer.
operator ()android::installd::FreeDelete84   void operator()(const void* ptr) const {
85     free(const_cast<void*>(ptr));
86   }
87 };
88 
89 // Alias for std::unique_ptr<> that uses the C function free() to delete objects.
90 template <typename T>
91 using UniqueCPtr = std::unique_ptr<T, FreeDelete>;
92 
invalid_unique_fd()93 static unique_fd invalid_unique_fd() {
94     return unique_fd(-1);
95 }
96 
is_debug_runtime()97 static bool is_debug_runtime() {
98     return android::base::GetProperty("persist.sys.dalvik.vm.lib.2", "") == "libartd.so";
99 }
100 
is_debuggable_build()101 static bool is_debuggable_build() {
102     return android::base::GetBoolProperty("ro.debuggable", false);
103 }
104 
clear_profile(const std::string & profile)105 static bool clear_profile(const std::string& profile) {
106     unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
107     if (ufd.get() < 0) {
108         if (errno != ENOENT) {
109             PLOG(WARNING) << "Could not open profile " << profile;
110             return false;
111         } else {
112             // Nothing to clear. That's ok.
113             return true;
114         }
115     }
116 
117     if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
118         if (errno != EWOULDBLOCK) {
119             PLOG(WARNING) << "Error locking profile " << profile;
120         }
121         // This implies that the app owning this profile is running
122         // (and has acquired the lock).
123         //
124         // If we can't acquire the lock bail out since clearing is useless anyway
125         // (the app will write again to the profile).
126         //
127         // Note:
128         // This does not impact the this is not an issue for the profiling correctness.
129         // In case this is needed because of an app upgrade, profiles will still be
130         // eventually cleared by the app itself due to checksum mismatch.
131         // If this is needed because profman advised, then keeping the data around
132         // until the next run is again not an issue.
133         //
134         // If the app attempts to acquire a lock while we've held one here,
135         // it will simply skip the current write cycle.
136         return false;
137     }
138 
139     bool truncated = ftruncate(ufd.get(), 0) == 0;
140     if (!truncated) {
141         PLOG(WARNING) << "Could not truncate " << profile;
142     }
143     if (flock(ufd.get(), LOCK_UN) != 0) {
144         PLOG(WARNING) << "Error unlocking profile " << profile;
145     }
146     return truncated;
147 }
148 
149 // Clear the reference profile for the given location.
150 // The location is the profile name for primary apks or the dex path for secondary dex files.
clear_reference_profile(const std::string & package_name,const std::string & location,bool is_secondary_dex)151 static bool clear_reference_profile(const std::string& package_name, const std::string& location,
152         bool is_secondary_dex) {
153     return clear_profile(create_reference_profile_path(package_name, location, is_secondary_dex));
154 }
155 
156 // Clear the reference profile for the given location.
157 // The location is the profile name for primary apks or the dex path for secondary dex files.
clear_current_profile(const std::string & package_name,const std::string & location,userid_t user,bool is_secondary_dex)158 static bool clear_current_profile(const std::string& package_name, const std::string& location,
159         userid_t user, bool is_secondary_dex) {
160     return clear_profile(create_current_profile_path(user, package_name, location,
161             is_secondary_dex));
162 }
163 
164 // Clear the reference profile for the primary apk of the given package.
165 // The location is the profile name for primary apks or the dex path for secondary dex files.
clear_primary_reference_profile(const std::string & package_name,const std::string & location)166 bool clear_primary_reference_profile(const std::string& package_name,
167         const std::string& location) {
168     return clear_reference_profile(package_name, location, /*is_secondary_dex*/false);
169 }
170 
171 // Clear all current profile for the primary apk of the given package.
172 // The location is the profile name for primary apks or the dex path for secondary dex files.
clear_primary_current_profiles(const std::string & package_name,const std::string & location)173 bool clear_primary_current_profiles(const std::string& package_name, const std::string& location) {
174     bool success = true;
175     // For secondary dex files, we don't really need the user but we use it for sanity checks.
176     std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
177     for (auto user : users) {
178         success &= clear_current_profile(package_name, location, user, /*is_secondary_dex*/false);
179     }
180     return success;
181 }
182 
183 // Clear the current profile for the primary apk of the given package and user.
clear_primary_current_profile(const std::string & package_name,const std::string & location,userid_t user)184 bool clear_primary_current_profile(const std::string& package_name, const std::string& location,
185         userid_t user) {
186     return clear_current_profile(package_name, location, user, /*is_secondary_dex*/false);
187 }
188 
SplitBySpaces(const std::string & str)189 static std::vector<std::string> SplitBySpaces(const std::string& str) {
190     if (str.empty()) {
191         return {};
192     }
193     return android::base::Split(str, " ");
194 }
195 
get_location_from_path(const char * path)196 static const char* get_location_from_path(const char* path) {
197     static constexpr char kLocationSeparator = '/';
198     const char *location = strrchr(path, kLocationSeparator);
199     if (location == nullptr) {
200         return path;
201     } else {
202         // Skip the separator character.
203         return location + 1;
204     }
205 }
206 
207 // ExecVHelper prepares and holds pointers to parsed command line arguments so that no allocations
208 // need to be performed between the fork and exec.
209 class ExecVHelper {
210   public:
211     // Store a placeholder for the binary name.
ExecVHelper()212     ExecVHelper() : args_(1u, std::string()) {}
213 
PrepareArgs(const std::string & bin)214     void PrepareArgs(const std::string& bin) {
215         CHECK(!args_.empty());
216         CHECK(args_[0].empty());
217         args_[0] = bin;
218         // Write char* into array.
219         for (const std::string& arg : args_) {
220             argv_.push_back(arg.c_str());
221         }
222         argv_.push_back(nullptr);  // Add null terminator.
223     }
224 
225     [[ noreturn ]]
Exec(int exit_code)226     void Exec(int exit_code) {
227         execv(argv_[0], (char * const *)&argv_[0]);
228         PLOG(ERROR) << "execv(" << argv_[0] << ") failed";
229         exit(exit_code);
230     }
231 
232     // Add an arg if it's not empty.
AddArg(const std::string & arg)233     void AddArg(const std::string& arg) {
234         if (!arg.empty()) {
235             args_.push_back(arg);
236         }
237     }
238 
239     // Add a runtime arg if it's not empty.
AddRuntimeArg(const std::string & arg)240     void AddRuntimeArg(const std::string& arg) {
241         if (!arg.empty()) {
242             args_.push_back("--runtime-arg");
243             args_.push_back(arg);
244         }
245     }
246 
247   protected:
248     // Holder arrays for backing arg storage.
249     std::vector<std::string> args_;
250 
251     // Argument poiners.
252     std::vector<const char*> argv_;
253 };
254 
MapPropertyToArg(const std::string & property,const std::string & format,const std::string & default_value="")255 static std::string MapPropertyToArg(const std::string& property,
256                                     const std::string& format,
257                                     const std::string& default_value = "") {
258   std::string prop = GetProperty(property, default_value);
259   if (!prop.empty()) {
260     return StringPrintf(format.c_str(), prop.c_str());
261   }
262   return "";
263 }
264 
265 // Determines which binary we should use for execution (the debug or non-debug version).
266 // e.g. dex2oatd vs dex2oat
select_execution_binary(const char * binary,const char * debug_binary,bool background_job_compile)267 static const char* select_execution_binary(const char* binary, const char* debug_binary,
268         bool background_job_compile) {
269     return select_execution_binary(
270         binary,
271         debug_binary,
272         background_job_compile,
273         is_debug_runtime(),
274         (android::base::GetProperty("ro.build.version.codename", "") == "REL"),
275         is_debuggable_build());
276 }
277 
278 // Determines which binary we should use for execution (the debug or non-debug version).
279 // e.g. dex2oatd vs dex2oat
280 // This is convenient method which is much easier to test because it doesn't read
281 // system properties.
select_execution_binary(const char * binary,const char * debug_binary,bool background_job_compile,bool is_debug_runtime,bool is_release,bool is_debuggable_build)282 const char* select_execution_binary(
283         const char* binary,
284         const char* debug_binary,
285         bool background_job_compile,
286         bool is_debug_runtime,
287         bool is_release,
288         bool is_debuggable_build) {
289     // Do not use debug binaries for release candidates (to give more soak time).
290     bool is_debug_bg_job = background_job_compile && is_debuggable_build && !is_release;
291 
292     // If the runtime was requested to use libartd.so, we'll run the debug version - assuming
293     // the file is present (it may not be on images with very little space available).
294     bool useDebug = (is_debug_runtime || is_debug_bg_job) && (access(debug_binary, X_OK) == 0);
295 
296     return useDebug ? debug_binary : binary;
297 }
298 
299 // Namespace for Android Runtime flags applied during boot time.
300 static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot";
301 // Feature flag name for running the JIT in Zygote experiment, b/119800099.
302 static const char* ENABLE_APEX_IMAGE = "enable_apex_image";
303 // Location of the apex image.
304 static const char* kApexImage = "/system/framework/apex.art";
305 
306 class RunDex2Oat : public ExecVHelper {
307   public:
RunDex2Oat(int zip_fd,int oat_fd,int input_vdex_fd,int output_vdex_fd,int image_fd,const char * input_file_name,const char * output_file_name,int swap_fd,const char * instruction_set,const char * compiler_filter,bool debuggable,bool post_bootcomplete,bool background_job_compile,int profile_fd,const char * class_loader_context,const std::string & class_loader_context_fds,int target_sdk_version,bool enable_hidden_api_checks,bool generate_compact_dex,int dex_metadata_fd,const char * compilation_reason)308     RunDex2Oat(int zip_fd,
309                int oat_fd,
310                int input_vdex_fd,
311                int output_vdex_fd,
312                int image_fd,
313                const char* input_file_name,
314                const char* output_file_name,
315                int swap_fd,
316                const char* instruction_set,
317                const char* compiler_filter,
318                bool debuggable,
319                bool post_bootcomplete,
320                bool background_job_compile,
321                int profile_fd,
322                const char* class_loader_context,
323                const std::string& class_loader_context_fds,
324                int target_sdk_version,
325                bool enable_hidden_api_checks,
326                bool generate_compact_dex,
327                int dex_metadata_fd,
328                const char* compilation_reason) {
329         // Get the relative path to the input file.
330         const char* relative_input_file_name = get_location_from_path(input_file_name);
331 
332         std::string dex2oat_Xms_arg = MapPropertyToArg("dalvik.vm.dex2oat-Xms", "-Xms%s");
333         std::string dex2oat_Xmx_arg = MapPropertyToArg("dalvik.vm.dex2oat-Xmx", "-Xmx%s");
334 
335         const char* threads_property = post_bootcomplete
336                 ? "dalvik.vm.dex2oat-threads"
337                 : "dalvik.vm.boot-dex2oat-threads";
338         std::string dex2oat_threads_arg = MapPropertyToArg(threads_property, "-j%s");
339 
340         std::string bootclasspath;
341         char* dex2oat_bootclasspath = getenv("DEX2OATBOOTCLASSPATH");
342         if (dex2oat_bootclasspath != nullptr) {
343             bootclasspath = StringPrintf("-Xbootclasspath:%s", dex2oat_bootclasspath);
344         }
345         // If DEX2OATBOOTCLASSPATH is not in the environment, dex2oat is going to query
346         // BOOTCLASSPATH.
347 
348         const std::string dex2oat_isa_features_key =
349                 StringPrintf("dalvik.vm.isa.%s.features", instruction_set);
350         std::string instruction_set_features_arg =
351             MapPropertyToArg(dex2oat_isa_features_key, "--instruction-set-features=%s");
352 
353         const std::string dex2oat_isa_variant_key =
354                 StringPrintf("dalvik.vm.isa.%s.variant", instruction_set);
355         std::string instruction_set_variant_arg =
356             MapPropertyToArg(dex2oat_isa_variant_key, "--instruction-set-variant=%s");
357 
358         const char* dex2oat_norelocation = "-Xnorelocate";
359 
360         const std::string dex2oat_flags = GetProperty("dalvik.vm.dex2oat-flags", "");
361         std::vector<std::string> dex2oat_flags_args = SplitBySpaces(dex2oat_flags);
362         ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags.c_str());
363 
364         // If we are booting without the real /data, don't spend time compiling.
365         std::string vold_decrypt = GetProperty("vold.decrypt", "");
366         bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" ||
367                                 vold_decrypt == "1";
368 
369         std::string resolve_startup_string_arg =
370                 MapPropertyToArg("persist.device_config.runtime.dex2oat_resolve_startup_strings",
371                                  "--resolve-startup-const-strings=%s");
372         if (resolve_startup_string_arg.empty()) {
373           // If empty, fall back to system property.
374           resolve_startup_string_arg =
375                 MapPropertyToArg("dalvik.vm.dex2oat-resolve-startup-strings",
376                                  "--resolve-startup-const-strings=%s");
377         }
378 
379         const std::string image_block_size_arg =
380                 MapPropertyToArg("dalvik.vm.dex2oat-max-image-block-size",
381                                  "--max-image-block-size=%s");
382 
383         const bool generate_debug_info = GetBoolProperty("debug.generate-debug-info", false);
384 
385         std::string image_format_arg;
386         if (image_fd >= 0) {
387             image_format_arg = MapPropertyToArg("dalvik.vm.appimageformat", "--image-format=%s");
388         }
389 
390         std::string dex2oat_large_app_threshold_arg =
391             MapPropertyToArg("dalvik.vm.dex2oat-very-large", "--very-large-app-threshold=%s");
392 
393 
394         const char* dex2oat_bin = select_execution_binary(
395             kDex2oatPath, kDex2oatDebugPath, background_job_compile);
396 
397         bool generate_minidebug_info = kEnableMinidebugInfo &&
398                 GetBoolProperty(kMinidebugInfoSystemProperty, kMinidebugInfoSystemPropertyDefault);
399 
400         std::string boot_image;
401         std::string use_apex_image =
402             server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,
403                                                                  ENABLE_APEX_IMAGE,
404                                                                  /*default_value=*/ "");
405         if (use_apex_image == "true") {
406           boot_image = StringPrintf("-Ximage:%s", kApexImage);
407         } else {
408           boot_image = MapPropertyToArg("dalvik.vm.boot-image", "-Ximage:%s");
409         }
410 
411         // clang FORTIFY doesn't let us use strlen in constant array bounds, so we
412         // use arraysize instead.
413         std::string zip_fd_arg = StringPrintf("--zip-fd=%d", zip_fd);
414         std::string zip_location_arg = StringPrintf("--zip-location=%s", relative_input_file_name);
415         std::string input_vdex_fd_arg = StringPrintf("--input-vdex-fd=%d", input_vdex_fd);
416         std::string output_vdex_fd_arg = StringPrintf("--output-vdex-fd=%d", output_vdex_fd);
417         std::string oat_fd_arg = StringPrintf("--oat-fd=%d", oat_fd);
418         std::string oat_location_arg = StringPrintf("--oat-location=%s", output_file_name);
419         std::string instruction_set_arg = StringPrintf("--instruction-set=%s", instruction_set);
420         std::string dex2oat_compiler_filter_arg;
421         std::string dex2oat_swap_fd;
422         std::string dex2oat_image_fd;
423         std::string target_sdk_version_arg;
424         if (target_sdk_version != 0) {
425             target_sdk_version_arg = StringPrintf("-Xtarget-sdk-version:%d", target_sdk_version);
426         }
427         std::string class_loader_context_arg;
428         std::string class_loader_context_fds_arg;
429         if (class_loader_context != nullptr) {
430             class_loader_context_arg = StringPrintf("--class-loader-context=%s",
431                                                     class_loader_context);
432             if (!class_loader_context_fds.empty()) {
433                 class_loader_context_fds_arg = StringPrintf("--class-loader-context-fds=%s",
434                                                             class_loader_context_fds.c_str());
435             }
436         }
437 
438         if (swap_fd >= 0) {
439             dex2oat_swap_fd = StringPrintf("--swap-fd=%d", swap_fd);
440         }
441         if (image_fd >= 0) {
442             dex2oat_image_fd = StringPrintf("--app-image-fd=%d", image_fd);
443         }
444 
445         // Compute compiler filter.
446         bool have_dex2oat_relocation_skip_flag = false;
447         if (skip_compilation) {
448             dex2oat_compiler_filter_arg = "--compiler-filter=extract";
449             have_dex2oat_relocation_skip_flag = true;
450         } else if (compiler_filter != nullptr) {
451             dex2oat_compiler_filter_arg = StringPrintf("--compiler-filter=%s", compiler_filter);
452         }
453 
454         if (dex2oat_compiler_filter_arg.empty()) {
455             dex2oat_compiler_filter_arg = MapPropertyToArg("dalvik.vm.dex2oat-filter",
456                                                            "--compiler-filter=%s");
457         }
458 
459         // Check whether all apps should be compiled debuggable.
460         if (!debuggable) {
461             debuggable = GetProperty("dalvik.vm.always_debuggable", "") == "1";
462         }
463         std::string profile_arg;
464         if (profile_fd != -1) {
465             profile_arg = StringPrintf("--profile-file-fd=%d", profile_fd);
466         }
467 
468         // Get the directory of the apk to pass as a base classpath directory.
469         std::string base_dir;
470         std::string apk_dir(input_file_name);
471         unsigned long dir_index = apk_dir.rfind('/');
472         bool has_base_dir = dir_index != std::string::npos;
473         if (has_base_dir) {
474             apk_dir = apk_dir.substr(0, dir_index);
475             base_dir = StringPrintf("--classpath-dir=%s", apk_dir.c_str());
476         }
477 
478         std::string dex_metadata_fd_arg = "--dm-fd=" + std::to_string(dex_metadata_fd);
479 
480         std::string compilation_reason_arg = compilation_reason == nullptr
481                 ? ""
482                 : std::string("--compilation-reason=") + compilation_reason;
483 
484         ALOGV("Running %s in=%s out=%s\n", dex2oat_bin, relative_input_file_name, output_file_name);
485 
486         // Disable cdex if update input vdex is true since this combination of options is not
487         // supported.
488         const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd);
489 
490         AddArg(zip_fd_arg);
491         AddArg(zip_location_arg);
492         AddArg(input_vdex_fd_arg);
493         AddArg(output_vdex_fd_arg);
494         AddArg(oat_fd_arg);
495         AddArg(oat_location_arg);
496         AddArg(instruction_set_arg);
497 
498         AddArg(instruction_set_variant_arg);
499         AddArg(instruction_set_features_arg);
500 
501         AddRuntimeArg(boot_image);
502         AddRuntimeArg(bootclasspath);
503         AddRuntimeArg(dex2oat_Xms_arg);
504         AddRuntimeArg(dex2oat_Xmx_arg);
505 
506         AddArg(resolve_startup_string_arg);
507         AddArg(image_block_size_arg);
508         AddArg(dex2oat_compiler_filter_arg);
509         AddArg(dex2oat_threads_arg);
510         AddArg(dex2oat_swap_fd);
511         AddArg(dex2oat_image_fd);
512 
513         if (generate_debug_info) {
514             AddArg("--generate-debug-info");
515         }
516         if (debuggable) {
517             AddArg("--debuggable");
518         }
519         AddArg(image_format_arg);
520         AddArg(dex2oat_large_app_threshold_arg);
521 
522         if (have_dex2oat_relocation_skip_flag) {
523             AddRuntimeArg(dex2oat_norelocation);
524         }
525         AddArg(profile_arg);
526         AddArg(base_dir);
527         AddArg(class_loader_context_arg);
528         AddArg(class_loader_context_fds_arg);
529         if (generate_minidebug_info) {
530             AddArg(kMinidebugDex2oatFlag);
531         }
532         if (disable_cdex) {
533             AddArg(kDisableCompactDexFlag);
534         }
535         AddRuntimeArg(target_sdk_version_arg);
536         if (enable_hidden_api_checks) {
537             AddRuntimeArg("-Xhidden-api-policy:enabled");
538         }
539 
540         if (dex_metadata_fd > -1) {
541             AddArg(dex_metadata_fd_arg);
542         }
543 
544         AddArg(compilation_reason_arg);
545 
546         // Do not add args after dex2oat_flags, they should override others for debugging.
547         args_.insert(args_.end(), dex2oat_flags_args.begin(), dex2oat_flags_args.end());
548 
549         PrepareArgs(dex2oat_bin);
550     }
551 };
552 
553 /*
554  * Whether dexopt should use a swap file when compiling an APK.
555  *
556  * If kAlwaysProvideSwapFile, do this on all devices (dex2oat will make a more informed decision
557  * itself, anyways).
558  *
559  * Otherwise, read "dalvik.vm.dex2oat-swap". If the property exists, return whether it is "true".
560  *
561  * Otherwise, return true if this is a low-mem device.
562  *
563  * Otherwise, return default value.
564  */
565 static bool kAlwaysProvideSwapFile = false;
566 static bool kDefaultProvideSwapFile = true;
567 
ShouldUseSwapFileForDexopt()568 static bool ShouldUseSwapFileForDexopt() {
569     if (kAlwaysProvideSwapFile) {
570         return true;
571     }
572 
573     // Check the "override" property. If it exists, return value == "true".
574     std::string dex2oat_prop_buf = GetProperty("dalvik.vm.dex2oat-swap", "");
575     if (!dex2oat_prop_buf.empty()) {
576         return dex2oat_prop_buf == "true";
577     }
578 
579     // Shortcut for default value. This is an implementation optimization for the process sketched
580     // above. If the default value is true, we can avoid to check whether this is a low-mem device,
581     // as low-mem is never returning false. The compiler will optimize this away if it can.
582     if (kDefaultProvideSwapFile) {
583         return true;
584     }
585 
586     if (GetBoolProperty("ro.config.low_ram", false)) {
587         return true;
588     }
589 
590     // Default value must be false here.
591     return kDefaultProvideSwapFile;
592 }
593 
SetDex2OatScheduling(bool set_to_bg)594 static void SetDex2OatScheduling(bool set_to_bg) {
595     if (set_to_bg) {
596         if (set_sched_policy(0, SP_BACKGROUND) < 0) {
597             PLOG(ERROR) << "set_sched_policy failed";
598             exit(DexoptReturnCodes::kSetSchedPolicy);
599         }
600         if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
601             PLOG(ERROR) << "setpriority failed";
602             exit(DexoptReturnCodes::kSetPriority);
603         }
604     }
605 }
606 
create_profile(uid_t uid,const std::string & profile,int32_t flags)607 static unique_fd create_profile(uid_t uid, const std::string& profile, int32_t flags) {
608     unique_fd fd(TEMP_FAILURE_RETRY(open(profile.c_str(), flags, 0600)));
609     if (fd.get() < 0) {
610         if (errno != EEXIST) {
611             PLOG(ERROR) << "Failed to create profile " << profile;
612             return invalid_unique_fd();
613         }
614     }
615     // Profiles should belong to the app; make sure of that by giving ownership to
616     // the app uid. If we cannot do that, there's no point in returning the fd
617     // since dex2oat/profman will fail with SElinux denials.
618     if (fchown(fd.get(), uid, uid) < 0) {
619         PLOG(ERROR) << "Could not chown profile " << profile;
620         return invalid_unique_fd();
621     }
622     return fd;
623 }
624 
open_profile(uid_t uid,const std::string & profile,int32_t flags)625 static unique_fd open_profile(uid_t uid, const std::string& profile, int32_t flags) {
626     // Do not follow symlinks when opening a profile:
627     //   - primary profiles should not contain symlinks in their paths
628     //   - secondary dex paths should have been already resolved and validated
629     flags |= O_NOFOLLOW;
630 
631     // Check if we need to create the profile
632     // Reference profiles and snapshots are created on the fly; so they might not exist beforehand.
633     unique_fd fd;
634     if ((flags & O_CREAT) != 0) {
635         fd = create_profile(uid, profile, flags);
636     } else {
637         fd.reset(TEMP_FAILURE_RETRY(open(profile.c_str(), flags)));
638     }
639 
640     if (fd.get() < 0) {
641         if (errno != ENOENT) {
642             // Profiles might be missing for various reasons. For example, in a
643             // multi-user environment, the profile directory for one user can be created
644             // after we start a merge. In this case the current profile for that user
645             // will not be found.
646             // Also, the secondary dex profiles might be deleted by the app at any time,
647             // so we can't we need to prepare if they are missing.
648             PLOG(ERROR) << "Failed to open profile " << profile;
649         }
650         return invalid_unique_fd();
651     }
652 
653     return fd;
654 }
655 
open_current_profile(uid_t uid,userid_t user,const std::string & package_name,const std::string & location,bool is_secondary_dex)656 static unique_fd open_current_profile(uid_t uid, userid_t user, const std::string& package_name,
657         const std::string& location, bool is_secondary_dex) {
658     std::string profile = create_current_profile_path(user, package_name, location,
659             is_secondary_dex);
660     return open_profile(uid, profile, O_RDONLY);
661 }
662 
open_reference_profile(uid_t uid,const std::string & package_name,const std::string & location,bool read_write,bool is_secondary_dex)663 static unique_fd open_reference_profile(uid_t uid, const std::string& package_name,
664         const std::string& location, bool read_write, bool is_secondary_dex) {
665     std::string profile = create_reference_profile_path(package_name, location, is_secondary_dex);
666     return open_profile(uid, profile, read_write ? (O_CREAT | O_RDWR) : O_RDONLY);
667 }
668 
open_spnashot_profile(uid_t uid,const std::string & package_name,const std::string & location)669 static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name,
670         const std::string& location) {
671     std::string profile = create_snapshot_profile_path(package_name, location);
672     return open_profile(uid, profile, O_CREAT | O_RDWR | O_TRUNC);
673 }
674 
open_profile_files(uid_t uid,const std::string & package_name,const std::string & location,bool is_secondary_dex,std::vector<unique_fd> * profiles_fd,unique_fd * reference_profile_fd)675 static void open_profile_files(uid_t uid, const std::string& package_name,
676             const std::string& location, bool is_secondary_dex,
677             /*out*/ std::vector<unique_fd>* profiles_fd, /*out*/ unique_fd* reference_profile_fd) {
678     // Open the reference profile in read-write mode as profman might need to save the merge.
679     *reference_profile_fd = open_reference_profile(uid, package_name, location,
680             /*read_write*/ true, is_secondary_dex);
681 
682     // For secondary dex files, we don't really need the user but we use it for sanity checks.
683     // Note: the user owning the dex file should be the current user.
684     std::vector<userid_t> users;
685     if (is_secondary_dex){
686         users.push_back(multiuser_get_user_id(uid));
687     } else {
688         users = get_known_users(/*volume_uuid*/ nullptr);
689     }
690     for (auto user : users) {
691         unique_fd profile_fd = open_current_profile(uid, user, package_name, location,
692                 is_secondary_dex);
693         // Add to the lists only if both fds are valid.
694         if (profile_fd.get() >= 0) {
695             profiles_fd->push_back(std::move(profile_fd));
696         }
697     }
698 }
699 
700 static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
701 static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
702 static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
703 static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
704 static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
705 
706 class RunProfman : public ExecVHelper {
707   public:
SetupArgs(const std::vector<unique_fd> & profile_fds,const unique_fd & reference_profile_fd,const std::vector<unique_fd> & apk_fds,const std::vector<std::string> & dex_locations,bool copy_and_update,bool store_aggregation_counters)708    void SetupArgs(const std::vector<unique_fd>& profile_fds,
709                   const unique_fd& reference_profile_fd,
710                   const std::vector<unique_fd>& apk_fds,
711                   const std::vector<std::string>& dex_locations,
712                   bool copy_and_update,
713                   bool store_aggregation_counters) {
714 
715         // TODO(calin): Assume for now we run in the bg compile job (which is in
716         // most of the invocation). With the current data flow, is not very easy or
717         // clean to discover this in RunProfman (it will require quite a messy refactoring).
718         const char* profman_bin = select_execution_binary(
719             kProfmanPath, kProfmanDebugPath, /*background_job_compile=*/ true);
720 
721         if (copy_and_update) {
722             CHECK_EQ(1u, profile_fds.size());
723             CHECK_EQ(1u, apk_fds.size());
724         }
725         if (reference_profile_fd != -1) {
726             AddArg("--reference-profile-file-fd=" + std::to_string(reference_profile_fd.get()));
727         }
728 
729         for (const unique_fd& fd : profile_fds) {
730             AddArg("--profile-file-fd=" + std::to_string(fd.get()));
731         }
732 
733         for (const unique_fd& fd : apk_fds) {
734             AddArg("--apk-fd=" + std::to_string(fd.get()));
735         }
736 
737         for (const std::string& dex_location : dex_locations) {
738             AddArg("--dex-location=" + dex_location);
739         }
740 
741         if (copy_and_update) {
742             AddArg("--copy-and-update-profile-key");
743         }
744 
745         if (store_aggregation_counters) {
746             AddArg("--store-aggregation-counters");
747         }
748 
749         // Do not add after dex2oat_flags, they should override others for debugging.
750         PrepareArgs(profman_bin);
751     }
752 
SetupMerge(const std::vector<unique_fd> & profiles_fd,const unique_fd & reference_profile_fd,const std::vector<unique_fd> & apk_fds=std::vector<unique_fd> (),const std::vector<std::string> & dex_locations=std::vector<std::string> (),bool store_aggregation_counters=false)753     void SetupMerge(const std::vector<unique_fd>& profiles_fd,
754                     const unique_fd& reference_profile_fd,
755                     const std::vector<unique_fd>& apk_fds = std::vector<unique_fd>(),
756                     const std::vector<std::string>& dex_locations = std::vector<std::string>(),
757                     bool store_aggregation_counters = false) {
758         SetupArgs(profiles_fd,
759                   reference_profile_fd,
760                   apk_fds,
761                   dex_locations,
762                   /*copy_and_update=*/false,
763                   store_aggregation_counters);
764     }
765 
SetupCopyAndUpdate(unique_fd && profile_fd,unique_fd && reference_profile_fd,unique_fd && apk_fd,const std::string & dex_location)766     void SetupCopyAndUpdate(unique_fd&& profile_fd,
767                             unique_fd&& reference_profile_fd,
768                             unique_fd&& apk_fd,
769                             const std::string& dex_location) {
770         // The fds need to stay open longer than the scope of the function, so put them into a local
771         // variable vector.
772         profiles_fd_.push_back(std::move(profile_fd));
773         apk_fds_.push_back(std::move(apk_fd));
774         reference_profile_fd_ = std::move(reference_profile_fd);
775         std::vector<std::string> dex_locations = {dex_location};
776         SetupArgs(profiles_fd_,
777                   reference_profile_fd_,
778                   apk_fds_,
779                   dex_locations,
780                   /*copy_and_update=*/true,
781                   /*store_aggregation_counters=*/false);
782     }
783 
SetupDump(const std::vector<unique_fd> & profiles_fd,const unique_fd & reference_profile_fd,const std::vector<std::string> & dex_locations,const std::vector<unique_fd> & apk_fds,const unique_fd & output_fd)784     void SetupDump(const std::vector<unique_fd>& profiles_fd,
785                    const unique_fd& reference_profile_fd,
786                    const std::vector<std::string>& dex_locations,
787                    const std::vector<unique_fd>& apk_fds,
788                    const unique_fd& output_fd) {
789         AddArg("--dump-only");
790         AddArg(StringPrintf("--dump-output-to-fd=%d", output_fd.get()));
791         SetupArgs(profiles_fd,
792                   reference_profile_fd,
793                   apk_fds,
794                   dex_locations,
795                   /*copy_and_update=*/false,
796                   /*store_aggregation_counters=*/false);
797     }
798 
Exec()799     void Exec() {
800         ExecVHelper::Exec(DexoptReturnCodes::kProfmanExec);
801     }
802 
803   private:
804     unique_fd reference_profile_fd_;
805     std::vector<unique_fd> profiles_fd_;
806     std::vector<unique_fd> apk_fds_;
807 };
808 
809 
810 
811 // Decides if profile guided compilation is needed or not based on existing profiles.
812 // The location is the package name for primary apks or the dex path for secondary dex files.
813 // Returns true if there is enough information in the current profiles that makes it
814 // worth to recompile the given location.
815 // If the return value is true all the current profiles would have been merged into
816 // the reference profiles accessible with open_reference_profile().
analyze_profiles(uid_t uid,const std::string & package_name,const std::string & location,bool is_secondary_dex)817 static bool analyze_profiles(uid_t uid, const std::string& package_name,
818         const std::string& location, bool is_secondary_dex) {
819     std::vector<unique_fd> profiles_fd;
820     unique_fd reference_profile_fd;
821     open_profile_files(uid, package_name, location, is_secondary_dex,
822         &profiles_fd, &reference_profile_fd);
823     if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
824         // Skip profile guided compilation because no profiles were found.
825         // Or if the reference profile info couldn't be opened.
826         return false;
827     }
828 
829     RunProfman profman_merge;
830     profman_merge.SetupMerge(profiles_fd, reference_profile_fd);
831     pid_t pid = fork();
832     if (pid == 0) {
833         /* child -- drop privileges before continuing */
834         drop_capabilities(uid);
835         profman_merge.Exec();
836     }
837     /* parent */
838     int return_code = wait_child(pid);
839     bool need_to_compile = false;
840     bool should_clear_current_profiles = false;
841     bool should_clear_reference_profile = false;
842     if (!WIFEXITED(return_code)) {
843         LOG(WARNING) << "profman failed for location " << location << ": " << return_code;
844     } else {
845         return_code = WEXITSTATUS(return_code);
846         switch (return_code) {
847             case PROFMAN_BIN_RETURN_CODE_COMPILE:
848                 need_to_compile = true;
849                 should_clear_current_profiles = true;
850                 should_clear_reference_profile = false;
851                 break;
852             case PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION:
853                 need_to_compile = false;
854                 should_clear_current_profiles = false;
855                 should_clear_reference_profile = false;
856                 break;
857             case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
858                 LOG(WARNING) << "Bad profiles for location " << location;
859                 need_to_compile = false;
860                 should_clear_current_profiles = true;
861                 should_clear_reference_profile = true;
862                 break;
863             case PROFMAN_BIN_RETURN_CODE_ERROR_IO:  // fall-through
864             case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
865                 // Temporary IO problem (e.g. locking). Ignore but log a warning.
866                 LOG(WARNING) << "IO error while reading profiles for location " << location;
867                 need_to_compile = false;
868                 should_clear_current_profiles = false;
869                 should_clear_reference_profile = false;
870                 break;
871            default:
872                 // Unknown return code or error. Unlink profiles.
873                 LOG(WARNING) << "Unknown error code while processing profiles for location "
874                         << location << ": " << return_code;
875                 need_to_compile = false;
876                 should_clear_current_profiles = true;
877                 should_clear_reference_profile = true;
878                 break;
879         }
880     }
881 
882     if (should_clear_current_profiles) {
883         if (is_secondary_dex) {
884             // For secondary dex files, the owning user is the current user.
885             clear_current_profile(package_name, location, multiuser_get_user_id(uid),
886                     is_secondary_dex);
887         } else  {
888             clear_primary_current_profiles(package_name, location);
889         }
890     }
891     if (should_clear_reference_profile) {
892         clear_reference_profile(package_name, location, is_secondary_dex);
893     }
894     return need_to_compile;
895 }
896 
897 // Decides if profile guided compilation is needed or not based on existing profiles.
898 // The analysis is done for the primary apks of the given package.
899 // Returns true if there is enough information in the current profiles that makes it
900 // worth to recompile the package.
901 // If the return value is true all the current profiles would have been merged into
902 // the reference profiles accessible with open_reference_profile().
analyze_primary_profiles(uid_t uid,const std::string & package_name,const std::string & profile_name)903 bool analyze_primary_profiles(uid_t uid, const std::string& package_name,
904         const std::string& profile_name) {
905     return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false);
906 }
907 
dump_profiles(int32_t uid,const std::string & pkgname,const std::string & profile_name,const std::string & code_path)908 bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name,
909         const std::string& code_path) {
910     std::vector<unique_fd> profile_fds;
911     unique_fd reference_profile_fd;
912     std::string out_file_name = StringPrintf("/data/misc/profman/%s-%s.txt",
913         pkgname.c_str(), profile_name.c_str());
914 
915     open_profile_files(uid, pkgname, profile_name, /*is_secondary_dex*/false,
916             &profile_fds, &reference_profile_fd);
917 
918     const bool has_reference_profile = (reference_profile_fd.get() != -1);
919     const bool has_profiles = !profile_fds.empty();
920 
921     if (!has_reference_profile && !has_profiles) {
922         LOG(ERROR)  << "profman dump: no profiles to dump for " << pkgname;
923         return false;
924     }
925 
926     unique_fd output_fd(open(out_file_name.c_str(),
927             O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0644));
928     if (fchmod(output_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
929         LOG(ERROR) << "installd cannot chmod file for dump_profile" << out_file_name;
930         return false;
931     }
932 
933     std::vector<std::string> dex_locations;
934     std::vector<unique_fd> apk_fds;
935     unique_fd apk_fd(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW));
936     if (apk_fd == -1) {
937         PLOG(ERROR) << "installd cannot open " << code_path.c_str();
938         return false;
939     }
940     dex_locations.push_back(get_location_from_path(code_path.c_str()));
941     apk_fds.push_back(std::move(apk_fd));
942 
943 
944     RunProfman profman_dump;
945     profman_dump.SetupDump(profile_fds, reference_profile_fd, dex_locations, apk_fds, output_fd);
946     pid_t pid = fork();
947     if (pid == 0) {
948         /* child -- drop privileges before continuing */
949         drop_capabilities(uid);
950         profman_dump.Exec();
951     }
952     /* parent */
953     int return_code = wait_child(pid);
954     if (!WIFEXITED(return_code)) {
955         LOG(WARNING) << "profman failed for package " << pkgname << ": "
956                 << return_code;
957         return false;
958     }
959     return true;
960 }
961 
copy_system_profile(const std::string & system_profile,uid_t packageUid,const std::string & package_name,const std::string & profile_name)962 bool copy_system_profile(const std::string& system_profile,
963         uid_t packageUid, const std::string& package_name, const std::string& profile_name) {
964     unique_fd in_fd(open(system_profile.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
965     unique_fd out_fd(open_reference_profile(packageUid,
966                      package_name,
967                      profile_name,
968                      /*read_write*/ true,
969                      /*secondary*/ false));
970     if (in_fd.get() < 0) {
971         PLOG(WARNING) << "Could not open profile " << system_profile;
972         return false;
973     }
974     if (out_fd.get() < 0) {
975         PLOG(WARNING) << "Could not open profile " << package_name;
976         return false;
977     }
978 
979     // As a security measure we want to write the profile information with the reduced capabilities
980     // of the package user id. So we fork and drop capabilities in the child.
981     pid_t pid = fork();
982     if (pid == 0) {
983         /* child -- drop privileges before continuing */
984         drop_capabilities(packageUid);
985 
986         if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
987             if (errno != EWOULDBLOCK) {
988                 PLOG(WARNING) << "Error locking profile " << package_name;
989             }
990             // This implies that the app owning this profile is running
991             // (and has acquired the lock).
992             //
993             // The app never acquires the lock for the reference profiles of primary apks.
994             // Only dex2oat from installd will do that. Since installd is single threaded
995             // we should not see this case. Nevertheless be prepared for it.
996             PLOG(WARNING) << "Failed to flock " << package_name;
997             return false;
998         }
999 
1000         bool truncated = ftruncate(out_fd.get(), 0) == 0;
1001         if (!truncated) {
1002             PLOG(WARNING) << "Could not truncate " << package_name;
1003         }
1004 
1005         // Copy over data.
1006         static constexpr size_t kBufferSize = 4 * 1024;
1007         char buffer[kBufferSize];
1008         while (true) {
1009             ssize_t bytes = read(in_fd.get(), buffer, kBufferSize);
1010             if (bytes == 0) {
1011                 break;
1012             }
1013             write(out_fd.get(), buffer, bytes);
1014         }
1015         if (flock(out_fd.get(), LOCK_UN) != 0) {
1016             PLOG(WARNING) << "Error unlocking profile " << package_name;
1017         }
1018         // Use _exit since we don't want to run the global destructors in the child.
1019         // b/62597429
1020         _exit(0);
1021     }
1022     /* parent */
1023     int return_code = wait_child(pid);
1024     return return_code == 0;
1025 }
1026 
replace_file_extension(const std::string & oat_path,const std::string & new_ext)1027 static std::string replace_file_extension(const std::string& oat_path, const std::string& new_ext) {
1028   // A standard dalvik-cache entry. Replace ".dex" with `new_ext`.
1029   if (EndsWith(oat_path, ".dex")) {
1030     std::string new_path = oat_path;
1031     new_path.replace(new_path.length() - strlen(".dex"), strlen(".dex"), new_ext);
1032     CHECK(EndsWith(new_path, new_ext));
1033     return new_path;
1034   }
1035 
1036   // An odex entry. Not that this may not be an extension, e.g., in the OTA
1037   // case (where the base name will have an extension for the B artifact).
1038   size_t odex_pos = oat_path.rfind(".odex");
1039   if (odex_pos != std::string::npos) {
1040     std::string new_path = oat_path;
1041     new_path.replace(odex_pos, strlen(".odex"), new_ext);
1042     CHECK_NE(new_path.find(new_ext), std::string::npos);
1043     return new_path;
1044   }
1045 
1046   // Don't know how to handle this.
1047   return "";
1048 }
1049 
1050 // Translate the given oat path to an art (app image) path. An empty string
1051 // denotes an error.
create_image_filename(const std::string & oat_path)1052 static std::string create_image_filename(const std::string& oat_path) {
1053     return replace_file_extension(oat_path, ".art");
1054 }
1055 
1056 // Translate the given oat path to a vdex path. An empty string denotes an error.
create_vdex_filename(const std::string & oat_path)1057 static std::string create_vdex_filename(const std::string& oat_path) {
1058     return replace_file_extension(oat_path, ".vdex");
1059 }
1060 
open_output_file(const char * file_name,bool recreate,int permissions)1061 static int open_output_file(const char* file_name, bool recreate, int permissions) {
1062     int flags = O_RDWR | O_CREAT;
1063     if (recreate) {
1064         if (unlink(file_name) < 0) {
1065             if (errno != ENOENT) {
1066                 PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
1067             }
1068         }
1069         flags |= O_EXCL;
1070     }
1071     return open(file_name, flags, permissions);
1072 }
1073 
set_permissions_and_ownership(int fd,bool is_public,int uid,const char * path,bool is_secondary_dex)1074 static bool set_permissions_and_ownership(
1075         int fd, bool is_public, int uid, const char* path, bool is_secondary_dex) {
1076     // Primary apks are owned by the system. Secondary dex files are owned by the app.
1077     int owning_uid = is_secondary_dex ? uid : AID_SYSTEM;
1078     if (fchmod(fd,
1079                S_IRUSR|S_IWUSR|S_IRGRP |
1080                (is_public ? S_IROTH : 0)) < 0) {
1081         ALOGE("installd cannot chmod '%s' during dexopt\n", path);
1082         return false;
1083     } else if (fchown(fd, owning_uid, uid) < 0) {
1084         ALOGE("installd cannot chown '%s' during dexopt\n", path);
1085         return false;
1086     }
1087     return true;
1088 }
1089 
IsOutputDalvikCache(const char * oat_dir)1090 static bool IsOutputDalvikCache(const char* oat_dir) {
1091   // InstallerConnection.java (which invokes installd) transforms Java null arguments
1092   // into '!'. Play it safe by handling it both.
1093   // TODO: ensure we never get null.
1094   // TODO: pass a flag instead of inferring if the output is dalvik cache.
1095   return oat_dir == nullptr || oat_dir[0] == '!';
1096 }
1097 
1098 // Best-effort check whether we can fit the the path into our buffers.
1099 // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
1100 // without a swap file, if necessary. Reference profiles file also add an extra ".prof"
1101 // extension to the cache path (5 bytes).
1102 // TODO(calin): move away from char* buffers and PKG_PATH_MAX.
validate_dex_path_size(const std::string & dex_path)1103 static bool validate_dex_path_size(const std::string& dex_path) {
1104     if (dex_path.size() >= (PKG_PATH_MAX - 8)) {
1105         LOG(ERROR) << "dex_path too long: " << dex_path;
1106         return false;
1107     }
1108     return true;
1109 }
1110 
create_oat_out_path(const char * apk_path,const char * instruction_set,const char * oat_dir,bool is_secondary_dex,char * out_oat_path)1111 static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
1112             const char* oat_dir, bool is_secondary_dex, /*out*/ char* out_oat_path) {
1113     if (!validate_dex_path_size(apk_path)) {
1114         return false;
1115     }
1116 
1117     if (!IsOutputDalvikCache(oat_dir)) {
1118         // Oat dirs for secondary dex files are already validated.
1119         if (!is_secondary_dex && validate_apk_path(oat_dir)) {
1120             ALOGE("cannot validate apk path with oat_dir '%s'\n", oat_dir);
1121             return false;
1122         }
1123         if (!calculate_oat_file_path(out_oat_path, oat_dir, apk_path, instruction_set)) {
1124             return false;
1125         }
1126     } else {
1127         if (!create_cache_path(out_oat_path, apk_path, instruction_set)) {
1128             return false;
1129         }
1130     }
1131     return true;
1132 }
1133 
1134 // Helper for fd management. This is similar to a unique_fd in that it closes the file descriptor
1135 // on destruction. It will also run the given cleanup (unless told not to) after closing.
1136 //
1137 // Usage example:
1138 //
1139 //   Dex2oatFileWrapper file(open(...),
1140 //                                                   [name]() {
1141 //                                                       unlink(name.c_str());
1142 //                                                   });
1143 //   // Note: care needs to be taken about name, as it needs to have a lifetime longer than the
1144 //            wrapper if captured as a reference.
1145 //
1146 //   if (file.get() == -1) {
1147 //       // Error opening...
1148 //   }
1149 //
1150 //   ...
1151 //   if (error) {
1152 //       // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will run
1153 //       // and delete the file (after the fd is closed).
1154 //       return -1;
1155 //   }
1156 //
1157 //   (Success case)
1158 //   file.SetCleanup(false);
1159 //   // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will not run
1160 //   // (leaving the file around; after the fd is closed).
1161 //
1162 class Dex2oatFileWrapper {
1163  public:
Dex2oatFileWrapper()1164     Dex2oatFileWrapper() : value_(-1), cleanup_(), do_cleanup_(true), auto_close_(true) {
1165     }
1166 
Dex2oatFileWrapper(int value,std::function<void ()> cleanup)1167     Dex2oatFileWrapper(int value, std::function<void ()> cleanup)
1168             : value_(value), cleanup_(cleanup), do_cleanup_(true), auto_close_(true) {}
1169 
Dex2oatFileWrapper(Dex2oatFileWrapper && other)1170     Dex2oatFileWrapper(Dex2oatFileWrapper&& other) {
1171         value_ = other.value_;
1172         cleanup_ = other.cleanup_;
1173         do_cleanup_ = other.do_cleanup_;
1174         auto_close_ = other.auto_close_;
1175         other.release();
1176     }
1177 
operator =(Dex2oatFileWrapper && other)1178     Dex2oatFileWrapper& operator=(Dex2oatFileWrapper&& other) {
1179         value_ = other.value_;
1180         cleanup_ = other.cleanup_;
1181         do_cleanup_ = other.do_cleanup_;
1182         auto_close_ = other.auto_close_;
1183         other.release();
1184         return *this;
1185     }
1186 
~Dex2oatFileWrapper()1187     ~Dex2oatFileWrapper() {
1188         reset(-1);
1189     }
1190 
get()1191     int get() {
1192         return value_;
1193     }
1194 
SetCleanup(bool cleanup)1195     void SetCleanup(bool cleanup) {
1196         do_cleanup_ = cleanup;
1197     }
1198 
reset(int new_value)1199     void reset(int new_value) {
1200         if (auto_close_ && value_ >= 0) {
1201             close(value_);
1202         }
1203         if (do_cleanup_ && cleanup_ != nullptr) {
1204             cleanup_();
1205         }
1206 
1207         value_ = new_value;
1208     }
1209 
reset(int new_value,std::function<void ()> new_cleanup)1210     void reset(int new_value, std::function<void ()> new_cleanup) {
1211         if (auto_close_ && value_ >= 0) {
1212             close(value_);
1213         }
1214         if (do_cleanup_ && cleanup_ != nullptr) {
1215             cleanup_();
1216         }
1217 
1218         value_ = new_value;
1219         cleanup_ = new_cleanup;
1220     }
1221 
DisableAutoClose()1222     void DisableAutoClose() {
1223         auto_close_ = false;
1224     }
1225 
1226  private:
release()1227     void release() {
1228         value_ = -1;
1229         do_cleanup_ = false;
1230         cleanup_ = nullptr;
1231     }
1232     int value_;
1233     std::function<void ()> cleanup_;
1234     bool do_cleanup_;
1235     bool auto_close_;
1236 };
1237 
1238 // (re)Creates the app image if needed.
maybe_open_app_image(const char * out_oat_path,bool generate_app_image,bool is_public,int uid,bool is_secondary_dex)1239 Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path,
1240         bool generate_app_image, bool is_public, int uid, bool is_secondary_dex) {
1241 
1242     // We don't create an image for secondary dex files.
1243     if (is_secondary_dex) {
1244         return Dex2oatFileWrapper();
1245     }
1246 
1247     const std::string image_path = create_image_filename(out_oat_path);
1248     if (image_path.empty()) {
1249         // Happens when the out_oat_path has an unknown extension.
1250         return Dex2oatFileWrapper();
1251     }
1252 
1253     // In case there is a stale image, remove it now. Ignore any error.
1254     unlink(image_path.c_str());
1255 
1256     // Not enabled, exit.
1257     if (!generate_app_image) {
1258         return Dex2oatFileWrapper();
1259     }
1260     std::string app_image_format = GetProperty("dalvik.vm.appimageformat", "");
1261     if (app_image_format.empty()) {
1262         return Dex2oatFileWrapper();
1263     }
1264     // Recreate is true since we do not want to modify a mapped image. If the app is
1265     // already running and we modify the image file, it can cause crashes (b/27493510).
1266     Dex2oatFileWrapper wrapper_fd(
1267             open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
1268             [image_path]() { unlink(image_path.c_str()); });
1269     if (wrapper_fd.get() < 0) {
1270         // Could not create application image file. Go on since we can compile without it.
1271         LOG(ERROR) << "installd could not create '" << image_path
1272                 << "' for image file during dexopt";
1273          // If we have a valid image file path but no image fd, explicitly erase the image file.
1274         if (unlink(image_path.c_str()) < 0) {
1275             if (errno != ENOENT) {
1276                 PLOG(ERROR) << "Couldn't unlink image file " << image_path;
1277             }
1278         }
1279     } else if (!set_permissions_and_ownership(
1280                 wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
1281         ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
1282         wrapper_fd.reset(-1);
1283     }
1284 
1285     return wrapper_fd;
1286 }
1287 
1288 // Creates the dexopt swap file if necessary and return its fd.
1289 // Returns -1 if there's no need for a swap or in case of errors.
maybe_open_dexopt_swap_file(const char * out_oat_path)1290 unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
1291     if (!ShouldUseSwapFileForDexopt()) {
1292         return invalid_unique_fd();
1293     }
1294     auto swap_file_name = std::string(out_oat_path) + ".swap";
1295     unique_fd swap_fd(open_output_file(
1296             swap_file_name.c_str(), /*recreate*/true, /*permissions*/0600));
1297     if (swap_fd.get() < 0) {
1298         // Could not create swap file. Optimistically go on and hope that we can compile
1299         // without it.
1300         ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name.c_str());
1301     } else {
1302         // Immediately unlink. We don't really want to hit flash.
1303         if (unlink(swap_file_name.c_str()) < 0) {
1304             PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
1305         }
1306     }
1307     return swap_fd;
1308 }
1309 
1310 // Opens the reference profiles if needed.
1311 // Note that the reference profile might not exist so it's OK if the fd will be -1.
maybe_open_reference_profile(const std::string & pkgname,const std::string & dex_path,const char * profile_name,bool profile_guided,bool is_public,int uid,bool is_secondary_dex)1312 Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname,
1313         const std::string& dex_path, const char* profile_name, bool profile_guided,
1314         bool is_public, int uid, bool is_secondary_dex) {
1315     // If we are not profile guided compilation, or we are compiling system server
1316     // do not bother to open the profiles; we won't be using them.
1317     if (!profile_guided || (pkgname[0] == '*')) {
1318         return Dex2oatFileWrapper();
1319     }
1320 
1321     // If this is a secondary dex path which is public do not open the profile.
1322     // We cannot compile public secondary dex paths with profiles. That's because
1323     // it will expose how the dex files are used by their owner.
1324     //
1325     // Note that the PackageManager is responsible to set the is_public flag for
1326     // primary apks and we do not check it here. In some cases, e.g. when
1327     // compiling with a public profile from the .dm file the PackageManager will
1328     // set is_public toghether with the profile guided compilation.
1329     if (is_secondary_dex && is_public) {
1330         return Dex2oatFileWrapper();
1331     }
1332 
1333     // Open reference profile in read only mode as dex2oat does not get write permissions.
1334     std::string location;
1335     if (is_secondary_dex) {
1336         location = dex_path;
1337     } else {
1338         if (profile_name == nullptr) {
1339             // This path is taken for system server re-compilation lunched from ZygoteInit.
1340             return Dex2oatFileWrapper();
1341         } else {
1342             location = profile_name;
1343         }
1344     }
1345     unique_fd ufd = open_reference_profile(uid, pkgname, location, /*read_write*/false,
1346             is_secondary_dex);
1347     const auto& cleanup = [pkgname, location, is_secondary_dex]() {
1348         clear_reference_profile(pkgname, location, is_secondary_dex);
1349     };
1350     return Dex2oatFileWrapper(ufd.release(), cleanup);
1351 }
1352 
1353 // Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
1354 // out_vdex_wrapper_fd. Returns true for success or false in case of errors.
open_vdex_files_for_dex2oat(const char * apk_path,const char * out_oat_path,int dexopt_needed,const char * instruction_set,bool is_public,int uid,bool is_secondary_dex,bool profile_guided,Dex2oatFileWrapper * in_vdex_wrapper_fd,Dex2oatFileWrapper * out_vdex_wrapper_fd)1355 bool open_vdex_files_for_dex2oat(const char* apk_path, const char* out_oat_path, int dexopt_needed,
1356         const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
1357         bool profile_guided, Dex2oatFileWrapper* in_vdex_wrapper_fd,
1358         Dex2oatFileWrapper* out_vdex_wrapper_fd) {
1359     CHECK(in_vdex_wrapper_fd != nullptr);
1360     CHECK(out_vdex_wrapper_fd != nullptr);
1361     // Open the existing VDEX. We do this before creating the new output VDEX, which will
1362     // unlink the old one.
1363     char in_odex_path[PKG_PATH_MAX];
1364     int dexopt_action = abs(dexopt_needed);
1365     bool is_odex_location = dexopt_needed < 0;
1366     std::string in_vdex_path_str;
1367 
1368     // Infer the name of the output VDEX.
1369     const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
1370     if (out_vdex_path_str.empty()) {
1371         return false;
1372     }
1373 
1374     bool update_vdex_in_place = false;
1375     if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
1376         // Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
1377         const char* path = nullptr;
1378         if (is_odex_location) {
1379             if (calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
1380                 path = in_odex_path;
1381             } else {
1382                 ALOGE("installd cannot compute input vdex location for '%s'\n", apk_path);
1383                 return false;
1384             }
1385         } else {
1386             path = out_oat_path;
1387         }
1388         in_vdex_path_str = create_vdex_filename(path);
1389         if (in_vdex_path_str.empty()) {
1390             ALOGE("installd cannot compute input vdex location for '%s'\n", path);
1391             return false;
1392         }
1393         // We can update in place when all these conditions are met:
1394         // 1) The vdex location to write to is the same as the vdex location to read (vdex files
1395         //    on /system typically cannot be updated in place).
1396         // 2) We dex2oat due to boot image change, because we then know the existing vdex file
1397         //    cannot be currently used by a running process.
1398         // 3) We are not doing a profile guided compilation, because dexlayout requires two
1399         //    different vdex files to operate.
1400         update_vdex_in_place =
1401             (in_vdex_path_str == out_vdex_path_str) &&
1402             (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) &&
1403             !profile_guided;
1404         if (update_vdex_in_place) {
1405             // Open the file read-write to be able to update it.
1406             in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
1407             if (in_vdex_wrapper_fd->get() == -1) {
1408                 // If we failed to open the file, we cannot update it in place.
1409                 update_vdex_in_place = false;
1410             }
1411         } else {
1412             in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
1413         }
1414     }
1415 
1416     // If we are updating the vdex in place, we do not need to recreate a vdex,
1417     // and can use the same existing one.
1418     if (update_vdex_in_place) {
1419         // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
1420         // have bogus stale vdex files.
1421         out_vdex_wrapper_fd->reset(
1422               in_vdex_wrapper_fd->get(),
1423               [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
1424         // Disable auto close for the in wrapper fd (it will be done when destructing the out
1425         // wrapper).
1426         in_vdex_wrapper_fd->DisableAutoClose();
1427     } else {
1428         out_vdex_wrapper_fd->reset(
1429               open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
1430               [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
1431         if (out_vdex_wrapper_fd->get() < 0) {
1432             ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
1433             return false;
1434         }
1435     }
1436     if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
1437             out_vdex_path_str.c_str(), is_secondary_dex)) {
1438         ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
1439         return false;
1440     }
1441 
1442     // If we got here we successfully opened the vdex files.
1443     return true;
1444 }
1445 
1446 // Opens the output oat file for the given apk.
1447 // If successful it stores the output path into out_oat_path and returns true.
open_oat_out_file(const char * apk_path,const char * oat_dir,bool is_public,int uid,const char * instruction_set,bool is_secondary_dex,char * out_oat_path)1448 Dex2oatFileWrapper open_oat_out_file(const char* apk_path, const char* oat_dir,
1449         bool is_public, int uid, const char* instruction_set, bool is_secondary_dex,
1450         char* out_oat_path) {
1451     if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
1452         return Dex2oatFileWrapper();
1453     }
1454     const std::string out_oat_path_str(out_oat_path);
1455     Dex2oatFileWrapper wrapper_fd(
1456             open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
1457             [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
1458     if (wrapper_fd.get() < 0) {
1459         PLOG(ERROR) << "installd cannot open output during dexopt" <<  out_oat_path;
1460     } else if (!set_permissions_and_ownership(
1461                 wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) {
1462         ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
1463         wrapper_fd.reset(-1);
1464     }
1465     return wrapper_fd;
1466 }
1467 
1468 // Creates RDONLY fds for oat and vdex files, if exist.
1469 // Returns false if it fails to create oat out path for the given apk path.
1470 // Note that the method returns true even if the files could not be opened.
maybe_open_oat_and_vdex_file(const std::string & apk_path,const std::string & oat_dir,const std::string & instruction_set,bool is_secondary_dex,unique_fd * oat_file_fd,unique_fd * vdex_file_fd)1471 bool maybe_open_oat_and_vdex_file(const std::string& apk_path,
1472                                   const std::string& oat_dir,
1473                                   const std::string& instruction_set,
1474                                   bool is_secondary_dex,
1475                                   unique_fd* oat_file_fd,
1476                                   unique_fd* vdex_file_fd) {
1477     char oat_path[PKG_PATH_MAX];
1478     if (!create_oat_out_path(apk_path.c_str(),
1479                              instruction_set.c_str(),
1480                              oat_dir.c_str(),
1481                              is_secondary_dex,
1482                              oat_path)) {
1483         LOG(ERROR) << "Could not create oat out path for "
1484                 << apk_path << " with oat dir " << oat_dir;
1485         return false;
1486     }
1487     oat_file_fd->reset(open(oat_path, O_RDONLY));
1488     if (oat_file_fd->get() < 0) {
1489         PLOG(INFO) << "installd cannot open oat file during dexopt" <<  oat_path;
1490     }
1491 
1492     std::string vdex_filename = create_vdex_filename(oat_path);
1493     vdex_file_fd->reset(open(vdex_filename.c_str(), O_RDONLY));
1494     if (vdex_file_fd->get() < 0) {
1495         PLOG(INFO) << "installd cannot open vdex file during dexopt" <<  vdex_filename;
1496     }
1497 
1498     return true;
1499 }
1500 
1501 // Updates the access times of out_oat_path based on those from apk_path.
update_out_oat_access_times(const char * apk_path,const char * out_oat_path)1502 void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
1503     struct stat input_stat;
1504     memset(&input_stat, 0, sizeof(input_stat));
1505     if (stat(apk_path, &input_stat) != 0) {
1506         PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
1507         return;
1508     }
1509 
1510     struct utimbuf ut;
1511     ut.actime = input_stat.st_atime;
1512     ut.modtime = input_stat.st_mtime;
1513     if (utime(out_oat_path, &ut) != 0) {
1514         PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
1515     }
1516 }
1517 
1518 // Runs (execv) dexoptanalyzer on the given arguments.
1519 // The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
1520 // If this is for a profile guided compilation, profile_was_updated will tell whether or not
1521 // the profile has changed.
1522 class RunDexoptAnalyzer : public ExecVHelper {
1523  public:
RunDexoptAnalyzer(const std::string & dex_file,int vdex_fd,int oat_fd,int zip_fd,const std::string & instruction_set,const std::string & compiler_filter,bool profile_was_updated,bool downgrade,const char * class_loader_context,const std::string & class_loader_context_fds)1524     RunDexoptAnalyzer(const std::string& dex_file,
1525                       int vdex_fd,
1526                       int oat_fd,
1527                       int zip_fd,
1528                       const std::string& instruction_set,
1529                       const std::string& compiler_filter,
1530                       bool profile_was_updated,
1531                       bool downgrade,
1532                       const char* class_loader_context,
1533                       const std::string& class_loader_context_fds) {
1534         CHECK_GE(zip_fd, 0);
1535 
1536         // We always run the analyzer in the background job.
1537         const char* dexoptanalyzer_bin = select_execution_binary(
1538              kDexoptanalyzerPath, kDexoptanalyzerDebugPath, /*background_job_compile=*/ true);
1539 
1540         std::string dex_file_arg = "--dex-file=" + dex_file;
1541         std::string oat_fd_arg = "--oat-fd=" + std::to_string(oat_fd);
1542         std::string vdex_fd_arg = "--vdex-fd=" + std::to_string(vdex_fd);
1543         std::string zip_fd_arg = "--zip-fd=" + std::to_string(zip_fd);
1544         std::string isa_arg = "--isa=" + instruction_set;
1545         std::string compiler_filter_arg = "--compiler-filter=" + compiler_filter;
1546         const char* assume_profile_changed = "--assume-profile-changed";
1547         const char* downgrade_flag = "--downgrade";
1548         std::string class_loader_context_arg = "--class-loader-context=";
1549         if (class_loader_context != nullptr) {
1550             class_loader_context_arg += class_loader_context;
1551         }
1552         std::string class_loader_context_fds_arg = "--class-loader-context-fds=";
1553         if (!class_loader_context_fds.empty()) {
1554             class_loader_context_fds_arg += class_loader_context_fds;
1555         }
1556 
1557         // program name, dex file, isa, filter
1558         AddArg(dex_file_arg);
1559         AddArg(isa_arg);
1560         AddArg(compiler_filter_arg);
1561         if (oat_fd >= 0) {
1562             AddArg(oat_fd_arg);
1563         }
1564         if (vdex_fd >= 0) {
1565             AddArg(vdex_fd_arg);
1566         }
1567         AddArg(zip_fd_arg);
1568         if (profile_was_updated) {
1569             AddArg(assume_profile_changed);
1570         }
1571         if (downgrade) {
1572             AddArg(downgrade_flag);
1573         }
1574         if (class_loader_context != nullptr) {
1575             AddArg(class_loader_context_arg);
1576             if (!class_loader_context_fds.empty()) {
1577                 AddArg(class_loader_context_fds_arg);
1578             }
1579         }
1580 
1581         PrepareArgs(dexoptanalyzer_bin);
1582     }
1583 
1584     // Dexoptanalyzer mode which flattens the given class loader context and
1585     // prints a list of its dex files in that flattened order.
RunDexoptAnalyzer(const char * class_loader_context)1586     RunDexoptAnalyzer(const char* class_loader_context) {
1587         CHECK(class_loader_context != nullptr);
1588 
1589         // We always run the analyzer in the background job.
1590         const char* dexoptanalyzer_bin = select_execution_binary(
1591              kDexoptanalyzerPath, kDexoptanalyzerDebugPath, /*background_job_compile=*/ true);
1592 
1593         AddArg("--flatten-class-loader-context");
1594         AddArg(std::string("--class-loader-context=") + class_loader_context);
1595         PrepareArgs(dexoptanalyzer_bin);
1596     }
1597 };
1598 
1599 // Prepares the oat dir for the secondary dex files.
prepare_secondary_dex_oat_dir(const std::string & dex_path,int uid,const char * instruction_set)1600 static bool prepare_secondary_dex_oat_dir(const std::string& dex_path, int uid,
1601         const char* instruction_set) {
1602     unsigned long dirIndex = dex_path.rfind('/');
1603     if (dirIndex == std::string::npos) {
1604         LOG(ERROR ) << "Unexpected dir structure for secondary dex " << dex_path;
1605         return false;
1606     }
1607     std::string dex_dir = dex_path.substr(0, dirIndex);
1608 
1609     // Create oat file output directory.
1610     mode_t oat_dir_mode = S_IRWXU | S_IRWXG | S_IXOTH;
1611     if (prepare_app_cache_dir(dex_dir, "oat", oat_dir_mode, uid, uid) != 0) {
1612         LOG(ERROR) << "Could not prepare oat dir for secondary dex: " << dex_path;
1613         return false;
1614     }
1615 
1616     char oat_dir[PKG_PATH_MAX];
1617     snprintf(oat_dir, PKG_PATH_MAX, "%s/oat", dex_dir.c_str());
1618 
1619     if (prepare_app_cache_dir(oat_dir, instruction_set, oat_dir_mode, uid, uid) != 0) {
1620         LOG(ERROR) << "Could not prepare oat/isa dir for secondary dex: " << dex_path;
1621         return false;
1622     }
1623 
1624     return true;
1625 }
1626 
1627 // Return codes for identifying the reason why dexoptanalyzer was not invoked when processing
1628 // secondary dex files. This return codes are returned by the child process created for
1629 // analyzing secondary dex files in process_secondary_dex_dexopt.
1630 
1631 enum DexoptAnalyzerSkipCodes {
1632   // The dexoptanalyzer was not invoked because of validation or IO errors.
1633   // Specific errors are encoded in the name.
1634   kSecondaryDexDexoptAnalyzerSkippedValidatePath = 200,
1635   kSecondaryDexDexoptAnalyzerSkippedOpenZip = 201,
1636   kSecondaryDexDexoptAnalyzerSkippedPrepareDir = 202,
1637   kSecondaryDexDexoptAnalyzerSkippedOpenOutput = 203,
1638   kSecondaryDexDexoptAnalyzerSkippedFailExec = 204,
1639   // The dexoptanalyzer was not invoked because the dex file does not exist anymore.
1640   kSecondaryDexDexoptAnalyzerSkippedNoFile = 205,
1641 };
1642 
1643 // Verifies the result of analyzing secondary dex files from process_secondary_dex_dexopt.
1644 // If the result is valid returns true and sets dexopt_needed_out to a valid value.
1645 // Returns false for errors or unexpected result values.
1646 // The result is expected to be either one of SECONDARY_DEX_* codes or a valid exit code
1647 // of dexoptanalyzer.
process_secondary_dexoptanalyzer_result(const std::string & dex_path,int result,int * dexopt_needed_out,std::string * error_msg)1648 static bool process_secondary_dexoptanalyzer_result(const std::string& dex_path, int result,
1649             int* dexopt_needed_out, std::string* error_msg) {
1650     // The result values are defined in dexoptanalyzer.
1651     switch (result) {
1652         case 0:  // dexoptanalyzer: no_dexopt_needed
1653             *dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
1654         case 1:  // dexoptanalyzer: dex2oat_from_scratch
1655             *dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
1656         case 4:  // dexoptanalyzer: dex2oat_for_bootimage_odex
1657             *dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
1658         case 5:  // dexoptanalyzer: dex2oat_for_filter_odex
1659             *dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
1660         case 2:  // dexoptanalyzer: dex2oat_for_bootimage_oat
1661         case 3:  // dexoptanalyzer: dex2oat_for_filter_oat
1662             *error_msg = StringPrintf("Dexoptanalyzer return the status of an oat file."
1663                                       " Expected odex file status for secondary dex %s"
1664                                       " : dexoptanalyzer result=%d",
1665                                       dex_path.c_str(),
1666                                       result);
1667             return false;
1668     }
1669 
1670     // Use a second switch for enum switch-case analysis.
1671     switch (static_cast<DexoptAnalyzerSkipCodes>(result)) {
1672         case kSecondaryDexDexoptAnalyzerSkippedNoFile:
1673             // If the file does not exist there's no need for dexopt.
1674             *dexopt_needed_out = NO_DEXOPT_NEEDED;
1675             return true;
1676 
1677         case kSecondaryDexDexoptAnalyzerSkippedValidatePath:
1678             *error_msg = "Dexoptanalyzer path validation failed";
1679             return false;
1680         case kSecondaryDexDexoptAnalyzerSkippedOpenZip:
1681             *error_msg = "Dexoptanalyzer open zip failed";
1682             return false;
1683         case kSecondaryDexDexoptAnalyzerSkippedPrepareDir:
1684             *error_msg = "Dexoptanalyzer dir preparation failed";
1685             return false;
1686         case kSecondaryDexDexoptAnalyzerSkippedOpenOutput:
1687             *error_msg = "Dexoptanalyzer open output failed";
1688             return false;
1689         case kSecondaryDexDexoptAnalyzerSkippedFailExec:
1690             *error_msg = "Dexoptanalyzer failed to execute";
1691             return false;
1692     }
1693 
1694     *error_msg = StringPrintf("Unexpected result from analyzing secondary dex %s result=%d",
1695                               dex_path.c_str(),
1696                               result);
1697     return false;
1698 }
1699 
1700 enum SecondaryDexAccess {
1701     kSecondaryDexAccessReadOk = 0,
1702     kSecondaryDexAccessDoesNotExist = 1,
1703     kSecondaryDexAccessPermissionError = 2,
1704     kSecondaryDexAccessIOError = 3
1705 };
1706 
check_secondary_dex_access(const std::string & dex_path)1707 static SecondaryDexAccess check_secondary_dex_access(const std::string& dex_path) {
1708     // Check if the path exists and can be read. If not, there's nothing to do.
1709     if (access(dex_path.c_str(), R_OK) == 0) {
1710         return kSecondaryDexAccessReadOk;
1711     } else {
1712         if (errno == ENOENT) {
1713             LOG(INFO) << "Secondary dex does not exist: " <<  dex_path;
1714             return kSecondaryDexAccessDoesNotExist;
1715         } else {
1716             PLOG(ERROR) << "Could not access secondary dex " << dex_path;
1717             return errno == EACCES
1718                 ? kSecondaryDexAccessPermissionError
1719                 : kSecondaryDexAccessIOError;
1720         }
1721     }
1722 }
1723 
is_file_public(const std::string & filename)1724 static bool is_file_public(const std::string& filename) {
1725     struct stat file_stat;
1726     if (stat(filename.c_str(), &file_stat) == 0) {
1727         return (file_stat.st_mode & S_IROTH) != 0;
1728     }
1729     return false;
1730 }
1731 
1732 // Create the oat file structure for the secondary dex 'dex_path' and assign
1733 // the individual path component to the 'out_' parameters.
create_secondary_dex_oat_layout(const std::string & dex_path,const std::string & isa,char * out_oat_dir,char * out_oat_isa_dir,char * out_oat_path,std::string * error_msg)1734 static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa,
1735         char* out_oat_dir, char* out_oat_isa_dir, char* out_oat_path, std::string* error_msg) {
1736     size_t dirIndex = dex_path.rfind('/');
1737     if (dirIndex == std::string::npos) {
1738         *error_msg = std::string("Unexpected dir structure for dex file ").append(dex_path);
1739         return false;
1740     }
1741     // TODO(calin): we have similar computations in at lest 3 other places
1742     // (InstalldNativeService, otapropt and dexopt). Unify them and get rid of snprintf by
1743     // using string append.
1744     std::string apk_dir = dex_path.substr(0, dirIndex);
1745     snprintf(out_oat_dir, PKG_PATH_MAX, "%s/oat", apk_dir.c_str());
1746     snprintf(out_oat_isa_dir, PKG_PATH_MAX, "%s/%s", out_oat_dir, isa.c_str());
1747 
1748     if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
1749             /*is_secondary_dex*/true, out_oat_path)) {
1750         *error_msg = std::string("Could not create oat path for secondary dex ").append(dex_path);
1751         return false;
1752     }
1753     return true;
1754 }
1755 
1756 // Validate that the dexopt_flags contain a valid storage flag and convert that to an installd
1757 // recognized storage flags (FLAG_STORAGE_CE or FLAG_STORAGE_DE).
validate_dexopt_storage_flags(int dexopt_flags,int * out_storage_flag,std::string * error_msg)1758 static bool validate_dexopt_storage_flags(int dexopt_flags,
1759                                           int* out_storage_flag,
1760                                           std::string* error_msg) {
1761     if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
1762         *out_storage_flag = FLAG_STORAGE_CE;
1763         if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1764             *error_msg = "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
1765             return false;
1766         }
1767     } else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
1768         *out_storage_flag = FLAG_STORAGE_DE;
1769     } else {
1770         *error_msg = "Secondary dex storage flag must be set";
1771         return false;
1772     }
1773     return true;
1774 }
1775 
get_class_loader_context_dex_paths(const char * class_loader_context,int uid,std::vector<std::string> * context_dex_paths)1776 static bool get_class_loader_context_dex_paths(const char* class_loader_context, int uid,
1777         /* out */ std::vector<std::string>* context_dex_paths) {
1778     if (class_loader_context == nullptr) {
1779       return true;
1780     }
1781 
1782     LOG(DEBUG) << "Getting dex paths for context " << class_loader_context;
1783 
1784     // Pipe to get the hash result back from our child process.
1785     unique_fd pipe_read, pipe_write;
1786     if (!Pipe(&pipe_read, &pipe_write)) {
1787         PLOG(ERROR) << "Failed to create pipe";
1788         return false;
1789     }
1790 
1791     pid_t pid = fork();
1792     if (pid == 0) {
1793         // child -- drop privileges before continuing.
1794         drop_capabilities(uid);
1795 
1796         // Route stdout to `pipe_write`
1797         while ((dup2(pipe_write, STDOUT_FILENO) == -1) && (errno == EINTR)) {}
1798         pipe_write.reset();
1799         pipe_read.reset();
1800 
1801         RunDexoptAnalyzer run_dexopt_analyzer(class_loader_context);
1802         run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
1803     }
1804 
1805     /* parent */
1806     pipe_write.reset();
1807 
1808     std::string str_dex_paths;
1809     if (!ReadFdToString(pipe_read, &str_dex_paths)) {
1810         PLOG(ERROR) << "Failed to read from pipe";
1811         return false;
1812     }
1813     pipe_read.reset();
1814 
1815     int return_code = wait_child(pid);
1816     if (!WIFEXITED(return_code)) {
1817         PLOG(ERROR) << "Error waiting for child dexoptanalyzer process";
1818         return false;
1819     }
1820 
1821     constexpr int kFlattenClassLoaderContextSuccess = 50;
1822     return_code = WEXITSTATUS(return_code);
1823     if (return_code != kFlattenClassLoaderContextSuccess) {
1824         LOG(ERROR) << "Dexoptanalyzer could not flatten class loader context, code=" << return_code;
1825         return false;
1826     }
1827 
1828     if (!str_dex_paths.empty()) {
1829         *context_dex_paths = android::base::Split(str_dex_paths, ":");
1830     }
1831     return true;
1832 }
1833 
open_dex_paths(const std::vector<std::string> & dex_paths,std::vector<unique_fd> * zip_fds,std::string * error_msg)1834 static int open_dex_paths(const std::vector<std::string>& dex_paths,
1835         /* out */ std::vector<unique_fd>* zip_fds, /* out */ std::string* error_msg) {
1836     for (const std::string& dex_path : dex_paths) {
1837         zip_fds->emplace_back(open(dex_path.c_str(), O_RDONLY));
1838         if (zip_fds->back().get() < 0) {
1839             *error_msg = StringPrintf(
1840                     "installd cannot open '%s' for input during dexopt", dex_path.c_str());
1841             if (errno == ENOENT) {
1842                 return kSecondaryDexDexoptAnalyzerSkippedNoFile;
1843             } else {
1844                 return kSecondaryDexDexoptAnalyzerSkippedOpenZip;
1845             }
1846         }
1847     }
1848     return 0;
1849 }
1850 
join_fds(const std::vector<unique_fd> & fds)1851 static std::string join_fds(const std::vector<unique_fd>& fds) {
1852     std::stringstream ss;
1853     bool is_first = true;
1854     for (const unique_fd& fd : fds) {
1855         if (is_first) {
1856             is_first = false;
1857         } else {
1858             ss << ":";
1859         }
1860         ss << fd.get();
1861     }
1862     return ss.str();
1863 }
1864 
1865 // Processes the dex_path as a secondary dex files and return true if the path dex file should
1866 // be compiled. Returns false for errors (logged) or true if the secondary dex path was process
1867 // successfully.
1868 // When returning true, the output parameters will be:
1869 //   - is_public_out: whether or not the oat file should not be made public
1870 //   - dexopt_needed_out: valid OatFileAsssitant::DexOptNeeded
1871 //   - oat_dir_out: the oat dir path where the oat file should be stored
process_secondary_dex_dexopt(const std::string & dex_path,const char * pkgname,int dexopt_flags,const char * volume_uuid,int uid,const char * instruction_set,const char * compiler_filter,bool * is_public_out,int * dexopt_needed_out,std::string * oat_dir_out,bool downgrade,const char * class_loader_context,const std::vector<std::string> & context_dex_paths,std::string * error_msg)1872 static bool process_secondary_dex_dexopt(const std::string& dex_path, const char* pkgname,
1873         int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
1874         const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
1875         std::string* oat_dir_out, bool downgrade, const char* class_loader_context,
1876         const std::vector<std::string>& context_dex_paths, /* out */ std::string* error_msg) {
1877     LOG(DEBUG) << "Processing secondary dex path " << dex_path;
1878     int storage_flag;
1879     if (!validate_dexopt_storage_flags(dexopt_flags, &storage_flag, error_msg)) {
1880         LOG(ERROR) << *error_msg;
1881         return false;
1882     }
1883     // Compute the oat dir as it's not easy to extract it from the child computation.
1884     char oat_path[PKG_PATH_MAX];
1885     char oat_dir[PKG_PATH_MAX];
1886     char oat_isa_dir[PKG_PATH_MAX];
1887     if (!create_secondary_dex_oat_layout(
1888             dex_path, instruction_set, oat_dir, oat_isa_dir, oat_path, error_msg)) {
1889         LOG(ERROR) << "Could not create secondary odex layout: " << *error_msg;
1890         return false;
1891     }
1892     oat_dir_out->assign(oat_dir);
1893 
1894     pid_t pid = fork();
1895     if (pid == 0) {
1896         // child -- drop privileges before continuing.
1897         drop_capabilities(uid);
1898 
1899         // Validate the path structure.
1900         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
1901             LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
1902             _exit(kSecondaryDexDexoptAnalyzerSkippedValidatePath);
1903         }
1904 
1905         // Open the dex file.
1906         unique_fd zip_fd;
1907         zip_fd.reset(open(dex_path.c_str(), O_RDONLY));
1908         if (zip_fd.get() < 0) {
1909             if (errno == ENOENT) {
1910                 _exit(kSecondaryDexDexoptAnalyzerSkippedNoFile);
1911             } else {
1912                 _exit(kSecondaryDexDexoptAnalyzerSkippedOpenZip);
1913             }
1914         }
1915 
1916         // Open class loader context dex files.
1917         std::vector<unique_fd> context_zip_fds;
1918         int open_dex_paths_rc = open_dex_paths(context_dex_paths, &context_zip_fds, error_msg);
1919         if (open_dex_paths_rc != 0) {
1920             _exit(open_dex_paths_rc);
1921         }
1922 
1923         // Prepare the oat directories.
1924         if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set)) {
1925             _exit(kSecondaryDexDexoptAnalyzerSkippedPrepareDir);
1926         }
1927 
1928         // Open the vdex/oat files if any.
1929         unique_fd oat_file_fd;
1930         unique_fd vdex_file_fd;
1931         if (!maybe_open_oat_and_vdex_file(dex_path,
1932                                           *oat_dir_out,
1933                                           instruction_set,
1934                                           true /* is_secondary_dex */,
1935                                           &oat_file_fd,
1936                                           &vdex_file_fd)) {
1937             _exit(kSecondaryDexDexoptAnalyzerSkippedOpenOutput);
1938         }
1939 
1940         // Analyze profiles.
1941         bool profile_was_updated = analyze_profiles(uid, pkgname, dex_path,
1942                 /*is_secondary_dex*/true);
1943 
1944         // Run dexoptanalyzer to get dexopt_needed code. This is not expected to return.
1945         // Note that we do not do it before the fork since opening the files is required to happen
1946         // after forking.
1947         RunDexoptAnalyzer run_dexopt_analyzer(dex_path,
1948                                               vdex_file_fd.get(),
1949                                               oat_file_fd.get(),
1950                                               zip_fd.get(),
1951                                               instruction_set,
1952                                               compiler_filter, profile_was_updated,
1953                                               downgrade,
1954                                               class_loader_context,
1955                                               join_fds(context_zip_fds));
1956         run_dexopt_analyzer.Exec(kSecondaryDexDexoptAnalyzerSkippedFailExec);
1957     }
1958 
1959     /* parent */
1960     int result = wait_child(pid);
1961     if (!WIFEXITED(result)) {
1962         *error_msg = StringPrintf("dexoptanalyzer failed for path %s: 0x%04x",
1963                                   dex_path.c_str(),
1964                                   result);
1965         LOG(ERROR) << *error_msg;
1966         return false;
1967     }
1968     result = WEXITSTATUS(result);
1969     // Check that we successfully executed dexoptanalyzer.
1970     bool success = process_secondary_dexoptanalyzer_result(dex_path,
1971                                                            result,
1972                                                            dexopt_needed_out,
1973                                                            error_msg);
1974     if (!success) {
1975         LOG(ERROR) << *error_msg;
1976     }
1977 
1978     LOG(DEBUG) << "Processed secondary dex file " << dex_path << " result=" << result;
1979 
1980     // Run dexopt only if needed or forced.
1981     // Note that dexoptanalyzer is executed even if force compilation is enabled (because it
1982     // makes the code simpler; force compilation is only needed during tests).
1983     if (success &&
1984         (result != kSecondaryDexDexoptAnalyzerSkippedNoFile) &&
1985         ((dexopt_flags & DEXOPT_FORCE) != 0)) {
1986         *dexopt_needed_out = DEX2OAT_FROM_SCRATCH;
1987     }
1988 
1989     // Check if we should make the oat file public.
1990     // Note that if the dex file is not public the compiled code cannot be made public.
1991     // It is ok to check this flag outside in the parent process.
1992     *is_public_out = ((dexopt_flags & DEXOPT_PUBLIC) != 0) && is_file_public(dex_path);
1993 
1994     return success;
1995 }
1996 
format_dexopt_error(int status,const char * dex_path)1997 static std::string format_dexopt_error(int status, const char* dex_path) {
1998   if (WIFEXITED(status)) {
1999     int int_code = WEXITSTATUS(status);
2000     const char* code_name = get_return_code_name(static_cast<DexoptReturnCodes>(int_code));
2001     if (code_name != nullptr) {
2002       return StringPrintf("Dex2oat invocation for %s failed: %s", dex_path, code_name);
2003     }
2004   }
2005   return StringPrintf("Dex2oat invocation for %s failed with 0x%04x", dex_path, status);
2006 }
2007 
dexopt(const char * dex_path,uid_t uid,const char * pkgname,const char * instruction_set,int dexopt_needed,const char * oat_dir,int dexopt_flags,const char * compiler_filter,const char * volume_uuid,const char * class_loader_context,const char * se_info,bool downgrade,int target_sdk_version,const char * profile_name,const char * dex_metadata_path,const char * compilation_reason,std::string * error_msg)2008 int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
2009         int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
2010         const char* volume_uuid, const char* class_loader_context, const char* se_info,
2011         bool downgrade, int target_sdk_version, const char* profile_name,
2012         const char* dex_metadata_path, const char* compilation_reason, std::string* error_msg) {
2013     CHECK(pkgname != nullptr);
2014     CHECK(pkgname[0] != 0);
2015     CHECK(error_msg != nullptr);
2016     CHECK_EQ(dexopt_flags & ~DEXOPT_MASK, 0)
2017         << "dexopt flags contains unknown fields: " << dexopt_flags;
2018 
2019     if (!validate_dex_path_size(dex_path)) {
2020         *error_msg = StringPrintf("Failed to validate %s", dex_path);
2021         return -1;
2022     }
2023 
2024     if (class_loader_context != nullptr && strlen(class_loader_context) > PKG_PATH_MAX) {
2025         *error_msg = StringPrintf("Class loader context exceeds the allowed size: %s",
2026                                   class_loader_context);
2027         LOG(ERROR) << *error_msg;
2028         return -1;
2029     }
2030 
2031     bool is_public = (dexopt_flags & DEXOPT_PUBLIC) != 0;
2032     bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
2033     bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
2034     bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
2035     bool is_secondary_dex = (dexopt_flags & DEXOPT_SECONDARY_DEX) != 0;
2036     bool background_job_compile = (dexopt_flags & DEXOPT_IDLE_BACKGROUND_JOB) != 0;
2037     bool enable_hidden_api_checks = (dexopt_flags & DEXOPT_ENABLE_HIDDEN_API_CHECKS) != 0;
2038     bool generate_compact_dex = (dexopt_flags & DEXOPT_GENERATE_COMPACT_DEX) != 0;
2039     bool generate_app_image = (dexopt_flags & DEXOPT_GENERATE_APP_IMAGE) != 0;
2040 
2041     // Check if we're dealing with a secondary dex file and if we need to compile it.
2042     std::string oat_dir_str;
2043     std::vector<std::string> context_dex_paths;
2044     if (is_secondary_dex) {
2045         if (!get_class_loader_context_dex_paths(class_loader_context, uid, &context_dex_paths)) {
2046             *error_msg = "Failed acquiring context dex paths";
2047             return -1;  // We had an error, logged in the process method.
2048         }
2049 
2050         if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
2051                 instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
2052                 downgrade, class_loader_context, context_dex_paths, error_msg)) {
2053             oat_dir = oat_dir_str.c_str();
2054             if (dexopt_needed == NO_DEXOPT_NEEDED) {
2055                 return 0;  // Nothing to do, report success.
2056             }
2057         } else {
2058             if (error_msg->empty()) {  // TODO: Make this a CHECK.
2059                 *error_msg = "Failed processing secondary.";
2060             }
2061             return -1;  // We had an error, logged in the process method.
2062         }
2063     } else {
2064         // Currently these flags are only used for secondary dex files.
2065         // Verify that they are not set for primary apks.
2066         CHECK((dexopt_flags & DEXOPT_STORAGE_CE) == 0);
2067         CHECK((dexopt_flags & DEXOPT_STORAGE_DE) == 0);
2068     }
2069 
2070     // Open the input file.
2071     unique_fd input_fd(open(dex_path, O_RDONLY, 0));
2072     if (input_fd.get() < 0) {
2073         *error_msg = StringPrintf("installd cannot open '%s' for input during dexopt", dex_path);
2074         LOG(ERROR) << *error_msg;
2075         return -1;
2076     }
2077 
2078     // Open class loader context dex files.
2079     std::vector<unique_fd> context_input_fds;
2080     if (open_dex_paths(context_dex_paths, &context_input_fds, error_msg) != 0) {
2081         LOG(ERROR) << *error_msg;
2082         return -1;
2083     }
2084 
2085     // Create the output OAT file.
2086     char out_oat_path[PKG_PATH_MAX];
2087     Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid,
2088             instruction_set, is_secondary_dex, out_oat_path);
2089     if (out_oat_fd.get() < 0) {
2090         *error_msg = "Could not open out oat file.";
2091         return -1;
2092     }
2093 
2094     // Open vdex files.
2095     Dex2oatFileWrapper in_vdex_fd;
2096     Dex2oatFileWrapper out_vdex_fd;
2097     if (!open_vdex_files_for_dex2oat(dex_path, out_oat_path, dexopt_needed, instruction_set,
2098             is_public, uid, is_secondary_dex, profile_guided, &in_vdex_fd, &out_vdex_fd)) {
2099         *error_msg = "Could not open vdex files.";
2100         return -1;
2101     }
2102 
2103     // Ensure that the oat dir and the compiler artifacts of secondary dex files have the correct
2104     // selinux context (we generate them on the fly during the dexopt invocation and they don't
2105     // fully inherit their parent context).
2106     // Note that for primary apk the oat files are created before, in a separate installd
2107     // call which also does the restorecon. TODO(calin): unify the paths.
2108     if (is_secondary_dex) {
2109         if (selinux_android_restorecon_pkgdir(oat_dir, se_info, uid,
2110                 SELINUX_ANDROID_RESTORECON_RECURSE)) {
2111             *error_msg = std::string("Failed to restorecon ").append(oat_dir);
2112             LOG(ERROR) << *error_msg;
2113             return -1;
2114         }
2115     }
2116 
2117     // Create a swap file if necessary.
2118     unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
2119 
2120     // Create the app image file if needed.
2121     Dex2oatFileWrapper image_fd = maybe_open_app_image(
2122             out_oat_path, generate_app_image, is_public, uid, is_secondary_dex);
2123 
2124     // Open the reference profile if needed.
2125     Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
2126             pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
2127 
2128     unique_fd dex_metadata_fd;
2129     if (dex_metadata_path != nullptr) {
2130         dex_metadata_fd.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW)));
2131         if (dex_metadata_fd.get() < 0) {
2132             PLOG(ERROR) << "Failed to open dex metadata file " << dex_metadata_path;
2133         }
2134     }
2135 
2136     LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---";
2137 
2138     RunDex2Oat runner(input_fd.get(),
2139                       out_oat_fd.get(),
2140                       in_vdex_fd.get(),
2141                       out_vdex_fd.get(),
2142                       image_fd.get(),
2143                       dex_path,
2144                       out_oat_path,
2145                       swap_fd.get(),
2146                       instruction_set,
2147                       compiler_filter,
2148                       debuggable,
2149                       boot_complete,
2150                       background_job_compile,
2151                       reference_profile_fd.get(),
2152                       class_loader_context,
2153                       join_fds(context_input_fds),
2154                       target_sdk_version,
2155                       enable_hidden_api_checks,
2156                       generate_compact_dex,
2157                       dex_metadata_fd.get(),
2158                       compilation_reason);
2159 
2160     pid_t pid = fork();
2161     if (pid == 0) {
2162         /* child -- drop privileges before continuing */
2163         drop_capabilities(uid);
2164 
2165         SetDex2OatScheduling(boot_complete);
2166         if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
2167             PLOG(ERROR) << "flock(" << out_oat_path << ") failed";
2168             _exit(DexoptReturnCodes::kFlock);
2169         }
2170 
2171         runner.Exec(DexoptReturnCodes::kDex2oatExec);
2172     } else {
2173         int res = wait_child(pid);
2174         if (res == 0) {
2175             LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' (success) ---";
2176         } else {
2177             LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' --- status=0x"
2178                          << std::hex << std::setw(4) << res << ", process failed";
2179             *error_msg = format_dexopt_error(res, dex_path);
2180             return res;
2181         }
2182     }
2183 
2184     update_out_oat_access_times(dex_path, out_oat_path);
2185 
2186     // We've been successful, don't delete output.
2187     out_oat_fd.SetCleanup(false);
2188     out_vdex_fd.SetCleanup(false);
2189     image_fd.SetCleanup(false);
2190     reference_profile_fd.SetCleanup(false);
2191 
2192     return 0;
2193 }
2194 
2195 // Try to remove the given directory. Log an error if the directory exists
2196 // and is empty but could not be removed.
rmdir_if_empty(const char * dir)2197 static bool rmdir_if_empty(const char* dir) {
2198     if (rmdir(dir) == 0) {
2199         return true;
2200     }
2201     if (errno == ENOENT || errno == ENOTEMPTY) {
2202         return true;
2203     }
2204     PLOG(ERROR) << "Failed to remove dir: " << dir;
2205     return false;
2206 }
2207 
2208 // Try to unlink the given file. Log an error if the file exists and could not
2209 // be unlinked.
unlink_if_exists(const std::string & file)2210 static bool unlink_if_exists(const std::string& file) {
2211     if (unlink(file.c_str()) == 0) {
2212         return true;
2213     }
2214     if (errno == ENOENT) {
2215         return true;
2216 
2217     }
2218     PLOG(ERROR) << "Could not unlink: " << file;
2219     return false;
2220 }
2221 
2222 enum ReconcileSecondaryDexResult {
2223     kReconcileSecondaryDexExists = 0,
2224     kReconcileSecondaryDexCleanedUp = 1,
2225     kReconcileSecondaryDexValidationError = 2,
2226     kReconcileSecondaryDexCleanUpError = 3,
2227     kReconcileSecondaryDexAccessIOError = 4,
2228 };
2229 
2230 // Reconcile the secondary dex 'dex_path' and its generated oat files.
2231 // Return true if all the parameters are valid and the secondary dex file was
2232 //   processed successfully (i.e. the dex_path either exists, or if not, its corresponding
2233 //   oat/vdex/art files where deleted successfully). In this case, out_secondary_dex_exists
2234 //   will be true if the secondary dex file still exists. If the secondary dex file does not exist,
2235 //   the method cleans up any previously generated compiler artifacts (oat, vdex, art).
2236 // Return false if there were errors during processing. In this case
2237 //   out_secondary_dex_exists will be set to false.
reconcile_secondary_dex_file(const std::string & dex_path,const std::string & pkgname,int uid,const std::vector<std::string> & isas,const std::unique_ptr<std::string> & volume_uuid,int storage_flag,bool * out_secondary_dex_exists)2238 bool reconcile_secondary_dex_file(const std::string& dex_path,
2239         const std::string& pkgname, int uid, const std::vector<std::string>& isas,
2240         const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
2241         /*out*/bool* out_secondary_dex_exists) {
2242     *out_secondary_dex_exists = false;  // start by assuming the file does not exist.
2243     if (isas.size() == 0) {
2244         LOG(ERROR) << "reconcile_secondary_dex_file called with empty isas vector";
2245         return false;
2246     }
2247 
2248     if (storage_flag != FLAG_STORAGE_CE && storage_flag != FLAG_STORAGE_DE) {
2249         LOG(ERROR) << "reconcile_secondary_dex_file called with invalid storage_flag: "
2250                 << storage_flag;
2251         return false;
2252     }
2253 
2254     // As a security measure we want to unlink art artifacts with the reduced capabilities
2255     // of the package user id. So we fork and drop capabilities in the child.
2256     pid_t pid = fork();
2257     if (pid == 0) {
2258         /* child -- drop privileges before continuing */
2259         drop_capabilities(uid);
2260 
2261         const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
2262         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr,
2263                 uid, storage_flag)) {
2264             LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
2265             _exit(kReconcileSecondaryDexValidationError);
2266         }
2267 
2268         SecondaryDexAccess access_check = check_secondary_dex_access(dex_path);
2269         switch (access_check) {
2270             case kSecondaryDexAccessDoesNotExist:
2271                  // File does not exist. Proceed with cleaning.
2272                 break;
2273             case kSecondaryDexAccessReadOk: _exit(kReconcileSecondaryDexExists);
2274             case kSecondaryDexAccessIOError: _exit(kReconcileSecondaryDexAccessIOError);
2275             case kSecondaryDexAccessPermissionError: _exit(kReconcileSecondaryDexValidationError);
2276             default:
2277                 LOG(ERROR) << "Unexpected result from check_secondary_dex_access: " << access_check;
2278                 _exit(kReconcileSecondaryDexValidationError);
2279         }
2280 
2281         // The secondary dex does not exist anymore or it's. Clear any generated files.
2282         char oat_path[PKG_PATH_MAX];
2283         char oat_dir[PKG_PATH_MAX];
2284         char oat_isa_dir[PKG_PATH_MAX];
2285         bool result = true;
2286         for (size_t i = 0; i < isas.size(); i++) {
2287             std::string error_msg;
2288             if (!create_secondary_dex_oat_layout(
2289                     dex_path,isas[i], oat_dir, oat_isa_dir, oat_path, &error_msg)) {
2290                 LOG(ERROR) << error_msg;
2291                 _exit(kReconcileSecondaryDexValidationError);
2292             }
2293 
2294             // Delete oat/vdex/art files.
2295             result = unlink_if_exists(oat_path) && result;
2296             result = unlink_if_exists(create_vdex_filename(oat_path)) && result;
2297             result = unlink_if_exists(create_image_filename(oat_path)) && result;
2298 
2299             // Delete profiles.
2300             std::string current_profile = create_current_profile_path(
2301                 multiuser_get_user_id(uid), pkgname, dex_path, /*is_secondary*/true);
2302             std::string reference_profile = create_reference_profile_path(
2303                 pkgname, dex_path, /*is_secondary*/true);
2304             result = unlink_if_exists(current_profile) && result;
2305             result = unlink_if_exists(reference_profile) && result;
2306 
2307             // We upgraded once the location of current profile for secondary dex files.
2308             // Check for any previous left-overs and remove them as well.
2309             std::string old_current_profile = dex_path + ".prof";
2310             result = unlink_if_exists(old_current_profile);
2311 
2312             // Try removing the directories as well, they might be empty.
2313             result = rmdir_if_empty(oat_isa_dir) && result;
2314             result = rmdir_if_empty(oat_dir) && result;
2315         }
2316         if (!result) {
2317             PLOG(ERROR) << "Failed to clean secondary dex artifacts for location " << dex_path;
2318         }
2319         _exit(result ? kReconcileSecondaryDexCleanedUp : kReconcileSecondaryDexAccessIOError);
2320     }
2321 
2322     int return_code = wait_child(pid);
2323     if (!WIFEXITED(return_code)) {
2324         LOG(WARNING) << "reconcile dex failed for location " << dex_path << ": " << return_code;
2325     } else {
2326         return_code = WEXITSTATUS(return_code);
2327     }
2328 
2329     LOG(DEBUG) << "Reconcile secondary dex path " << dex_path << " result=" << return_code;
2330 
2331     switch (return_code) {
2332         case kReconcileSecondaryDexCleanedUp:
2333         case kReconcileSecondaryDexValidationError:
2334             // If we couldn't validate assume the dex file does not exist.
2335             // This will purge the entry from the PM records.
2336             *out_secondary_dex_exists = false;
2337             return true;
2338         case kReconcileSecondaryDexExists:
2339             *out_secondary_dex_exists = true;
2340             return true;
2341         case kReconcileSecondaryDexAccessIOError:
2342             // We had an access IO error.
2343             // Return false so that we can try again.
2344             // The value of out_secondary_dex_exists does not matter in this case and by convention
2345             // is set to false.
2346             *out_secondary_dex_exists = false;
2347             return false;
2348         default:
2349             LOG(ERROR) << "Unexpected code from reconcile_secondary_dex_file: " << return_code;
2350             *out_secondary_dex_exists = false;
2351             return false;
2352     }
2353 }
2354 
2355 // Compute and return the hash (SHA-256) of the secondary dex file at dex_path.
2356 // Returns true if all parameters are valid and the hash successfully computed and stored in
2357 // out_secondary_dex_hash.
2358 // Also returns true with an empty hash if the file does not currently exist or is not accessible to
2359 // the app.
2360 // For any other errors (e.g. if any of the parameters are invalid) returns false.
hash_secondary_dex_file(const std::string & dex_path,const std::string & pkgname,int uid,const std::unique_ptr<std::string> & volume_uuid,int storage_flag,std::vector<uint8_t> * out_secondary_dex_hash)2361 bool hash_secondary_dex_file(const std::string& dex_path, const std::string& pkgname, int uid,
2362         const std::unique_ptr<std::string>& volume_uuid, int storage_flag,
2363         std::vector<uint8_t>* out_secondary_dex_hash) {
2364     out_secondary_dex_hash->clear();
2365 
2366     const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
2367 
2368     if (storage_flag != FLAG_STORAGE_CE && storage_flag != FLAG_STORAGE_DE) {
2369         LOG(ERROR) << "hash_secondary_dex_file called with invalid storage_flag: "
2370                 << storage_flag;
2371         return false;
2372     }
2373 
2374     // Pipe to get the hash result back from our child process.
2375     unique_fd pipe_read, pipe_write;
2376     if (!Pipe(&pipe_read, &pipe_write)) {
2377         PLOG(ERROR) << "Failed to create pipe";
2378         return false;
2379     }
2380 
2381     // Fork so that actual access to the files is done in the app's own UID, to ensure we only
2382     // access data the app itself can access.
2383     pid_t pid = fork();
2384     if (pid == 0) {
2385         // child -- drop privileges before continuing
2386         drop_capabilities(uid);
2387         pipe_read.reset();
2388 
2389         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr, uid, storage_flag)) {
2390             LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
2391             _exit(DexoptReturnCodes::kHashValidatePath);
2392         }
2393 
2394         unique_fd fd(TEMP_FAILURE_RETRY(open(dex_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)));
2395         if (fd == -1) {
2396             if (errno == EACCES || errno == ENOENT) {
2397                 // Not treated as an error.
2398                 _exit(0);
2399             }
2400             PLOG(ERROR) << "Failed to open secondary dex " << dex_path;
2401             _exit(DexoptReturnCodes::kHashOpenPath);
2402         }
2403 
2404         SHA256_CTX ctx;
2405         SHA256_Init(&ctx);
2406 
2407         std::vector<uint8_t> buffer(65536);
2408         while (true) {
2409             ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
2410             if (bytes_read == 0) {
2411                 break;
2412             } else if (bytes_read == -1) {
2413                 PLOG(ERROR) << "Failed to read secondary dex " << dex_path;
2414                 _exit(DexoptReturnCodes::kHashReadDex);
2415             }
2416 
2417             SHA256_Update(&ctx, buffer.data(), bytes_read);
2418         }
2419 
2420         std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
2421         SHA256_Final(hash.data(), &ctx);
2422         if (!WriteFully(pipe_write, hash.data(), hash.size())) {
2423             _exit(DexoptReturnCodes::kHashWrite);
2424         }
2425 
2426         _exit(0);
2427     }
2428 
2429     // parent
2430     pipe_write.reset();
2431 
2432     out_secondary_dex_hash->resize(SHA256_DIGEST_LENGTH);
2433     if (!ReadFully(pipe_read, out_secondary_dex_hash->data(), out_secondary_dex_hash->size())) {
2434         out_secondary_dex_hash->clear();
2435     }
2436     return wait_child(pid) == 0;
2437 }
2438 
2439 // Helper for move_ab, so that we can have common failure-case cleanup.
unlink_and_rename(const char * from,const char * to)2440 static bool unlink_and_rename(const char* from, const char* to) {
2441     // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
2442     // return a failure.
2443     struct stat s;
2444     if (stat(to, &s) == 0) {
2445         if (!S_ISREG(s.st_mode)) {
2446             LOG(ERROR) << from << " is not a regular file to replace for A/B.";
2447             return false;
2448         }
2449         if (unlink(to) != 0) {
2450             LOG(ERROR) << "Could not unlink " << to << " to move A/B.";
2451             return false;
2452         }
2453     } else {
2454         // This may be a permission problem. We could investigate the error code, but we'll just
2455         // let the rename failure do the work for us.
2456     }
2457 
2458     // Try to rename "to" to "from."
2459     if (rename(from, to) != 0) {
2460         PLOG(ERROR) << "Could not rename " << from << " to " << to;
2461         return false;
2462     }
2463     return true;
2464 }
2465 
2466 // Move/rename a B artifact (from) to an A artifact (to).
move_ab_path(const std::string & b_path,const std::string & a_path)2467 static bool move_ab_path(const std::string& b_path, const std::string& a_path) {
2468     // Check whether B exists.
2469     {
2470         struct stat s;
2471         if (stat(b_path.c_str(), &s) != 0) {
2472             // Silently ignore for now. The service calling this isn't smart enough to understand
2473             // lack of artifacts at the moment.
2474             return false;
2475         }
2476         if (!S_ISREG(s.st_mode)) {
2477             LOG(ERROR) << "A/B artifact " << b_path << " is not a regular file.";
2478             // Try to unlink, but swallow errors.
2479             unlink(b_path.c_str());
2480             return false;
2481         }
2482     }
2483 
2484     // Rename B to A.
2485     if (!unlink_and_rename(b_path.c_str(), a_path.c_str())) {
2486         // Delete the b_path so we don't try again (or fail earlier).
2487         if (unlink(b_path.c_str()) != 0) {
2488             PLOG(ERROR) << "Could not unlink " << b_path;
2489         }
2490 
2491         return false;
2492     }
2493 
2494     return true;
2495 }
2496 
move_ab(const char * apk_path,const char * instruction_set,const char * oat_dir)2497 bool move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
2498     // Get the current slot suffix. No suffix, no A/B.
2499     const std::string slot_suffix = GetProperty("ro.boot.slot_suffix", "");
2500     if (slot_suffix.empty()) {
2501         return false;
2502     }
2503 
2504     if (!ValidateTargetSlotSuffix(slot_suffix)) {
2505         LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
2506         return false;
2507     }
2508 
2509     // Validate other inputs.
2510     if (validate_apk_path(apk_path) != 0) {
2511         LOG(ERROR) << "Invalid apk_path: " << apk_path;
2512         return false;
2513     }
2514     if (validate_apk_path(oat_dir) != 0) {
2515         LOG(ERROR) << "Invalid oat_dir: " << oat_dir;
2516         return false;
2517     }
2518 
2519     char a_path[PKG_PATH_MAX];
2520     if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
2521         return false;
2522     }
2523     const std::string a_vdex_path = create_vdex_filename(a_path);
2524     const std::string a_image_path = create_image_filename(a_path);
2525 
2526     // B path = A path + slot suffix.
2527     const std::string b_path = StringPrintf("%s.%s", a_path, slot_suffix.c_str());
2528     const std::string b_vdex_path = StringPrintf("%s.%s", a_vdex_path.c_str(), slot_suffix.c_str());
2529     const std::string b_image_path = StringPrintf("%s.%s",
2530                                                   a_image_path.c_str(),
2531                                                   slot_suffix.c_str());
2532 
2533     bool success = true;
2534     if (move_ab_path(b_path, a_path)) {
2535         if (move_ab_path(b_vdex_path, a_vdex_path)) {
2536             // Note: we can live without an app image. As such, ignore failure to move the image file.
2537             //       If we decide to require the app image, or the app image being moved correctly,
2538             //       then change accordingly.
2539             constexpr bool kIgnoreAppImageFailure = true;
2540 
2541             if (!a_image_path.empty()) {
2542                 if (!move_ab_path(b_image_path, a_image_path)) {
2543                     unlink(a_image_path.c_str());
2544                     if (!kIgnoreAppImageFailure) {
2545                         success = false;
2546                     }
2547                 }
2548             }
2549         } else {
2550             // Cleanup: delete B image, ignore errors.
2551             unlink(b_image_path.c_str());
2552             success = false;
2553         }
2554     } else {
2555         // Cleanup: delete B image, ignore errors.
2556         unlink(b_vdex_path.c_str());
2557         unlink(b_image_path.c_str());
2558         success = false;
2559     }
2560     return success;
2561 }
2562 
delete_odex(const char * apk_path,const char * instruction_set,const char * oat_dir)2563 bool delete_odex(const char* apk_path, const char* instruction_set, const char* oat_dir) {
2564     // Delete the oat/odex file.
2565     char out_path[PKG_PATH_MAX];
2566     if (!create_oat_out_path(apk_path, instruction_set, oat_dir,
2567             /*is_secondary_dex*/false, out_path)) {
2568         return false;
2569     }
2570 
2571     // In case of a permission failure report the issue. Otherwise just print a warning.
2572     auto unlink_and_check = [](const char* path) -> bool {
2573         int result = unlink(path);
2574         if (result != 0) {
2575             if (errno == EACCES || errno == EPERM) {
2576                 PLOG(ERROR) << "Could not unlink " << path;
2577                 return false;
2578             }
2579             PLOG(WARNING) << "Could not unlink " << path;
2580         }
2581         return true;
2582     };
2583 
2584     // Delete the oat/odex file.
2585     bool return_value_oat = unlink_and_check(out_path);
2586 
2587     // Derive and delete the app image.
2588     bool return_value_art = unlink_and_check(create_image_filename(out_path).c_str());
2589 
2590     // Derive and delete the vdex file.
2591     bool return_value_vdex = unlink_and_check(create_vdex_filename(out_path).c_str());
2592 
2593     // Report success.
2594     return return_value_oat && return_value_art && return_value_vdex;
2595 }
2596 
is_absolute_path(const std::string & path)2597 static bool is_absolute_path(const std::string& path) {
2598     if (path.find('/') != 0 || path.find("..") != std::string::npos) {
2599         LOG(ERROR) << "Invalid absolute path " << path;
2600         return false;
2601     } else {
2602         return true;
2603     }
2604 }
2605 
is_valid_instruction_set(const std::string & instruction_set)2606 static bool is_valid_instruction_set(const std::string& instruction_set) {
2607     // TODO: add explicit whitelisting of instruction sets
2608     if (instruction_set.find('/') != std::string::npos) {
2609         LOG(ERROR) << "Invalid instruction set " << instruction_set;
2610         return false;
2611     } else {
2612         return true;
2613     }
2614 }
2615 
calculate_oat_file_path_default(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)2616 bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir,
2617         const char *apk_path, const char *instruction_set) {
2618     std::string oat_dir_ = oat_dir;
2619     std::string apk_path_ = apk_path;
2620     std::string instruction_set_ = instruction_set;
2621 
2622     if (!is_absolute_path(oat_dir_)) return false;
2623     if (!is_absolute_path(apk_path_)) return false;
2624     if (!is_valid_instruction_set(instruction_set_)) return false;
2625 
2626     std::string::size_type end = apk_path_.rfind('.');
2627     std::string::size_type start = apk_path_.rfind('/', end);
2628     if (end == std::string::npos || start == std::string::npos) {
2629         LOG(ERROR) << "Invalid apk_path " << apk_path_;
2630         return false;
2631     }
2632 
2633     std::string res_ = oat_dir_ + '/' + instruction_set + '/'
2634             + apk_path_.substr(start + 1, end - start - 1) + ".odex";
2635     const char* res = res_.c_str();
2636     if (strlen(res) >= PKG_PATH_MAX) {
2637         LOG(ERROR) << "Result too large";
2638         return false;
2639     } else {
2640         strlcpy(path, res, PKG_PATH_MAX);
2641         return true;
2642     }
2643 }
2644 
calculate_odex_file_path_default(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)2645 bool calculate_odex_file_path_default(char path[PKG_PATH_MAX], const char *apk_path,
2646         const char *instruction_set) {
2647     std::string apk_path_ = apk_path;
2648     std::string instruction_set_ = instruction_set;
2649 
2650     if (!is_absolute_path(apk_path_)) return false;
2651     if (!is_valid_instruction_set(instruction_set_)) return false;
2652 
2653     std::string::size_type end = apk_path_.rfind('.');
2654     std::string::size_type start = apk_path_.rfind('/', end);
2655     if (end == std::string::npos || start == std::string::npos) {
2656         LOG(ERROR) << "Invalid apk_path " << apk_path_;
2657         return false;
2658     }
2659 
2660     std::string oat_dir = apk_path_.substr(0, start + 1) + "oat";
2661     return calculate_oat_file_path_default(path, oat_dir.c_str(), apk_path, instruction_set);
2662 }
2663 
create_cache_path_default(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)2664 bool create_cache_path_default(char path[PKG_PATH_MAX], const char *src,
2665         const char *instruction_set) {
2666     std::string src_ = src;
2667     std::string instruction_set_ = instruction_set;
2668 
2669     if (!is_absolute_path(src_)) return false;
2670     if (!is_valid_instruction_set(instruction_set_)) return false;
2671 
2672     for (auto it = src_.begin() + 1; it < src_.end(); ++it) {
2673         if (*it == '/') {
2674             *it = '@';
2675         }
2676     }
2677 
2678     std::string res_ = android_data_dir + DALVIK_CACHE + '/' + instruction_set_ + src_
2679             + DALVIK_CACHE_POSTFIX;
2680     const char* res = res_.c_str();
2681     if (strlen(res) >= PKG_PATH_MAX) {
2682         LOG(ERROR) << "Result too large";
2683         return false;
2684     } else {
2685         strlcpy(path, res, PKG_PATH_MAX);
2686         return true;
2687     }
2688 }
2689 
open_classpath_files(const std::string & classpath,std::vector<unique_fd> * apk_fds,std::vector<std::string> * dex_locations)2690 bool open_classpath_files(const std::string& classpath, std::vector<unique_fd>* apk_fds,
2691         std::vector<std::string>* dex_locations) {
2692     std::vector<std::string> classpaths_elems = base::Split(classpath, ":");
2693     for (const std::string& elem : classpaths_elems) {
2694         unique_fd fd(TEMP_FAILURE_RETRY(open(elem.c_str(), O_RDONLY)));
2695         if (fd < 0) {
2696             PLOG(ERROR) << "Could not open classpath elem " << elem;
2697             return false;
2698         } else {
2699             apk_fds->push_back(std::move(fd));
2700             dex_locations->push_back(elem);
2701         }
2702     }
2703     return true;
2704 }
2705 
create_app_profile_snapshot(int32_t app_id,const std::string & package_name,const std::string & profile_name,const std::string & classpath)2706 static bool create_app_profile_snapshot(int32_t app_id,
2707                                         const std::string& package_name,
2708                                         const std::string& profile_name,
2709                                         const std::string& classpath) {
2710     int app_shared_gid = multiuser_get_shared_gid(/*user_id*/ 0, app_id);
2711 
2712     unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
2713     if (snapshot_fd < 0) {
2714         return false;
2715     }
2716 
2717     std::vector<unique_fd> profiles_fd;
2718     unique_fd reference_profile_fd;
2719     open_profile_files(app_shared_gid, package_name, profile_name, /*is_secondary_dex*/ false,
2720             &profiles_fd, &reference_profile_fd);
2721     if (profiles_fd.empty() || (reference_profile_fd.get() < 0)) {
2722         return false;
2723     }
2724 
2725     profiles_fd.push_back(std::move(reference_profile_fd));
2726 
2727     // Open the class paths elements. These will be used to filter out profile data that does
2728     // not belong to the classpath during merge.
2729     std::vector<unique_fd> apk_fds;
2730     std::vector<std::string> dex_locations;
2731     if (!open_classpath_files(classpath, &apk_fds, &dex_locations)) {
2732         return false;
2733     }
2734 
2735     RunProfman args;
2736     args.SetupMerge(profiles_fd, snapshot_fd, apk_fds, dex_locations);
2737     pid_t pid = fork();
2738     if (pid == 0) {
2739         /* child -- drop privileges before continuing */
2740         drop_capabilities(app_shared_gid);
2741         args.Exec();
2742     }
2743 
2744     /* parent */
2745     int return_code = wait_child(pid);
2746     if (!WIFEXITED(return_code)) {
2747         LOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
2748         return false;
2749     }
2750 
2751     return true;
2752 }
2753 
create_boot_image_profile_snapshot(const std::string & package_name,const std::string & profile_name,const std::string & classpath)2754 static bool create_boot_image_profile_snapshot(const std::string& package_name,
2755                                                const std::string& profile_name,
2756                                                const std::string& classpath) {
2757     // The reference profile directory for the android package might not be prepared. Do it now.
2758     const std::string ref_profile_dir =
2759             create_primary_reference_profile_package_dir_path(package_name);
2760     if (fs_prepare_dir(ref_profile_dir.c_str(), 0770, AID_SYSTEM, AID_SYSTEM) != 0) {
2761         PLOG(ERROR) << "Failed to prepare " << ref_profile_dir;
2762         return false;
2763     }
2764 
2765     // Return false for empty class path since it may otherwise return true below if profiles is
2766     // empty.
2767     if (classpath.empty()) {
2768         PLOG(ERROR) << "Class path is empty";
2769         return false;
2770     }
2771 
2772     // Open and create the snapshot profile.
2773     unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
2774 
2775     // Collect all non empty profiles.
2776     // The collection will traverse all applications profiles and find the non empty files.
2777     // This has the potential of inspecting a large number of files and directories (depending
2778     // on the number of applications and users). So there is a slight increase in the chance
2779     // to get get occasionally I/O errors (e.g. for opening the file). When that happens do not
2780     // fail the snapshot and aggregate whatever profile we could open.
2781     //
2782     // The profile snapshot is a best effort based on available data it's ok if some data
2783     // from some apps is missing. It will be counter productive for the snapshot to fail
2784     // because we could not open or read some of the files.
2785     std::vector<std::string> profiles;
2786     if (!collect_profiles(&profiles)) {
2787         LOG(WARNING) << "There were errors while collecting the profiles for the boot image.";
2788     }
2789 
2790     // If we have no profiles return early.
2791     if (profiles.empty()) {
2792         return true;
2793     }
2794 
2795     // Open the classpath elements. These will be used to filter out profile data that does
2796     // not belong to the classpath during merge.
2797     std::vector<unique_fd> apk_fds;
2798     std::vector<std::string> dex_locations;
2799     if (!open_classpath_files(classpath, &apk_fds, &dex_locations)) {
2800         return false;
2801     }
2802 
2803     // If we could not open any files from the classpath return an error.
2804     if (apk_fds.empty()) {
2805         LOG(ERROR) << "Could not open any of the classpath elements.";
2806         return false;
2807     }
2808 
2809     // Aggregate the profiles in batches of kAggregationBatchSize.
2810     // We do this to avoid opening a huge a amount of files.
2811     static constexpr size_t kAggregationBatchSize = 10;
2812 
2813     std::vector<unique_fd> profiles_fd;
2814     for (size_t i = 0; i < profiles.size(); )  {
2815         for (size_t k = 0; k < kAggregationBatchSize && i < profiles.size(); k++, i++) {
2816             unique_fd fd = open_profile(AID_SYSTEM, profiles[i], O_RDONLY);
2817             if (fd.get() >= 0) {
2818                 profiles_fd.push_back(std::move(fd));
2819             }
2820         }
2821         RunProfman args;
2822         args.SetupMerge(profiles_fd,
2823                         snapshot_fd,
2824                         apk_fds,
2825                         dex_locations,
2826                         /*store_aggregation_counters=*/true);
2827         pid_t pid = fork();
2828         if (pid == 0) {
2829             /* child -- drop privileges before continuing */
2830             drop_capabilities(AID_SYSTEM);
2831 
2832             // The introduction of new access flags into boot jars causes them to
2833             // fail dex file verification.
2834             args.Exec();
2835         }
2836 
2837         /* parent */
2838         int return_code = wait_child(pid);
2839         if (!WIFEXITED(return_code)) {
2840             PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
2841             return false;
2842         }
2843         return true;
2844     }
2845     return true;
2846 }
2847 
create_profile_snapshot(int32_t app_id,const std::string & package_name,const std::string & profile_name,const std::string & classpath)2848 bool create_profile_snapshot(int32_t app_id, const std::string& package_name,
2849         const std::string& profile_name, const std::string& classpath) {
2850     if (app_id == -1) {
2851         return create_boot_image_profile_snapshot(package_name, profile_name, classpath);
2852     } else {
2853         return create_app_profile_snapshot(app_id, package_name, profile_name, classpath);
2854     }
2855 }
2856 
prepare_app_profile(const std::string & package_name,userid_t user_id,appid_t app_id,const std::string & profile_name,const std::string & code_path,const std::unique_ptr<std::string> & dex_metadata)2857 bool prepare_app_profile(const std::string& package_name,
2858                          userid_t user_id,
2859                          appid_t app_id,
2860                          const std::string& profile_name,
2861                          const std::string& code_path,
2862                          const std::unique_ptr<std::string>& dex_metadata) {
2863     // Prepare the current profile.
2864     std::string cur_profile  = create_current_profile_path(user_id, package_name, profile_name,
2865             /*is_secondary_dex*/ false);
2866     uid_t uid = multiuser_get_uid(user_id, app_id);
2867     if (fs_prepare_file_strict(cur_profile.c_str(), 0600, uid, uid) != 0) {
2868         PLOG(ERROR) << "Failed to prepare " << cur_profile;
2869         return false;
2870     }
2871 
2872     // Check if we need to install the profile from the dex metadata.
2873     if (dex_metadata == nullptr) {
2874         return true;
2875     }
2876 
2877     // We have a dex metdata. Merge the profile into the reference profile.
2878     unique_fd ref_profile_fd = open_reference_profile(uid, package_name, profile_name,
2879             /*read_write*/ true, /*is_secondary_dex*/ false);
2880     unique_fd dex_metadata_fd(TEMP_FAILURE_RETRY(
2881             open(dex_metadata->c_str(), O_RDONLY | O_NOFOLLOW)));
2882     unique_fd apk_fd(TEMP_FAILURE_RETRY(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW)));
2883     if (apk_fd < 0) {
2884         PLOG(ERROR) << "Could not open code path " << code_path;
2885         return false;
2886     }
2887 
2888     RunProfman args;
2889     args.SetupCopyAndUpdate(std::move(dex_metadata_fd),
2890                             std::move(ref_profile_fd),
2891                             std::move(apk_fd),
2892                             code_path);
2893     pid_t pid = fork();
2894     if (pid == 0) {
2895         /* child -- drop privileges before continuing */
2896         gid_t app_shared_gid = multiuser_get_shared_gid(user_id, app_id);
2897         drop_capabilities(app_shared_gid);
2898 
2899         // The copy and update takes ownership over the fds.
2900         args.Exec();
2901     }
2902 
2903     /* parent */
2904     int return_code = wait_child(pid);
2905     if (!WIFEXITED(return_code)) {
2906         PLOG(WARNING) << "profman failed for " << package_name << ":" << profile_name;
2907         return false;
2908     }
2909     return true;
2910 }
2911 
2912 }  // namespace installd
2913 }  // namespace android
2914