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 #include <csignal>
16 #include <sys/prctl.h>
17 #include <vector>
18
19 #include "errors.h"
20 #include "local_ability_manager.h"
21 #include "malloc.h"
22 #include "parameter.h"
23 #include "parse_util.h"
24 #include "safwk_log.h"
25 #include "securec.h"
26 #include "string_ex.h"
27 #include "system_ability_definition.h"
28 #include "hisysevent_adapter.h"
29
30 using namespace OHOS;
31 using std::string;
32
33 namespace {
34 constexpr const char* PARAM_PREFIX_M = "-m";
35 constexpr const char* EVENT_TYPE = "eventId";
36 constexpr const char* EVENT_NAME = "name";
37 constexpr const char* EVENT_VALUE = "value";
38 constexpr const char* EVENT_EXTRA_DATA_ID = "extraDataId";
39 #ifdef CONFIG_USE_JEMALLOC_DFX_INTF
40 constexpr const char* MALLOPT_CONFIG_SEPARATOR = ":";
41 #endif
42 using ProcessNameSetFunc = std::function<void(const string&)>;
43
44 constexpr auto DEFAULT_JSON = "/system/usr/default.json";
45 // The pid name can be up to 16 bytes long, including the terminating null byte.
46 // So need to set the max length of pid name to 15 bytes.
47 constexpr size_t MAX_LEN_PID_NAME = 15;
48 constexpr int ID_INDEX = 1;
49 constexpr int NAME_INDEX = 2;
50 constexpr int VALUE_INDEX = 3;
51 constexpr int EXTRA_DATA_ID_INDEX = 4;
52 constexpr int PROFILE_INDEX = 1;
53 constexpr int EVENT_INDEX = 2;
54 constexpr int DEFAULT_SAID = -1;
55 constexpr int DEFAULT_LOAD = 1;
56 constexpr int ONDEMAND_LOAD = 2;
57 constexpr int ARGC_LIMIT = 2;
58 constexpr int PARTEVENT_NUM = 5;
59 constexpr int MAX_LENGTH = 2000;
60 constexpr int MALLOPT_CONFIG_LEN = 2;
61 }
62
StartMemoryHook(const string & processName)63 static void StartMemoryHook(const string& processName)
64 {
65 const int paramBufLen = 128;
66 const char defaultValue[paramBufLen] = { 0 };
67 const char targetPrefix[] = "startup:";
68 const int targetPrefixLen = 8;
69 char paramValue[paramBufLen] = { 0 };
70 int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue));
71 if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) {
72 return;
73 }
74
75 if (processName.find(paramValue + targetPrefixLen) == 0) {
76 const int hookSignal = 36;
77 HILOGI(TAG, "raise hook signal %{public}d to %{public}s", hookSignal, processName.c_str());
78 raise(hookSignal);
79 }
80 }
81
SetProcName(const string & filePath,const ProcessNameSetFunc & setProcessName)82 static void SetProcName(const string& filePath, const ProcessNameSetFunc& setProcessName)
83 {
84 std::vector<string> strVector;
85 SplitStr(filePath, "/", strVector);
86 auto vectorSize = strVector.size();
87 if (vectorSize > 0) {
88 auto& fileName = strVector[vectorSize - 1];
89 auto dotPos = fileName.find(".");
90 if (dotPos == string::npos) {
91 return;
92 }
93 string profileName = fileName.substr(0, dotPos);
94 setProcessName(profileName);
95 if (dotPos > MAX_LEN_PID_NAME) {
96 dotPos = MAX_LEN_PID_NAME;
97 }
98 profileName = fileName.substr(0, dotPos);
99 int32_t ret = prctl(PR_SET_NAME, profileName.c_str());
100 if (ret != 0) {
101 HILOGI(TAG, "call the system API prctl failed!");
102 }
103 StartMemoryHook(profileName);
104 }
105 }
106
107 // check argv size with SAID_INDEX before using the function
ParseArgv(char * argv[],nlohmann::json & eventMap,int eventIndex)108 static int32_t ParseArgv(char *argv[], nlohmann::json& eventMap, int eventIndex)
109 {
110 string eventStr(argv[eventIndex]);
111 HILOGI(TAG, "ParseArgv extraArgv eventStr:%{public}s!", eventStr.c_str());
112 int32_t saId = DEFAULT_SAID;
113 if (eventStr.size() > MAX_LENGTH) {
114 return DEFAULT_SAID;
115 }
116 std::size_t pos = eventStr.find("#");
117 std::vector<string> eventVec;
118 while (pos != std::string::npos) {
119 std::string eventPart = eventStr.substr(0, pos);
120 eventVec.push_back(eventPart);
121 eventStr = eventStr.substr(pos + 1, eventStr.size() - pos - 1);
122 pos = eventStr.find("#");
123 }
124 if (eventVec.size() != PARTEVENT_NUM) {
125 HILOGE(TAG, "eventVec size is not true");
126 return DEFAULT_SAID;
127 }
128 if (!StrToInt(eventVec[0], saId)) {
129 HILOGE(TAG, "eventVec[0] StrToInt said error");
130 return DEFAULT_SAID;
131 }
132 eventMap[EVENT_TYPE] = atoi(eventVec[ID_INDEX].c_str());
133 eventMap[EVENT_NAME] = eventVec[NAME_INDEX];
134 eventMap[EVENT_VALUE] = eventVec[VALUE_INDEX];
135 eventMap[EVENT_EXTRA_DATA_ID] = atoi(eventVec[EXTRA_DATA_ID_INDEX].c_str());
136 HILOGD(TAG, "ParseArgv extraDataId :%{public}d!", atoi(eventVec[EXTRA_DATA_ID_INDEX].c_str()));
137 return saId;
138 }
139
CheckSaId(int32_t saId)140 static bool CheckSaId(int32_t saId)
141 {
142 return (saId >= FIRST_SYS_ABILITY_ID) && (saId <= LAST_SYS_ABILITY_ID);
143 }
144
DoStartSAProcess(int argc,char * argv[],int32_t saId)145 static int DoStartSAProcess(int argc, char *argv[], int32_t saId)
146 {
147 auto setProcessName = [argc, argv](const string& name) -> void {
148 char *endCh = strchr(argv[argc - 1], 0);
149 if (endCh == nullptr) {
150 HILOGW(TAG, "argv is invalid");
151 return;
152 }
153 uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]);
154 uintptr_t end = reinterpret_cast<uintptr_t>(endCh);
155 uintptr_t argvSize = end - start;
156
157 if (memset_s(argv[0], argvSize, 0, argvSize) != EOK) {
158 HILOGW(TAG, "failed to clear argv:%{public}s", strerror(errno));
159 return;
160 }
161 if (strcpy_s(argv[0], argvSize, name.c_str()) != EOK) {
162 HILOGW(TAG, "failed to set process name:%{public}s", strerror(errno));
163 return;
164 }
165 KHILOGI(TAG, "Set process name to %{public}s", argv[0]);
166 };
167 // Load default system abilities related shared libraries from specific format profile
168 // when this process starts.
169 string profilePath(DEFAULT_JSON);
170 if (argc > DEFAULT_LOAD) {
171 string filePath(argv[PROFILE_INDEX]);
172 if (filePath.empty() || filePath.find(".json") == string::npos) {
173 HILOGE(TAG, "profile file path is invalid!");
174 return 0;
175 }
176 SetProcName(filePath, setProcessName);
177 profilePath = std::move(filePath);
178 }
179 LocalAbilityManager::GetInstance().DoStartSAProcess(profilePath, saId);
180 return 0;
181 }
182
InitMallopt(int argc,char * argv[],int & ondemandLoad,int & eventIndex)183 static void InitMallopt(int argc, char *argv[], int& ondemandLoad, int& eventIndex)
184 {
185 #ifdef CONFIG_USE_JEMALLOC_DFX_INTF
186 std::vector<std::string> malloptStrList;
187 #endif
188 if (argc < ARGC_LIMIT) {
189 HILOGE(TAG, "argc is too small");
190 return;
191 }
192 for (int i = 0; i < argc - 1; ++i) {
193 if (strcmp(PARAM_PREFIX_M, argv[i]) == 0) {
194 #ifdef CONFIG_USE_JEMALLOC_DFX_INTF
195 malloptStrList.emplace_back(argv[i + 1]);
196 #endif
197 ondemandLoad += MALLOPT_CONFIG_LEN;
198 eventIndex += MALLOPT_CONFIG_LEN;
199 }
200 }
201 #ifdef CONFIG_USE_JEMALLOC_DFX_INTF
202 for (size_t i = 0; i < malloptStrList.size(); i++) {
203 std::vector<std::string> malloptItem;
204 SplitStr(malloptStrList[i], MALLOPT_CONFIG_SEPARATOR, malloptItem);
205 if (malloptItem.size() != MALLOPT_CONFIG_LEN) {
206 HILOGE(TAG, "mallopt config string : %{public}s is invalid", malloptStrList[i].c_str());
207 continue;
208 }
209 int key = atoi(malloptItem[0].c_str());
210 int value = atoi(malloptItem[1].c_str());
211
212 int err = mallopt(key, value);
213 if (err != 1) {
214 HILOGE(TAG, "mallopt failed, malloptStr : %{public}s, result : %{public}d", malloptStrList[i].c_str(), err);
215 }
216 }
217 #endif
218 }
219
main(int argc,char * argv[])220 int main(int argc, char *argv[])
221 {
222 HILOGI(TAG, "enter SAFWK main, proc:%{public}d", getpid());
223 int ondemandLoad = ONDEMAND_LOAD;
224 int eventIndex = EVENT_INDEX;
225 InitMallopt(argc, argv, ondemandLoad, eventIndex);
226 // Load ondemand system abilities related shared libraries from specific json-format profile
227 // when this process starts.
228 int32_t saId = DEFAULT_SAID;
229 if (argc > ondemandLoad) {
230 nlohmann::json eventMap;
231 if (eventIndex >= argc) {
232 ReportSaMainExit("sa services path config error");
233 HILOGE(TAG, "sa services path config error!");
234 return 0;
235 }
236 saId = ParseArgv(argv, eventMap, eventIndex);
237 if (!CheckSaId(saId)) {
238 ReportSaMainExit("saId is invalid");
239 HILOGE(TAG, "saId is invalid!");
240 return 0;
241 }
242 LocalAbilityManager::GetInstance().SetStartReason(saId, eventMap);
243 }
244
245 DoStartSAProcess(argc, argv, saId);
246 return 0;
247 }
248