• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 <fcntl.h>
18 #include <array>
19 #include <cinttypes>
20 #include <csignal>
21 #include <dirent.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/types.h>
30 #include <sys/wait.h>
31 #include <unistd.h>
32 #include <sys/stat.h>
33 
34 #include "application_info.h"
35 #include "bundle_mgr_proxy.h"
36 #include "file_ex.h"
37 #include "iservice_registry.h"
38 #include "logging.h"
39 #include "system_ability_definition.h"
40 
41 using namespace OHOS;
42 using namespace OHOS::AppExecFwk;
43 namespace COMMON {
44 constexpr int EXECVP_ERRNO = 2;
45 const int SHELL_UID = 2000;
46 const std::string DEFAULT_PATH = "/data/local/tmp/";
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 
53 
IsProcessRunning(int & lockFileFd)54 bool IsProcessRunning(int& lockFileFd)
55 {
56     setgid(SHELL_UID);
57     char buffer[PATH_MAX + 1] = {0};
58     readlink("/proc/self/exe", buffer, PATH_MAX);
59     std::string processName = buffer;
60     int pos = static_cast<int>(processName.find_last_of('/'));
61     if (pos != 0) {
62         processName = processName.substr(pos + 1, processName.size());
63     }
64 
65     std::string fileName = DEFAULT_PATH + processName + ".pid";
66     umask(S_IWOTH);
67     int fd = open(fileName.c_str(), O_WRONLY | O_CREAT, static_cast<mode_t>(0664)); // 0664: rw-rw-r--
68     if (fd < 0) {
69         const int bufSize = 256;
70         char buf[bufSize] = {0};
71         strerror_r(errno, buf, bufSize);
72         HILOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, fileName.c_str(), errno, buf);
73         return false;
74     }
75     int flags = fcntl(fd, F_GETFD);
76     if (flags == -1) {
77         close(fd);
78         HILOG_ERROR(LOG_CORE, "%s: get fd flags failed!", __func__);
79         return false;
80     }
81     flags |= FD_CLOEXEC;
82     if (fcntl(fd, F_SETFD, flags) == -1) {
83         close(fd);
84         HILOG_ERROR(LOG_CORE, "%s: set fd_cloexec failed!", __func__);
85         return false;
86     }
87     if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
88         // 进程正在运行,加锁失败
89         close(fd);
90         printf("%s is running, please don't start it again.\n", processName.c_str());
91         HILOG_ERROR(LOG_CORE, "%s is running, please don't start it again.", processName.c_str());
92         return true;
93     }
94     std::string pidStr = std::to_string(getpid());
95     auto nbytes = write(fd, pidStr.data(), pidStr.size());
96     lockFileFd = fd;
97     CHECK_TRUE(static_cast<size_t>(nbytes) == pidStr.size(), false, "write pid FAILED!");
98     return false;
99 }
100 
IsProcessExist(const std::string & processName,int & pid)101 bool IsProcessExist(const std::string& processName, int& pid)
102 {
103     DIR* dir = opendir("/proc");
104     CHECK_NOTNULL(dir, false, "open /proc dir failed");
105     struct dirent* ptr;
106     int pidValue = INVALID_PID;
107     while ((ptr = readdir(dir)) != nullptr) {
108         if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
109             continue;
110         }
111         if ((!isdigit(*ptr->d_name)) || ptr->d_type != DT_DIR) {
112             continue;
113         }
114         char filePath[FILE_PATH_SIZE] = {0};
115         int len = snprintf_s(filePath, FILE_PATH_SIZE, FILE_PATH_SIZE - 1, "/proc/%s/cmdline", ptr->d_name);
116         if (len < 0) {
117             HILOG_WARN(LOG_CORE, "maybe, the contents of cmdline had be cut off");
118             continue;
119         }
120         FILE* fp = fopen(filePath, "r");
121         if (fp == nullptr) {
122             HILOG_WARN(LOG_CORE, "open file failed!");
123             break;
124         }
125         char buf[BUFFER_SIZE] = {0};
126         if (fgets(buf, sizeof(buf) - 1, fp) == nullptr) {
127             fclose(fp);
128             continue;
129         }
130         std::string str(buf);
131         size_t found = str.rfind("/");
132         std::string fullProcess;
133         if (found != std::string::npos) {
134             fullProcess = str.substr(found + 1);
135         } else {
136             fullProcess = str;
137         }
138         if (fullProcess == processName) {
139             pidValue = atoi(ptr->d_name);
140             fclose(fp);
141             break;
142         }
143         fclose(fp);
144     }
145     closedir(dir);
146     if (pidValue != INVALID_PID) {
147         pid = pidValue;
148     }
149     return pidValue != INVALID_PID;
150 }
151 
CloseStdio()152 static void CloseStdio()
153 {
154     close(STDIN_FILENO);
155     close(STDOUT_FILENO);
156     close(STDERR_FILENO);
157 }
158 
StartProcess(const std::string & processBin,std::vector<char * > & argv)159 int StartProcess(const std::string& processBin, std::vector<char*>& argv)
160 {
161     int pid = fork();
162     if (pid == 0) {
163         CloseStdio();
164         argv.push_back(nullptr); // last item in argv must be NULL
165         int retval = execvp(processBin.c_str(), argv.data());
166         if (retval == -1 && errno == EXECVP_ERRNO) {
167             printf("warning: %s does not exist!\n", processBin.c_str());
168             HILOG_WARN(LOG_CORE, "warning: %s does not exist!", processBin.c_str());
169         }
170         _exit(EXIT_FAILURE);
171     }
172 
173     return pid;
174 }
175 
KillProcess(int pid)176 int KillProcess(int pid)
177 {
178     if (pid == -1) {
179         return -1;
180     }
181     int stat;
182     kill(pid, SIGTERM);
183     if (waitpid(pid, &stat, 0) == -1) {
184         if (errno != EINTR) {
185             stat = -1;
186         }
187     }
188     return stat;
189 }
190 
PrintMallinfoLog(const std::string & mallInfoPrefix)191 void PrintMallinfoLog(const std::string& mallInfoPrefix)
192 {
193 #ifdef HOOK_ENABLE
194     struct mallinfo2 mallinfo = mallinfo2();
195     std::string mallinfoLog = mallInfoPrefix;
196     mallinfoLog += "arena = " + std::to_string(mallinfo.arena) + ", ordblks = " + std::to_string(mallinfo.ordblks);
197     mallinfoLog += ", smblks = " + std::to_string(mallinfo.smblks) + ", hblks = " + std::to_string(mallinfo.hblks);
198     mallinfoLog += ", hblkhd = " + std::to_string(mallinfo.hblkhd) + ", usmblks = " + std::to_string(mallinfo.usmblks);
199     mallinfoLog +=
200         ", fsmblks = " + std::to_string(mallinfo.fsmblks) + ", uordblks = " + std::to_string(mallinfo.uordblks);
201     mallinfoLog +=
202         ", fordblks = " + std::to_string(mallinfo.fordblks) + ", keepcost = " + std::to_string(mallinfo.keepcost);
203     HILOG_INFO(LOG_CORE, "%s", mallinfoLog.c_str());
204 #endif  // HOOK_ENABLE
205 }
206 
CustomFdClose(int & fd)207 inline int CustomFdClose(int& fd)
208 {
209     int ret = close(fd);
210     if (ret == 0) {
211         fd = -1;
212     }
213     return ret;
214 }
215 
CustomFdFclose(FILE ** fp)216 inline int CustomFdFclose(FILE** fp)
217 {
218     int ret = fclose(*fp);
219     if (ret == 0) {
220         *fp = nullptr;
221     }
222     return ret;
223 }
224 
CustomPopen(const std::vector<std::string> & command,const char * type,int fds[],volatile pid_t & childPid,bool needUnblock)225 FILE* CustomPopen(const std::vector<std::string>& command, const char* type, int fds[],
226                   volatile pid_t& childPid, bool needUnblock)
227 {
228     HILOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
229     if (command.empty() || type == nullptr) {
230         HILOG_ERROR(LOG_CORE, "%s: param invalid", __func__);
231         return nullptr;
232     }
233 
234     // only allow "r" or "w"
235     if ((type[0] != 'r' && type[0] != 'w') || type[1] != 0) {
236         errno = EINVAL;
237         return  nullptr;
238     }
239 
240     CHECK_TRUE(pipe(fds) == 0, nullptr, "Pipe open failed!");
241 
242     pid_t pid = fork();
243     if (pid == -1) {
244         perror("fork");
245         exit(1);
246     }
247 
248     if (pid == 0) {
249         char* const envp[] = {nullptr};
250         // execve : the last argv must be nullptr.
251         std::vector<char*> argv(command.size() + 1, nullptr);
252         for (size_t i = 0, cmdSize = command.size(); i < cmdSize; i++) {
253             argv[i] = const_cast<char*>(command[i].data());
254         }
255 
256         if (strncmp(type, "r", strlen(type)) == 0) {
257             CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "CustomFdClose failed!");
258             dup2(fds[WRITE], STDOUT_FILENO); // Redirect stdout to pipe
259             CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "CustomFdClose failed!");
260         } else {
261             CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "CustomFdClose failed!");
262             dup2(fds[READ], STDIN_FILENO); // Redirect stdin to pipe
263             CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "CustomFdClose failed!");
264         }
265 
266         setpgid(pid, pid);
267         // exe path = argv[0]; exe name = argv[1]
268         if (execve(argv[0], &argv[1], envp) == -1) {
269             HILOG_ERROR(LOG_CORE, "execve failed {%s:%s}", __func__, strerror(errno));
270             exit(EXIT_FAILURE);
271         }
272     }
273 
274     if (!needUnblock) {
275         if (strncmp(type, "r", strlen(type)) == 0) {
276             // Close the WRITE end of the pipe since parent's fd is read-only
277             CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "%s %d CustomFdClose failed! errno(%s)\n",
278                 __func__, __LINE__, strerror(errno));
279         } else {
280             // Close the READ end of the pipe since parent's fd is write-only
281             CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "%s %d CustomFdClose failed! errno(%s)\n",
282                 __func__, __LINE__, strerror(errno));
283         }
284     }
285 
286     // Make sure the parent pipe reads and writes exist;CustomPUnblock will use.
287     childPid = pid;
288     if (strncmp(type, "r", strlen(type)) == 0) {
289         HILOG_DEBUG(LOG_CORE, "END %s fds[READ]: success!", __func__);
290         return fdopen(fds[READ], "r");
291     }
292 
293     HILOG_DEBUG(LOG_CORE, "END %s fds[WRITE]: success!", __func__);
294     return fdopen(fds[WRITE], "w");
295 }
296 
CustomPclose(FILE * fp,int fds[],volatile pid_t & childPid,bool needUnblock)297 int CustomPclose(FILE* fp, int fds[], volatile pid_t& childPid, bool needUnblock)
298 {
299     HILOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
300     CHECK_NOTNULL(fp, -1, "NOTE %s: fp is null", __func__);
301 
302     int stat = 0;
303 
304     if (needUnblock) {
305         HILOG_DEBUG(LOG_CORE, "NOTE Kill Endless Loop Child %d.", childPid);
306         kill(childPid, SIGKILL);
307     }
308 
309     while (waitpid(childPid, &stat, 0) == -1) {
310         HILOG_ERROR(LOG_CORE, "%s: %s.", __func__, strerror(errno));
311         if (errno == EINTR) {
312             continue;
313         }
314         break;
315     }
316 
317     if (needUnblock) {
318         if (fileno(fp) == fds[READ]) {
319             fds[READ] = -1;
320             CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, -1, "CustomFdClose failed!");
321         } else if (fileno(fp) == fds[WRITE]) {
322             fds[WRITE] = -1;
323             CHECK_TRUE(CustomFdClose(fds[READ]) == 0, -1, "CustomFdClose failed!");
324         } else {
325             HILOG_INFO(LOG_CORE, "%s: Can't find fp in fds[READ/WRITE].", __func__);
326         }
327     }
328 
329     CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!");
330 
331     HILOG_DEBUG(LOG_CORE, "END %s: success!", __func__);
332     return stat;
333 }
334 
335 // IF pipe fds is block, before release other threads, you need call CustomPUnblock
CustomPUnblock(int fds[])336 int CustomPUnblock(int fds[])
337 {
338     HILOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
339 
340     CHECK_TRUE(fds[READ] != -1 && fds[WRITE] != -1, -1, "END fds[READ/WRITE]=-1");
341 
342     int stat = fcntl(fds[READ], F_GETFL);
343     CHECK_TRUE(stat != -1, -1, "END fcntl(F_GETFL) failed!");
344 
345     if (!(stat & O_NONBLOCK)) {
346         HILOG_DEBUG(LOG_CORE, "NOTE %s: ready!Unblock r_fd and close all", __func__);
347         const char* eof = "\n\0";
348         write(fds[WRITE], eof, strlen(eof) + 1);
349         fcntl(fds[READ], F_SETFL, O_NONBLOCK);
350     }
351     HILOG_DEBUG(LOG_CORE, "END %s: success!", __func__);
352     return 0;
353 }
354 
GetServicePort()355 int GetServicePort()
356 {
357     const std::string portRangePath = "/proc/sys/net/ipv4/ip_local_port_range";
358     std::ifstream file(portRangePath.c_str());
359     CHECK_TRUE(file.is_open(), -1, "Open file failed! filePath:%s", portRangePath.c_str());
360 
361     std::string rangeStr;
362     copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(rangeStr));
363 
364     int minPort;
365     int maxPort;
366     std::istringstream istr(rangeStr);
367     istr >> minPort >> maxPort;
368     const int offset = 3168; // To be compatible with previously used port 50051;
369     int port = (minPort + maxPort) / 2 + offset;
370     HILOG_DEBUG(LOG_CORE, "Service port is: %d", port);
371     return port;
372 }
373 
SplitString(const std::string & str,const std::string & sep,std::vector<std::string> & ret)374 void SplitString(const std::string& str, const std::string &sep, std::vector<std::string>& ret)
375 {
376     if (str.empty()) {
377         HILOG_ERROR(LOG_CORE, "The string splited is empty!");
378         return;
379     }
380     std::string::size_type beginPos = str.find_first_not_of(sep);
381     std::string::size_type findPos = 0;
382     while (beginPos != std::string::npos) {
383         findPos = str.find(sep, beginPos);
384         std::string tmp;
385         if (findPos != std::string::npos) {
386             tmp = str.substr(beginPos, findPos - beginPos);
387             beginPos = findPos + sep.length();
388         } else {
389             tmp = str.substr(beginPos);
390             beginPos = findPos;
391         }
392         if (!tmp.empty()) {
393             ret.push_back(tmp);
394             tmp.clear();
395         }
396     }
397 }
398 
CheckApplicationPermission(int pid,const std::string & processName)399 bool CheckApplicationPermission(int pid, const std::string& processName)
400 {
401     std::string bundleName;
402     if (pid > 0) {
403         std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
404         if (!LoadStringFromFile(filePath, bundleName)) {
405             HILOG_ERROR(LOG_CORE, "Get process name by pid failed!");
406             return false;
407         }
408         bundleName.resize(strlen(bundleName.c_str()));
409     } else {
410         bundleName = processName;
411     }
412     CHECK_TRUE(!bundleName.empty(), false, "Pid or process name is illegal!");
413 
414     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
415     CHECK_NOTNULL(sam, false, "GetSystemAbilityManager failed!");
416     sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
417     CHECK_NOTNULL(remoteObject, false, "Get BundleMgr SA failed!");
418     sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject);
419     int uid = proxy->GetUidByDebugBundleName(bundleName, Constants::ANY_USERID);
420     CHECK_TRUE(uid >= 0, false, "Get %s uid = %d", bundleName.c_str(), uid);
421     return true;
422 }
423 
VerifyPath(const std::string & filePath,const std::vector<std::string> & validPaths)424 bool VerifyPath(const std::string& filePath, const std::vector<std::string>& validPaths)
425 {
426     if (validPaths.size() == 0) {
427         return true;
428     }
429 
430     for (const std::string& path : validPaths) {
431         if (filePath.rfind(path, 0) == 0) {
432             return true;
433         }
434     }
435     return false;
436 }
437 
ReadFile(const std::string & filePath,const std::vector<std::string> & validPaths,std::string & fileContent)438 bool ReadFile(const std::string &filePath, const std::vector<std::string>& validPaths, std::string& fileContent)
439 {
440     char* realFilePath = realpath(filePath.c_str(), nullptr);
441     CHECK_NOTNULL(realFilePath, false, "Fail to realPath: %s", filePath.c_str());
442 
443     std::string realFilePathStr(realFilePath);
444     free(realFilePath);
445     CHECK_TRUE(VerifyPath(realFilePathStr, validPaths), false, "Fail to VerifyPath: %s", realFilePathStr.c_str());
446 
447     std::ifstream fileStream(realFilePathStr, std::ios::in);
448     CHECK_TRUE(fileStream.is_open(), false, "Fail to open file %s", realFilePathStr.c_str());
449 
450     std::istreambuf_iterator<char> firstIt = { fileStream };
451     std::string content(firstIt, {});
452     fileContent = content;
453     return true;
454 }
455 
GetErrorMsg()456 std::string GetErrorMsg()
457 {
458     const int bufSize = 256;
459     char buffer[bufSize] = { 0 };
460     strerror_r(errno, buffer, bufSize);
461     std::string errorMsg(buffer);
462     return errorMsg;
463 }
464 
GetTimeStr()465 std::string GetTimeStr()
466 {
467     time_t now = time(nullptr);
468     struct tm tmTime;
469     localtime_r(&now, &tmTime);
470 
471     char buffer[32] = {0};
472     // 1900: count of years
473     (void)sprintf_s(buffer, sizeof(buffer), "%04d%02d%02d_%02d%02d%02d", tmTime.tm_year + 1900, tmTime.tm_mon + 1,
474         tmTime.tm_mday, tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec);
475     std::string timeStr(buffer);
476     return timeStr;
477 }
478 
479 // get clockid by str, return CLOCK_REALTIME as default
GetClockId(const std::string & clockIdStr)480 clockid_t GetClockId(const std::string& clockIdStr)
481 {
482     const std::map<std::string, clockid_t> clockIdMap = {
483         {"realtime",            CLOCK_REALTIME},
484         {"mono",                CLOCK_MONOTONIC},
485         {"process_cputime_id",  CLOCK_PROCESS_CPUTIME_ID},
486         {"thread_cputime_id",   CLOCK_THREAD_CPUTIME_ID},
487         {"mono_raw",            CLOCK_MONOTONIC_RAW},
488         {"realtime_coarse",     CLOCK_REALTIME_COARSE},
489         {"mono_coarse",         CLOCK_MONOTONIC_COARSE},
490         {"boot",                CLOCK_BOOTTIME},
491         {"realtime_alarm",      CLOCK_REALTIME_ALARM},
492         {"boot_alarm",          CLOCK_BOOTTIME_ALARM},
493         {"sgi_cycle",           CLOCK_SGI_CYCLE},
494         {"tai",                 CLOCK_TAI},
495     };
496 
497     clockid_t clockId = CLOCK_REALTIME;
498     auto iter = clockIdMap.find(clockIdStr);
499     if (iter != clockIdMap.end()) {
500         clockId = iter->second;
501     }
502     return clockId;
503 }
504 
AdaptSandboxPath(std::string & filePath,int pid)505 void AdaptSandboxPath(std::string& filePath, int pid)
506 {
507     if (filePath.find("/data/storage") == 0 && access(filePath.c_str(), F_OK) != 0) {
508         filePath = "/proc/" + std::to_string(pid) + "/root/" + filePath;
509     }
510 }
511 } // namespace COMMON
512