• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  ** Copyright 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 
17 #include <algorithm>
18 #include <inttypes.h>
19 #include <limits>
20 #include <random>
21 #include <regex>
22 #include <selinux/android.h>
23 #include <selinux/avc.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/capability.h>
27 #include <sys/prctl.h>
28 #include <sys/stat.h>
29 #include <sys/wait.h>
30 
31 #include <android-base/logging.h>
32 #include <android-base/macros.h>
33 #include <android-base/stringprintf.h>
34 #include <android-base/strings.h>
35 #include <cutils/fs.h>
36 #include <cutils/properties.h>
37 #include <dex2oat_return_codes.h>
38 #include <log/log.h>
39 #include <private/android_filesystem_config.h>
40 
41 #include "dexopt.h"
42 #include "file_parsing.h"
43 #include "globals.h"
44 #include "installd_constants.h"
45 #include "installd_deps.h"  // Need to fill in requirements of commands.
46 #include "otapreopt_utils.h"
47 #include "system_properties.h"
48 #include "utils.h"
49 
50 #ifndef LOG_TAG
51 #define LOG_TAG "otapreopt"
52 #endif
53 
54 #define BUFFER_MAX    1024  /* input buffer for commands */
55 #define TOKEN_MAX     16    /* max number of arguments in buffer */
56 #define REPLY_MAX     256   /* largest reply allowed */
57 
58 using android::base::EndsWith;
59 using android::base::Join;
60 using android::base::Split;
61 using android::base::StartsWith;
62 using android::base::StringPrintf;
63 
64 namespace android {
65 namespace installd {
66 
67 // Check expected values for dexopt flags. If you need to change this:
68 //
69 //   RUN AN A/B OTA TO MAKE SURE THINGS STILL WORK!
70 //
71 // You most likely need to increase the protocol version and all that entails!
72 
73 static_assert(DEXOPT_PUBLIC         == 1 << 1, "DEXOPT_PUBLIC unexpected.");
74 static_assert(DEXOPT_DEBUGGABLE     == 1 << 2, "DEXOPT_DEBUGGABLE unexpected.");
75 static_assert(DEXOPT_BOOTCOMPLETE   == 1 << 3, "DEXOPT_BOOTCOMPLETE unexpected.");
76 static_assert(DEXOPT_PROFILE_GUIDED == 1 << 4, "DEXOPT_PROFILE_GUIDED unexpected.");
77 static_assert(DEXOPT_SECONDARY_DEX  == 1 << 5, "DEXOPT_SECONDARY_DEX unexpected.");
78 static_assert(DEXOPT_FORCE          == 1 << 6, "DEXOPT_FORCE unexpected.");
79 static_assert(DEXOPT_STORAGE_CE     == 1 << 7, "DEXOPT_STORAGE_CE unexpected.");
80 static_assert(DEXOPT_STORAGE_DE     == 1 << 8, "DEXOPT_STORAGE_DE unexpected.");
81 
82 static_assert(DEXOPT_MASK           == 0x1fe, "DEXOPT_MASK unexpected.");
83 
84 
85 
86 template<typename T>
RoundDown(T x,typename std::decay<T>::type n)87 static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
88     return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
89 }
90 
91 template<typename T>
RoundUp(T x,typename std::remove_reference<T>::type n)92 static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
93     return RoundDown(x + n - 1, n);
94 }
95 
96 class OTAPreoptService {
97  public:
98     // Main driver. Performs the following steps.
99     //
100     // 1) Parse options (read system properties etc from B partition).
101     //
102     // 2) Read in package data.
103     //
104     // 3) Prepare environment variables.
105     //
106     // 4) Prepare(compile) boot image, if necessary.
107     //
108     // 5) Run update.
Main(int argc,char ** argv)109     int Main(int argc, char** argv) {
110         if (!ReadArguments(argc, argv)) {
111             LOG(ERROR) << "Failed reading command line.";
112             return 1;
113         }
114 
115         if (!ReadSystemProperties()) {
116             LOG(ERROR)<< "Failed reading system properties.";
117             return 2;
118         }
119 
120         if (!ReadEnvironment()) {
121             LOG(ERROR) << "Failed reading environment properties.";
122             return 3;
123         }
124 
125         if (!CheckAndInitializeInstalldGlobals()) {
126             LOG(ERROR) << "Failed initializing globals.";
127             return 4;
128         }
129 
130         PrepareEnvironment();
131 
132         if (!PrepareBootImage(/* force */ false)) {
133             LOG(ERROR) << "Failed preparing boot image.";
134             return 5;
135         }
136 
137         int dexopt_retcode = RunPreopt();
138 
139         return dexopt_retcode;
140     }
141 
GetProperty(const char * key,char * value,const char * default_value) const142     int GetProperty(const char* key, char* value, const char* default_value) const {
143         const std::string* prop_value = system_properties_.GetProperty(key);
144         if (prop_value == nullptr) {
145             if (default_value == nullptr) {
146                 return 0;
147             }
148             // Copy in the default value.
149             strncpy(value, default_value, kPropertyValueMax - 1);
150             value[kPropertyValueMax - 1] = 0;
151             return strlen(default_value);// TODO: Need to truncate?
152         }
153         size_t size = std::min(kPropertyValueMax - 1, prop_value->length());
154         strncpy(value, prop_value->data(), size);
155         value[size] = 0;
156         return static_cast<int>(size);
157     }
158 
GetOTADataDirectory() const159     std::string GetOTADataDirectory() const {
160         return StringPrintf("%s/%s", GetOtaDirectoryPrefix().c_str(), target_slot_.c_str());
161     }
162 
GetTargetSlot() const163     const std::string& GetTargetSlot() const {
164         return target_slot_;
165     }
166 
167 private:
168 
169     struct Parameters {
170         const char *apk_path;
171         uid_t uid;
172         const char *pkgName;
173         const char *instruction_set;
174         int dexopt_needed;
175         const char* oat_dir;
176         int dexopt_flags;
177         const char* compiler_filter;
178         const char* volume_uuid;
179         const char* shared_libraries;
180         const char* se_info;
181     };
182 
ReadSystemProperties()183     bool ReadSystemProperties() {
184         static constexpr const char* kPropertyFiles[] = {
185                 "/default.prop", "/system/build.prop"
186         };
187 
188         for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
189             if (!system_properties_.Load(kPropertyFiles[i])) {
190                 return false;
191             }
192         }
193 
194         return true;
195     }
196 
ReadEnvironment()197     bool ReadEnvironment() {
198         // Parse the environment variables from init.environ.rc, which have the form
199         //   export NAME VALUE
200         // For simplicity, don't respect string quotation. The values we are interested in can be
201         // encoded without them.
202         std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
203         bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) {
204             std::smatch export_match;
205             if (!std::regex_match(line, export_match, export_regex)) {
206                 return true;
207             }
208 
209             if (export_match.size() != 3) {
210                 return true;
211             }
212 
213             std::string name = export_match[1].str();
214             std::string value = export_match[2].str();
215 
216             system_properties_.SetProperty(name, value);
217 
218             return true;
219         });
220         if (!parse_result) {
221             return false;
222         }
223 
224         if (system_properties_.GetProperty(kAndroidDataPathPropertyName) == nullptr) {
225             return false;
226         }
227         android_data_ = *system_properties_.GetProperty(kAndroidDataPathPropertyName);
228 
229         if (system_properties_.GetProperty(kAndroidRootPathPropertyName) == nullptr) {
230             return false;
231         }
232         android_root_ = *system_properties_.GetProperty(kAndroidRootPathPropertyName);
233 
234         if (system_properties_.GetProperty(kBootClassPathPropertyName) == nullptr) {
235             return false;
236         }
237         boot_classpath_ = *system_properties_.GetProperty(kBootClassPathPropertyName);
238 
239         if (system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) == nullptr) {
240             return false;
241         }
242         asec_mountpoint_ = *system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME);
243 
244         return true;
245     }
246 
GetAndroidData() const247     const std::string& GetAndroidData() const {
248         return android_data_;
249     }
250 
GetAndroidRoot() const251     const std::string& GetAndroidRoot() const {
252         return android_root_;
253     }
254 
GetOtaDirectoryPrefix() const255     const std::string GetOtaDirectoryPrefix() const {
256         return GetAndroidData() + "/ota";
257     }
258 
CheckAndInitializeInstalldGlobals()259     bool CheckAndInitializeInstalldGlobals() {
260         // init_globals_from_data_and_root requires "ASEC_MOUNTPOINT" in the environment. We
261         // do not use any datapath that includes this, but we'll still have to set it.
262         CHECK(system_properties_.GetProperty(ASEC_MOUNTPOINT_ENV_NAME) != nullptr);
263         int result = setenv(ASEC_MOUNTPOINT_ENV_NAME, asec_mountpoint_.c_str(), 0);
264         if (result != 0) {
265             LOG(ERROR) << "Could not set ASEC_MOUNTPOINT environment variable";
266             return false;
267         }
268 
269         if (!init_globals_from_data_and_root(GetAndroidData().c_str(), GetAndroidRoot().c_str())) {
270             LOG(ERROR) << "Could not initialize globals; exiting.";
271             return false;
272         }
273 
274         // This is different from the normal installd. We only do the base
275         // directory, the rest will be created on demand when each app is compiled.
276         if (access(GetOtaDirectoryPrefix().c_str(), R_OK) < 0) {
277             LOG(ERROR) << "Could not access " << GetOtaDirectoryPrefix();
278             return false;
279         }
280 
281         return true;
282     }
283 
ParseUInt(const char * in,uint32_t * out)284     bool ParseUInt(const char* in, uint32_t* out) {
285         char* end;
286         long long int result = strtoll(in, &end, 0);
287         if (in == end || *end != '\0') {
288             return false;
289         }
290         if (result < std::numeric_limits<uint32_t>::min() ||
291                 std::numeric_limits<uint32_t>::max() < result) {
292             return false;
293         }
294         *out = static_cast<uint32_t>(result);
295         return true;
296     }
297 
ReadArguments(int argc,char ** argv)298     bool ReadArguments(int argc, char** argv) {
299         // Expected command line:
300         //   target-slot [version] dexopt {DEXOPT_PARAMETERS}
301 
302         const char* target_slot_arg = argv[1];
303         if (target_slot_arg == nullptr) {
304             LOG(ERROR) << "Missing parameters";
305             return false;
306         }
307         // Sanitize value. Only allow (a-zA-Z0-9_)+.
308         target_slot_ = target_slot_arg;
309         if (!ValidateTargetSlotSuffix(target_slot_)) {
310             LOG(ERROR) << "Target slot suffix not legal: " << target_slot_;
311             return false;
312         }
313 
314         // Check for version or "dexopt" next.
315         if (argv[2] == nullptr) {
316             LOG(ERROR) << "Missing parameters";
317             return false;
318         }
319 
320         if (std::string("dexopt").compare(argv[2]) == 0) {
321             // This is version 1 (N) or pre-versioning version 2.
322             constexpr int kV2ArgCount =   1   // "otapreopt"
323                                         + 1   // slot
324                                         + 1   // "dexopt"
325                                         + 1   // apk_path
326                                         + 1   // uid
327                                         + 1   // pkg
328                                         + 1   // isa
329                                         + 1   // dexopt_needed
330                                         + 1   // oat_dir
331                                         + 1   // dexopt_flags
332                                         + 1   // filter
333                                         + 1   // volume
334                                         + 1   // libs
335                                         + 1;  // seinfo
336             if (argc == kV2ArgCount) {
337                 return ReadArgumentsV2(argc, argv, false);
338             } else {
339                 return ReadArgumentsV1(argc, argv);
340             }
341         }
342 
343         uint32_t version;
344         if (!ParseUInt(argv[2], &version)) {
345             LOG(ERROR) << "Could not parse version: " << argv[2];
346             return false;
347         }
348 
349         switch (version) {
350             case 2:
351                 return ReadArgumentsV2(argc, argv, true);
352 
353             default:
354                 LOG(ERROR) << "Unsupported version " << version;
355                 return false;
356         }
357     }
358 
ReadArgumentsV2(int argc ATTRIBUTE_UNUSED,char ** argv,bool versioned)359     bool ReadArgumentsV2(int argc ATTRIBUTE_UNUSED, char** argv, bool versioned) {
360         size_t dexopt_index = versioned ? 3 : 2;
361 
362         // Check for "dexopt".
363         if (argv[dexopt_index] == nullptr) {
364             LOG(ERROR) << "Missing parameters";
365             return false;
366         }
367         if (std::string("dexopt").compare(argv[dexopt_index]) != 0) {
368             LOG(ERROR) << "Expected \"dexopt\"";
369             return false;
370         }
371 
372         size_t param_index = 0;
373         for (;; ++param_index) {
374             const char* param = argv[dexopt_index + 1 + param_index];
375             if (param == nullptr) {
376                 break;
377             }
378 
379             switch (param_index) {
380                 case 0:
381                     package_parameters_.apk_path = param;
382                     break;
383 
384                 case 1:
385                     package_parameters_.uid = atoi(param);
386                     break;
387 
388                 case 2:
389                     package_parameters_.pkgName = param;
390                     break;
391 
392                 case 3:
393                     package_parameters_.instruction_set = param;
394                     break;
395 
396                 case 4:
397                     package_parameters_.dexopt_needed = atoi(param);
398                     break;
399 
400                 case 5:
401                     package_parameters_.oat_dir = param;
402                     break;
403 
404                 case 6:
405                     package_parameters_.dexopt_flags = atoi(param);
406                     break;
407 
408                 case 7:
409                     package_parameters_.compiler_filter = param;
410                     break;
411 
412                 case 8:
413                     package_parameters_.volume_uuid = ParseNull(param);
414                     break;
415 
416                 case 9:
417                     package_parameters_.shared_libraries = ParseNull(param);
418                     break;
419 
420                 case 10:
421                     package_parameters_.se_info = ParseNull(param);
422                     break;
423 
424                 default:
425                     LOG(ERROR) << "Too many arguments, got " << param;
426                     return false;
427             }
428         }
429 
430         if (param_index != 11) {
431             LOG(ERROR) << "Not enough parameters";
432             return false;
433         }
434 
435         return true;
436     }
437 
ReplaceMask(int input,int old_mask,int new_mask)438     static int ReplaceMask(int input, int old_mask, int new_mask) {
439         return (input & old_mask) != 0 ? new_mask : 0;
440     }
441 
ReadArgumentsV1(int argc ATTRIBUTE_UNUSED,char ** argv)442     bool ReadArgumentsV1(int argc ATTRIBUTE_UNUSED, char** argv) {
443         // Check for "dexopt".
444         if (argv[2] == nullptr) {
445             LOG(ERROR) << "Missing parameters";
446             return false;
447         }
448         if (std::string("dexopt").compare(argv[2]) != 0) {
449             LOG(ERROR) << "Expected \"dexopt\"";
450             return false;
451         }
452 
453         size_t param_index = 0;
454         for (;; ++param_index) {
455             const char* param = argv[3 + param_index];
456             if (param == nullptr) {
457                 break;
458             }
459 
460             switch (param_index) {
461                 case 0:
462                     package_parameters_.apk_path = param;
463                     break;
464 
465                 case 1:
466                     package_parameters_.uid = atoi(param);
467                     break;
468 
469                 case 2:
470                     package_parameters_.pkgName = param;
471                     break;
472 
473                 case 3:
474                     package_parameters_.instruction_set = param;
475                     break;
476 
477                 case 4: {
478                     // Version 1 had:
479                     //   DEXOPT_DEX2OAT_NEEDED       = 1
480                     //   DEXOPT_PATCHOAT_NEEDED      = 2
481                     //   DEXOPT_SELF_PATCHOAT_NEEDED = 3
482                     // We will simply use DEX2OAT_FROM_SCRATCH.
483                     package_parameters_.dexopt_needed = DEX2OAT_FROM_SCRATCH;
484                     break;
485                 }
486 
487                 case 5:
488                     package_parameters_.oat_dir = param;
489                     break;
490 
491                 case 6: {
492                     // Version 1 had:
493                     constexpr int OLD_DEXOPT_PUBLIC         = 1 << 1;
494                     // Note: DEXOPT_SAFEMODE has been removed.
495                     // constexpr int OLD_DEXOPT_SAFEMODE       = 1 << 2;
496                     constexpr int OLD_DEXOPT_DEBUGGABLE     = 1 << 3;
497                     constexpr int OLD_DEXOPT_BOOTCOMPLETE   = 1 << 4;
498                     constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5;
499                     constexpr int OLD_DEXOPT_OTA            = 1 << 6;
500                     int input = atoi(param);
501                     package_parameters_.dexopt_flags =
502                             ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) |
503                             ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) |
504                             ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) |
505                             ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) |
506                             ReplaceMask(input, OLD_DEXOPT_OTA, 0);
507                     break;
508                 }
509 
510                 case 7:
511                     package_parameters_.compiler_filter = param;
512                     break;
513 
514                 case 8:
515                     package_parameters_.volume_uuid = ParseNull(param);
516                     break;
517 
518                 case 9:
519                     package_parameters_.shared_libraries = ParseNull(param);
520                     break;
521 
522                 default:
523                     LOG(ERROR) << "Too many arguments, got " << param;
524                     return false;
525             }
526         }
527 
528         if (param_index != 10) {
529             LOG(ERROR) << "Not enough parameters";
530             return false;
531         }
532 
533         // Set se_info to null. It is only relevant for secondary dex files, which we won't
534         // receive from a v1 A side.
535         package_parameters_.se_info = nullptr;
536 
537         return true;
538     }
539 
PrepareEnvironment()540     void PrepareEnvironment() {
541         environ_.push_back(StringPrintf("BOOTCLASSPATH=%s", boot_classpath_.c_str()));
542         environ_.push_back(StringPrintf("ANDROID_DATA=%s", GetOTADataDirectory().c_str()));
543         environ_.push_back(StringPrintf("ANDROID_ROOT=%s", android_root_.c_str()));
544 
545         for (const std::string& e : environ_) {
546             putenv(const_cast<char*>(e.c_str()));
547         }
548     }
549 
550     // Ensure that we have the right boot image. The first time any app is
551     // compiled, we'll try to generate it.
PrepareBootImage(bool force) const552     bool PrepareBootImage(bool force) const {
553         if (package_parameters_.instruction_set == nullptr) {
554             LOG(ERROR) << "Instruction set missing.";
555             return false;
556         }
557         const char* isa = package_parameters_.instruction_set;
558 
559         // Check whether the file exists where expected.
560         std::string dalvik_cache = GetOTADataDirectory() + "/" + DALVIK_CACHE;
561         std::string isa_path = dalvik_cache + "/" + isa;
562         std::string art_path = isa_path + "/system@framework@boot.art";
563         std::string oat_path = isa_path + "/system@framework@boot.oat";
564         bool cleared = false;
565         if (access(art_path.c_str(), F_OK) == 0 && access(oat_path.c_str(), F_OK) == 0) {
566             // Files exist, assume everything is alright if not forced. Otherwise clean up.
567             if (!force) {
568                 return true;
569             }
570             ClearDirectory(isa_path);
571             cleared = true;
572         }
573 
574         // Reset umask in otapreopt, so that we control the the access for the files we create.
575         umask(0);
576 
577         // Create the directories, if necessary.
578         if (access(dalvik_cache.c_str(), F_OK) != 0) {
579             if (!CreatePath(dalvik_cache)) {
580                 PLOG(ERROR) << "Could not create dalvik-cache dir " << dalvik_cache;
581                 return false;
582             }
583         }
584         if (access(isa_path.c_str(), F_OK) != 0) {
585             if (!CreatePath(isa_path)) {
586                 PLOG(ERROR) << "Could not create dalvik-cache isa dir";
587                 return false;
588             }
589         }
590 
591         // Prepare to create.
592         if (!cleared) {
593             ClearDirectory(isa_path);
594         }
595 
596         std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
597         if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
598           return PatchoatBootImage(art_path, isa);
599         } else {
600           // No preopted boot image. Try to compile.
601           return Dex2oatBootImage(boot_classpath_, art_path, oat_path, isa);
602         }
603     }
604 
CreatePath(const std::string & path)605     static bool CreatePath(const std::string& path) {
606         // Create the given path. Use string processing instead of dirname, as dirname's need for
607         // a writable char buffer is painful.
608 
609         // First, try to use the full path.
610         if (mkdir(path.c_str(), 0711) == 0) {
611             return true;
612         }
613         if (errno != ENOENT) {
614             PLOG(ERROR) << "Could not create path " << path;
615             return false;
616         }
617 
618         // Now find the parent and try that first.
619         size_t last_slash = path.find_last_of('/');
620         if (last_slash == std::string::npos || last_slash == 0) {
621             PLOG(ERROR) << "Could not create " << path;
622             return false;
623         }
624 
625         if (!CreatePath(path.substr(0, last_slash))) {
626             return false;
627         }
628 
629         if (mkdir(path.c_str(), 0711) == 0) {
630             return true;
631         }
632         PLOG(ERROR) << "Could not create " << path;
633         return false;
634     }
635 
ClearDirectory(const std::string & dir)636     static void ClearDirectory(const std::string& dir) {
637         DIR* c_dir = opendir(dir.c_str());
638         if (c_dir == nullptr) {
639             PLOG(WARNING) << "Unable to open " << dir << " to delete it's contents";
640             return;
641         }
642 
643         for (struct dirent* de = readdir(c_dir); de != nullptr; de = readdir(c_dir)) {
644             const char* name = de->d_name;
645             if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
646                 continue;
647             }
648             // We only want to delete regular files and symbolic links.
649             std::string file = StringPrintf("%s/%s", dir.c_str(), name);
650             if (de->d_type != DT_REG && de->d_type != DT_LNK) {
651                 LOG(WARNING) << "Unexpected file "
652                              << file
653                              << " of type "
654                              << std::hex
655                              << de->d_type
656                              << " encountered.";
657             } else {
658                 // Try to unlink the file.
659                 if (unlink(file.c_str()) != 0) {
660                     PLOG(ERROR) << "Unable to unlink " << file;
661                 }
662             }
663         }
664         CHECK_EQ(0, closedir(c_dir)) << "Unable to close directory.";
665     }
666 
PatchoatBootImage(const std::string & art_path,const char * isa) const667     bool PatchoatBootImage(const std::string& art_path, const char* isa) const {
668         // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
669 
670         std::vector<std::string> cmd;
671         cmd.push_back("/system/bin/patchoat");
672 
673         cmd.push_back("--input-image-location=/system/framework/boot.art");
674         cmd.push_back(StringPrintf("--output-image-file=%s", art_path.c_str()));
675 
676         cmd.push_back(StringPrintf("--instruction-set=%s", isa));
677 
678         int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
679                                                           ART_BASE_ADDRESS_MAX_DELTA);
680         cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
681 
682         std::string error_msg;
683         bool result = Exec(cmd, &error_msg);
684         if (!result) {
685             LOG(ERROR) << "Could not generate boot image: " << error_msg;
686         }
687         return result;
688     }
689 
Dex2oatBootImage(const std::string & boot_cp,const std::string & art_path,const std::string & oat_path,const char * isa) const690     bool Dex2oatBootImage(const std::string& boot_cp,
691                           const std::string& art_path,
692                           const std::string& oat_path,
693                           const char* isa) const {
694         // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
695         std::vector<std::string> cmd;
696         cmd.push_back("/system/bin/dex2oat");
697         cmd.push_back(StringPrintf("--image=%s", art_path.c_str()));
698         for (const std::string& boot_part : Split(boot_cp, ":")) {
699             cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str()));
700         }
701         cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
702 
703         int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
704                 ART_BASE_ADDRESS_MAX_DELTA);
705         cmd.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
706 
707         cmd.push_back(StringPrintf("--instruction-set=%s", isa));
708 
709         // These things are pushed by AndroidRuntime, see frameworks/base/core/jni/AndroidRuntime.cpp.
710         AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xms",
711                 "-Xms",
712                 true,
713                 cmd);
714         AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xmx",
715                 "-Xmx",
716                 true,
717                 cmd);
718         AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-filter",
719                 "--compiler-filter=",
720                 false,
721                 cmd);
722         cmd.push_back("--image-classes=/system/etc/preloaded-classes");
723         // TODO: Compiled-classes.
724         const std::string* extra_opts =
725                 system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
726         if (extra_opts != nullptr) {
727             std::vector<std::string> extra_vals = Split(*extra_opts, " ");
728             cmd.insert(cmd.end(), extra_vals.begin(), extra_vals.end());
729         }
730         // TODO: Should we lower this? It's usually set close to max, because
731         //       normally there's not much else going on at boot.
732         AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-threads",
733                 "-j",
734                 false,
735                 cmd);
736         AddCompilerOptionFromSystemProperty(
737                 StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(),
738                 "--instruction-set-variant=",
739                 false,
740                 cmd);
741         AddCompilerOptionFromSystemProperty(
742                 StringPrintf("dalvik.vm.isa.%s.features", isa).c_str(),
743                 "--instruction-set-features=",
744                 false,
745                 cmd);
746 
747         std::string error_msg;
748         bool result = Exec(cmd, &error_msg);
749         if (!result) {
750             LOG(ERROR) << "Could not generate boot image: " << error_msg;
751         }
752         return result;
753     }
754 
ParseNull(const char * arg)755     static const char* ParseNull(const char* arg) {
756         // b/38186355. Revert soon.
757         if (strcmp(arg, "!null") == 0) {
758             return nullptr;
759         }
760         return (strcmp(arg, "!") == 0) ? nullptr : arg;
761     }
762 
ShouldSkipPreopt() const763     bool ShouldSkipPreopt() const {
764         // There's one thing we have to be careful about: we may/will be asked to compile an app
765         // living in the system image. This may be a valid request - if the app wasn't compiled,
766         // e.g., if the system image wasn't large enough to include preopted files. However, the
767         // data we have is from the old system, so the driver (the OTA service) can't actually
768         // know. Thus, we will get requests for apps that have preopted components. To avoid
769         // duplication (we'd generate files that are not used and are *not* cleaned up), do two
770         // simple checks:
771         //
772         // 1) Does the apk_path start with the value of ANDROID_ROOT? (~in the system image)
773         //    (For simplicity, assume the value of ANDROID_ROOT does not contain a symlink.)
774         //
775         // 2) If you replace the name in the apk_path with "oat," does the path exist?
776         //    (=have a subdirectory for preopted files)
777         //
778         // If the answer to both is yes, skip the dexopt.
779         //
780         // Note: while one may think it's OK to call dexopt and it will fail (because APKs should
781         //       be stripped), that's not true for APKs signed outside the build system (so the
782         //       jar content must be exactly the same).
783 
784         //       (This is ugly as it's the only thing where we need to understand the contents
785         //        of package_parameters_, but it beats postponing the decision or using the call-
786         //        backs to do weird things.)
787         const char* apk_path = package_parameters_.apk_path;
788         CHECK(apk_path != nullptr);
789         if (StartsWith(apk_path, android_root_.c_str())) {
790             const char* last_slash = strrchr(apk_path, '/');
791             if (last_slash != nullptr) {
792                 std::string path(apk_path, last_slash - apk_path + 1);
793                 CHECK(EndsWith(path, "/"));
794                 path = path + "oat";
795                 if (access(path.c_str(), F_OK) == 0) {
796                     return true;
797                 }
798             }
799         }
800 
801         // Another issue is unavailability of files in the new system. If the partition
802         // layout changes, otapreopt_chroot may not know about this. Then files from that
803         // partition will not be available and fail to build. This is problematic, as
804         // this tool will wipe the OTA artifact cache and try again (for robustness after
805         // a failed OTA with remaining cache artifacts).
806         if (access(apk_path, F_OK) != 0) {
807             LOG(WARNING) << "Skipping preopt of non-existing package " << apk_path;
808             return true;
809         }
810 
811         return false;
812     }
813 
814     // Run dexopt with the parameters of package_parameters_.
Dexopt()815     int Dexopt() {
816         return dexopt(package_parameters_.apk_path,
817                       package_parameters_.uid,
818                       package_parameters_.pkgName,
819                       package_parameters_.instruction_set,
820                       package_parameters_.dexopt_needed,
821                       package_parameters_.oat_dir,
822                       package_parameters_.dexopt_flags,
823                       package_parameters_.compiler_filter,
824                       package_parameters_.volume_uuid,
825                       package_parameters_.shared_libraries,
826                       package_parameters_.se_info);
827     }
828 
RunPreopt()829     int RunPreopt() {
830         if (ShouldSkipPreopt()) {
831             return 0;
832         }
833 
834         int dexopt_result = Dexopt();
835         if (dexopt_result == 0) {
836             return 0;
837         }
838 
839         // If the dexopt failed, we may have a stale boot image from a previous OTA run.
840         // Then regenerate and retry.
841         if (WEXITSTATUS(dexopt_result) ==
842                 static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
843             if (!PrepareBootImage(/* force */ true)) {
844                 LOG(ERROR) << "Forced boot image creating failed. Original error return was "
845                         << dexopt_result;
846                 return dexopt_result;
847             }
848 
849             int dexopt_result_boot_image_retry = Dexopt();
850             if (dexopt_result_boot_image_retry == 0) {
851                 return 0;
852             }
853         }
854 
855         // If this was a profile-guided run, we may have profile version issues. Try to downgrade,
856         // if possible.
857         if ((package_parameters_.dexopt_flags & DEXOPT_PROFILE_GUIDED) == 0) {
858             return dexopt_result;
859         }
860 
861         LOG(WARNING) << "Downgrading compiler filter in an attempt to progress compilation";
862         package_parameters_.dexopt_flags &= ~DEXOPT_PROFILE_GUIDED;
863         return Dexopt();
864     }
865 
866     ////////////////////////////////////
867     // Helpers, mostly taken from ART //
868     ////////////////////////////////////
869 
870     // Wrapper on fork/execv to run a command in a subprocess.
Exec(const std::vector<std::string> & arg_vector,std::string * error_msg)871     static bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg) {
872         const std::string command_line = Join(arg_vector, ' ');
873 
874         CHECK_GE(arg_vector.size(), 1U) << command_line;
875 
876         // Convert the args to char pointers.
877         const char* program = arg_vector[0].c_str();
878         std::vector<char*> args;
879         for (size_t i = 0; i < arg_vector.size(); ++i) {
880             const std::string& arg = arg_vector[i];
881             char* arg_str = const_cast<char*>(arg.c_str());
882             CHECK(arg_str != nullptr) << i;
883             args.push_back(arg_str);
884         }
885         args.push_back(nullptr);
886 
887         // Fork and exec.
888         pid_t pid = fork();
889         if (pid == 0) {
890             // No allocation allowed between fork and exec.
891 
892             // Change process groups, so we don't get reaped by ProcessManager.
893             setpgid(0, 0);
894 
895             execv(program, &args[0]);
896 
897             PLOG(ERROR) << "Failed to execv(" << command_line << ")";
898             // _exit to avoid atexit handlers in child.
899             _exit(1);
900         } else {
901             if (pid == -1) {
902                 *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
903                         command_line.c_str(), strerror(errno));
904                 return false;
905             }
906 
907             // wait for subprocess to finish
908             int status;
909             pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
910             if (got_pid != pid) {
911                 *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
912                         "wanted %d, got %d: %s",
913                         command_line.c_str(), pid, got_pid, strerror(errno));
914                 return false;
915             }
916             if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
917                 *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
918                         command_line.c_str());
919                 return false;
920             }
921         }
922         return true;
923     }
924 
925     // Choose a random relocation offset. Taken from art/runtime/gc/image_space.cc.
ChooseRelocationOffsetDelta(int32_t min_delta,int32_t max_delta)926     static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
927         constexpr size_t kPageSize = PAGE_SIZE;
928         CHECK_EQ(min_delta % kPageSize, 0u);
929         CHECK_EQ(max_delta % kPageSize, 0u);
930         CHECK_LT(min_delta, max_delta);
931 
932         std::default_random_engine generator;
933         generator.seed(GetSeed());
934         std::uniform_int_distribution<int32_t> distribution(min_delta, max_delta);
935         int32_t r = distribution(generator);
936         if (r % 2 == 0) {
937             r = RoundUp(r, kPageSize);
938         } else {
939             r = RoundDown(r, kPageSize);
940         }
941         CHECK_LE(min_delta, r);
942         CHECK_GE(max_delta, r);
943         CHECK_EQ(r % kPageSize, 0u);
944         return r;
945     }
946 
GetSeed()947     static uint64_t GetSeed() {
948 #ifdef __BIONIC__
949         // Bionic exposes arc4random, use it.
950         uint64_t random_data;
951         arc4random_buf(&random_data, sizeof(random_data));
952         return random_data;
953 #else
954 #error "This is only supposed to run with bionic. Otherwise, implement..."
955 #endif
956     }
957 
AddCompilerOptionFromSystemProperty(const char * system_property,const char * prefix,bool runtime,std::vector<std::string> & out) const958     void AddCompilerOptionFromSystemProperty(const char* system_property,
959             const char* prefix,
960             bool runtime,
961             std::vector<std::string>& out) const {
962         const std::string* value = system_properties_.GetProperty(system_property);
963         if (value != nullptr) {
964             if (runtime) {
965                 out.push_back("--runtime-arg");
966             }
967             if (prefix != nullptr) {
968                 out.push_back(StringPrintf("%s%s", prefix, value->c_str()));
969             } else {
970                 out.push_back(*value);
971             }
972         }
973     }
974 
975     static constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH";
976     static constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT";
977     static constexpr const char* kAndroidDataPathPropertyName = "ANDROID_DATA";
978     // The index of the instruction-set string inside the package parameters. Needed for
979     // some special-casing that requires knowledge of the instruction-set.
980     static constexpr size_t kISAIndex = 3;
981 
982     // Stores the system properties read out of the B partition. We need to use these properties
983     // to compile, instead of the A properties we could get from init/get_property.
984     SystemProperties system_properties_;
985 
986     // Some select properties that are always needed.
987     std::string target_slot_;
988     std::string android_root_;
989     std::string android_data_;
990     std::string boot_classpath_;
991     std::string asec_mountpoint_;
992 
993     Parameters package_parameters_;
994 
995     // Store environment values we need to set.
996     std::vector<std::string> environ_;
997 };
998 
999 OTAPreoptService gOps;
1000 
1001 ////////////////////////
1002 // Plug-in functions. //
1003 ////////////////////////
1004 
get_property(const char * key,char * value,const char * default_value)1005 int get_property(const char *key, char *value, const char *default_value) {
1006     return gOps.GetProperty(key, value, default_value);
1007 }
1008 
1009 // Compute the output path of
calculate_oat_file_path(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)1010 bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir,
1011                              const char *apk_path,
1012                              const char *instruction_set) {
1013     const char *file_name_start;
1014     const char *file_name_end;
1015 
1016     file_name_start = strrchr(apk_path, '/');
1017     if (file_name_start == nullptr) {
1018         ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
1019         return false;
1020     }
1021     file_name_end = strrchr(file_name_start, '.');
1022     if (file_name_end == nullptr) {
1023         ALOGE("apk_path '%s' has no extension\n", apk_path);
1024         return false;
1025     }
1026 
1027     // Calculate file_name
1028     file_name_start++;  // Move past '/', is valid as file_name_end is valid.
1029     size_t file_name_len = file_name_end - file_name_start;
1030     std::string file_name(file_name_start, file_name_len);
1031 
1032     // <apk_parent_dir>/oat/<isa>/<file_name>.odex.b
1033     snprintf(path,
1034              PKG_PATH_MAX,
1035              "%s/%s/%s.odex.%s",
1036              oat_dir,
1037              instruction_set,
1038              file_name.c_str(),
1039              gOps.GetTargetSlot().c_str());
1040     return true;
1041 }
1042 
1043 /*
1044  * Computes the odex file for the given apk_path and instruction_set.
1045  * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
1046  *
1047  * Returns false if it failed to determine the odex file path.
1048  */
calculate_odex_file_path(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)1049 bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
1050                               const char *instruction_set) {
1051     const char *path_end = strrchr(apk_path, '/');
1052     if (path_end == nullptr) {
1053         ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
1054         return false;
1055     }
1056     std::string path_component(apk_path, path_end - apk_path);
1057 
1058     const char *name_begin = path_end + 1;
1059     const char *extension_start = strrchr(name_begin, '.');
1060     if (extension_start == nullptr) {
1061         ALOGE("apk_path '%s' has no extension.\n", apk_path);
1062         return false;
1063     }
1064     std::string name_component(name_begin, extension_start - name_begin);
1065 
1066     std::string new_path = StringPrintf("%s/oat/%s/%s.odex.%s",
1067                                         path_component.c_str(),
1068                                         instruction_set,
1069                                         name_component.c_str(),
1070                                         gOps.GetTargetSlot().c_str());
1071     if (new_path.length() >= PKG_PATH_MAX) {
1072         LOG(ERROR) << "apk_path of " << apk_path << " is too long: " << new_path;
1073         return false;
1074     }
1075     strcpy(path, new_path.c_str());
1076     return true;
1077 }
1078 
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)1079 bool create_cache_path(char path[PKG_PATH_MAX],
1080                        const char *src,
1081                        const char *instruction_set) {
1082     size_t srclen = strlen(src);
1083 
1084         /* demand that we are an absolute path */
1085     if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
1086         return false;
1087     }
1088 
1089     if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
1090         return false;
1091     }
1092 
1093     std::string from_src = std::string(src + 1);
1094     std::replace(from_src.begin(), from_src.end(), '/', '@');
1095 
1096     std::string assembled_path = StringPrintf("%s/%s/%s/%s%s",
1097                                               gOps.GetOTADataDirectory().c_str(),
1098                                               DALVIK_CACHE,
1099                                               instruction_set,
1100                                               from_src.c_str(),
1101                                               DALVIK_CACHE_POSTFIX);
1102 
1103     if (assembled_path.length() + 1 > PKG_PATH_MAX) {
1104         return false;
1105     }
1106     strcpy(path, assembled_path.c_str());
1107 
1108     return true;
1109 }
1110 
log_callback(int type,const char * fmt,...)1111 static int log_callback(int type, const char *fmt, ...) {
1112     va_list ap;
1113     int priority;
1114 
1115     switch (type) {
1116         case SELINUX_WARNING:
1117             priority = ANDROID_LOG_WARN;
1118             break;
1119         case SELINUX_INFO:
1120             priority = ANDROID_LOG_INFO;
1121             break;
1122         default:
1123             priority = ANDROID_LOG_ERROR;
1124             break;
1125     }
1126     va_start(ap, fmt);
1127     LOG_PRI_VA(priority, "SELinux", fmt, ap);
1128     va_end(ap);
1129     return 0;
1130 }
1131 
otapreopt_main(const int argc,char * argv[])1132 static int otapreopt_main(const int argc, char *argv[]) {
1133     int selinux_enabled = (is_selinux_enabled() > 0);
1134 
1135     setenv("ANDROID_LOG_TAGS", "*:v", 1);
1136     android::base::InitLogging(argv);
1137 
1138     if (argc < 2) {
1139         ALOGE("Expecting parameters");
1140         exit(1);
1141     }
1142 
1143     union selinux_callback cb;
1144     cb.func_log = log_callback;
1145     selinux_set_callback(SELINUX_CB_LOG, cb);
1146 
1147     if (selinux_enabled && selinux_status_open(true) < 0) {
1148         ALOGE("Could not open selinux status; exiting.\n");
1149         exit(1);
1150     }
1151 
1152     int ret = android::installd::gOps.Main(argc, argv);
1153 
1154     return ret;
1155 }
1156 
1157 }  // namespace installd
1158 }  // namespace android
1159 
main(const int argc,char * argv[])1160 int main(const int argc, char *argv[]) {
1161     return android::installd::otapreopt_main(argc, argv);
1162 }
1163