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