• 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