installd_dexopt_test.cpp revision c4f6a0b6333980a069900e2afff2c755f30fe09c
1/* 2 * Copyright (C) 2017 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 <cstdlib> 18#include <fcntl.h> 19#include <stdlib.h> 20#include <string.h> 21#include <sys/types.h> 22#include <sys/stat.h> 23 24#include <android-base/file.h> 25#include <android-base/logging.h> 26#include <android-base/stringprintf.h> 27#include <android-base/unique_fd.h> 28 29#include <cutils/properties.h> 30 31#include <gtest/gtest.h> 32 33#include <selinux/android.h> 34#include <selinux/avc.h> 35 36#include "dexopt.h" 37#include "InstalldNativeService.h" 38#include "globals.h" 39#include "tests/test_utils.h" 40#include "utils.h" 41 42using android::base::ReadFully; 43using android::base::unique_fd; 44 45namespace android { 46namespace installd { 47 48// TODO(calin): try to dedup this code. 49#if defined(__arm__) 50static const std::string kRuntimeIsa = "arm"; 51#elif defined(__aarch64__) 52static const std::string kRuntimeIsa = "arm64"; 53#elif defined(__mips__) && !defined(__LP64__) 54static const std::string kRuntimeIsa = "mips"; 55#elif defined(__mips__) && defined(__LP64__) 56static const std::string kRuntimeIsa = "mips64"; 57#elif defined(__i386__) 58static const std::string kRuntimeIsa = "x86"; 59#elif defined(__x86_64__) 60static const std::string kRuntimeIsa = "x86_64"; 61#else 62static const std::string kRuntimeIsa = "none"; 63#endif 64 65int get_property(const char *key, char *value, const char *default_value) { 66 return property_get(key, value, default_value); 67} 68 69bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path, 70 const char *instruction_set) { 71 return calculate_oat_file_path_default(path, oat_dir, apk_path, instruction_set); 72} 73 74bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path, 75 const char *instruction_set) { 76 return calculate_odex_file_path_default(path, apk_path, instruction_set); 77} 78 79bool create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set) { 80 return create_cache_path_default(path, src, instruction_set); 81} 82 83static void run_cmd(const std::string& cmd) { 84 system(cmd.c_str()); 85} 86 87static void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) { 88 ::mkdir(path.c_str(), mode); 89 ::chown(path.c_str(), owner, group); 90 ::chmod(path.c_str(), mode); 91} 92 93static int log_callback(int type, const char *fmt, ...) { // NOLINT 94 va_list ap; 95 int priority; 96 97 switch (type) { 98 case SELINUX_WARNING: 99 priority = ANDROID_LOG_WARN; 100 break; 101 case SELINUX_INFO: 102 priority = ANDROID_LOG_INFO; 103 break; 104 default: 105 priority = ANDROID_LOG_ERROR; 106 break; 107 } 108 va_start(ap, fmt); 109 LOG_PRI_VA(priority, "SELinux", fmt, ap); 110 va_end(ap); 111 return 0; 112} 113 114static bool init_selinux() { 115 int selinux_enabled = (is_selinux_enabled() > 0); 116 117 union selinux_callback cb; 118 cb.func_log = log_callback; 119 selinux_set_callback(SELINUX_CB_LOG, cb); 120 121 if (selinux_enabled && selinux_status_open(true) < 0) { 122 LOG(ERROR) << "Could not open selinux status; exiting"; 123 return false; 124 } 125 126 return true; 127} 128 129// Base64 encoding of a simple dex files with 2 methods. 130static const char kDexFile[] = 131 "UEsDBBQAAAAIAOiOYUs9y6BLCgEAABQCAAALABwAY2xhc3Nlcy5kZXhVVAkAA/Ns+lkOHv1ZdXgL" 132 "AAEEI+UCAASIEwAAS0mt4DIwNmX4qpn7j/2wA7v7N+ZvoQpCJRlVx5SWa4YaiDAxMBQwMDBUhJkI" 133 "MUBBDyMDAzsDRJwFxAdioBDDHAYEYAbiFUAM1M5wAIhFGCGKDIDYAogdgNgDiH2BOAiI0xghekDm" 134 "sQIxGxQzM6ACRijNhCbOhCZfyohdPYyuh8szgtVkMkLsLhAAqeCDi+ejibPZZOZlltgxsDnqZSWW" 135 "JTKwOUFoZh9HayDhZM0g5AMS0M9JzEvX90/KSk0usWZgDAMaws5nAyXBzmpoYGlgAjsAyJoBMp0b" 136 "zQ8gGhbOTEhhzYwU3qxIYc2GFN6MClC/AhUyKUDMAYU9M1Qc5F8GKBscVgIQM0FxCwBQSwECHgMU" 137 "AAAACADojmFLPcugSwoBAAAUAgAACwAYAAAAAAAAAAAAoIEAAAAAY2xhc3Nlcy5kZXhVVAUAA/Ns" 138 "+ll1eAsAAQQj5QIABIgTAABQSwUGAAAAAAEAAQBRAAAATwEAAAAA"; 139 140 141class DexoptTest : public testing::Test { 142protected: 143 static constexpr bool kDebug = false; 144 static constexpr uid_t kSystemUid = 1000; 145 static constexpr uid_t kSystemGid = 1000; 146 static constexpr int32_t kOSdkVersion = 25; 147 static constexpr int32_t kAppDataFlags = FLAG_STORAGE_CE | FLAG_STORAGE_DE; 148 static constexpr int32_t kTestUserId = 0; 149 static constexpr uid_t kTestAppId = 19999; 150 151 const gid_t kTestAppUid = multiuser_get_uid(kTestUserId, kTestAppId); 152 const uid_t kTestAppGid = multiuser_get_shared_gid(kTestUserId, kTestAppId); 153 154 InstalldNativeService* service_; 155 std::unique_ptr<std::string> volume_uuid_; 156 std::string package_name_; 157 std::string apk_path_; 158 std::string app_apk_dir_; 159 std::string app_private_dir_ce_; 160 std::string app_private_dir_de_; 161 std::string se_info_; 162 std::string app_oat_dir_; 163 164 int64_t ce_data_inode_; 165 166 std::string secondary_dex_ce_; 167 std::string secondary_dex_ce_link_; 168 std::string secondary_dex_de_; 169 170 virtual void SetUp() { 171 setenv("ANDROID_LOG_TAGS", "*:v", 1); 172 android::base::InitLogging(nullptr); 173 // Initialize the globals holding the file system main paths (/data/, /system/ etc..). 174 // This is needed in order to compute the application and profile paths. 175 ASSERT_TRUE(init_globals_from_data_and_root()); 176 // Initialize selinux log callbacks. 177 // This ensures that selinux is up and running and re-directs the selinux messages 178 // to logcat (in order to make it easier to investigate test results). 179 ASSERT_TRUE(init_selinux()); 180 service_ = new InstalldNativeService(); 181 182 volume_uuid_ = nullptr; 183 package_name_ = "com.installd.test.dexopt"; 184 se_info_ = "default"; 185 app_apk_dir_ = android_app_dir + package_name_; 186 187 create_mock_app(); 188 } 189 190 virtual void TearDown() { 191 if (!kDebug) { 192 service_->destroyAppData( 193 volume_uuid_, package_name_, kTestUserId, kAppDataFlags, ce_data_inode_); 194 run_cmd("rm -rf " + app_apk_dir_); 195 run_cmd("rm -rf " + app_private_dir_ce_); 196 run_cmd("rm -rf " + app_private_dir_de_); 197 } 198 delete service_; 199 } 200 201 void create_mock_app() { 202 // Create the oat dir. 203 app_oat_dir_ = app_apk_dir_ + "/oat"; 204 mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755); 205 service_->createOatDir(app_oat_dir_, kRuntimeIsa); 206 207 // Copy the primary apk. 208 apk_path_ = app_apk_dir_ + "/base.jar"; 209 ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644)); 210 211 // Create the app user data. 212 ASSERT_TRUE(service_->createAppData( 213 volume_uuid_, 214 package_name_, 215 kTestUserId, 216 kAppDataFlags, 217 kTestAppUid, 218 se_info_, 219 kOSdkVersion, 220 &ce_data_inode_).isOk()); 221 222 // Create a secondary dex file on CE storage 223 const char* volume_uuid_cstr = volume_uuid_ == nullptr ? nullptr : volume_uuid_->c_str(); 224 app_private_dir_ce_ = create_data_user_ce_package_path( 225 volume_uuid_cstr, kTestUserId, package_name_.c_str()); 226 secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar"; 227 ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_ce_, kTestAppUid, kTestAppGid, 0600)); 228 std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link( 229 volume_uuid_cstr, kTestUserId, package_name_.c_str()); 230 secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar"; 231 232 // Create a secondary dex file on DE storage. 233 app_private_dir_de_ = create_data_user_de_package_path( 234 volume_uuid_cstr, kTestUserId, package_name_.c_str()); 235 secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar"; 236 ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_de_, kTestAppUid, kTestAppGid, 0600)); 237 238 // Fix app data uid. 239 ASSERT_TRUE(service_->fixupAppData(volume_uuid_, kTestUserId).isOk()); 240 } 241 242 243 std::string GetSecondaryDexArtifact(const std::string& path, const std::string& type) { 244 std::string::size_type end = path.rfind('.'); 245 std::string::size_type start = path.rfind('/', end); 246 return path.substr(0, start) + "/oat/" + kRuntimeIsa + "/" + 247 path.substr(start + 1, end - start) + type; 248 } 249 250 void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag, 251 bool should_binder_call_succeed, bool should_dex_be_compiled = true, 252 int32_t uid = -1) { 253 if (uid == -1) { 254 uid = kTestAppUid; 255 } 256 std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_)); 257 int32_t dexopt_needed = 0; // does not matter; 258 std::unique_ptr<std::string> out_path = nullptr; // does not matter 259 int32_t dex_flags = DEXOPT_SECONDARY_DEX | dex_storage_flag; 260 std::string compiler_filter = "speed-profile"; 261 std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&")); 262 std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_)); 263 bool downgrade = false; 264 int32_t target_sdk_version = 0; // default 265 std::unique_ptr<std::string> profile_name_ptr = nullptr; 266 267 binder::Status result = service_->dexopt(path, 268 uid, 269 package_name_ptr, 270 kRuntimeIsa, 271 dexopt_needed, 272 out_path, 273 dex_flags, 274 compiler_filter, 275 volume_uuid_, 276 class_loader_context_ptr, 277 se_info_ptr, 278 downgrade, 279 target_sdk_version, 280 profile_name_ptr); 281 ASSERT_EQ(should_binder_call_succeed, result.isOk()); 282 int expected_access = should_dex_be_compiled ? 0 : -1; 283 std::string odex = GetSecondaryDexArtifact(path, "odex"); 284 std::string vdex = GetSecondaryDexArtifact(path, "vdex"); 285 std::string art = GetSecondaryDexArtifact(path, "art"); 286 ASSERT_EQ(expected_access, access(odex.c_str(), R_OK)); 287 ASSERT_EQ(expected_access, access(vdex.c_str(), R_OK)); 288 ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image. 289 } 290 291 void reconcile_secondary_dex(const std::string& path, int32_t storage_flag, 292 bool should_binder_call_succeed, bool should_dex_exist, bool should_dex_be_deleted, 293 int32_t uid = -1, std::string* package_override = nullptr) { 294 if (uid == -1) { 295 uid = kTestAppUid; 296 } 297 std::vector<std::string> isas; 298 isas.push_back(kRuntimeIsa); 299 bool out_secondary_dex_exists = false; 300 binder::Status result = service_->reconcileSecondaryDexFile( 301 path, 302 package_override == nullptr ? package_name_ : *package_override, 303 uid, 304 isas, 305 volume_uuid_, 306 storage_flag, 307 &out_secondary_dex_exists); 308 309 ASSERT_EQ(should_binder_call_succeed, result.isOk()); 310 ASSERT_EQ(should_dex_exist, out_secondary_dex_exists); 311 312 int expected_access = should_dex_be_deleted ? -1 : 0; 313 std::string odex = GetSecondaryDexArtifact(path, "odex"); 314 std::string vdex = GetSecondaryDexArtifact(path, "vdex"); 315 std::string art = GetSecondaryDexArtifact(path, "art"); 316 ASSERT_EQ(expected_access, access(odex.c_str(), F_OK)); 317 ASSERT_EQ(expected_access, access(vdex.c_str(), F_OK)); 318 ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image. 319 } 320 321 void CheckFileAccess(const std::string& file, uid_t uid, gid_t gid, mode_t mode) { 322 struct stat st; 323 ASSERT_EQ(0, stat(file.c_str(), &st)); 324 ASSERT_EQ(uid, st.st_uid); 325 ASSERT_EQ(gid, st.st_gid); 326 ASSERT_EQ(mode, st.st_mode); 327 } 328 329 void CompilePrimaryDexOk(std::string compiler_filter, 330 int32_t dex_flags, 331 const char* oat_dir, 332 int32_t uid, 333 int32_t dexopt_needed, 334 bool downgrade = false) { 335 return CompilePrimaryDex( 336 compiler_filter, dex_flags, oat_dir, uid, dexopt_needed, downgrade, true); 337 } 338 339 void CompilePrimaryDexFail(std::string compiler_filter, 340 int32_t dex_flags, 341 const char* oat_dir, 342 int32_t uid, 343 int32_t dexopt_needed, 344 bool downgrade = false) { 345 return CompilePrimaryDex( 346 compiler_filter, dex_flags, oat_dir, uid, dexopt_needed, downgrade, false); 347 } 348 349 void CompilePrimaryDex(std::string compiler_filter, 350 int32_t dex_flags, 351 const char* oat_dir, 352 int32_t uid, 353 int32_t dexopt_needed, 354 bool downgrade, 355 bool should_binder_call_succeed) { 356 std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_)); 357 std::unique_ptr<std::string> out_path( 358 oat_dir == nullptr ? nullptr : new std::string(oat_dir)); 359 std::unique_ptr<std::string> class_loader_context_ptr(new std::string("&")); 360 std::unique_ptr<std::string> se_info_ptr(new std::string(se_info_)); 361 int32_t target_sdk_version = 0; // default 362 std::unique_ptr<std::string> profile_name_ptr(new std::string("primary.prof")); 363 364 bool prof_result; 365 binder::Status prof_binder_result = service_->prepareAppProfile( 366 package_name_, kTestUserId, kTestAppId, *profile_name_ptr, /*code path*/ "base.apk", 367 /*dex_metadata*/ nullptr, &prof_result); 368 369 ASSERT_TRUE(prof_binder_result.isOk()); 370 ASSERT_TRUE(prof_result); 371 372 binder::Status result = service_->dexopt(apk_path_, 373 uid, 374 package_name_ptr, 375 kRuntimeIsa, 376 dexopt_needed, 377 out_path, 378 dex_flags, 379 compiler_filter, 380 volume_uuid_, 381 class_loader_context_ptr, 382 se_info_ptr, 383 downgrade, 384 target_sdk_version, 385 profile_name_ptr); 386 ASSERT_EQ(should_binder_call_succeed, result.isOk()); 387 388 if (!should_binder_call_succeed) { 389 return; 390 } 391 // Check the access to the compiler output. 392 // - speed-profile artifacts are not world-wide readable. 393 // - files are owned by the system uid. 394 std::string odex = GetPrimaryDexArtifact(oat_dir, apk_path_, "odex"); 395 std::string vdex = GetPrimaryDexArtifact(oat_dir, apk_path_, "vdex"); 396 std::string art = GetPrimaryDexArtifact(oat_dir, apk_path_, "art"); 397 398 mode_t mode = S_IFREG | (compiler_filter == "speed-profile" ? 0640 : 0644); 399 CheckFileAccess(odex, kSystemUid, uid, mode); 400 CheckFileAccess(vdex, kSystemUid, uid, mode); 401 CheckFileAccess(odex, kSystemUid, uid, mode); 402 403 // empty profiles do not generate an image. 404 // todo: add tests with non-empty profiles. 405 struct stat st; 406 ASSERT_EQ(-1, stat(art.c_str(), &st)); 407 } 408 409 std::string GetPrimaryDexArtifact(const char* oat_dir, 410 const std::string& dex_path, 411 const std::string& type) { 412 if (oat_dir == nullptr) { 413 std::string path = dex_path; 414 for (auto it = path.begin() + 1; it < path.end(); ++it) { 415 if (*it == '/') { 416 *it = '@'; 417 } 418 } 419 return android_data_dir + DALVIK_CACHE + '/' + kRuntimeIsa + "/" + path 420 + "@classes.dex"; 421 } else { 422 std::string::size_type name_end = dex_path.rfind('.'); 423 std::string::size_type name_start = dex_path.rfind('/'); 424 return std::string(oat_dir) + "/" + kRuntimeIsa + "/" + 425 dex_path.substr(name_start + 1, name_end - name_start) + type; 426 } 427 } 428}; 429 430 431TEST_F(DexoptTest, DexoptSecondaryCe) { 432 LOG(INFO) << "DexoptSecondaryCe"; 433 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE, 434 /*binder_ok*/ true, /*compile_ok*/ true); 435} 436 437TEST_F(DexoptTest, DexoptSecondaryCeLink) { 438 LOG(INFO) << "DexoptSecondaryCeLink"; 439 CompileSecondaryDex(secondary_dex_ce_link_, DEXOPT_STORAGE_CE, 440 /*binder_ok*/ true, /*compile_ok*/ true); 441} 442 443TEST_F(DexoptTest, DexoptSecondaryDe) { 444 LOG(INFO) << "DexoptSecondaryDe"; 445 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE, 446 /*binder_ok*/ true, /*compile_ok*/ true); 447} 448 449TEST_F(DexoptTest, DexoptSecondaryDoesNotExist) { 450 LOG(INFO) << "DexoptSecondaryDoesNotExist"; 451 // If the file validates but does not exist we do not treat it as an error. 452 CompileSecondaryDex(secondary_dex_ce_ + "not.there", DEXOPT_STORAGE_CE, 453 /*binder_ok*/ true, /*compile_ok*/ false); 454} 455 456TEST_F(DexoptTest, DexoptSecondaryStorageValidationError) { 457 LOG(INFO) << "DexoptSecondaryStorageValidationError"; 458 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_DE, 459 /*binder_ok*/ false, /*compile_ok*/ false); 460} 461 462TEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) { 463 LOG(INFO) << "DexoptSecondaryAppOwnershipValidationError"; 464 CompileSecondaryDex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE, 465 /*binder_ok*/ false, /*compile_ok*/ false); 466} 467 468TEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) { 469 LOG(INFO) << "DexoptSecondaryAcessViaDifferentUidError"; 470 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE, 471 /*binder_ok*/ false, /*compile_ok*/ false, kSystemUid); 472} 473 474TEST_F(DexoptTest, DexoptPrimaryPublic) { 475 LOG(INFO) << "DexoptPrimaryPublic"; 476 CompilePrimaryDexOk("verify", 477 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC, 478 app_oat_dir_.c_str(), 479 kTestAppGid, 480 DEX2OAT_FROM_SCRATCH); 481} 482 483TEST_F(DexoptTest, DexoptPrimaryProfileNonPublic) { 484 LOG(INFO) << "DexoptPrimaryProfileNonPublic"; 485 CompilePrimaryDexOk("speed-profile", 486 DEXOPT_BOOTCOMPLETE, 487 app_oat_dir_.c_str(), 488 kTestAppGid, 489 DEX2OAT_FROM_SCRATCH); 490} 491 492TEST_F(DexoptTest, DexoptPrimaryProfilePublic) { 493 LOG(INFO) << "DexoptPrimaryProfilePublic"; 494 CompilePrimaryDexOk("verify", 495 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC, 496 app_oat_dir_.c_str(), 497 kTestAppGid, 498 DEX2OAT_FROM_SCRATCH); 499} 500 501TEST_F(DexoptTest, DexoptPrimaryBackgroundOk) { 502 LOG(INFO) << "DexoptPrimaryBackgroundOk"; 503 CompilePrimaryDexOk("speed-profile", 504 DEXOPT_IDLE_BACKGROUND_JOB, 505 app_oat_dir_.c_str(), 506 kTestAppGid, 507 DEX2OAT_FROM_SCRATCH); 508} 509 510TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) { 511 LOG(INFO) << "DexoptPrimaryFailedInvalidFilter"; 512 CompilePrimaryDexFail("awesome-filter", 513 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC, 514 app_oat_dir_.c_str(), 515 kTestAppGid, 516 DEX2OAT_FROM_SCRATCH); 517} 518 519class PrimaryDexReCompilationTest : public DexoptTest { 520 public: 521 virtual void SetUp() { 522 DexoptTest::SetUp(); 523 CompilePrimaryDexOk("verify", 524 DEXOPT_BOOTCOMPLETE | DEXOPT_PUBLIC, 525 app_oat_dir_.c_str(), 526 kTestAppGid, 527 DEX2OAT_FROM_SCRATCH); 528 std::string odex = GetSecondaryDexArtifact(apk_path_, "odex"); 529 std::string vdex = GetSecondaryDexArtifact(apk_path_, "vdex"); 530 531 first_compilation_odex_fd_.reset(open(odex.c_str(), O_RDONLY)); 532 first_compilation_vdex_fd_.reset(open(vdex.c_str(), O_RDONLY)); 533 } 534 535 virtual void TearDown() { 536 first_compilation_odex_fd_.reset(-1); 537 first_compilation_vdex_fd_.reset(-1); 538 DexoptTest::TearDown(); 539 } 540 541 protected: 542 unique_fd first_compilation_odex_fd_; 543 unique_fd first_compilation_vdex_fd_; 544}; 545 546TEST_F(PrimaryDexReCompilationTest, DexoptPrimaryUpdateInPlaceVdex) { 547 LOG(INFO) << "DexoptPrimaryUpdateInPlaceVdex"; 548 549 CompilePrimaryDexOk("verify", 550 DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC, 551 app_oat_dir_.c_str(), 552 kTestAppGid, 553 DEX2OAT_FOR_BOOT_IMAGE); 554} 555 556class ReconcileTest : public DexoptTest { 557 virtual void SetUp() { 558 DexoptTest::SetUp(); 559 CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE, 560 /*binder_ok*/ true, /*compile_ok*/ true); 561 CompileSecondaryDex(secondary_dex_de_, DEXOPT_STORAGE_DE, 562 /*binder_ok*/ true, /*compile_ok*/ true); 563 } 564}; 565 566TEST_F(ReconcileTest, ReconcileSecondaryCeExists) { 567 LOG(INFO) << "ReconcileSecondaryCeExists"; 568 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE, 569 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false); 570} 571 572TEST_F(ReconcileTest, ReconcileSecondaryCeLinkExists) { 573 LOG(INFO) << "ReconcileSecondaryCeLinkExists"; 574 reconcile_secondary_dex(secondary_dex_ce_link_, FLAG_STORAGE_CE, 575 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false); 576} 577 578TEST_F(ReconcileTest, ReconcileSecondaryDeExists) { 579 LOG(INFO) << "ReconcileSecondaryDeExists"; 580 reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE, 581 /*binder_ok*/ true, /*dex_ok */ true, /*odex_deleted*/ false); 582} 583 584TEST_F(ReconcileTest, ReconcileSecondaryDeDoesNotExist) { 585 LOG(INFO) << "ReconcileSecondaryDeDoesNotExist"; 586 run_cmd("rm -rf " + secondary_dex_de_); 587 reconcile_secondary_dex(secondary_dex_de_, FLAG_STORAGE_DE, 588 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ true); 589} 590 591TEST_F(ReconcileTest, ReconcileSecondaryStorageValidationError) { 592 // Validation errors will not clean the odex/vdex/art files but will mark 593 // the file as non existent so that the PM knows it should purge it from its 594 // records. 595 LOG(INFO) << "ReconcileSecondaryStorageValidationError"; 596 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_DE, 597 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false); 598} 599 600TEST_F(ReconcileTest, ReconcileSecondaryAppOwnershipValidationError) { 601 LOG(INFO) << "ReconcileSecondaryAppOwnershipValidationError"; 602 // Attempt to reconcile the dex files of the test app from a different app. 603 std::string another_app = "another.app"; 604 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE, 605 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid, &another_app); 606} 607 608TEST_F(ReconcileTest, ReconcileSecondaryAcessViaDifferentUidError) { 609 LOG(INFO) << "ReconcileSecondaryAcessViaDifferentUidError"; 610 reconcile_secondary_dex(secondary_dex_ce_, FLAG_STORAGE_CE, 611 /*binder_ok*/ true, /*dex_ok */ false, /*odex_deleted*/ false, kSystemUid); 612} 613 614class ProfileTest : public DexoptTest { 615 protected: 616 std::string cur_profile_; 617 std::string ref_profile_; 618 std::string snap_profile_; 619 620 static constexpr const char* kPrimaryProfile = "primary.prof"; 621 622 virtual void SetUp() { 623 DexoptTest::SetUp(); 624 cur_profile_ = create_current_profile_path( 625 kTestUserId, package_name_, kPrimaryProfile, /*is_secondary_dex*/ false); 626 ref_profile_ = create_reference_profile_path(package_name_, kPrimaryProfile, 627 /*is_secondary_dex*/ false); 628 snap_profile_ = create_snapshot_profile_path(package_name_, kPrimaryProfile); 629 } 630 631 void SetupProfile(const std::string& path, uid_t uid, gid_t gid, mode_t mode, 632 int32_t num_dex) { 633 run_cmd("profman --generate-test-profile-seed=" + std::to_string(num_dex) + 634 " --generate-test-profile-num-dex=" + std::to_string(num_dex) + 635 " --generate-test-profile=" + path); 636 ::chmod(path.c_str(), mode); 637 ::chown(path.c_str(), uid, gid); 638 } 639 640 void SetupProfiles(bool setup_ref) { 641 SetupProfile(cur_profile_, kTestAppUid, kTestAppGid, 0600, 1); 642 if (setup_ref) { 643 SetupProfile(ref_profile_, kTestAppUid, kTestAppGid, 0600, 2); 644 } 645 } 646 647 void createProfileSnapshot(int32_t appid, const std::string& package_name, 648 bool expected_result) { 649 bool result; 650 binder::Status binder_result = service_->createProfileSnapshot( 651 appid, package_name, kPrimaryProfile, apk_path_, &result); 652 ASSERT_TRUE(binder_result.isOk()); 653 ASSERT_EQ(expected_result, result); 654 655 if (!expected_result) { 656 // Do not check the files if we expect to fail. 657 return; 658 } 659 660 // Check that the snapshot was created witht he expected acess flags. 661 CheckFileAccess(snap_profile_, kSystemUid, kSystemGid, 0600 | S_IFREG); 662 663 // The snapshot should be equivalent to the merge of profiles. 664 std::string expected_profile_content = snap_profile_ + ".expected"; 665 run_cmd("rm -f " + expected_profile_content); 666 run_cmd("touch " + expected_profile_content); 667 run_cmd("profman --profile-file=" + cur_profile_ + 668 " --profile-file=" + ref_profile_ + 669 " --reference-profile-file=" + expected_profile_content); 670 671 ASSERT_TRUE(AreFilesEqual(expected_profile_content, snap_profile_)); 672 673 pid_t pid = fork(); 674 if (pid == 0) { 675 /* child */ 676 TransitionToSystemServer(); 677 678 // System server should be able to open the the spanshot. 679 unique_fd fd(open(snap_profile_.c_str(), O_RDONLY)); 680 ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno); 681 _exit(0); 682 } 683 /* parent */ 684 ASSERT_TRUE(WIFEXITED(wait_child(pid))); 685 } 686 687 void mergePackageProfiles(const std::string& package_name, 688 const std::string& code_path, 689 bool expected_result) { 690 bool result; 691 binder::Status binder_result = service_->mergeProfiles( 692 kTestAppUid, package_name, code_path, &result); 693 ASSERT_TRUE(binder_result.isOk()); 694 ASSERT_EQ(expected_result, result); 695 696 if (!expected_result) { 697 // Do not check the files if we expect to fail. 698 return; 699 } 700 701 // Check that the snapshot was created witht he expected acess flags. 702 CheckFileAccess(ref_profile_, kTestAppUid, kTestAppUid, 0600 | S_IFREG); 703 704 // The snapshot should be equivalent to the merge of profiles. 705 std::string ref_profile_content = ref_profile_ + ".expected"; 706 run_cmd("rm -f " + ref_profile_content); 707 run_cmd("touch " + ref_profile_content); 708 run_cmd("profman --profile-file=" + cur_profile_ + 709 " --profile-file=" + ref_profile_ + 710 " --reference-profile-file=" + ref_profile_content); 711 712 ASSERT_TRUE(AreFilesEqual(ref_profile_content, ref_profile_)); 713 } 714 715 // TODO(calin): add dex metadata tests once the ART change is merged. 716 void preparePackageProfile(const std::string& package_name, const std::string& profile_name, 717 bool expected_result) { 718 bool result; 719 binder::Status binder_result = service_->prepareAppProfile( 720 package_name, kTestUserId, kTestAppId, profile_name, /*code path*/ "base.apk", 721 /*dex_metadata*/ nullptr, &result); 722 ASSERT_TRUE(binder_result.isOk()); 723 ASSERT_EQ(expected_result, result); 724 725 if (!expected_result) { 726 // Do not check the files if we expect to fail. 727 return; 728 } 729 730 std::string code_path_cur_prof = create_current_profile_path( 731 kTestUserId, package_name, profile_name, /*is_secondary_dex*/ false); 732 std::string code_path_ref_profile = create_reference_profile_path(package_name, 733 profile_name, /*is_secondary_dex*/ false); 734 735 // Check that we created the current profile. 736 CheckFileAccess(code_path_cur_prof, kTestAppUid, kTestAppUid, 0600 | S_IFREG); 737 738 // Without dex metadata we don't generate a reference profile. 739 ASSERT_EQ(-1, access(code_path_ref_profile.c_str(), R_OK)); 740 } 741 742 protected: 743 void TransitionToSystemServer() { 744 ASSERT_TRUE(DropCapabilities(kSystemUid, kSystemGid)); 745 int32_t res = selinux_android_setcontext( 746 kSystemUid, true, se_info_.c_str(), "system_server"); 747 ASSERT_EQ(0, res) << "Failed to setcon " << strerror(errno); 748 } 749 750 bool AreFilesEqual(const std::string& file1, const std::string& file2) { 751 std::vector<uint8_t> content1; 752 std::vector<uint8_t> content2; 753 754 if (!ReadAll(file1, &content1)) return false; 755 if (!ReadAll(file2, &content2)) return false; 756 return content1 == content2; 757 } 758 759 bool ReadAll(const std::string& file, std::vector<uint8_t>* content) { 760 unique_fd fd(open(file.c_str(), O_RDONLY)); 761 if (fd < 0) { 762 PLOG(ERROR) << "Failed to open " << file; 763 return false; 764 } 765 struct stat st; 766 if (fstat(fd, &st) != 0) { 767 PLOG(ERROR) << "Failed to stat " << file; 768 return false; 769 } 770 content->resize(st.st_size); 771 bool result = ReadFully(fd, content->data(), content->size()); 772 if (!result) { 773 PLOG(ERROR) << "Failed to read " << file; 774 } 775 return result; 776 } 777}; 778 779TEST_F(ProfileTest, ProfileSnapshotOk) { 780 LOG(INFO) << "ProfileSnapshotOk"; 781 782 SetupProfiles(/*setup_ref*/ true); 783 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true); 784} 785 786// The reference profile is created on the fly. We need to be able to 787// snapshot without one. 788TEST_F(ProfileTest, ProfileSnapshotOkNoReference) { 789 LOG(INFO) << "ProfileSnapshotOkNoReference"; 790 791 SetupProfiles(/*setup_ref*/ false); 792 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true); 793} 794 795TEST_F(ProfileTest, ProfileSnapshotFailWrongPackage) { 796 LOG(INFO) << "ProfileSnapshotFailWrongPackage"; 797 798 SetupProfiles(/*setup_ref*/ true); 799 createProfileSnapshot(kTestAppId, "not.there", /*expected_result*/ false); 800} 801 802TEST_F(ProfileTest, ProfileSnapshotDestroySnapshot) { 803 LOG(INFO) << "ProfileSnapshotDestroySnapshot"; 804 805 SetupProfiles(/*setup_ref*/ true); 806 createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true); 807 808 binder::Status binder_result = service_->destroyProfileSnapshot(package_name_, kPrimaryProfile); 809 ASSERT_TRUE(binder_result.isOk()); 810 struct stat st; 811 ASSERT_EQ(-1, stat(snap_profile_.c_str(), &st)); 812 ASSERT_EQ(ENOENT, errno); 813} 814 815TEST_F(ProfileTest, ProfileMergeOk) { 816 LOG(INFO) << "ProfileMergeOk"; 817 818 SetupProfiles(/*setup_ref*/ true); 819 mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true); 820} 821 822// The reference profile is created on the fly. We need to be able to 823// merge without one. 824TEST_F(ProfileTest, ProfileMergeOkNoReference) { 825 LOG(INFO) << "ProfileMergeOkNoReference"; 826 827 SetupProfiles(/*setup_ref*/ false); 828 mergePackageProfiles(package_name_, "primary.prof", /*expected_result*/ true); 829} 830 831TEST_F(ProfileTest, ProfileMergeFailWrongPackage) { 832 LOG(INFO) << "ProfileMergeFailWrongPackage"; 833 834 SetupProfiles(/*setup_ref*/ true); 835 mergePackageProfiles("not.there", "primary.prof", /*expected_result*/ false); 836} 837 838TEST_F(ProfileTest, ProfileDirOk) { 839 LOG(INFO) << "ProfileDirOk"; 840 841 std::string cur_profile_dir = create_primary_current_profile_package_dir_path( 842 kTestUserId, package_name_); 843 std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_, 844 kPrimaryProfile, /*is_secondary_dex*/false); 845 std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_); 846 847 CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR); 848 CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR); 849} 850 851// Verify that the profile directories are fixed up during an upgrade. 852// (The reference profile directory is prepared lazily). 853TEST_F(ProfileTest, ProfileDirOkAfterFixup) { 854 LOG(INFO) << "ProfileDirOkAfterFixup"; 855 856 std::string cur_profile_dir = create_primary_current_profile_package_dir_path( 857 kTestUserId, package_name_); 858 std::string cur_profile_file = create_current_profile_path(kTestUserId, package_name_, 859 kPrimaryProfile, /*is_secondary_dex*/false); 860 std::string ref_profile_dir = create_primary_reference_profile_package_dir_path(package_name_); 861 862 // Simulate a pre-P setup by changing the owner to kTestAppGid and permissions to 0700. 863 ASSERT_EQ(0, chown(ref_profile_dir.c_str(), kTestAppGid, kTestAppGid)); 864 ASSERT_EQ(0, chmod(ref_profile_dir.c_str(), 0700)); 865 866 // Run createAppData again which will offer to fix-up the profile directories. 867 ASSERT_TRUE(service_->createAppData( 868 volume_uuid_, 869 package_name_, 870 kTestUserId, 871 kAppDataFlags, 872 kTestAppUid, 873 se_info_, 874 kOSdkVersion, 875 &ce_data_inode_).isOk()); 876 877 // Check the file access. 878 CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR); 879 CheckFileAccess(ref_profile_dir, kSystemUid, kTestAppGid, 0770 | S_IFDIR); 880} 881 882TEST_F(ProfileTest, ProfilePrepareOk) { 883 LOG(INFO) << "ProfilePrepareOk"; 884 preparePackageProfile(package_name_, "split.prof", /*expected_result*/ true); 885} 886 887TEST_F(ProfileTest, ProfilePrepareFailInvalidPackage) { 888 LOG(INFO) << "ProfilePrepareFailInvalidPackage"; 889 preparePackageProfile("not.there.package", "split.prof", /*expected_result*/ false); 890} 891 892TEST_F(ProfileTest, ProfilePrepareFailProfileChangedUid) { 893 LOG(INFO) << "ProfilePrepareFailProfileChangedUid"; 894 SetupProfiles(/*setup_ref*/ false); 895 // Change the uid on the profile to trigger a failure. 896 ::chown(cur_profile_.c_str(), kTestAppUid + 1, kTestAppGid + 1); 897 preparePackageProfile(package_name_, "primary.prof", /*expected_result*/ false); 898} 899 900 901class BootProfileTest : public ProfileTest { 902 public: 903 virtual void setup() { 904 ProfileTest::SetUp(); 905 intial_android_profiles_dir = android_profiles_dir; 906 } 907 908 virtual void TearDown() { 909 android_profiles_dir = intial_android_profiles_dir; 910 ProfileTest::TearDown(); 911 } 912 913 void UpdateAndroidProfilesDir(const std::string& profile_dir) { 914 android_profiles_dir = profile_dir; 915 // We need to create the reference profile directory in the new profile dir. 916 run_cmd("mkdir -p " + profile_dir + "/ref"); 917 } 918 919 void createBootImageProfileSnapshot(const std::string& classpath, bool expected_result) { 920 bool result; 921 binder::Status binder_result = service_->createProfileSnapshot( 922 -1, "android", "android.prof", classpath, &result); 923 ASSERT_TRUE(binder_result.isOk()); 924 ASSERT_EQ(expected_result, result); 925 926 if (!expected_result) { 927 // Do not check the files if we expect to fail. 928 return; 929 } 930 931 // Check that the snapshot was created with he expected access flags. 932 const std::string boot_profile = create_snapshot_profile_path("android", "android.prof"); 933 CheckFileAccess(boot_profile, kSystemUid, kSystemGid, 0600 | S_IFREG); 934 935 pid_t pid = fork(); 936 if (pid == 0) { 937 /* child */ 938 TransitionToSystemServer(); 939 940 // System server should be able to open the snapshot. 941 unique_fd fd(open(boot_profile.c_str(), O_RDONLY)); 942 ASSERT_TRUE(fd > -1) << "Failed to open profile as kSystemUid: " << strerror(errno); 943 _exit(0); 944 } 945 /* parent */ 946 ASSERT_TRUE(WIFEXITED(wait_child(pid))); 947 } 948 protected: 949 std::string intial_android_profiles_dir; 950}; 951 952TEST_F(BootProfileTest, BootProfileSnapshotOk) { 953 LOG(INFO) << "BootProfileSnapshotOk"; 954 char* boot_classpath = getenv("BOOTCLASSPATH"); 955 ASSERT_TRUE(boot_classpath != nullptr); 956 createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true); 957} 958 959TEST_F(BootProfileTest, BootProfileSnapshotFailEmptyClasspath) { 960 LOG(INFO) << "BootProfileSnapshotFailEmptyClasspath"; 961 962 createBootImageProfileSnapshot(/*boot_classpath*/ "", /*expected_result*/ false); 963} 964 965TEST_F(BootProfileTest, BootProfileSnapshotOkNoProfiles) { 966 LOG(INFO) << "BootProfileSnapshotOkNoProfiles"; 967 char* boot_classpath = getenv("BOOTCLASSPATH"); 968 ASSERT_TRUE(boot_classpath != nullptr); 969 970 // The app_apk_dir has no profiles. So we shouldn't be able to merge anything. 971 // Still, this is not a failure case. 972 UpdateAndroidProfilesDir(app_apk_dir_); 973 createBootImageProfileSnapshot(boot_classpath, /*expected_result*/ true); 974} 975 976// Verify that profile collection. 977TEST_F(BootProfileTest, CollectProfiles) { 978 LOG(INFO) << "CollectProfiles"; 979 980 // Create some profile directories mimicking the real profile structure. 981 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/ref"); 982 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/0/"); 983 run_cmd("mkdir -p " + app_private_dir_de_ + "/profiles/cur/1/"); 984 // Create an empty profile. 985 run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/1/primary.prof"); 986 // Create a random file. 987 run_cmd("touch " + app_private_dir_de_ + "/profiles/cur/0/non.profile.file"); 988 989 // Create some non-empty profiles. 990 std::string current_prof = app_private_dir_de_ + "/profiles/cur/0/primary.prof"; 991 run_cmd("echo 1 > " + current_prof); 992 std::string ref_prof = app_private_dir_de_ + "/profiles/ref/primary.prof"; 993 run_cmd("echo 1 > " + ref_prof); 994 995 UpdateAndroidProfilesDir(app_private_dir_de_ + "/profiles"); 996 997 std::vector<std::string> profiles; 998 collect_profiles(&profiles); 999 1000 // Only two profiles should be in the output. 1001 ASSERT_EQ(2u, profiles.size()); 1002 ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), current_prof) != profiles.end()); 1003 ASSERT_TRUE(std::find(profiles.begin(), profiles.end(), ref_prof) != profiles.end()); 1004} 1005 1006} // namespace installd 1007} // namespace android 1008