• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
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 
16 #include "hidebug_base.h"
17 
18 #include <dlfcn.h>
19 #include <errno.h>
20 #include <inttypes.h>
21 #include <limits.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 
28 #include "securec.h"
29 
30 #ifdef HIDEBUG_IN_INIT
31 #include "init_module_engine.h"
32 #include "init_log.h"
33 #define HIDEBUG_LOGE(...) INIT_LOGE(__VA_ARGS__)
34 #define HIDEBUG_LOGI(...) INIT_LOGI(__VA_ARGS__)
35 #define LOG_PRIV_PUBLIC ""
36 #else
37 #include <parameter.h>
38 #include <sysparam_errno.h>
39 #include <hilog/log.h>
40 #include "hichecker_wrapper.h"
41 
42 #undef LOG_DOMAIN
43 #undef LOG_TAG
44 #define LOG_DOMAIN 0xD002D0A
45 #define LOG_TAG "HiDebug_Native"
46 
47 #define HIDEBUG_LOGE(...) HILOG_ERROR(LOG_CORE, __VA_ARGS__)
48 #define HIDEBUG_LOGI(...) HILOG_INFO(LOG_CORE, __VA_ARGS__)
49 #define LOG_PRIV_PUBLIC "{public}"
50 #endif
51 
52 #define PARAM_BUF_LEN 128
53 #define SLASH_CHR '/'
54 const char * const LIBC_HOOK_PARAM = "libc.hook_mode";
55 
56 #ifdef HIDEBUG_BUILD_VARIANT_ROOT
57 #define MAX_PARA_LEN 50
58 #define MAX_PARA_CNT 20
59 #define QUERYNAME_LEN 80
60 #define COLON_CHR ':'
61 
62 struct Params {
63     char key[MAX_PARA_LEN];
64     char value[MAX_PARA_LEN];
65 };
66 
ParseKeyValue(const char * input,uint32_t * paramCnt,struct Params * result,const uint32_t paramSize)67 static void ParseKeyValue(const char *input, uint32_t *paramCnt, struct Params *result, const uint32_t paramSize)
68 {
69     if (*paramCnt >= paramSize) {
70         HIDEBUG_LOGE("Parameters is Full.");
71         return;
72     }
73     const char *colonPos = strchr(input, COLON_CHR);
74     if (colonPos == NULL) {
75         HIDEBUG_LOGE("params is illegal.");
76         return;
77     }
78     errno_t err = strncpy_s(result[*paramCnt].key, MAX_PARA_LEN, input, colonPos - input);
79     if (err != EOK) {
80         HIDEBUG_LOGE("strncpy_s copy key strings failed.");
81         return;
82     }
83     err = strncpy_s(result[*paramCnt].value, MAX_PARA_LEN, colonPos + 1, strlen(colonPos + 1));
84     if (err != EOK) {
85         HIDEBUG_LOGE("strncpy_s copy value strings failed.");
86         return;
87     }
88     (*paramCnt)++;
89 }
90 
SplitParams(char * input,struct Params * result,const uint32_t paramSize)91 static uint32_t SplitParams(char *input, struct Params *result, const uint32_t paramSize)
92 {
93     uint32_t paramCnt = 0;
94     const char space[] = " ";
95     char *param;
96     char *next = NULL;
97     param = strtok_s(input, space, &next);
98     while (param != NULL) {
99         ParseKeyValue(param, &paramCnt, result, paramSize);
100         param = strtok_s(NULL, space, &next);
101     }
102     return paramCnt;
103 }
104 
QueryParams(const char * queryName,char * result,const uint32_t size)105 static bool QueryParams(const char *queryName, char *result, const uint32_t size)
106 {
107     if (result == NULL || size > PARAM_BUF_LEN) {
108         return false;
109     }
110 #ifdef HIDEBUG_IN_INIT
111     uint32_t bufferSize = size;
112     int retLen = SystemReadParam(queryName, result, &bufferSize);
113     if (retLen != 0 || bufferSize == 0 || bufferSize > PARAM_BUF_LEN - 1) {
114         return false;
115     }
116     result[bufferSize] = '\0';
117 #else
118     int retLen = GetParameter(queryName, NULL, result, size);
119     if (retLen <= 0 || retLen > PARAM_BUF_LEN - 1) {
120         return false;
121     }
122     result[retLen] = '\0';
123 #endif
124     return true;
125 }
126 
ConcatenateParamName(char * queryName,const size_t size,const char * serviceName)127 static bool ConcatenateParamName(char* queryName, const size_t size, const char* serviceName)
128 {
129     if (strcat_s(queryName, size, serviceName) != EOK) {
130         HIDEBUG_LOGE("strcat_s query name failed.");
131         return false;
132     }
133     return true;
134 }
135 
InitHiDebugEnvParams(const char * queryName)136 static bool InitHiDebugEnvParams(const char *queryName)
137 {
138     char paramOutBuf[PARAM_BUF_LEN] = { 0 };
139     if (!QueryParams(queryName, paramOutBuf, PARAM_BUF_LEN)) {
140         return false;
141     }
142     struct Params params[MAX_PARA_CNT];
143     uint32_t paramsCnt = SplitParams(paramOutBuf, params, MAX_PARA_CNT);
144     for (uint32_t i = 0; i < paramsCnt; ++i) {
145         if (setenv(params[i].key, params[i].value, 1) != 0) { // 1 : overwrite
146             HIDEBUG_LOGE("setenv failed, err: %" LOG_PRIV_PUBLIC "s", strerror(errno));
147         }
148     }
149     return paramsCnt > 0;
150 }
151 
InitEnvParam(const char * serviceName)152 static bool InitEnvParam(const char *serviceName)
153 {
154     char paramOutBuf[PARAM_BUF_LEN] = { 0 };
155     if (!QueryParams("const.debuggable", paramOutBuf, PARAM_BUF_LEN) || strcmp(paramOutBuf, "1") != 0) {
156         return false;
157     }
158     char onceName[QUERYNAME_LEN] = "hiviewdfx.debugenv.";
159     if (!ConcatenateParamName(onceName, sizeof(onceName), serviceName)) {
160         return false;
161     }
162     if (InitHiDebugEnvParams(onceName)) {
163         return true;
164     }
165     char persistName[QUERYNAME_LEN] = "persist.hiviewdfx.debugenv.";
166     return ConcatenateParamName(persistName, sizeof(persistName), serviceName) && InitHiDebugEnvParams(persistName);
167 }
168 #endif
169 
FilterServiceName(const char * inputName)170 static const char* FilterServiceName(const char *inputName)
171 {
172     const char *ret = strrchr(inputName, SLASH_CHR);
173     if (ret == NULL) {
174         return inputName;
175     }
176     return ret + 1;
177 }
178 
GetMallocHookStartupValue(const char * param,char * path,int size)179 static int GetMallocHookStartupValue(const char *param, char *path, int size)
180 {
181     if (path == NULL || size <= 0) {
182         return -1;
183     }
184 
185     const char *ptr = param;
186 
187     while (*ptr && *ptr != ':') {
188         ++ptr;
189     }
190     if (*ptr == ':') {
191         ++ptr;
192     }
193     const int paramLength = 7;
194     if (strncmp(param, "startup", paramLength) == 0) {
195         if (*ptr == '\"') {
196             ++ptr;
197             int idx = 0;
198             while (idx < size - 1 && *ptr && *ptr != '\"') {
199                 path[idx++] = *ptr++;
200             }
201             path[idx] = '\0';
202         } else {
203             int idx = 0;
204             while (idx < size - 1 && *ptr) {
205                 path[idx++] = *ptr++;
206             }
207             path[idx] = '\0';
208         }
209     }
210     return 0;
211 }
212 
MatchMallocHookStartupProp(const char * thisName)213 static bool MatchMallocHookStartupProp(const char *thisName)
214 {
215     char paramOutBuf[PARAM_BUF_LEN] = { 0 };
216     char targetProcName[PARAM_BUF_LEN] = { 0 };
217 
218 #ifdef HIDEBUG_IN_INIT
219     uint32_t size = PARAM_BUF_LEN;
220     int retLen = SystemReadParam(LIBC_HOOK_PARAM, paramOutBuf, &size);
221     if (retLen != 0 || size <= 0) {
222         return 0;
223     }
224     retLen = (int)size;
225 #else
226     char defStrValue[PARAM_BUF_LEN] = { 0 };
227     int retLen = GetParameter(LIBC_HOOK_PARAM, defStrValue, paramOutBuf, PARAM_BUF_LEN);
228     if (retLen == 0) {
229         return 0;
230     }
231 #endif
232     const int paramLength = 8;
233     if (strncmp(paramOutBuf, "startup:", paramLength) != 0) {
234         return false;
235     }
236     retLen = GetMallocHookStartupValue(paramOutBuf, targetProcName, PARAM_BUF_LEN);
237     if (retLen == -1) {
238         HIDEBUG_LOGE("malloc hook parse startup value failed");
239         return false;
240     }
241 
242     const int targetProcNameSize = strlen(targetProcName);
243     if (strncmp(targetProcName, "init", targetProcNameSize) == 0) {
244         HIDEBUG_LOGI("malloc hook: this target proc '%" LOG_PRIV_PUBLIC "s' no hook", targetProcName);
245         return false;
246     }
247 
248     if (strcmp(thisName, targetProcName) == 0) {
249         return true;
250     }
251     return false;
252 }
253 
SetupMallocHookAtStartup(const char * thisName)254 static int SetupMallocHookAtStartup(const char *thisName)
255 {
256     const int hookSignal = 36;
257     if (!MatchMallocHookStartupProp(thisName)) {
258         return 0;
259     }
260     HIDEBUG_LOGI("malloc send hook signal.");
261     return raise(hookSignal);
262 }
263 
InitEnvironmentParam(const char * inputName)264 bool InitEnvironmentParam(const char *inputName)
265 {
266     if (inputName == NULL) {
267         HIDEBUG_LOGE("input service name is null.");
268         return false;
269     }
270     const char *serviceName = FilterServiceName(inputName);
271     if (*serviceName == '\0') {
272         HIDEBUG_LOGE("input service name is illegal.");
273         return false;
274     }
275 #ifndef HIDEBUG_IN_INIT
276     InitHicheckerParamWrapper(serviceName);
277 #endif
278 
279 #ifdef HAS_MUSL_STARTUP_MALLOC_HOOK_INTF
280     setup_malloc_hook_mode();
281 #else
282     SetupMallocHookAtStartup(serviceName);
283 #endif
284 
285 #ifdef HIDEBUG_BUILD_VARIANT_ROOT
286     return InitEnvParam(serviceName);
287 #else
288     return true;
289 #endif
290 }
291