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 <unistd.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 45static void StartMemoryHook(const char* processName) 46{ 47 const char defaultValue[PARAM_BUF_LEN] = { 0 }; 48 const char targetPrefix[] = "startup:"; 49 const int targetPrefixLen = strlen(targetPrefix); 50 char paramValue[PARAM_BUF_LEN] = { 0 }; 51 int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue)); 52 if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) { 53 return; 54 } 55 if (strstr(paramValue + targetPrefixLen, processName) != NULL) { 56 const int hookSignal = 36; // 36: native memory hooked signal 57 HDF_LOGE("raise hook signal %{public}d to %{public}s", hookSignal, processName); 58 raise(hookSignal); 59 } 60} 61 62bool HdfStringToInt(const char *str, int *value) 63{ 64 if (str == NULL || value == NULL) { 65 return false; 66 } 67 68 char *end = NULL; 69 errno = 0; 70 const int base = 10; 71 long result = strtol(str, &end, base); 72 if (end == str || end[0] != '\0' || errno == ERANGE || result > INT_MAX || result < INT_MIN) { 73 return false; 74 } 75 76 *value = (int)result; 77 return true; 78} 79 80static void SetProcTitle(char **argv, const char *newTitle) 81{ 82 size_t len = strlen(argv[0]); 83 if (strlen(newTitle) > len) { 84 HDF_LOGE("failed to set new process title because the '%{public}s' is too long", newTitle); 85 return; 86 } 87 (void)memset_s(argv[0], len, 0, len); 88 if (strcpy_s(argv[0], len + 1, newTitle) != EOK) { 89 HDF_LOGE("failed to set new process title"); 90 return; 91 } 92 prctl(PR_SET_NAME, newTitle); 93} 94 95static void HdfSetProcPriority(char **argv) 96{ 97 int32_t schedPriority = 0; 98 int32_t procPriority = 0; 99 100 if (!HdfStringToInt(argv[DEVHOST_PROCESS_PRI_POS], &procPriority)) { 101 HDF_LOGE("procPriority parameter error: %{public}s", argv[DEVHOST_PROCESS_PRI_POS]); 102 return; 103 } 104 if (!HdfStringToInt(argv[DEVHOST_THREAD_PRI_POS], &schedPriority)) { 105 HDF_LOGE("schedPriority parameter error: %{public}s", argv[DEVHOST_THREAD_PRI_POS]); 106 return; 107 } 108 109 if (setpriority(PRIO_PROCESS, 0, procPriority) != 0) { 110 HDF_LOGE("host setpriority failed: %{public}d", errno); 111 } 112 113 struct sched_param param = {0}; 114 param.sched_priority = schedPriority; 115 if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) { 116 HDF_LOGE("host sched_setscheduler failed: %{public}d", errno); 117 } else { 118 HDF_LOGI("host sched_setscheduler succeed:%{public}d %{public}d", procPriority, schedPriority); 119 } 120} 121 122static void SetMallopt(int argc, char **argv) 123{ 124 for (int i = DEVHOST_MIN_INPUT_PARAM_NUM; i < argc - 1; i += MALLOPT_PARA_CNT) { 125 int32_t malloptKey = 0; 126 int32_t malloptValue = 0; 127 int ret = 0; 128 if (!HdfStringToInt(argv[i], &malloptKey)) { 129 HDF_LOGE("malloptKey parameter error:%{public}s", argv[i]); 130 continue; 131 } 132 if (!HdfStringToInt(argv[i + 1], &malloptValue)) { 133 HDF_LOGE("malloptValue parameter error:%{public}s", argv[i + 1]); 134 continue; 135 } 136 ret = mallopt(malloptKey, malloptValue); 137 if (ret != 1) { 138 HDF_LOGE("mallopt failed, malloptKey:%{public}d, malloptValue:%{public}d, ret:%{public}d", 139 malloptKey, malloptValue, ret); 140 continue; 141 } 142 HDF_LOGI("host set mallopt succeed, mallopt:%{public}d %{public}d", malloptKey, malloptValue); 143 } 144 return; 145} 146 147static void SetHostProperties(int argc, char **argv, const char *hostName) 148{ 149 SetProcTitle(argv, hostName); 150 StartMemoryHook(hostName); 151 if ((strcmp(argv[DEVHOST_PROCESS_PRI_POS], INVALID_PRIORITY) != 0) && 152 (strcmp(argv[DEVHOST_THREAD_PRI_POS], INVALID_PRIORITY) != 0)) { 153 HdfSetProcPriority(argv); 154 } 155 if (argc > DEVHOST_MIN_INPUT_PARAM_NUM) { 156 SetMallopt(argc, argv); 157 } 158} 159 160int main(int argc, char **argv) 161{ 162 if (argc < DEVHOST_MIN_INPUT_PARAM_NUM) { 163 HDF_LOGE("Devhost main parameter error, argc: %{public}d", argc); 164 return HDF_ERR_INVALID_PARAM; 165 } 166 prctl(PR_SET_PDEATHSIG, SIGKILL); // host process should exit with devmgr process 167 int hostId = 0; 168 if (!HdfStringToInt(argv[DEVHOST_INPUT_PARAM_HOSTID_POS], &hostId)) { 169 HDF_LOGE("Devhost main parameter error, argv[1]: %{public}s", argv[DEVHOST_INPUT_PARAM_HOSTID_POS]); 170 return HDF_ERR_INVALID_PARAM; 171 } 172 const char *hostName = argv[DEVHOST_HOST_NAME_POS]; 173 HDF_LOGI("hdf device host %{public}s %{public}d start", hostName, hostId); 174 SetHostProperties(argc, argv, hostName); 175 struct IDevHostService *instance = DevHostServiceNewInstance(hostId, hostName); 176 if (instance == NULL || instance->StartService == NULL) { 177 HDF_LOGE("DevHostServiceGetInstance fail"); 178 return HDF_ERR_INVALID_OBJECT; 179 } 180 HDF_LOGD("create IDevHostService of %{public}s success", hostName); 181 DevHostDumpInit(); 182 HDF_LOGD("%{public}s start device service begin", hostName); 183 int status = instance->StartService(instance); 184 if (status != HDF_SUCCESS) { 185 HDF_LOGE("Devhost StartService fail, return: %{public}d", status); 186 DevHostServiceFreeInstance(instance); 187 DevHostDumpDeInit(); 188 return status; 189 } 190 HdfPowerManagerInit(); 191 struct DevHostServiceFull *fullService = (struct DevHostServiceFull *)instance; 192 struct HdfMessageLooper *looper = &fullService->looper; 193 if ((looper != NULL) && (looper->Start != NULL)) { 194 HDF_LOGI("%{public}s start loop", hostName); 195 looper->Start(looper); 196 } 197 HdfPowerManagerExit(); 198 DevHostDumpDeInit(); 199 HDF_LOGI("hdf device host %{public}s %{public}d %{public}d exit", hostName, hostId, status); 200 if (strcmp(hostName, "camera_host") == 0) { 201 _exit(status); 202 } 203 return status; 204} 205