1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
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 MAX_PARA_LEN 50
53 #define MAX_PARA_CNT 20
54 #define PARAM_BUF_LEN 128
55 #define QUERYNAME_LEN 80
56 #define COLON_CHR ':'
57 #define SLASH_CHR '/'
58 const char * const LIBC_HOOK_PARAM = "libc.hook_mode";
59
60 static struct Params {
61 char key[MAX_PARA_LEN];
62 char value[MAX_PARA_LEN];
63 } g_params[MAX_PARA_CNT];
64
65 int g_paramCnt = 0;
66
ParseKeyValue(const char * input)67 static void ParseKeyValue(const char *input)
68 {
69 if (g_paramCnt >= MAX_PARA_CNT) {
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(g_params[g_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(g_params[g_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 g_paramCnt++;
89 }
90
SplitParams(char * input)91 static void SplitParams(char *input)
92 {
93 g_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);
100 param = strtok_s(NULL, space, &next);
101 }
102 }
103
QueryParams(const char * queryName)104 static int QueryParams(const char *queryName)
105 {
106 g_paramCnt = 0;
107 char paramOutBuf[PARAM_BUF_LEN] = { 0 };
108 #ifdef HIDEBUG_IN_INIT
109 uint32_t size = PARAM_BUF_LEN;
110 int retLen = SystemReadParam(queryName, paramOutBuf, &size);
111 if (retLen != 0 || size <= 0 || size > PARAM_BUF_LEN - 1) {
112 return 0;
113 }
114 retLen = (int)size;
115 #else
116 char defStrValue[PARAM_BUF_LEN] = { 0 };
117 int retLen = GetParameter(queryName, defStrValue, paramOutBuf, PARAM_BUF_LEN);
118 if (retLen == 0 || retLen > PARAM_BUF_LEN - 1) {
119 return 0;
120 }
121 #endif
122 paramOutBuf[retLen] = '\0';
123 SplitParams(paramOutBuf);
124 return g_paramCnt;
125 }
126
FilterServiceName(const char * inputName)127 static const char* FilterServiceName(const char *inputName)
128 {
129 const char *ret = strrchr(inputName, SLASH_CHR);
130 if (ret == NULL) {
131 return inputName;
132 }
133 return ret + 1;
134 }
135
GetMallocHookStartupValue(const char * param,char * path,int size)136 static int GetMallocHookStartupValue(const char *param, char *path, int size)
137 {
138 if (path == NULL || size <= 0) {
139 return -1;
140 }
141
142 const char *ptr = param;
143
144 while (*ptr && *ptr != ':') {
145 ++ptr;
146 }
147 if (*ptr == ':') {
148 ++ptr;
149 }
150 const int paramLength = 7;
151 if (strncmp(param, "startup", paramLength) == 0) {
152 if (*ptr == '\"') {
153 ++ptr;
154 int idx = 0;
155 while (idx < size - 1 && *ptr && *ptr != '\"') {
156 path[idx++] = *ptr++;
157 }
158 path[idx] = '\0';
159 } else {
160 int idx = 0;
161 while (idx < size - 1 && *ptr) {
162 path[idx++] = *ptr++;
163 }
164 path[idx] = '\0';
165 }
166 }
167 return 0;
168 }
169
MatchMallocHookStartupProp(const char * thisName)170 static bool MatchMallocHookStartupProp(const char *thisName)
171 {
172 char paramOutBuf[PARAM_BUF_LEN] = { 0 };
173 char targetProcName[PARAM_BUF_LEN] = { 0 };
174
175 #ifdef HIDEBUG_IN_INIT
176 uint32_t size = PARAM_BUF_LEN;
177 int retLen = SystemReadParam(LIBC_HOOK_PARAM, paramOutBuf, &size);
178 if (retLen != 0 || size <= 0) {
179 return 0;
180 }
181 retLen = (int)size;
182 #else
183 char defStrValue[PARAM_BUF_LEN] = { 0 };
184 int retLen = GetParameter(LIBC_HOOK_PARAM, defStrValue, paramOutBuf, PARAM_BUF_LEN);
185 if (retLen == 0) {
186 return 0;
187 }
188 #endif
189 const int paramLength = 8;
190 if (strncmp(paramOutBuf, "startup:", paramLength) != 0) {
191 return false;
192 }
193 retLen = GetMallocHookStartupValue(paramOutBuf, targetProcName, PARAM_BUF_LEN);
194 if (retLen == -1) {
195 HIDEBUG_LOGE("malloc hook parse startup value failed");
196 return false;
197 }
198
199 const int targetProcNameSize = strlen(targetProcName);
200 if (strncmp(targetProcName, "init", targetProcNameSize) == 0 ||
201 strncmp(targetProcName, "appspawn", targetProcNameSize) == 0) {
202 HIDEBUG_LOGI("malloc hook: this target proc '%" LOG_PRIV_PUBLIC "s' no hook", targetProcName);
203 return false;
204 }
205
206 if (strncmp(thisName, targetProcName, targetProcNameSize) == 0) {
207 return true;
208 }
209 return false;
210 }
211
SetupMallocHookAtStartup(const char * thisName)212 static int SetupMallocHookAtStartup(const char *thisName)
213 {
214 const int hookSignal = 36;
215 if (!MatchMallocHookStartupProp(thisName)) {
216 return 0;
217 }
218 HIDEBUG_LOGI("malloc send hook signal.");
219 return raise(hookSignal);
220 }
221
InitEnvironmentParam(const char * inputName)222 bool InitEnvironmentParam(const char *inputName)
223 {
224 if (inputName == NULL) {
225 HIDEBUG_LOGE("input service name is null.");
226 return false;
227 }
228 const char *serviceName = FilterServiceName(inputName);
229 if (*serviceName == '\0') {
230 HIDEBUG_LOGE("input service name is illegal.");
231 return false;
232 }
233 #ifndef HIDEBUG_IN_INIT
234 InitHicheckerParamWrapper(serviceName);
235 #endif
236 errno_t err = 0;
237 char persistName[QUERYNAME_LEN] = "persist.hiviewdfx.debugenv.";
238 char onceName[QUERYNAME_LEN] = "hiviewdfx.debugenv.";
239 err = strcat_s(onceName, sizeof(onceName), serviceName);
240 if (err != EOK) {
241 HIDEBUG_LOGE("strcat_s query name failed.");
242 return false;
243 }
244 err = strcat_s(persistName, sizeof(persistName), serviceName);
245 if (err != EOK) {
246 HIDEBUG_LOGE("strcat_s persist query name failed.");
247 return false;
248 }
249
250 #ifdef HAS_MUSL_STARTUP_MALLOC_HOOK_INTF
251 setup_malloc_hook_mode();
252 #else
253 SetupMallocHookAtStartup(serviceName);
254 #endif
255 if (QueryParams(onceName) == 0 && QueryParams(persistName) == 0) {
256 return false;
257 }
258 for (int i = 0; i < g_paramCnt; ++i) {
259 if (setenv(g_params[i].key, g_params[i].value, 1) != 0) { // 1 : overwrite
260 HIDEBUG_LOGE("setenv failed, err: %" LOG_PRIV_PUBLIC "s", strerror(errno));
261 }
262 }
263 return true;
264 }
265