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