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 <signal.h>
19 #include <stdlib.h>
20 #include <sys/prctl.h>
21
22 #include "securec.h"
23 #include "parameter.h"
24 #include "devhost_service.h"
25 #include "devhost_service_full.h"
26 #include "hdf_base.h"
27 #include "hdf_log.h"
28 #include "hdf_power_manager.h"
29
30 #define HDF_LOG_TAG hdf_device_host
31 #define DEVHOST_INPUT_PARAM_NUM 3
32 #define DEVHOST_INPUT_PARAM_HOSTID_POS 1
33 #define PARAM_BUF_LEN 128
34
StartMemoryHook(const char * processName)35 static void StartMemoryHook(const char* processName)
36 {
37 const char defaultValue[PARAM_BUF_LEN] = { 0 };
38 const char targetPrefix[] = "startup:";
39 const int targetPrefixLen = strlen(targetPrefix);
40 char paramValue[PARAM_BUF_LEN] = { 0 };
41 int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue));
42 if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) {
43 return;
44 }
45 if (strstr(paramValue + targetPrefixLen, processName) != NULL) {
46 const int hookSignal = 36; // 36: native memory hooked signal
47 HDF_LOGE("raise hook signal %{public}d to %{public}s", hookSignal, processName);
48 raise(hookSignal);
49 }
50 }
51
HdfStringToInt(const char * str,int * value)52 bool HdfStringToInt(const char *str, int *value)
53 {
54 if (str == NULL || value == NULL) {
55 return false;
56 }
57
58 char *end = NULL;
59 errno = 0;
60 const int base = 10;
61 long result = strtol(str, &end, base);
62 if (end == str || end[0] != '\0' || errno == ERANGE || result > INT_MAX || result < INT_MIN) {
63 return false;
64 }
65
66 *value = (int)result;
67 return true;
68 }
69
SetProcTitle(char ** argv,const char * newTitle)70 static void SetProcTitle(char **argv, const char *newTitle)
71 {
72 size_t len = strlen(argv[0]);
73 if (strlen(newTitle) > len) {
74 HDF_LOGE("failed to set new process title because the '%{public}s' is too long", newTitle);
75 return;
76 }
77 (void)memset_s(argv[0], len, 0, len);
78 if (strcpy_s(argv[0], len + 1, newTitle) != EOK) {
79 HDF_LOGE("failed to set new process title");
80 return;
81 }
82 prctl(PR_SET_NAME, newTitle);
83 }
84
main(int argc,char ** argv)85 int main(int argc, char **argv)
86 {
87 if (argc != DEVHOST_INPUT_PARAM_NUM) {
88 HDF_LOGE("Devhost main parameter error, argc: %{public}d", argc);
89 return HDF_ERR_INVALID_PARAM;
90 }
91
92 prctl(PR_SET_PDEATHSIG, SIGKILL); // host process should exit with devmgr process
93
94 int hostId = 0;
95 if (!HdfStringToInt(argv[DEVHOST_INPUT_PARAM_HOSTID_POS], &hostId)) {
96 HDF_LOGE("Devhost main parameter error, argv[1]: %{public}s", argv[DEVHOST_INPUT_PARAM_HOSTID_POS]);
97 return HDF_ERR_INVALID_PARAM;
98 }
99 const char *hostName = argv[argc - 1];
100 HDF_LOGI("hdf device host %{public}s %{public}d start", hostName, hostId);
101 SetProcTitle(argv, hostName);
102 StartMemoryHook(hostName);
103
104 struct IDevHostService *instance = DevHostServiceNewInstance(hostId, hostName);
105 if (instance == NULL || instance->StartService == NULL) {
106 HDF_LOGE("DevHostServiceGetInstance fail");
107 return HDF_ERR_INVALID_OBJECT;
108 }
109 int status = instance->StartService(instance);
110 if (status != HDF_SUCCESS) {
111 HDF_LOGE("Devhost StartService fail, return: %{public}d", status);
112 DevHostServiceFreeInstance(instance);
113 return status;
114 }
115 HdfPowerManagerInit();
116 struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance;
117 struct HdfMessageLooper *looper = &fullService->looper;
118 if ((looper != NULL) && (looper->Start != NULL)) {
119 looper->Start(looper);
120 }
121
122 DevHostServiceFreeInstance(instance);
123 HdfPowerManagerExit();
124 HDF_LOGI("hdf device host %{public}s %{public}d exit", hostName, hostId);
125 return status;
126 }
127