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