• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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