• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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