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 "otapreopt_parameters.h" 18 19 #include <cstring> 20 21 #include <android-base/logging.h> 22 23 #include "dexopt.h" 24 #include "installd_constants.h" 25 #include "otapreopt_utils.h" 26 27 #ifndef LOG_TAG 28 #define LOG_TAG "otapreopt" 29 #endif 30 31 namespace android { 32 namespace installd { 33 34 static bool ParseBool(const char* in) { 35 if (strcmp(in, "true") == 0) { 36 return true; 37 } 38 return false; 39 } 40 41 static const char* ParseNull(const char* arg) { 42 return (strcmp(arg, "!") == 0) ? nullptr : arg; 43 } 44 45 static bool ParseUInt(const char* in, uint32_t* out) { 46 char* end; 47 long long int result = strtoll(in, &end, 0); 48 if (in == end || *end != '\0') { 49 return false; 50 } 51 if (result < std::numeric_limits<uint32_t>::min() || 52 std::numeric_limits<uint32_t>::max() < result) { 53 return false; 54 } 55 *out = static_cast<uint32_t>(result); 56 return true; 57 } 58 59 bool OTAPreoptParameters::ReadArguments(int argc, const char** argv) { 60 // Expected command line: 61 // target-slot [version] dexopt {DEXOPT_PARAMETERS} 62 63 const char* target_slot_arg = argv[1]; 64 if (target_slot_arg == nullptr) { 65 LOG(ERROR) << "Missing parameters"; 66 return false; 67 } 68 // Sanitize value. Only allow (a-zA-Z0-9_)+. 69 target_slot = target_slot_arg; 70 if (!ValidateTargetSlotSuffix(target_slot)) { 71 LOG(ERROR) << "Target slot suffix not legal: " << target_slot; 72 return false; 73 } 74 75 // Check for version or "dexopt" next. 76 if (argv[2] == nullptr) { 77 LOG(ERROR) << "Missing parameters"; 78 return false; 79 } 80 81 if (std::string("dexopt").compare(argv[2]) == 0) { 82 // This is version 1 (N) or pre-versioning version 2. 83 constexpr int kV2ArgCount = 1 // "otapreopt" 84 + 1 // slot 85 + 1 // "dexopt" 86 + 1 // apk_path 87 + 1 // uid 88 + 1 // pkg 89 + 1 // isa 90 + 1 // dexopt_needed 91 + 1 // oat_dir 92 + 1 // dexopt_flags 93 + 1 // filter 94 + 1 // volume 95 + 1 // libs 96 + 1; // seinfo 97 if (argc == kV2ArgCount) { 98 return ReadArgumentsPostV1(2, argv, false); 99 } else { 100 return ReadArgumentsV1(argv); 101 } 102 } 103 104 uint32_t version; 105 if (!ParseUInt(argv[2], &version)) { 106 LOG(ERROR) << "Could not parse version: " << argv[2]; 107 return false; 108 } 109 110 return ReadArgumentsPostV1(version, argv, true); 111 } 112 113 static int ReplaceMask(int input, int old_mask, int new_mask) { 114 return (input & old_mask) != 0 ? new_mask : 0; 115 } 116 117 void OTAPreoptParameters::SetDefaultsForPostV1Arguments() { 118 // Set se_info to null. It is only relevant for secondary dex files, which we won't 119 // receive from a v1 A side. 120 se_info = nullptr; 121 122 // Set downgrade to false. It is only relevant when downgrading compiler 123 // filter, which is not the case during ota. 124 downgrade = false; 125 126 // Set target_sdk_version to 0, ie the platform SDK version. This is 127 // conservative and may force some classes to verify at runtime. 128 target_sdk_version = 0; 129 130 // Set the profile name to the primary apk profile. 131 profile_name = "primary.prof"; 132 133 // By default we don't have a dex metadata file. 134 dex_metadata_path = nullptr; 135 136 // The compilation reason is ab-ota (match the system property pm.dexopt.ab-ota) 137 compilation_reason = "ab-ota"; 138 139 // Flag is enabled by default for A/B otas. 140 dexopt_flags = DEXOPT_GENERATE_COMPACT_DEX; 141 } 142 143 bool OTAPreoptParameters::ReadArgumentsV1(const char** argv) { 144 // Check for "dexopt". 145 if (argv[2] == nullptr) { 146 LOG(ERROR) << "Missing parameters"; 147 return false; 148 } 149 if (std::string("dexopt").compare(argv[2]) != 0) { 150 LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[2]; 151 return false; 152 } 153 154 SetDefaultsForPostV1Arguments(); 155 156 size_t param_index = 0; 157 for (;; ++param_index) { 158 const char* param = argv[3 + param_index]; 159 if (param == nullptr) { 160 break; 161 } 162 163 switch (param_index) { 164 case 0: 165 apk_path = param; 166 break; 167 168 case 1: 169 uid = atoi(param); 170 break; 171 172 case 2: 173 pkgName = param; 174 break; 175 176 case 3: 177 instruction_set = param; 178 break; 179 180 case 4: { 181 // Version 1 had: 182 // DEXOPT_DEX2OAT_NEEDED = 1 183 // DEXOPT_PATCHOAT_NEEDED = 2 184 // DEXOPT_SELF_PATCHOAT_NEEDED = 3 185 // We will simply use DEX2OAT_FROM_SCRATCH. 186 dexopt_needed = DEX2OAT_FROM_SCRATCH; 187 break; 188 } 189 190 case 5: 191 oat_dir = param; 192 break; 193 194 case 6: { 195 // Version 1 had: 196 constexpr int OLD_DEXOPT_PUBLIC = 1 << 1; 197 // Note: DEXOPT_SAFEMODE has been removed. 198 // constexpr int OLD_DEXOPT_SAFEMODE = 1 << 2; 199 constexpr int OLD_DEXOPT_DEBUGGABLE = 1 << 3; 200 constexpr int OLD_DEXOPT_BOOTCOMPLETE = 1 << 4; 201 constexpr int OLD_DEXOPT_PROFILE_GUIDED = 1 << 5; 202 constexpr int OLD_DEXOPT_OTA = 1 << 6; 203 static_assert(DEXOPT_GENERATE_COMPACT_DEX > OLD_DEXOPT_OTA, "must not overlap"); 204 int input = atoi(param); 205 dexopt_flags |= 206 ReplaceMask(input, OLD_DEXOPT_PUBLIC, DEXOPT_PUBLIC) | 207 ReplaceMask(input, OLD_DEXOPT_DEBUGGABLE, DEXOPT_DEBUGGABLE) | 208 ReplaceMask(input, OLD_DEXOPT_BOOTCOMPLETE, DEXOPT_BOOTCOMPLETE) | 209 ReplaceMask(input, OLD_DEXOPT_PROFILE_GUIDED, DEXOPT_PROFILE_GUIDED) | 210 ReplaceMask(input, OLD_DEXOPT_OTA, 0); 211 break; 212 } 213 214 case 7: 215 compiler_filter = param; 216 break; 217 218 case 8: 219 volume_uuid = ParseNull(param); 220 break; 221 222 case 9: 223 shared_libraries = ParseNull(param); 224 break; 225 226 default: 227 LOG(ERROR) << "Too many arguments, got " << param; 228 return false; 229 } 230 } 231 232 if (param_index != 10) { 233 LOG(ERROR) << "Not enough parameters"; 234 return false; 235 } 236 237 return true; 238 } 239 240 bool OTAPreoptParameters::ReadArgumentsPostV1(uint32_t version, const char** argv, bool versioned) { 241 size_t num_args_expected = 0; 242 switch (version) { 243 case 2: num_args_expected = 11; break; 244 case 3: num_args_expected = 12; break; 245 case 4: num_args_expected = 13; break; 246 case 5: num_args_expected = 14; break; 247 case 6: num_args_expected = 15; break; 248 case 7: 249 // Version 8 adds a new dexopt flag: DEXOPT_GENERATE_COMPACT_DEX 250 case 8: num_args_expected = 16; break; 251 // Version 9 adds a new dexopt flag: DEXOPT_GENERATE_APP_IMAGE 252 case 9: num_args_expected = 16; break; 253 // Version 10 is a compatibility bump. 254 case 10: num_args_expected = 16; break; 255 default: 256 LOG(ERROR) << "Don't know how to read arguments for version " << version; 257 return false; 258 } 259 size_t dexopt_index = versioned ? 3 : 2; 260 261 // Check for "dexopt". 262 if (argv[dexopt_index] == nullptr) { 263 LOG(ERROR) << "Missing parameters"; 264 return false; 265 } 266 if (std::string("dexopt").compare(argv[dexopt_index]) != 0) { 267 LOG(ERROR) << "Expected \"dexopt\" but found: " << argv[dexopt_index]; 268 return false; 269 } 270 271 // Validate the number of arguments. 272 size_t num_args_actual = 0; 273 while (argv[dexopt_index + 1 + num_args_actual] != nullptr) { 274 num_args_actual++; 275 } 276 277 if (num_args_actual != num_args_expected) { 278 LOG(ERROR) << "Invalid number of arguments. expected=" 279 << num_args_expected << " actual=" << num_args_actual; 280 return false; 281 } 282 283 // The number of arguments is OK. 284 // Configure the default values for the parameters that were added after V1. 285 // The default values will be overwritten in case they are passed as arguments. 286 SetDefaultsForPostV1Arguments(); 287 288 for (size_t param_index = 0; param_index < num_args_actual; ++param_index) { 289 const char* param = argv[dexopt_index + 1 + param_index]; 290 switch (param_index) { 291 case 0: 292 apk_path = param; 293 break; 294 295 case 1: 296 uid = atoi(param); 297 break; 298 299 case 2: 300 pkgName = param; 301 break; 302 303 case 3: 304 instruction_set = param; 305 break; 306 307 case 4: 308 dexopt_needed = atoi(param); 309 break; 310 311 case 5: 312 oat_dir = param; 313 break; 314 315 case 6: 316 dexopt_flags = atoi(param); 317 // Add CompactDex generation flag for versions less than 8 since it wasn't passed 318 // from the package manager. Only conditionally set the flag here so that it can 319 // be fully controlled by the package manager. 320 dexopt_flags |= (version < 8) ? DEXOPT_GENERATE_COMPACT_DEX : 0u; 321 break; 322 323 case 7: 324 compiler_filter = param; 325 break; 326 327 case 8: 328 volume_uuid = ParseNull(param); 329 break; 330 331 case 9: 332 shared_libraries = ParseNull(param); 333 break; 334 335 case 10: 336 se_info = ParseNull(param); 337 break; 338 339 case 11: 340 downgrade = ParseBool(param); 341 break; 342 343 case 12: 344 target_sdk_version = atoi(param); 345 break; 346 347 case 13: 348 profile_name = ParseNull(param); 349 break; 350 351 case 14: 352 dex_metadata_path = ParseNull(param); 353 break; 354 355 case 15: 356 compilation_reason = ParseNull(param); 357 break; 358 359 default: 360 LOG(FATAL) << "Should not get here. Did you call ReadArguments " 361 << "with the right expectation? index=" << param_index 362 << " num_args=" << num_args_actual; 363 return false; 364 } 365 } 366 367 if (version < 10) { 368 // Do not accept '&' as shared libraries from versions prior to 10. These may lead 369 // to runtime crashes. The server side of version 10+ should send the correct 370 // context in almost all cases (e.g., only for actual shared packages). 371 if (shared_libraries != nullptr && std::string("&") == shared_libraries) { 372 return false; 373 } 374 } 375 376 return true; 377 } 378 379 } // namespace installd 380 } // namespace android 381