106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include "hidebug_base.h"
1706f6ba60Sopenharmony_ci
1806f6ba60Sopenharmony_ci#include <dlfcn.h>
1906f6ba60Sopenharmony_ci#include <errno.h>
2006f6ba60Sopenharmony_ci#include <inttypes.h>
2106f6ba60Sopenharmony_ci#include <limits.h>
2206f6ba60Sopenharmony_ci#include <signal.h>
2306f6ba60Sopenharmony_ci#include <stdio.h>
2406f6ba60Sopenharmony_ci#include <stdlib.h>
2506f6ba60Sopenharmony_ci#include <string.h>
2606f6ba60Sopenharmony_ci#include <unistd.h>
2706f6ba60Sopenharmony_ci
2806f6ba60Sopenharmony_ci#include "securec.h"
2906f6ba60Sopenharmony_ci
3006f6ba60Sopenharmony_ci#ifdef HIDEBUG_IN_INIT
3106f6ba60Sopenharmony_ci#include "init_module_engine.h"
3206f6ba60Sopenharmony_ci#include "init_log.h"
3306f6ba60Sopenharmony_ci#define HIDEBUG_LOGE(...) INIT_LOGE(__VA_ARGS__)
3406f6ba60Sopenharmony_ci#define HIDEBUG_LOGI(...) INIT_LOGI(__VA_ARGS__)
3506f6ba60Sopenharmony_ci#define LOG_PRIV_PUBLIC ""
3606f6ba60Sopenharmony_ci#else
3706f6ba60Sopenharmony_ci#include <parameter.h>
3806f6ba60Sopenharmony_ci#include <sysparam_errno.h>
3906f6ba60Sopenharmony_ci#include <hilog/log.h>
4006f6ba60Sopenharmony_ci#include "hichecker_wrapper.h"
4106f6ba60Sopenharmony_ci
4206f6ba60Sopenharmony_ci#undef LOG_DOMAIN
4306f6ba60Sopenharmony_ci#undef LOG_TAG
4406f6ba60Sopenharmony_ci#define LOG_DOMAIN 0xD002D0A
4506f6ba60Sopenharmony_ci#define LOG_TAG "HiDebug_Native"
4606f6ba60Sopenharmony_ci
4706f6ba60Sopenharmony_ci#define HIDEBUG_LOGE(...) HILOG_ERROR(LOG_CORE, __VA_ARGS__)
4806f6ba60Sopenharmony_ci#define HIDEBUG_LOGI(...) HILOG_INFO(LOG_CORE, __VA_ARGS__)
4906f6ba60Sopenharmony_ci#define LOG_PRIV_PUBLIC "{public}"
5006f6ba60Sopenharmony_ci#endif
5106f6ba60Sopenharmony_ci
5206f6ba60Sopenharmony_ci#define MAX_PARA_LEN 50
5306f6ba60Sopenharmony_ci#define MAX_PARA_CNT 20
5406f6ba60Sopenharmony_ci#define PARAM_BUF_LEN 128
5506f6ba60Sopenharmony_ci#define QUERYNAME_LEN 80
5606f6ba60Sopenharmony_ci#define COLON_CHR ':'
5706f6ba60Sopenharmony_ci#define SLASH_CHR '/'
5806f6ba60Sopenharmony_ciconst char * const LIBC_HOOK_PARAM = "libc.hook_mode";
5906f6ba60Sopenharmony_ci
6006f6ba60Sopenharmony_cistruct Params {
6106f6ba60Sopenharmony_ci    char key[MAX_PARA_LEN];
6206f6ba60Sopenharmony_ci    char value[MAX_PARA_LEN];
6306f6ba60Sopenharmony_ci};
6406f6ba60Sopenharmony_ci
6506f6ba60Sopenharmony_cistatic void ParseKeyValue(const char *input, uint32_t *paramCnt, struct Params *result, const uint32_t paramSize)
6606f6ba60Sopenharmony_ci{
6706f6ba60Sopenharmony_ci    if (*paramCnt >= paramSize) {
6806f6ba60Sopenharmony_ci        HIDEBUG_LOGE("Parameters is Full.");
6906f6ba60Sopenharmony_ci        return;
7006f6ba60Sopenharmony_ci    }
7106f6ba60Sopenharmony_ci    const char *colonPos = strchr(input, COLON_CHR);
7206f6ba60Sopenharmony_ci    if (colonPos == NULL) {
7306f6ba60Sopenharmony_ci        HIDEBUG_LOGE("params is illegal.");
7406f6ba60Sopenharmony_ci        return;
7506f6ba60Sopenharmony_ci    }
7606f6ba60Sopenharmony_ci    errno_t err = strncpy_s(result[*paramCnt].key, MAX_PARA_LEN, input, colonPos - input);
7706f6ba60Sopenharmony_ci    if (err != EOK) {
7806f6ba60Sopenharmony_ci        HIDEBUG_LOGE("strncpy_s copy key strings failed.");
7906f6ba60Sopenharmony_ci        return;
8006f6ba60Sopenharmony_ci    }
8106f6ba60Sopenharmony_ci    err = strncpy_s(result[*paramCnt].value, MAX_PARA_LEN, colonPos + 1, strlen(colonPos + 1));
8206f6ba60Sopenharmony_ci    if (err != EOK) {
8306f6ba60Sopenharmony_ci        HIDEBUG_LOGE("strncpy_s copy value strings failed.");
8406f6ba60Sopenharmony_ci        return;
8506f6ba60Sopenharmony_ci    }
8606f6ba60Sopenharmony_ci    (*paramCnt)++;
8706f6ba60Sopenharmony_ci}
8806f6ba60Sopenharmony_ci
8906f6ba60Sopenharmony_cistatic uint32_t SplitParams(char *input, struct Params *result, const uint32_t paramSize)
9006f6ba60Sopenharmony_ci{
9106f6ba60Sopenharmony_ci    uint32_t paramCnt = 0;
9206f6ba60Sopenharmony_ci    const char space[] = " ";
9306f6ba60Sopenharmony_ci    char *param;
9406f6ba60Sopenharmony_ci    char *next = NULL;
9506f6ba60Sopenharmony_ci    param = strtok_s(input, space, &next);
9606f6ba60Sopenharmony_ci    while (param != NULL) {
9706f6ba60Sopenharmony_ci        ParseKeyValue(param, &paramCnt, result, paramSize);
9806f6ba60Sopenharmony_ci        param = strtok_s(NULL, space, &next);
9906f6ba60Sopenharmony_ci    }
10006f6ba60Sopenharmony_ci    return paramCnt;
10106f6ba60Sopenharmony_ci}
10206f6ba60Sopenharmony_ci
10306f6ba60Sopenharmony_cistatic bool QueryParams(const char *queryName, char *result, const uint32_t size)
10406f6ba60Sopenharmony_ci{
10506f6ba60Sopenharmony_ci    if (result == NULL || size > PARAM_BUF_LEN) {
10606f6ba60Sopenharmony_ci        return false;
10706f6ba60Sopenharmony_ci    }
10806f6ba60Sopenharmony_ci#ifdef HIDEBUG_IN_INIT
10906f6ba60Sopenharmony_ci    uint32_t bufferSize = size;
11006f6ba60Sopenharmony_ci    int retLen = SystemReadParam(queryName, result, &bufferSize);
11106f6ba60Sopenharmony_ci    if (retLen != 0 || bufferSize == 0 || bufferSize > PARAM_BUF_LEN - 1) {
11206f6ba60Sopenharmony_ci        return false;
11306f6ba60Sopenharmony_ci    }
11406f6ba60Sopenharmony_ci    result[bufferSize] = '\0';
11506f6ba60Sopenharmony_ci#else
11606f6ba60Sopenharmony_ci    int retLen = GetParameter(queryName, NULL, result, size);
11706f6ba60Sopenharmony_ci    if (retLen <= 0 || retLen > PARAM_BUF_LEN - 1) {
11806f6ba60Sopenharmony_ci        return false;
11906f6ba60Sopenharmony_ci    }
12006f6ba60Sopenharmony_ci    result[retLen] = '\0';
12106f6ba60Sopenharmony_ci#endif
12206f6ba60Sopenharmony_ci    return true;
12306f6ba60Sopenharmony_ci}
12406f6ba60Sopenharmony_ci
12506f6ba60Sopenharmony_cistatic bool ConcatenateParamName(char* queryName, const size_t size, const char* serviceName)
12606f6ba60Sopenharmony_ci{
12706f6ba60Sopenharmony_ci    if (strcat_s(queryName, size, serviceName) != EOK) {
12806f6ba60Sopenharmony_ci        HIDEBUG_LOGE("strcat_s query name failed.");
12906f6ba60Sopenharmony_ci        return false;
13006f6ba60Sopenharmony_ci    }
13106f6ba60Sopenharmony_ci    return true;
13206f6ba60Sopenharmony_ci}
13306f6ba60Sopenharmony_ci
13406f6ba60Sopenharmony_cistatic bool InitHiDebugEnvParams(const char *queryName)
13506f6ba60Sopenharmony_ci{
13606f6ba60Sopenharmony_ci    char paramOutBuf[PARAM_BUF_LEN] = { 0 };
13706f6ba60Sopenharmony_ci    if (!QueryParams(queryName, paramOutBuf, PARAM_BUF_LEN)) {
13806f6ba60Sopenharmony_ci        return false;
13906f6ba60Sopenharmony_ci    }
14006f6ba60Sopenharmony_ci    struct Params params[MAX_PARA_CNT];
14106f6ba60Sopenharmony_ci    uint32_t paramsCnt = SplitParams(paramOutBuf, params, MAX_PARA_CNT);
14206f6ba60Sopenharmony_ci    for (uint32_t i = 0; i < paramsCnt; ++i) {
14306f6ba60Sopenharmony_ci        if (setenv(params[i].key, params[i].value, 1) != 0) { // 1 : overwrite
14406f6ba60Sopenharmony_ci            HIDEBUG_LOGE("setenv failed, err: %" LOG_PRIV_PUBLIC "s", strerror(errno));
14506f6ba60Sopenharmony_ci        }
14606f6ba60Sopenharmony_ci    }
14706f6ba60Sopenharmony_ci    return paramsCnt > 0;
14806f6ba60Sopenharmony_ci}
14906f6ba60Sopenharmony_ci
15006f6ba60Sopenharmony_cistatic const char* FilterServiceName(const char *inputName)
15106f6ba60Sopenharmony_ci{
15206f6ba60Sopenharmony_ci    const char *ret = strrchr(inputName, SLASH_CHR);
15306f6ba60Sopenharmony_ci    if (ret == NULL) {
15406f6ba60Sopenharmony_ci        return inputName;
15506f6ba60Sopenharmony_ci    }
15606f6ba60Sopenharmony_ci    return ret + 1;
15706f6ba60Sopenharmony_ci}
15806f6ba60Sopenharmony_ci
15906f6ba60Sopenharmony_cistatic int GetMallocHookStartupValue(const char *param, char *path, int size)
16006f6ba60Sopenharmony_ci{
16106f6ba60Sopenharmony_ci    if (path == NULL || size <= 0) {
16206f6ba60Sopenharmony_ci        return -1;
16306f6ba60Sopenharmony_ci    }
16406f6ba60Sopenharmony_ci
16506f6ba60Sopenharmony_ci    const char *ptr = param;
16606f6ba60Sopenharmony_ci
16706f6ba60Sopenharmony_ci    while (*ptr && *ptr != ':') {
16806f6ba60Sopenharmony_ci        ++ptr;
16906f6ba60Sopenharmony_ci    }
17006f6ba60Sopenharmony_ci    if (*ptr == ':') {
17106f6ba60Sopenharmony_ci        ++ptr;
17206f6ba60Sopenharmony_ci    }
17306f6ba60Sopenharmony_ci    const int paramLength = 7;
17406f6ba60Sopenharmony_ci    if (strncmp(param, "startup", paramLength) == 0) {
17506f6ba60Sopenharmony_ci        if (*ptr == '\"') {
17606f6ba60Sopenharmony_ci            ++ptr;
17706f6ba60Sopenharmony_ci            int idx = 0;
17806f6ba60Sopenharmony_ci            while (idx < size - 1 && *ptr && *ptr != '\"') {
17906f6ba60Sopenharmony_ci                path[idx++] = *ptr++;
18006f6ba60Sopenharmony_ci            }
18106f6ba60Sopenharmony_ci            path[idx] = '\0';
18206f6ba60Sopenharmony_ci        } else {
18306f6ba60Sopenharmony_ci            int idx = 0;
18406f6ba60Sopenharmony_ci            while (idx < size - 1 && *ptr) {
18506f6ba60Sopenharmony_ci                path[idx++] = *ptr++;
18606f6ba60Sopenharmony_ci            }
18706f6ba60Sopenharmony_ci            path[idx] = '\0';
18806f6ba60Sopenharmony_ci        }
18906f6ba60Sopenharmony_ci    }
19006f6ba60Sopenharmony_ci    return 0;
19106f6ba60Sopenharmony_ci}
19206f6ba60Sopenharmony_ci
19306f6ba60Sopenharmony_cistatic bool MatchMallocHookStartupProp(const char *thisName)
19406f6ba60Sopenharmony_ci{
19506f6ba60Sopenharmony_ci    char paramOutBuf[PARAM_BUF_LEN] = { 0 };
19606f6ba60Sopenharmony_ci    char targetProcName[PARAM_BUF_LEN] = { 0 };
19706f6ba60Sopenharmony_ci
19806f6ba60Sopenharmony_ci#ifdef HIDEBUG_IN_INIT
19906f6ba60Sopenharmony_ci    uint32_t size = PARAM_BUF_LEN;
20006f6ba60Sopenharmony_ci    int retLen = SystemReadParam(LIBC_HOOK_PARAM, paramOutBuf, &size);
20106f6ba60Sopenharmony_ci    if (retLen != 0 || size <= 0) {
20206f6ba60Sopenharmony_ci        return 0;
20306f6ba60Sopenharmony_ci    }
20406f6ba60Sopenharmony_ci    retLen = (int)size;
20506f6ba60Sopenharmony_ci#else
20606f6ba60Sopenharmony_ci    char defStrValue[PARAM_BUF_LEN] = { 0 };
20706f6ba60Sopenharmony_ci    int retLen = GetParameter(LIBC_HOOK_PARAM, defStrValue, paramOutBuf, PARAM_BUF_LEN);
20806f6ba60Sopenharmony_ci    if (retLen == 0) {
20906f6ba60Sopenharmony_ci        return 0;
21006f6ba60Sopenharmony_ci    }
21106f6ba60Sopenharmony_ci#endif
21206f6ba60Sopenharmony_ci    const int paramLength = 8;
21306f6ba60Sopenharmony_ci    if (strncmp(paramOutBuf, "startup:", paramLength) != 0) {
21406f6ba60Sopenharmony_ci        return false;
21506f6ba60Sopenharmony_ci    }
21606f6ba60Sopenharmony_ci    retLen = GetMallocHookStartupValue(paramOutBuf, targetProcName, PARAM_BUF_LEN);
21706f6ba60Sopenharmony_ci    if (retLen == -1) {
21806f6ba60Sopenharmony_ci        HIDEBUG_LOGE("malloc hook parse startup value failed");
21906f6ba60Sopenharmony_ci        return false;
22006f6ba60Sopenharmony_ci    }
22106f6ba60Sopenharmony_ci
22206f6ba60Sopenharmony_ci    const int targetProcNameSize = strlen(targetProcName);
22306f6ba60Sopenharmony_ci    if (strncmp(targetProcName, "init", targetProcNameSize) == 0) {
22406f6ba60Sopenharmony_ci        HIDEBUG_LOGI("malloc hook: this target proc '%" LOG_PRIV_PUBLIC "s' no hook", targetProcName);
22506f6ba60Sopenharmony_ci        return false;
22606f6ba60Sopenharmony_ci    }
22706f6ba60Sopenharmony_ci
22806f6ba60Sopenharmony_ci    if (strcmp(thisName, targetProcName) == 0) {
22906f6ba60Sopenharmony_ci        return true;
23006f6ba60Sopenharmony_ci    }
23106f6ba60Sopenharmony_ci    return false;
23206f6ba60Sopenharmony_ci}
23306f6ba60Sopenharmony_ci
23406f6ba60Sopenharmony_cistatic int SetupMallocHookAtStartup(const char *thisName)
23506f6ba60Sopenharmony_ci{
23606f6ba60Sopenharmony_ci    const int hookSignal = 36;
23706f6ba60Sopenharmony_ci    if (!MatchMallocHookStartupProp(thisName)) {
23806f6ba60Sopenharmony_ci        return 0;
23906f6ba60Sopenharmony_ci    }
24006f6ba60Sopenharmony_ci    HIDEBUG_LOGI("malloc send hook signal.");
24106f6ba60Sopenharmony_ci    return raise(hookSignal);
24206f6ba60Sopenharmony_ci}
24306f6ba60Sopenharmony_ci
24406f6ba60Sopenharmony_cibool InitEnvironmentParam(const char *inputName)
24506f6ba60Sopenharmony_ci{
24606f6ba60Sopenharmony_ci    if (inputName == NULL) {
24706f6ba60Sopenharmony_ci        HIDEBUG_LOGE("input service name is null.");
24806f6ba60Sopenharmony_ci        return false;
24906f6ba60Sopenharmony_ci    }
25006f6ba60Sopenharmony_ci    const char *serviceName = FilterServiceName(inputName);
25106f6ba60Sopenharmony_ci    if (*serviceName == '\0') {
25206f6ba60Sopenharmony_ci        HIDEBUG_LOGE("input service name is illegal.");
25306f6ba60Sopenharmony_ci        return false;
25406f6ba60Sopenharmony_ci    }
25506f6ba60Sopenharmony_ci#ifndef HIDEBUG_IN_INIT
25606f6ba60Sopenharmony_ci    InitHicheckerParamWrapper(serviceName);
25706f6ba60Sopenharmony_ci#endif
25806f6ba60Sopenharmony_ci
25906f6ba60Sopenharmony_ci#ifdef HAS_MUSL_STARTUP_MALLOC_HOOK_INTF
26006f6ba60Sopenharmony_ci    setup_malloc_hook_mode();
26106f6ba60Sopenharmony_ci#else
26206f6ba60Sopenharmony_ci    SetupMallocHookAtStartup(serviceName);
26306f6ba60Sopenharmony_ci#endif
26406f6ba60Sopenharmony_ci
26506f6ba60Sopenharmony_ci    char paramOutBuf[PARAM_BUF_LEN] = { 0 };
26606f6ba60Sopenharmony_ci    if (!QueryParams("const.debuggable", paramOutBuf, PARAM_BUF_LEN) || strcmp(paramOutBuf, "1") != 0) {
26706f6ba60Sopenharmony_ci        return false;
26806f6ba60Sopenharmony_ci    }
26906f6ba60Sopenharmony_ci    char onceName[QUERYNAME_LEN] = "hiviewdfx.debugenv.";
27006f6ba60Sopenharmony_ci    if (!ConcatenateParamName(onceName, sizeof(onceName), serviceName)) {
27106f6ba60Sopenharmony_ci        return false;
27206f6ba60Sopenharmony_ci    }
27306f6ba60Sopenharmony_ci    if (InitHiDebugEnvParams(onceName)) {
27406f6ba60Sopenharmony_ci        return true;
27506f6ba60Sopenharmony_ci    }
27606f6ba60Sopenharmony_ci    char persistName[QUERYNAME_LEN] = "persist.hiviewdfx.debugenv.";
27706f6ba60Sopenharmony_ci    return ConcatenateParamName(persistName, sizeof(onceName), serviceName) && InitHiDebugEnvParams(persistName);
27806f6ba60Sopenharmony_ci}
279