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 "parameter.h"
22 #include "safwk_log.h"
23 #include "securec.h"
24 #include "string_ex.h"
25 #include "system_ability_definition.h"
26
27 using namespace OHOS;
28 using std::string;
29
30 namespace {
31 const string TAG = "SaMain";
32
33 using ProcessNameSetFunc = std::function<void(const string&)>;
34
35 constexpr auto DEFAULT_XML = "/system/usr/default.xml";
36 // The pid name can be up to 16 bytes long, including the terminating null byte.
37 // So need to set the max length of pid name to 15 bytes.
38 constexpr size_t MAX_LEN_PID_NAME = 15;
39
40 constexpr int PROFILE_INDEX = 1;
41 constexpr int SAID_INDEX = 2;
42 constexpr int DEFAULT_SAID = -1;
43 constexpr int DEFAULT_LOAD = 1;
44 constexpr int ONDEMAND_LOAD = 2;
45 }
46
StartMemoryHook(const string & processName)47 static void StartMemoryHook(const string& processName)
48 {
49 const int paramBufLen = 128;
50 const char defaultValue[paramBufLen] = { 0 };
51 const char targetPrefix[] = "startup:";
52 const int targetPrefixLen = 8;
53 char paramValue[paramBufLen] = { 0 };
54 int retParam = GetParameter("libc.hook_mode", defaultValue, paramValue, sizeof(paramValue));
55 if (retParam <= 0 || strncmp(paramValue, targetPrefix, targetPrefixLen) != 0) {
56 return;
57 }
58
59 if (processName.find(paramValue + targetPrefixLen) == 0) {
60 const int hookSignal = 36;
61 HILOGI(TAG, "raise hook signal %{public}d to %{public}s", hookSignal, processName.c_str());
62 raise(hookSignal);
63 }
64 }
65
SetProcName(const string & filePath,const ProcessNameSetFunc & setProcessName)66 static void SetProcName(const string& filePath, const ProcessNameSetFunc& setProcessName)
67 {
68 std::vector<string> strVector;
69 SplitStr(filePath, "/", strVector);
70 auto vectorSize = strVector.size();
71 if (vectorSize > 0) {
72 auto& fileName = strVector[vectorSize - 1];
73 auto dotPos = fileName.find(".");
74 if (dotPos == string::npos) {
75 return;
76 }
77 if (dotPos > MAX_LEN_PID_NAME) {
78 dotPos = MAX_LEN_PID_NAME;
79 }
80 string profileName = fileName.substr(0, dotPos);
81 int32_t ret = prctl(PR_SET_NAME, profileName.c_str());
82 if (ret != 0) {
83 HILOGI(TAG, "call the system API prctl failed!");
84 }
85 setProcessName(profileName);
86 StartMemoryHook(profileName);
87 }
88 }
89
90 // check argv size with SAID_INDEX before using the function
ParseSaId(char * argv[])91 static int32_t ParseSaId(char *argv[])
92 {
93 string saIdStr(argv[SAID_INDEX]);
94 int32_t saId = DEFAULT_SAID;
95 if (!StrToInt(saIdStr, saId)) {
96 return DEFAULT_SAID;
97 }
98 return saId;
99 }
100
CheckSaId(int32_t saId)101 static bool CheckSaId(int32_t saId)
102 {
103 return (saId >= FIRST_SYS_ABILITY_ID) && (saId <= LAST_SYS_ABILITY_ID);
104 }
105
main(int argc,char * argv[])106 int main(int argc, char *argv[])
107 {
108 HILOGI(TAG, "[PerformanceTest] SAFWK main entry process starting!");
109 auto setProcessName = [argc, argv](const string& name) -> void {
110 uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]);
111 uintptr_t end = reinterpret_cast<uintptr_t>(strchr(argv[argc - 1], 0));
112 uintptr_t argvSize = end - start;
113
114 if (memset_s(argv[0], argvSize, 0, argvSize) != EOK) {
115 HILOGW(TAG, "failed to clear argv:%s", strerror(errno));
116 return;
117 }
118 if (strcpy_s(argv[0], argvSize, name.c_str()) != EOK) {
119 HILOGW(TAG, "failed to set process name:%s", strerror(errno));
120 return;
121 }
122 HILOGI(TAG, "Set process name to %{public}s", argv[0]);
123 };
124 // Load ondemand system abilities related shared libraries from specific xml-format profile
125 // when this process starts.
126 int32_t saId = DEFAULT_SAID;
127 if (argc > ONDEMAND_LOAD) {
128 saId = ParseSaId(argv);
129 if (!CheckSaId(saId)) {
130 HILOGE(TAG, "saId is invalid!");
131 return 0;
132 }
133 }
134 // Load default system abilities related shared libraries from specific xml-format profile,
135 // when this process starts.
136 string profilePath(DEFAULT_XML);
137 if (argc > DEFAULT_LOAD) {
138 string filePath(argv[PROFILE_INDEX]);
139 if (filePath.empty() || filePath.find(".xml") == string::npos) {
140 HILOGE(TAG, "profile file path is invalid!");
141 return 0;
142 }
143 SetProcName(filePath, setProcessName);
144 profilePath = std::move(filePath);
145 }
146 LocalAbilityManager::GetInstance().DoStartSAProcess(profilePath, saId);
147 return 0;
148 }
149