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 "ipc_test_helper.h"
17 #include <csignal>
18 #include <string>
19 #include <securec.h>
20 #include <sys/time.h>
21 #include <unistd.h>
22 #include "ipc_debug.h"
23 #include "nativetoken_kit.h"
24 #include "test_service_client.h"
25 #include "token_setproc.h"
26
27 using namespace OHOS::HiviewDFX;
28 namespace OHOS {
29 static const int MAX_NAME_LEN = 256;
30 static const int MAX_BUFFER_SIZE = 1024;
31 static const int SLEEP_TIME = 500000; // ms
32 static const int SECOND_TO_MS = 1000;
33 static const int ONE_SECOND = 1; // seconds
34 static const int MAX_CHECK_COUNT = 10;
35 static const int SIG_KILL = 9;
36 static bool flag = true;
37
AddPermission()38 void AddPermission()
39 {
40 if (flag) {
41 uint64_t tokenId;
42 NativeTokenInfoParams infoInstance = {
43 .dcapsNum = 0,
44 .permsNum = 0,
45 .aclsNum = 0,
46 .dcaps = NULL,
47 .perms = NULL,
48 .acls = NULL,
49 .processName = "com.ipc.test",
50 .aplStr = "normal",
51 };
52 tokenId = GetAccessTokenId(&infoInstance);
53 SetSelfTokenID(tokenId);
54 flag = false;
55 }
56 }
57
GetTestAppName(int appId)58 const std::string &IPCTestHelper::GetTestAppName(int appId)
59 {
60 static std::map<unsigned int, std::string> appNames = {
61 { IPC_TEST_NONE, ""},
62 { IPC_TEST_SAMGR, "samgr" },
63 { IPC_TEST_SERVER, "ipc_server_test" },
64 { IPC_TEST_SERVER_EXTRA, "ipc_server_test_extra" },
65 { IPC_TEST_CLIENT, "ipc_client_test" },
66 { IPC_TEST_MSG_SERVER, "ipcmsg_server" },
67 { IPC_TEST_MSG_CLIENT, "ipcmsg_client" },
68 };
69
70 if (appNames.count(appId)) {
71 return appNames[appId];
72 }
73
74 return appNames[IPC_TEST_NONE];
75 }
76
IPCTestHelper()77 IPCTestHelper::IPCTestHelper()
78 {
79 AddPermission();
80 }
81
~IPCTestHelper()82 IPCTestHelper::~IPCTestHelper()
83 {
84 TearDownTestSuite();
85 }
86
GetPidByName(std::string task_name)87 pid_t IPCTestHelper::GetPidByName(std::string task_name)
88 {
89 struct dirent *ptr = nullptr;
90 FILE *fp = nullptr;
91
92 char filepath[MAX_NAME_LEN + 1];
93 char curTaskName[MAX_NAME_LEN + 1];
94 char buf[MAX_BUFFER_SIZE];
95 pid_t pid = INVALID_PID;
96
97 DIR *dir = opendir("/proc");
98 if (dir == nullptr) {
99 return pid;
100 }
101
102 for (;;) {
103 ptr = readdir(dir);
104 if (ptr == nullptr) {
105 break;
106 }
107
108 if ((strcmp(ptr->d_name, ".") == 0) ||
109 (strcmp(ptr->d_name, "..") == 0) ||
110 (ptr->d_type != DT_DIR)) {
111 continue;
112 }
113
114 if (sprintf_s(filepath, sizeof(filepath), "/proc/%s/status", ptr->d_name) <= 0) {
115 ZLOGE(LABEL, "format file failed");
116 closedir(dir);
117 return INVALID_PID;
118 }
119
120 fp = fopen(filepath, "r");
121 if (fp == nullptr) {
122 continue;
123 }
124
125 if (fgets(buf, MAX_BUFFER_SIZE - 1, fp) == nullptr) {
126 fclose(fp);
127 continue;
128 }
129
130 if (sscanf_s(buf, "%*s %s", curTaskName, sizeof(curTaskName)) <= 0) {
131 ZLOGE(LABEL, "could not find current task");
132 }
133
134 if (!strcmp(task_name.c_str(), curTaskName)) {
135 if (sscanf_s(ptr->d_name, "%d", &pid) <= 0) {
136 ZLOGE(LABEL, "could not find target task");
137 }
138 }
139
140 fclose(fp);
141 }
142
143 closedir(dir);
144
145 return pid;
146 }
147
GetChildPids(std::vector<pid_t> & childPids)148 bool IPCTestHelper::GetChildPids(std::vector<pid_t> &childPids)
149 {
150 pid_t current = getpid();
151 ZLOGD(LABEL, "current pid %d\n", current);
152 const std::string taskPath = "/proc/" + std::to_string(current) + "/task";
153 DIR *dir = opendir(taskPath.c_str());
154 if (dir == nullptr) {
155 return false;
156 }
157 struct dirent *ptr = nullptr;
158 for (;;) {
159 ptr = readdir(dir);
160 if (ptr == nullptr) {
161 break;
162 }
163
164 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
165 continue;
166 }
167
168 if (ptr->d_type != DT_DIR) {
169 continue;
170 }
171
172 pid_t child = std::stoi(ptr->d_name);
173 if (child == current) {
174 continue;
175 }
176
177 childPids.push_back(child);
178 ZLOGD(LABEL, "child pid %d", child);
179 }
180
181 closedir(dir);
182
183 return true;
184 }
185
StartExecutable(std::string name,std::string args)186 pid_t IPCTestHelper::StartExecutable(std::string name, std::string args)
187 {
188 pid_t execPid;
189 int checkCount = 0;
190 const char *ld_library_path = getenv("LD_LIBRARY_PATH");
191
192 if (ld_library_path != nullptr) {
193 unsetenv("LD_LIBRARY_PATH");
194 }
195
196 std::string cmd1 = "chmod +x /system/bin/" + name;
197 int res = system(cmd1.c_str());
198 ZLOGD(LABEL, "%s, res = %d\n", cmd1.c_str(), res);
199
200 // kill the program if the program is already exist.
201 execPid = GetPidByName(name);
202 StopExecutable(execPid);
203
204 std::string cmd2 = name + " " + args + "&";
205 res = system(cmd2.c_str());
206
207 if (ld_library_path != nullptr) {
208 setenv("LD_LIBRARY_PATH", ld_library_path, 1);
209 }
210
211 ZLOGD(LABEL, "%s res = %d\n", cmd2.c_str(), res);
212
213 do {
214 execPid = GetPidByName(name);
215 sleep(ONE_SECOND);
216
217 if (execPid != INVALID_PID) {
218 break;
219 }
220 } while (checkCount++ < MAX_CHECK_COUNT);
221
222 ZLOGD(LABEL, "start %s done, pid:%d\n", name.c_str(), execPid);
223 return execPid;
224 }
225
StopExecutable(pid_t pid)226 bool IPCTestHelper::StopExecutable(pid_t pid)
227 {
228 if (pid != INVALID_PID) {
229 ZLOGD(LABEL, "kill pid = %d\n", pid);
230 kill(pid, SIG_KILL);
231 }
232
233 return true;
234 }
235
StopExecutable(std::string name)236 bool IPCTestHelper::StopExecutable(std::string name)
237 {
238 pid_t pid = GetPidByName(name);
239 if (pid != INVALID_PID) {
240 ZLOGD(LABEL, "%s pid = %d, kill it\n", name.c_str(), pid);
241 kill(pid, SIG_KILL);
242 }
243
244 return true;
245 }
246
PrepareTestSuite()247 bool IPCTestHelper::PrepareTestSuite()
248 {
249 pid_t pid = GetTestAppPid(IPC_TEST_SAMGR);
250 if (pid == INVALID_PID) {
251 usleep(SLEEP_TIME);
252 pid = StartTestApp(IPC_TEST_SAMGR);
253 ZLOGD(LABEL, "StartSystemServer done");
254 }
255
256 return (pid != INVALID_PID);
257 }
258
TearDownTestSuite()259 bool IPCTestHelper::TearDownTestSuite()
260 {
261 for (auto it = testPids_.begin(); it != testPids_.end();) {
262 ZLOGD(LABEL, "kill %s", it->first.c_str());
263 StopExecutable(it->second);
264 it = testPids_.erase(it);
265 }
266
267 return true;
268 }
AddTestAppPid(const std::string & appName,const int & pid)269 void IPCTestHelper::AddTestAppPid(const std::string &appName, const int &pid)
270 {
271 std::lock_guard<std::mutex> auto_lock(mutex_);
272 testPids_.insert(std::make_pair(appName, pid));
273 }
274
RemoveTestAppPid(const std::string & appName)275 void IPCTestHelper::RemoveTestAppPid(const std::string &appName)
276 {
277 std::lock_guard<std::mutex> auto_lock(mutex_);
278 auto it = testPids_.find(appName);
279 if (it != testPids_.end()) {
280 testPids_.erase(appName);
281 }
282 }
283
StartTestApp(int appId,const int & cmdId)284 bool IPCTestHelper::StartTestApp(int appId, const int &cmdId)
285 {
286 int pid = INVALID_PID;
287 std::string appName = GetTestAppName(appId);
288 if (!appName.empty()) {
289 if (cmdId > 0) {
290 pid = StartExecutable(appName, std::to_string(cmdId));
291 } else {
292 pid = StartExecutable(appName);
293 }
294 }
295
296 if (pid != INVALID_PID) {
297 RemoveTestAppPid(appName); // should remove it if exist;
298 AddTestAppPid(appName, pid);
299 }
300
301 ZLOGD(LABEL, "StartTestApp:%d cmdId=%d pid = %d", appId, cmdId, pid);
302 return (pid != INVALID_PID);
303 }
304
StopTestApp(int appId)305 bool IPCTestHelper::StopTestApp(int appId)
306 {
307 std::string appName = GetTestAppName(appId);
308 if (appName.empty()) {
309 return false;
310 }
311
312 pid_t pid = GetTestAppPid(appId);
313 if (pid != INVALID_PID) {
314 pid = StopExecutable(pid);
315 RemoveTestAppPid(appName);
316 usleep(SLEEP_TIME);
317 }
318
319 return (pid != INVALID_PID);
320 }
321
322
GetTestAppPid(int appId)323 pid_t IPCTestHelper::GetTestAppPid(int appId)
324 {
325 ZLOGE(LABEL, "GetTestAppPid appId=%d", appId);
326 int pid = INVALID_PID;
327 std::string appName = GetTestAppName(appId);
328 if (appName.empty()) {
329 return INVALID_PID;
330 }
331
332 auto it = testPids_.find(appName);
333 if (it != testPids_.end()) {
334 pid = it->second;
335 } else {
336 pid = GetPidByName(appName);
337 }
338
339 ZLOGE(LABEL, "GetTestAppPid return pid=%d", pid);
340 return pid;
341 }
342
GetPid()343 pid_t IPCTestHelper::GetPid()
344 {
345 pid_t pid = getpid();
346 ZLOGD(LABEL, "return pid=%{public}d", pid);
347 return pid;
348 }
349
GetUid()350 uid_t IPCTestHelper::GetUid()
351 {
352 uid_t uid = getuid();
353 ZLOGD(LABEL, "return uid=%{public}d", uid);
354 return uid;
355 }
356
GetCurrentTimeMs()357 long IPCTestHelper::GetCurrentTimeMs()
358 {
359 struct timeval tv;
360 gettimeofday(&tv, nullptr);
361 return tv.tv_sec * SECOND_TO_MS + tv.tv_usec / SECOND_TO_MS;
362 }
363 } // namespace OHOS
364