• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <errno.h>
17 #include <limits.h>
18 #include <sched.h>
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <sys/prctl.h>
22 #include <sys/resource.h>
23 #include <getopt.h>
24 
25 #include "securec.h"
26 #include "parameter.h"
27 #include "malloc.h"
28 #include "devhost_dump.h"
29 #include "devhost_service.h"
30 #include "devhost_service_full.h"
31 #include "hdf_base.h"
32 #include "hdf_core_log.h"
33 #include "hdf_power_manager.h"
34 
35 #define HDF_LOG_TAG                    hdf_device_host
36 #define DEVHOST_MIN_INPUT_PARAM_NUM    5
37 #define DEVHOST_INPUT_PARAM_HOSTID_POS 1
38 #define DEVHOST_HOST_NAME_POS          2
39 #define DEVHOST_PROCESS_PRI_POS        3
40 #define DEVHOST_THREAD_PRI_POS         4
41 #define PARAM_BUF_LEN 128
42 #define MALLOPT_PARA_CNT 2
43 #define INVALID_PRIORITY "0"
44 #define DEVHOST_ARGUMENT 2
45 
46 typedef struct {
47     int hostId;
48     const char *hostName;
49     int schedPriority;
50     int processPriority;
51     int malloptKey;
52     int malloptValue;
53 } HostConfig;
54 
HdfStringToInt(const char * str,int * value)55 bool HdfStringToInt(const char *str, int *value)
56 {
57     if (str == NULL || value == NULL) {
58         return false;
59     }
60 
61     char *end = NULL;
62     errno = 0;
63     const int base = 10;
64     long result = strtol(str, &end, base);
65     if (end == str || end[0] != '\0' || errno == ERANGE || result > INT_MAX || result < INT_MIN) {
66         return false;
67     }
68 
69     *value = (int)result;
70     return true;
71 }
72 
SetMallopt(int32_t malloptKey,int32_t malloptValue)73 static void SetMallopt(int32_t malloptKey, int32_t malloptValue)
74 {
75     int ret = mallopt(malloptKey, malloptValue);
76     if (ret != 1) {
77         HDF_LOGE("mallopt failed, malloptKey:%{public}d, malloptValue:%{public}d, ret:%{public}d",
78             malloptKey, malloptValue, ret);
79             return;
80     }
81     HDF_LOGI("host set mallopt succeed, mallopt:%{public}d %{public}d", malloptKey, malloptValue);
82 }
83 
84 typedef int32_t (*CommandFunc)(const char *key, const char *value, HostConfig *config);
85 typedef struct CommandToFunc {
86     const char *opt;
87     CommandFunc func;
88 }CommandToFunc;
89 
CommandIFunc(const char * key,const char * value,HostConfig * config)90 static int32_t CommandIFunc(const char *key, const char *value, HostConfig *config)
91 {
92     (void)key;
93     if (!HdfStringToInt(value, &config->hostId)) {
94         HDF_LOGE("Invalid process ID: %{public}s", value);
95         return HDF_ERR_INVALID_PARAM;
96     }
97     return HDF_SUCCESS;
98 }
99 
CommandNFunc(const char * key,const char * value,HostConfig * config)100 static int32_t CommandNFunc(const char *key, const char *value, HostConfig *config)
101 {
102     (void)key;
103     config->hostName = value;
104     return HDF_SUCCESS;
105 }
106 
CommandPFunc(const char * key,const char * value,HostConfig * config)107 static int32_t CommandPFunc(const char *key, const char *value, HostConfig *config)
108 {
109     (void)key;
110     if (!HdfStringToInt(value, &config->processPriority)) {
111         HDF_LOGE("Invalid process ID: %{public}s", value);
112     }
113     return HDF_SUCCESS;
114 }
115 
CommandSFunc(const char * key,const char * value,HostConfig * config)116 static int32_t CommandSFunc(const char *key, const char *value, HostConfig *config)
117 {
118     (void)key;
119     if (!HdfStringToInt(value, &config->schedPriority)) {
120         HDF_LOGE("Invalid process ID: %{public}s", value);
121     }
122     return HDF_SUCCESS;
123 }
124 
CommandMFunc(const char * key,const char * value,HostConfig * config)125 static int32_t CommandMFunc(const char *key, const char *value, HostConfig *config)
126 {
127     (void)key;
128     if (!HdfStringToInt(value, &config->malloptKey)) {
129         HDF_LOGE("Invalid process ID: %{public}s", value);
130     }
131     return HDF_SUCCESS;
132 }
133 
CommandVFunc(const char * key,const char * value,HostConfig * config)134 static int32_t CommandVFunc(const char *key, const char *value, HostConfig *config)
135 {
136     (void)key;
137     if (!HdfStringToInt(value, &config->malloptValue)) {
138         HDF_LOGE("Invalid process ID: %{public}s", value);
139     }
140     return HDF_SUCCESS;
141 }
142 
CommandNumFunc(const char * key,const char * value,HostConfig * config)143 static int32_t CommandNumFunc(const char *key, const char *value, HostConfig *config)
144 {
145     int32_t malloptKey = 0;
146     int32_t malloptValue = 0;
147     if (!HdfStringToInt(value, &malloptValue)) {
148         HDF_LOGE("Invalid value: %{public}s", value);
149     }
150     if (!HdfStringToInt(key, &malloptKey)) {
151         HDF_LOGE("Invalid key: %{public}s", key);
152     }
153     SetMallopt(malloptKey, malloptValue);
154     return HDF_SUCCESS;
155 }
156 
157 static struct CommandToFunc g_commandFuncs[] = {
158     {"-i", CommandIFunc},
159     {"-n", CommandNFunc},
160     {"-p", CommandPFunc},
161     {"-s", CommandSFunc},
162     {"-m", CommandMFunc},
163     {"-v", CommandVFunc},
164     {"-1005", CommandNumFunc},
165     {"-1006", CommandNumFunc},
166     {"-1007", CommandNumFunc},
167     {"-1008", CommandNumFunc},
168     {"-1009", CommandNumFunc},
169     {"-1010", CommandNumFunc},
170     {"-1011", CommandNumFunc},
171     {"-1012", CommandNumFunc},
172     {"-1013", CommandNumFunc},
173     {"-1014", CommandNumFunc},
174 };
175 
StartMemoryHook(const char * processName)176 static void StartMemoryHook(const char* processName)
177 {
178     const char defaultValue[PARAM_BUF_LEN] = { 0 };
179     const char targetPrefix[] = "startup:";
180     const int targetPrefixLen = strlen(targetPrefix);
181     char paramValue[PARAM_BUF_LEN] = { 0 };
182     int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue));
183     if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) {
184         return;
185     }
186     if (strstr(paramValue + targetPrefixLen, processName) != NULL) {
187         const int hookSignal = 36; // 36: native memory hooked signal
188         HDF_LOGE("raise hook signal %{public}d to %{public}s", hookSignal, processName);
189         raise(hookSignal);
190     }
191 }
192 
SetProcTitle(char ** argv,const char * newTitle)193 static void SetProcTitle(char **argv, const char *newTitle)
194 {
195     if (newTitle == NULL) {
196         HDF_LOGE("failed because newTitle is NULL");
197         return;
198     }
199     size_t len = strlen(argv[0]); // 获取原始进程标题的长度
200     if (strlen(newTitle) > len) { // 如果新标题的长度超过原始标题的长度
201         HDF_LOGE("failed to set new process title because the '%{public}s' is too long", newTitle); // 打印错误日志
202         return; // 退出函数
203     }
204     (void)memset_s(argv[0], len, 0, len); // 将原始标题的内存清零
205     if (strcpy_s(argv[0], len + 1, newTitle) != EOK) { // 将新标题复制到原始标题的位置
206         HDF_LOGE("failed to set new process title"); // 如果复制失败,打印错误日志
207         return; // 退出函数
208     }
209     prctl(PR_SET_NAME, newTitle); // 使用 prctl 系统调用设置进程的名字
210 }
211 
HdfSetProcPriority(int32_t procPriority,int32_t schedPriority)212 static void HdfSetProcPriority(int32_t procPriority, int32_t schedPriority)
213 {
214     if (setpriority(PRIO_PROCESS, 0, procPriority) != 0) {
215         HDF_LOGE("host setpriority failed: %{public}d", errno);
216     }
217 
218     struct sched_param param = {0};
219     param.sched_priority = schedPriority;
220     if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
221         HDF_LOGE("host sched_setscheduler failed: %{public}d", errno);
222     } else {
223         HDF_LOGI("host sched_setscheduler succeed:%{public}d %{public}d", procPriority, schedPriority);
224     }
225 }
226 
FindFunc(const char * arg,const char * value,HostConfig * config)227 static int FindFunc(const char* arg, const char* value, HostConfig *config)
228 {
229     for (size_t i = 0; i < sizeof(g_commandFuncs) / sizeof(g_commandFuncs[0]); ++i) {
230         if (strcmp(g_commandFuncs[i].opt, arg) == 0) {
231             return g_commandFuncs[i].func(arg, value, config);
232         }
233     }
234     HDF_LOGE("FindFunc failed: %{public}s", arg);
235     return HDF_ERR_INVALID_PARAM;
236 }
237 
ParseCommandLineArgs(int argc,char ** argv,HostConfig * config)238 static int ParseCommandLineArgs(int argc, char **argv, HostConfig *config)
239 {
240     for (int i = 1; i < argc; i += DEVHOST_ARGUMENT) {
241         const char* arg = argv[i];
242 
243         if (arg == NULL) {
244             HDF_LOGE("NULL argument:arg");
245             continue;
246         }
247 
248         int valueIndex = i + 1;
249         if (valueIndex >= argc) {
250             HDF_LOGE("Missing argument for -%{public}s", arg);
251             continue;
252         }
253         const char* value = argv[valueIndex];
254         if (value == NULL) {
255             HDF_LOGE("NULL argument: value");
256             continue;
257         }
258         if (FindFunc(arg, value, config) != HDF_SUCCESS) {
259             HDF_LOGE("argument Parse failed for -%s", arg);
260         }
261     }
262     return HDF_SUCCESS;
263 }
264 
InitializeHost(const HostConfig * config,char ** argv)265 static int InitializeHost(const HostConfig *config, char **argv)
266 {
267     prctl(PR_SET_PDEATHSIG, SIGKILL); // host process should exit with devmgr process
268 
269     HDF_LOGI("hdf device host %{public}s %{public}d start", config->hostName, config->hostId);
270     SetProcTitle(argv, config->hostName);
271     StartMemoryHook(config->hostName);
272     if ((config->processPriority != 0) && (config->schedPriority != 0)) {
273         HdfSetProcPriority(config->processPriority, config->schedPriority);
274     }
275     if ((config->malloptKey != 0) && (config->malloptValue != 0)) {
276         SetMallopt(config->malloptKey, config->malloptValue);
277     }
278     return HDF_SUCCESS;
279 }
280 
StartHostService(const HostConfig * config)281 static int StartHostService(const HostConfig *config)
282 {
283     struct IDevHostService *instance = DevHostServiceNewInstance(config->hostId, config->hostName);
284     if (instance == NULL || instance->StartService == NULL) {
285         HDF_LOGE("DevHostServiceGetInstance fail");
286         return HDF_ERR_INVALID_OBJECT;
287     }
288     HDF_LOGD("create IDevHostService of %{public}s success", config->hostName);
289 
290     DevHostDumpInit();
291     HDF_LOGD("%{public}s start device service begin", config->hostName);
292     int status = instance->StartService(instance);
293     if (status != HDF_SUCCESS) {
294         HDF_LOGE("Devhost StartService fail, return: %{public}d", status);
295         DevHostServiceFreeInstance(instance);
296         DevHostDumpDeInit();
297         return status;
298     }
299 
300     HdfPowerManagerInit();
301     struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance;
302     struct HdfMessageLooper *looper = &fullService->looper;
303     if ((looper != NULL) && (looper->Start != NULL)) {
304         HDF_LOGI("%{public}s start loop", config->hostName);
305         looper->Start(looper);
306     }
307 
308     DevHostServiceFreeInstance(instance);
309     HdfPowerManagerExit();
310     DevHostDumpDeInit();
311     return HDF_SUCCESS;
312 }
313 
main(int argc,char ** argv)314 int main(int argc, char **argv)
315 {
316     if (argc < DEVHOST_MIN_INPUT_PARAM_NUM) {
317         HDF_LOGE("Devhost main parameter error, argc: %{public}d", argc);
318         return HDF_ERR_INVALID_PARAM;
319     }
320 
321     HostConfig config = {0};
322     if (ParseCommandLineArgs(argc, argv, &config) != HDF_SUCCESS) {
323         HDF_LOGE("ParseCommandLineArgs(argc, argv, &config) != HDF_SUCCESS");
324         return HDF_ERR_INVALID_PARAM;
325     }
326 
327     if (InitializeHost(&config, argv) != HDF_SUCCESS) {
328         return HDF_ERR_INVALID_PARAM;
329     }
330 
331     int status = StartHostService(&config);
332     HDF_LOGI("hdf device host %{public}s %{public}d exit", config.hostName, config.hostId);
333     return status;
334 }
335