• 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 
24 #include "securec.h"
25 #include "parameter.h"
26 #include "devhost_dump.h"
27 #include "devhost_service.h"
28 #include "devhost_service_full.h"
29 #include "hdf_base.h"
30 #include "hdf_log.h"
31 #include "hdf_power_manager.h"
32 
33 #define HDF_LOG_TAG                    hdf_device_host
34 #define DEVHOST_INPUT_PARAM_NUM        3
35 #define DEVHOST_PARAM_NUM_WITH_PRI     5
36 #define DEVHOST_INPUT_PARAM_HOSTID_POS 1
37 #define DEVHOST_HOST_NAME_POS          2
38 #define DEVHOST_PROCESS_PRI_POS        3
39 #define DEVHOST_THREAD_PRI_POS         4
40 #define PARAM_BUF_LEN 128
41 
StartMemoryHook(const char * processName)42 static void StartMemoryHook(const char* processName)
43 {
44     const char defaultValue[PARAM_BUF_LEN] = { 0 };
45     const char targetPrefix[] = "startup:";
46     const int targetPrefixLen = strlen(targetPrefix);
47     char paramValue[PARAM_BUF_LEN] = { 0 };
48     int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue));
49     if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) {
50         return;
51     }
52     if (strstr(paramValue + targetPrefixLen, processName) != NULL) {
53         const int hookSignal = 36; // 36: native memory hooked signal
54         HDF_LOGE("raise hook signal %{public}d to %{public}s", hookSignal, processName);
55         raise(hookSignal);
56     }
57 }
58 
HdfStringToInt(const char * str,int * value)59 bool HdfStringToInt(const char *str, int *value)
60 {
61     if (str == NULL || value == NULL) {
62         return false;
63     }
64 
65     char *end = NULL;
66     errno = 0;
67     const int base = 10;
68     long result = strtol(str, &end, base);
69     if (end == str || end[0] != '\0' || errno == ERANGE || result > INT_MAX || result < INT_MIN) {
70         return false;
71     }
72 
73     *value = (int)result;
74     return true;
75 }
76 
SetProcTitle(char ** argv,const char * newTitle)77 static void SetProcTitle(char **argv, const char *newTitle)
78 {
79     size_t len = strlen(argv[0]);
80     if (strlen(newTitle) > len) {
81         HDF_LOGE("failed to set new process title because the '%{public}s' is too long", newTitle);
82         return;
83     }
84     (void)memset_s(argv[0], len, 0, len);
85     if (strcpy_s(argv[0], len + 1, newTitle) != EOK) {
86         HDF_LOGE("failed to set new process title");
87         return;
88     }
89     prctl(PR_SET_NAME, newTitle);
90 }
91 
HdfSetProcPriority(char ** argv)92 static void HdfSetProcPriority(char **argv)
93 {
94     int32_t schedPriority = 0;
95     int32_t procPriority = 0;
96 
97     if (!HdfStringToInt(argv[DEVHOST_PROCESS_PRI_POS], &procPriority)) {
98         HDF_LOGE("procPriority parameter error: %{public}s", argv[DEVHOST_PROCESS_PRI_POS]);
99         return;
100     }
101     if (!HdfStringToInt(argv[DEVHOST_THREAD_PRI_POS], &schedPriority)) {
102         HDF_LOGE("schedPriority parameter error: %{public}s", argv[DEVHOST_THREAD_PRI_POS]);
103         return;
104     }
105 
106     if (setpriority(PRIO_PROCESS, 0, procPriority) != 0) {
107         HDF_LOGE("host setpriority failed: %{public}d", errno);
108     }
109 
110     struct sched_param param = {0};
111     param.sched_priority = schedPriority;
112     if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
113         HDF_LOGE("host sched_setscheduler failed: %{public}d", errno);
114     } else {
115         HDF_LOGI("host sched_setscheduler succeed:%{public}d %{public}d", procPriority, schedPriority);
116     }
117 }
118 
main(int argc,char ** argv)119 int main(int argc, char **argv)
120 {
121     if ((argc != DEVHOST_INPUT_PARAM_NUM) && (argc != DEVHOST_PARAM_NUM_WITH_PRI)) {
122         HDF_LOGE("Devhost main parameter error, argc: %{public}d", argc);
123         return HDF_ERR_INVALID_PARAM;
124     }
125 
126     prctl(PR_SET_PDEATHSIG, SIGKILL); // host process should exit with devmgr process
127 
128     int hostId = 0;
129     if (!HdfStringToInt(argv[DEVHOST_INPUT_PARAM_HOSTID_POS], &hostId)) {
130         HDF_LOGE("Devhost main parameter error, argv[1]: %{public}s", argv[DEVHOST_INPUT_PARAM_HOSTID_POS]);
131         return HDF_ERR_INVALID_PARAM;
132     }
133 
134     const char *hostName = argv[DEVHOST_HOST_NAME_POS];
135     HDF_LOGI("hdf device host %{public}s %{public}d start", hostName, hostId);
136     SetProcTitle(argv, hostName);
137     StartMemoryHook(hostName);
138     if (argc == DEVHOST_PARAM_NUM_WITH_PRI) {
139         HdfSetProcPriority(argv);
140     }
141 
142     struct IDevHostService *instance = DevHostServiceNewInstance(hostId, hostName);
143     if (instance == NULL || instance->StartService == NULL) {
144         HDF_LOGE("DevHostServiceGetInstance fail");
145         return HDF_ERR_INVALID_OBJECT;
146     }
147 
148     DevHostDumpInit();
149     int status = instance->StartService(instance);
150     if (status != HDF_SUCCESS) {
151         HDF_LOGE("Devhost StartService fail, return: %{public}d", status);
152         DevHostServiceFreeInstance(instance);
153         DevHostDumpDeInit();
154         return status;
155     }
156 
157     HdfPowerManagerInit();
158     struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance;
159     struct HdfMessageLooper *looper = &fullService->looper;
160     if ((looper != NULL) && (looper->Start != NULL)) {
161         looper->Start(looper);
162     }
163 
164     DevHostServiceFreeInstance(instance);
165     HdfPowerManagerExit();
166     DevHostDumpDeInit();
167     HDF_LOGI("hdf device host %{public}s %{public}d exit", hostName, hostId);
168     return status;
169 }
170