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, ¶mCnt, 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