1 /*
2 * Copyright (c) 2021-2022 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 "common.h"
17 #include <array>
18 #include <cinttypes>
19 #include <csignal>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <fstream>
23 #include <iostream>
24 #ifdef HOOK_ENABLE
25 #include <malloc.h>
26 #endif
27 #include <sstream>
28 #include <sys/file.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <unistd.h>
33 #include "application_info.h"
34 #include "bundle_mgr_proxy.h"
35 #include "file_ex.h"
36 #include "iservice_registry.h"
37 #include "logging.h"
38 #include "system_ability_definition.h"
39
40 using namespace OHOS;
41 using namespace OHOS::AppExecFwk;
42 namespace COMMON {
43 constexpr int EXECVP_ERRNO = 2;
44 const int SHELL_UID = 2000;
45 const std::string DEFAULT_PATH = "/data/local/tmp/";
46 constexpr int PIPE_LEN = 2;
47 constexpr int READ = 0;
48 constexpr int WRITE = 1;
49 const int FILE_PATH_SIZE = 512;
50 const int BUFFER_SIZE = 1024;
51 const int INVALID_PID = -1;
52
IsProcessRunning()53 bool IsProcessRunning()
54 {
55 setgid(SHELL_UID);
56 char buffer[PATH_MAX + 1] = {0};
57 readlink("/proc/self/exe", buffer, PATH_MAX);
58 std::string processName = buffer;
59 int pos = static_cast<int>(processName.find_last_of('/'));
60 if (pos != 0) {
61 processName = processName.substr(pos + 1, processName.size());
62 }
63
64 std::string fileName = DEFAULT_PATH + processName + ".pid";
65 umask(S_IWOTH);
66 int fd = open(fileName.c_str(), O_WRONLY | O_CREAT, static_cast<mode_t>(0664)); // 0664: rw-rw-r--
67 if (fd < 0) {
68 const int bufSize = 256;
69 char buf[bufSize] = { 0 };
70 strerror_r(errno, buf, bufSize);
71 HILOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, fileName.c_str(), errno, buf);
72 return false;
73 }
74
75 if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
76 // 进程正在运行,加锁失败
77 close(fd);
78 printf("%s is running, please don't start it again.\n", processName.c_str());
79 HILOG_ERROR(LOG_CORE, "%s is running, please don't start it again.", processName.c_str());
80 return true;
81 }
82
83 std::string pidStr = std::to_string(getpid());
84 auto nbytes = write(fd, pidStr.data(), pidStr.size());
85 CHECK_TRUE(static_cast<size_t>(nbytes) == pidStr.size(), false, "write pid FAILED!");
86 return false;
87 }
88
IsProcessExist(std::string & processName,int & pid)89 bool IsProcessExist(std::string& processName, int& pid)
90 {
91 DIR* dir = opendir("/proc");
92 if (dir == nullptr) {
93 HILOG_ERROR(LOG_CORE, "open /proc dir failed");
94 return false;
95 }
96 struct dirent* ptr;
97 int pidValue = INVALID_PID;
98 while ((ptr = readdir(dir)) != nullptr) {
99 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
100 continue;
101 }
102 if ((!isdigit(*ptr->d_name)) || ptr->d_type != DT_DIR) {
103 continue;
104 }
105 char filePath[FILE_PATH_SIZE] = {0};
106 int len = snprintf_s(filePath, FILE_PATH_SIZE, FILE_PATH_SIZE - 1, "/proc/%s/cmdline", ptr->d_name);
107 if (len < 0) {
108 HILOG_WARN(LOG_CORE, "maybe, the contents of cmdline had be cut off");
109 continue;
110 }
111 FILE* fp = fopen(filePath, "r");
112 if (fp == nullptr) {
113 HILOG_WARN(LOG_CORE, "open file failed!");
114 break;
115 }
116 char buf[BUFFER_SIZE] = {0};
117 if (fgets(buf, sizeof(buf) - 1, fp) == nullptr) {
118 fclose(fp);
119 continue;
120 }
121 std::string str(buf);
122 size_t found = str.rfind("/");
123 std::string fullProcess;
124 if (found != std::string::npos) {
125 fullProcess = str.substr(found + 1);
126 } else {
127 fullProcess = str;
128 }
129 if (fullProcess == processName) {
130 pidValue = atoi(ptr->d_name);
131 fclose(fp);
132 break;
133 }
134 fclose(fp);
135 }
136 closedir(dir);
137 if (pidValue != INVALID_PID) {
138 pid = pidValue;
139 }
140 return pidValue != INVALID_PID;
141 }
142
CloseStdio()143 static void CloseStdio()
144 {
145 close(STDIN_FILENO);
146 close(STDOUT_FILENO);
147 close(STDERR_FILENO);
148 }
149
StartProcess(const std::string & processBin,std::vector<char * > & argv)150 int StartProcess(const std::string& processBin, std::vector<char*>& argv)
151 {
152 int pid = fork();
153 if (pid == 0) {
154 CloseStdio();
155 argv.push_back(nullptr); // last item in argv must be NULL
156 int retval = execvp(processBin.c_str(), argv.data());
157 if (retval == -1 && errno == EXECVP_ERRNO) {
158 printf("warning: %s does not exist!\n", processBin.c_str());
159 HILOG_WARN(LOG_CORE, "warning: %s does not exist!", processBin.c_str());
160 }
161 _exit(EXIT_FAILURE);
162 }
163
164 return pid;
165 }
166
KillProcess(int pid)167 int KillProcess(int pid)
168 {
169 if (pid == -1) {
170 return -1;
171 }
172 int stat;
173 kill(pid, SIGKILL);
174 if (waitpid(pid, &stat, 0) == -1) {
175 if (errno != EINTR) {
176 stat = -1;
177 }
178 }
179 return stat;
180 }
181
PrintMallinfoLog(const std::string & mallInfoPrefix)182 void PrintMallinfoLog(const std::string& mallInfoPrefix)
183 {
184 #ifdef HOOK_ENABLE
185 struct mallinfo2 mallinfo = mallinfo2();
186 std::string mallinfoLog = mallInfoPrefix;
187 mallinfoLog += "arena = " + std::to_string(mallinfo.arena) + ", ordblks = " + std::to_string(mallinfo.ordblks);
188 mallinfoLog += ", smblks = " + std::to_string(mallinfo.smblks) + ", hblks = " + std::to_string(mallinfo.hblks);
189 mallinfoLog += ", hblkhd = " + std::to_string(mallinfo.hblkhd) + ", usmblks = " + std::to_string(mallinfo.usmblks);
190 mallinfoLog +=
191 ", fsmblks = " + std::to_string(mallinfo.fsmblks) + ", uordblks = " + std::to_string(mallinfo.uordblks);
192 mallinfoLog +=
193 ", fordblks = " + std::to_string(mallinfo.fordblks) + ", keepcost = " + std::to_string(mallinfo.keepcost);
194 HILOG_INFO(LOG_CORE, "%s", mallinfoLog.c_str());
195 #endif // HOOK_ENABLE
196 }
197
CustomPopen(int & childPid,const std::string & filePath,std::vector<std::string> & argv,const char * type)198 FILE* CustomPopen(int& childPid, const std::string& filePath, std::vector<std::string>& argv, const char* type)
199 {
200 if (type == nullptr) {
201 HILOG_ERROR(LOG_CORE, "Common:%s param invalid", __func__);
202 return nullptr;
203 }
204 int fd[PIPE_LEN];
205 pipe(fd);
206 pid_t pid = fork();
207 if (pid == -1) {
208 HILOG_ERROR(LOG_CORE, "Common:%s fork failed!", __func__);
209 return nullptr;
210 }
211 // child process
212 if (pid == 0) {
213 if (!strncmp(type, "r", strlen(type))) {
214 close(fd[READ]);
215 dup2(fd[WRITE], STDOUT_FILENO); // Redirect stdout to pipe
216 dup2(fd[WRITE], STDERR_FILENO); // 2: Redirect stderr to pipe
217 } else {
218 close(fd[WRITE]);
219 dup2(fd[READ], 0); // Redirect stdin to pipe
220 }
221 setpgid(pid, pid);
222 std::vector<char*> vectArgv;
223 for (auto& item : argv) {
224 vectArgv.push_back(const_cast<char*>(item.c_str()));
225 }
226 // execv : the last argv must be nullptr.
227 vectArgv.push_back(nullptr);
228 execv(filePath.c_str(), &vectArgv[0]);
229 exit(0);
230 } else {
231 if (!strncmp(type, "r", strlen(type))) {
232 // Close the WRITE end of the pipe since parent's fd is read-only
233 close(fd[WRITE]);
234 } else {
235 // Close the READ end of the pipe since parent's fd is write-only
236 close(fd[READ]);
237 }
238 }
239 childPid = pid;
240 if (!strncmp(type, "r", strlen(type))) {
241 return fdopen(fd[READ], "r");
242 }
243 return fdopen(fd[WRITE], "w");
244 }
245
CustomPclose(FILE * fp,int childPid)246 int CustomPclose(FILE* fp, int childPid)
247 {
248 HILOG_INFO(LOG_CORE, "BEGN %s: ready!", __func__);
249 CHECK_NOTNULL(fp, -1, "NOTE %s: fp is null", __func__);
250 int stat = 0;
251 if (fclose(fp) != 0) {
252 const int bufSize = 256;
253 char buf[bufSize] = {0};
254 strerror_r(errno, buf, bufSize);
255 HILOG_ERROR(LOG_CORE, "Common: %s fclose failed! errno(%d:%s)", __func__, errno, buf);
256 }
257 if (waitpid(childPid, &stat, 0) == -1) {
258 if (errno != EINTR) {
259 const int bufSize = 256;
260 char buf[bufSize] = {0};
261 strerror_r(errno, buf, bufSize);
262 HILOG_ERROR(LOG_CORE, "Common: %s waitpid failed! errno(%d:%s)", __func__, errno, buf);
263 return stat;
264 }
265 }
266 HILOG_INFO(LOG_CORE, "END %s: success!", __func__);
267 return stat;
268 }
269
GetServicePort()270 int GetServicePort()
271 {
272 const std::string portRangePath = "/proc/sys/net/ipv4/ip_local_port_range";
273 std::ifstream file(portRangePath.c_str());
274 if (!file.is_open()) {
275 HILOG_ERROR(LOG_CORE, "Open file failed! filePath:%s", portRangePath.c_str());
276 return -1;
277 }
278 std::string rangeStr;
279 copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(rangeStr));
280
281 int minPort;
282 int maxPort;
283 std::istringstream istr(rangeStr);
284 istr >> minPort >> maxPort;
285 const int offset = 3168; // To be compatible with previously used port 50051;
286 int port = (minPort + maxPort) / 2 + offset;
287 HILOG_DEBUG(LOG_CORE, "Service port is: %d", port);
288 return port;
289 }
290
SplitString(const std::string & str,const std::string & sep,std::vector<std::string> & ret)291 void SplitString(const std::string& str, const std::string &sep, std::vector<std::string>& ret)
292 {
293 if (str.empty()) {
294 HILOG_ERROR(LOG_CORE, "The string splited is empty!");
295 return;
296 }
297 std::string::size_type beginPos = str.find_first_not_of(sep);
298 std::string::size_type findPos = 0;
299 while (beginPos != std::string::npos) {
300 findPos = str.find(sep, beginPos);
301 std::string tmp;
302 if (findPos != std::string::npos) {
303 tmp = str.substr(beginPos, findPos - beginPos);
304 beginPos = findPos + sep.length();
305 } else {
306 tmp = str.substr(beginPos);
307 beginPos = findPos;
308 }
309 if (!tmp.empty()) {
310 ret.push_back(tmp);
311 tmp.clear();
312 }
313 }
314 }
315
CheckApplicationPermission(int pid,const std::string & processName)316 bool CheckApplicationPermission(int pid, const std::string& processName)
317 {
318 std::string bundleName;
319 if (pid > 0) {
320 std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
321 if (!LoadStringFromFile(filePath, bundleName)) {
322 HILOG_ERROR(LOG_CORE, "Get process name by pid failed!");
323 return false;
324 }
325 bundleName = bundleName.substr(0, strlen(bundleName.c_str()));
326 } else {
327 bundleName = processName;
328 }
329 if (bundleName.empty()) {
330 HILOG_ERROR(LOG_CORE, "Pid or process name is illegal!");
331 return false;
332 }
333
334 sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
335 if (sam == nullptr) {
336 HILOG_ERROR(LOG_CORE, "GetSystemAbilityManager failed!");
337 return false;
338 }
339 sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
340 if (remoteObject == nullptr) {
341 HILOG_ERROR(LOG_CORE, "Get BundleMgr SA failed!");
342 return false;
343 }
344 sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject);
345 int uid = proxy->GetUidByDebugBundleName(bundleName, Constants::ANY_USERID);
346 if (uid < 0) {
347 HILOG_ERROR(LOG_CORE, "Get %s uid = %d", bundleName.c_str(), uid);
348 return false;
349 }
350 return true;
351 }
352
VerifyPath(const std::string & filePath,const std::vector<std::string> & validPaths)353 bool VerifyPath(const std::string& filePath, const std::vector<std::string>& validPaths)
354 {
355 if (validPaths.size() == 0) {
356 return true;
357 }
358
359 for (const std::string& path : validPaths) {
360 if (filePath.rfind(path, 0) == 0) {
361 return true;
362 }
363 }
364 return false;
365 }
366
ReadFile(const std::string & filePath,const std::vector<std::string> & validPaths,std::string & fileContent)367 bool ReadFile(const std::string &filePath, const std::vector<std::string>& validPaths, std::string& fileContent)
368 {
369 char* realFilePath = realpath(filePath.c_str(), nullptr);
370 if (realFilePath == nullptr) {
371 HILOG_ERROR(LOG_CORE, "Fail to realPath: %s", filePath.c_str());
372 return false;
373 }
374
375 std::string realFilePathStr(realFilePath);
376 free(realFilePath);
377 if (!VerifyPath(realFilePathStr, validPaths)) {
378 HILOG_ERROR(LOG_CORE, "Fail to VerifyPath: %s", realFilePathStr.c_str());
379 return false;
380 }
381
382 std::ifstream fileStream(realFilePathStr, std::ios::in);
383 if (!fileStream.is_open()) {
384 HILOG_ERROR(LOG_CORE, "Fail to open file %s", realFilePathStr.c_str());
385 return false;
386 }
387
388 std::istreambuf_iterator<char> firstIt = { fileStream };
389 std::string content(firstIt, {});
390 fileContent = content;
391 return true;
392 }
393
GetErrorMsg()394 std::string GetErrorMsg()
395 {
396 const int bufSize = 256;
397 char buffer[bufSize] = { 0 };
398 strerror_r(errno, buffer, bufSize);
399 std::string errorMsg(buffer);
400 return errorMsg;
401 }
402 } // namespace COMMON
403