169570cc8Sopenharmony_ci/* 269570cc8Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 369570cc8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 469570cc8Sopenharmony_ci * you may not use this file except in compliance with the License. 569570cc8Sopenharmony_ci * You may obtain a copy of the License at 669570cc8Sopenharmony_ci * 769570cc8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 869570cc8Sopenharmony_ci * 969570cc8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1069570cc8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1169570cc8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1269570cc8Sopenharmony_ci * See the License for the specific language governing permissions and 1369570cc8Sopenharmony_ci * limitations under the License. 1469570cc8Sopenharmony_ci */ 1569570cc8Sopenharmony_ci#include "appspawn_hook.h" 1669570cc8Sopenharmony_ci#include "appspawn_msg.h" 1769570cc8Sopenharmony_ci#include "appspawn_manager.h" 1869570cc8Sopenharmony_ci#include "appspawn_utils.h" 1969570cc8Sopenharmony_ci#include "parameter.h" 2069570cc8Sopenharmony_ci#include "securec.h" 2169570cc8Sopenharmony_ci 2269570cc8Sopenharmony_ci// for stub 2369570cc8Sopenharmony_ciextern bool may_init_gwp_asan(bool forceInit); 2469570cc8Sopenharmony_ci 2569570cc8Sopenharmony_ci// ide-asan 2669570cc8Sopenharmony_ci#ifndef ASAN_DETECTOR 2769570cc8Sopenharmony_ci 2869570cc8Sopenharmony_ci#if defined(__aarch64__) || defined(__x86_64__) 2969570cc8Sopenharmony_ci#define ASAN_LD_PRELOAD "/system/lib64/libclang_rt.asan.so" 3069570cc8Sopenharmony_ci#else 3169570cc8Sopenharmony_ci#define ASAN_LD_PRELOAD "/system/lib/libclang_rt.asan.so" 3269570cc8Sopenharmony_ci#endif 3369570cc8Sopenharmony_ci#define HWASAN_LD_PRELOAD "/system/lib64/libclang_rt.hwasan.so" 3469570cc8Sopenharmony_ci#define TSAN_LD_PRELOAD "/system/lib64/libclang_rt.tsan.so" 3569570cc8Sopenharmony_ci 3669570cc8Sopenharmony_ci#define ASAN_OPTIONS "include=/system/etc/asan.options" 3769570cc8Sopenharmony_ci#define HWASAN_OPTIONS "include=/system/etc/asan.options" 3869570cc8Sopenharmony_ci#define TSAN_OPTIONS "include=/system/etc/tsan.options" 3969570cc8Sopenharmony_ci#define UBSAN_OPTIONS "print_stacktrace=1:print_module_map=2:log_exe_name=1" 4069570cc8Sopenharmony_ci 4169570cc8Sopenharmony_ci// 配置表数据 4269570cc8Sopenharmony_cistatic const EnvConfig g_configTable[] = { 4369570cc8Sopenharmony_ci { APP_FLAGS_HWASAN_ENABLED, HWASAN_LD_PRELOAD, NULL, NULL, NULL, HWASAN_OPTIONS }, 4469570cc8Sopenharmony_ci { APP_FLAGS_ASANENABLED, ASAN_LD_PRELOAD, ASAN_OPTIONS, NULL, NULL, NULL }, 4569570cc8Sopenharmony_ci { APP_FLAGS_TSAN_ENABLED, TSAN_LD_PRELOAD, NULL, TSAN_OPTIONS, NULL, NULL }, 4669570cc8Sopenharmony_ci { APP_FLAGS_UBSAN_ENABLED, NULL, NULL, NULL, UBSAN_OPTIONS, NULL }, 4769570cc8Sopenharmony_ci}; 4869570cc8Sopenharmony_ci 4969570cc8Sopenharmony_cistatic int SetAsanEnabledEnv(const AppSpawnMgr *content, const AppSpawningCtx *property) 5069570cc8Sopenharmony_ci{ 5169570cc8Sopenharmony_ci size_t configTableSize = sizeof(g_configTable) / sizeof(g_configTable[0]); 5269570cc8Sopenharmony_ci for (size_t i = 0; i < configTableSize; ++i) { 5369570cc8Sopenharmony_ci if (CheckAppMsgFlagsSet(property, g_configTable[i].flag)) { 5469570cc8Sopenharmony_ci if (g_configTable[i].ldPreload) { 5569570cc8Sopenharmony_ci setenv("LD_PRELOAD", g_configTable[i].ldPreload, 1); 5669570cc8Sopenharmony_ci } 5769570cc8Sopenharmony_ci if (g_configTable[i].asanOptions) { 5869570cc8Sopenharmony_ci setenv("ASAN_OPTIONS", g_configTable[i].asanOptions, 1); 5969570cc8Sopenharmony_ci } else { 6069570cc8Sopenharmony_ci unsetenv("ASAN_OPTIONS"); 6169570cc8Sopenharmony_ci } 6269570cc8Sopenharmony_ci if (g_configTable[i].tsanOptions) { 6369570cc8Sopenharmony_ci setenv("TSAN_OPTIONS", g_configTable[i].tsanOptions, 1); 6469570cc8Sopenharmony_ci } else { 6569570cc8Sopenharmony_ci unsetenv("TSAN_OPTIONS"); 6669570cc8Sopenharmony_ci } 6769570cc8Sopenharmony_ci if (g_configTable[i].ubsanOptions) { 6869570cc8Sopenharmony_ci setenv("UBSAN_OPTIONS", g_configTable[i].ubsanOptions, 1); 6969570cc8Sopenharmony_ci } else { 7069570cc8Sopenharmony_ci unsetenv("UBSAN_OPTIONS"); 7169570cc8Sopenharmony_ci } 7269570cc8Sopenharmony_ci if (g_configTable[i].hwasanOptions) { 7369570cc8Sopenharmony_ci setenv("HWASAN_OPTIONS", g_configTable[i].hwasanOptions, 1); 7469570cc8Sopenharmony_ci } else { 7569570cc8Sopenharmony_ci unsetenv("HWASAN_OPTIONS"); 7669570cc8Sopenharmony_ci } 7769570cc8Sopenharmony_ci APPSPAWN_LOGV("SetAsanEnabledEnv %{public}d,%{public}s,%{public}s,%{public}s,%{public}s,%{public}s", 7869570cc8Sopenharmony_ci g_configTable[i].flag, g_configTable[i].ldPreload, g_configTable[i].asanOptions, 7969570cc8Sopenharmony_ci g_configTable[i].tsanOptions, g_configTable[i].ubsanOptions, g_configTable[i].hwasanOptions); 8069570cc8Sopenharmony_ci return 0; 8169570cc8Sopenharmony_ci } 8269570cc8Sopenharmony_ci } 8369570cc8Sopenharmony_ci return -1; 8469570cc8Sopenharmony_ci} 8569570cc8Sopenharmony_ci#endif 8669570cc8Sopenharmony_ci 8769570cc8Sopenharmony_cistatic void SetGwpAsanEnabled(const AppSpawnMgr *content, const AppSpawningCtx *property) 8869570cc8Sopenharmony_ci{ 8969570cc8Sopenharmony_ci if (!(CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE) || 9069570cc8Sopenharmony_ci CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_NORMAL))) { 9169570cc8Sopenharmony_ci return; 9269570cc8Sopenharmony_ci } 9369570cc8Sopenharmony_ci if (IsDeveloperModeOn(property)) { 9469570cc8Sopenharmony_ci APPSPAWN_LOGV("SetGwpAsanEnabled with flags: %{public}d", 9569570cc8Sopenharmony_ci CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE)); 9669570cc8Sopenharmony_ci may_init_gwp_asan(CheckAppMsgFlagsSet(property, APP_FLAGS_GWP_ENABLED_FORCE)); 9769570cc8Sopenharmony_ci } 9869570cc8Sopenharmony_ci} 9969570cc8Sopenharmony_ci 10069570cc8Sopenharmony_ci#ifdef ASAN_DETECTOR 10169570cc8Sopenharmony_ci#define WRAP_VALUE_MAX_LENGTH 96 10269570cc8Sopenharmony_cistatic int CheckSupportColdStart(const char *bundleName) 10369570cc8Sopenharmony_ci{ 10469570cc8Sopenharmony_ci char wrapBundleNameKey[WRAP_VALUE_MAX_LENGTH] = {0}; 10569570cc8Sopenharmony_ci char wrapBundleNameValue[WRAP_VALUE_MAX_LENGTH] = {0}; 10669570cc8Sopenharmony_ci 10769570cc8Sopenharmony_ci int len = sprintf_s(wrapBundleNameKey, WRAP_VALUE_MAX_LENGTH, "wrap.%s", bundleName); 10869570cc8Sopenharmony_ci APPSPAWN_CHECK(len > 0 && (len < WRAP_VALUE_MAX_LENGTH), return -1, "Invalid to format wrapBundleNameKey"); 10969570cc8Sopenharmony_ci 11069570cc8Sopenharmony_ci int ret = GetParameter(wrapBundleNameKey, "", wrapBundleNameValue, WRAP_VALUE_MAX_LENGTH); 11169570cc8Sopenharmony_ci APPSPAWN_CHECK(ret > 0 && (!strcmp(wrapBundleNameValue, "asan_wrapper")), return -1, 11269570cc8Sopenharmony_ci "Not wrap %{public}s.", bundleName); 11369570cc8Sopenharmony_ci APPSPAWN_LOGI("Asan: GetParameter %{public}s the value is %{public}s.", wrapBundleNameKey, wrapBundleNameValue); 11469570cc8Sopenharmony_ci return 0; 11569570cc8Sopenharmony_ci} 11669570cc8Sopenharmony_ci#endif 11769570cc8Sopenharmony_ci 11869570cc8Sopenharmony_cistatic int AsanSpawnGetSpawningFlag(AppSpawnMgr *content, AppSpawningCtx *property) 11969570cc8Sopenharmony_ci{ 12069570cc8Sopenharmony_ci APPSPAWN_LOGV("Prepare spawn app %{public}s", GetProcessName(property)); 12169570cc8Sopenharmony_ci#ifdef ASAN_DETECTOR 12269570cc8Sopenharmony_ci if (CheckSupportColdStart(GetBundleName(property)) == 0) { 12369570cc8Sopenharmony_ci property->client.flags |= APP_COLD_START; 12469570cc8Sopenharmony_ci property->client.flags |= APP_ASAN_DETECTOR; 12569570cc8Sopenharmony_ci if (property->forkCtx.coldRunPath) { 12669570cc8Sopenharmony_ci free(property->forkCtx.coldRunPath); 12769570cc8Sopenharmony_ci } 12869570cc8Sopenharmony_ci#ifndef CJAPP_SPAWN 12969570cc8Sopenharmony_ci property->forkCtx.coldRunPath = strdup("/system/asan/bin/appspawn"); 13069570cc8Sopenharmony_ci#elif NATIVE_SPAWN 13169570cc8Sopenharmony_ci property->forkCtx.coldRunPath = strdup("/system/asan/bin/nativespawn"); 13269570cc8Sopenharmony_ci#else 13369570cc8Sopenharmony_ci property->forkCtx.coldRunPath = strdup("/system/asan/bin/cjappspawn"); 13469570cc8Sopenharmony_ci#endif 13569570cc8Sopenharmony_ci if (property->forkCtx.coldRunPath == NULL) { 13669570cc8Sopenharmony_ci APPSPAWN_LOGE("Failed to set asan exec path %{public}s", GetProcessName(property)); 13769570cc8Sopenharmony_ci } 13869570cc8Sopenharmony_ci } 13969570cc8Sopenharmony_ci#endif 14069570cc8Sopenharmony_ci return 0; 14169570cc8Sopenharmony_ci} 14269570cc8Sopenharmony_ci 14369570cc8Sopenharmony_cistatic int AsanSpawnInitSpawningEnv(AppSpawnMgr *content, AppSpawningCtx *property) 14469570cc8Sopenharmony_ci{ 14569570cc8Sopenharmony_ci if (GetAppSpawnMsgType(property) == MSG_SPAWN_NATIVE_PROCESS) { 14669570cc8Sopenharmony_ci return 0; 14769570cc8Sopenharmony_ci } 14869570cc8Sopenharmony_ci#ifndef ASAN_DETECTOR 14969570cc8Sopenharmony_ci int ret = SetAsanEnabledEnv(content, property); 15069570cc8Sopenharmony_ci if (ret == 0) { 15169570cc8Sopenharmony_ci APPSPAWN_LOGI("SetAsanEnabledEnv cold start app %{public}s", GetProcessName(property)); 15269570cc8Sopenharmony_ci property->client.flags |= APP_COLD_START; 15369570cc8Sopenharmony_ci } 15469570cc8Sopenharmony_ci#endif 15569570cc8Sopenharmony_ci (void)SetGwpAsanEnabled(content, property); 15669570cc8Sopenharmony_ci return 0; 15769570cc8Sopenharmony_ci} 15869570cc8Sopenharmony_ci 15969570cc8Sopenharmony_ciMODULE_CONSTRUCTOR(void) 16069570cc8Sopenharmony_ci{ 16169570cc8Sopenharmony_ci APPSPAWN_LOGV("Load asan module ..."); 16269570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON, AsanSpawnInitSpawningEnv); 16369570cc8Sopenharmony_ci AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_COMMON, AsanSpawnGetSpawningFlag); 16469570cc8Sopenharmony_ci} 165