1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "appspawn_hook.h" 16#include "appspawn_msg.h" 17#include "appspawn_manager.h" 18#include "appspawn_utils.h" 19#include "parameter.h" 20#include "securec.h" 21 22// for stub 23extern bool may_init_gwp_asan(bool forceInit); 24 25// ide-asan 26#ifndef ASAN_DETECTOR 27 28#if defined(__aarch64__) || defined(__x86_64__) 29#define ASAN_LD_PRELOAD "/system/lib64/libclang_rt.asan.so" 30#else 31#define ASAN_LD_PRELOAD "/system/lib/libclang_rt.asan.so" 32#endif 33#define HWASAN_LD_PRELOAD "/system/lib64/libclang_rt.hwasan.so" 34#define TSAN_LD_PRELOAD "/system/lib64/libclang_rt.tsan.so" 35 36#define ASAN_OPTIONS "include=/system/etc/asan.options" 37#define HWASAN_OPTIONS "include=/system/etc/asan.options" 38#define TSAN_OPTIONS "include=/system/etc/tsan.options" 39#define UBSAN_OPTIONS "print_stacktrace=1:print_module_map=2:log_exe_name=1" 40 41// 配置表数据 42static const EnvConfig g_configTable[] = { 43 { APP_FLAGS_HWASAN_ENABLED, HWASAN_LD_PRELOAD, NULL, NULL, NULL, HWASAN_OPTIONS }, 44 { APP_FLAGS_ASANENABLED, ASAN_LD_PRELOAD, ASAN_OPTIONS, NULL, NULL, NULL }, 45 { APP_FLAGS_TSAN_ENABLED, TSAN_LD_PRELOAD, NULL, TSAN_OPTIONS, NULL, NULL }, 46 { APP_FLAGS_UBSAN_ENABLED, NULL, NULL, NULL, UBSAN_OPTIONS, NULL }, 47}; 48 49static int SetAsanEnabledEnv(const AppSpawnMgr *content, const AppSpawningCtx *property) 50{ 51 size_t configTableSize = sizeof(g_configTable) / sizeof(g_configTable[0]); 52 for (size_t i = 0; i < configTableSize; ++i) { 53 if (CheckAppMsgFlagsSet(property, g_configTable[i].flag)) { 54 if (g_configTable[i].ldPreload) { 55 setenv("LD_PRELOAD", g_configTable[i].ldPreload, 1); 56 } 57 if (g_configTable[i].asanOptions) { 58 setenv("ASAN_OPTIONS", g_configTable[i].asanOptions, 1); 59 } else { 60 unsetenv("ASAN_OPTIONS"); 61 } 62 if (g_configTable[i].tsanOptions) { 63 setenv("TSAN_OPTIONS", g_configTable[i].tsanOptions, 1); 64 } else { 65 unsetenv("TSAN_OPTIONS"); 66 } 67 if (g_configTable[i].ubsanOptions) { 68 setenv("UBSAN_OPTIONS", g_configTable[i].ubsanOptions, 1); 69 } else { 70 unsetenv("UBSAN_OPTIONS"); 71 } 72 if (g_configTable[i].hwasanOptions) { 73 setenv("HWASAN_OPTIONS", g_configTable[i].hwasanOptions, 1); 74 } else { 75 unsetenv("HWASAN_OPTIONS"); 76 } 77 APPSPAWN_LOGV("SetAsanEnabledEnv %{public}d,%{public}s,%{public}s,%{public}s,%{public}s,%{public}s", 78 g_configTable[i].flag, g_configTable[i].ldPreload, g_configTable[i].asanOptions, 79 g_configTable[i].tsanOptions, g_configTable[i].ubsanOptions, g_configTable[i].hwasanOptions); 80 return 0; 81 } 82 } 83 return -1; 84} 85#endif 86 87static void SetGwpAsanEnabled(const AppSpawnMgr *content, const AppSpawningCtx *property) 88{ 89 if (!(CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE) || 90 CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_NORMAL))) { 91 return; 92 } 93 if (IsDeveloperModeOn(property)) { 94 APPSPAWN_LOGV("SetGwpAsanEnabled with flags: %{public}d", 95 CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE)); 96 may_init_gwp_asan(CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE)); 97 } 98} 99 100#ifdef ASAN_DETECTOR 101#define WRAP_VALUE_MAX_LENGTH 96 102static int CheckSupportColdStart(const char *bundleName) 103{ 104 char wrapBundleNameKey[WRAP_VALUE_MAX_LENGTH] = {0}; 105 char wrapBundleNameValue[WRAP_VALUE_MAX_LENGTH] = {0}; 106 107 int len = sprintf_s(wrapBundleNameKey, WRAP_VALUE_MAX_LENGTH, "wrap.%s", bundleName); 108 APPSPAWN_CHECK(len > 0 && (len < WRAP_VALUE_MAX_LENGTH), return -1, "Invalid to format wrapBundleNameKey"); 109 110 int ret = GetParameter(wrapBundleNameKey, "", wrapBundleNameValue, WRAP_VALUE_MAX_LENGTH); 111 APPSPAWN_CHECK(ret > 0 && (!strcmp(wrapBundleNameValue, "asan_wrapper")), return -1, 112 "Not wrap %{public}s.", bundleName); 113 APPSPAWN_LOGI("Asan: GetParameter %{public}s the value is %{public}s.", wrapBundleNameKey, wrapBundleNameValue); 114 return 0; 115} 116#endif 117 118static int AsanSpawnGetSpawningFlag(AppSpawnMgr *content, AppSpawningCtx *property) 119{ 120 APPSPAWN_LOGV("Prepare spawn app %{public}s", GetProcessName(property)); 121#ifdef ASAN_DETECTOR 122 if (CheckSupportColdStart(GetBundleName(property)) == 0) { 123 property->client.flags |= APP_COLD_START; 124 property->client.flags |= APP_ASAN_DETECTOR; 125 if (property->forkCtx.coldRunPath) { 126 free(property->forkCtx.coldRunPath); 127 } 128#ifndef CJAPP_SPAWN 129 property->forkCtx.coldRunPath = strdup("/system/asan/bin/appspawn"); 130#elif NATIVE_SPAWN 131 property->forkCtx.coldRunPath = strdup("/system/asan/bin/nativespawn"); 132#else 133 property->forkCtx.coldRunPath = strdup("/system/asan/bin/cjappspawn"); 134#endif 135 if (property->forkCtx.coldRunPath == NULL) { 136 APPSPAWN_LOGE("Failed to set asan exec path %{public}s", GetProcessName(property)); 137 } 138 } 139#endif 140 return 0; 141} 142 143static int AsanSpawnInitSpawningEnv(AppSpawnMgr *content, AppSpawningCtx *property) 144{ 145 if (GetAppSpawnMsgType(property) == MSG_SPAWN_NATIVE_PROCESS) { 146 return 0; 147 } 148#ifndef ASAN_DETECTOR 149 int ret = SetAsanEnabledEnv(content, property); 150 if (ret == 0) { 151 APPSPAWN_LOGI("SetAsanEnabledEnv cold start app %{public}s", GetProcessName(property)); 152 property->client.flags |= APP_COLD_START; 153 } 154#endif 155 (void)SetGwpAsanEnabled(content, property); 156 return 0; 157} 158 159MODULE_CONSTRUCTOR(void) 160{ 161 APPSPAWN_LOGV("Load asan module ..."); 162 AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON, AsanSpawnInitSpawningEnv); 163 AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_COMMON, AsanSpawnGetSpawningFlag); 164} 165