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