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