1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
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 #include <parameter.h>
25 #include <parameters.h>
26 #include <sstream>
27 #include <sys/file.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 
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 #include "os_account_info.h"
40 #include "os_account_manager.h"
41 
42 using namespace OHOS;
43 using namespace OHOS::AppExecFwk;
44 namespace COMMON {
45 namespace {
46 const std::map<std::string, clockid_t> clockIdMap = {
47     {"realtime",            CLOCK_REALTIME},
48     {"mono",                CLOCK_MONOTONIC},
49     {"process_cputime_id",  CLOCK_PROCESS_CPUTIME_ID},
50     {"thread_cputime_id",   CLOCK_THREAD_CPUTIME_ID},
51     {"mono_raw",            CLOCK_MONOTONIC_RAW},
52     {"realtime_coarse",     CLOCK_REALTIME_COARSE},
53     {"mono_coarse",         CLOCK_MONOTONIC_COARSE},
54     {"boot",                CLOCK_BOOTTIME},
55     {"realtime_alarm",      CLOCK_REALTIME_ALARM},
56     {"boot_alarm",          CLOCK_BOOTTIME_ALARM},
57     {"sgi_cycle",           CLOCK_SGI_CYCLE},
58     {"tai",                 CLOCK_TAI},
59 };
60 constexpr int EXECVP_ERRNO = 2;
61 const int SHELL_UID = 2000;
62 const std::string DEFAULT_PATH = "/data/local/tmp/";
63 constexpr int READ = 0;
64 constexpr int WRITE = 1;
65 const int FILE_PATH_SIZE = 512;
66 const int BUFFER_SIZE = 1024;
67 const int INVALID_PID = -1;
68 constexpr int32_t EC_INVALID_VALUE = -2;
69 const std::string KEY_HIVIEW_USER_TYPE = "const.logsystem.versiontype";
70 const uint32_t MAX_CMD_ARGV = 50;
71 const uint32_t MIN_CMD_ARGV = 2;
72 const std::set<std::string> CMD_WHITE_LIST = {
73     "/system/bin/hiperf",    "/system/bin/hitrace",     "/system/bin/hisysevent",         "/system/bin/hidumper",
74     "/system/bin/SP_daemon", "/system/bin/hiprofilerd", "/system/bin/hiprofiler_plugins", "/system/bin/native_daemon",
75     "/system/bin/hilog"};
76 }  // namespace
77 
IsProcessRunning(int& lockFileFd)78 bool IsProcessRunning(int& lockFileFd)
79 {
80     setgid(SHELL_UID);
81     char buffer[PATH_MAX + 1] = {0};
82     readlink("/proc/self/exe", buffer, PATH_MAX);
83     std::string processName = buffer;
84     int pos = static_cast<int>(processName.find_last_of('/'));
85     if (pos != 0) {
86         processName = processName.substr(pos + 1, processName.size());
87     }
88 
89     std::string fileName = DEFAULT_PATH + processName + ".pid";
90     umask(S_IWOTH);
91     int fd = open(fileName.c_str(), O_WRONLY | O_CREAT, static_cast<mode_t>(0664)); // 0664: rw-rw-r--
92     if (fd < 0) {
93         const int bufSize = 256;
94         char buf[bufSize] = {0};
95         strerror_r(errno, buf, bufSize);
96         PROFILER_LOG_ERROR(LOG_CORE, "%s:failed to open(%s), errno(%d:%s)", __func__, fileName.c_str(), errno, buf);
97         return false;
98     }
99     int flags = fcntl(fd, F_GETFD);
100     if (flags == -1) {
101         close(fd);
102         PROFILER_LOG_ERROR(LOG_CORE, "%s: get fd flags failed!", __func__);
103         return false;
104     }
105     flags |= FD_CLOEXEC;
106     if (fcntl(fd, F_SETFD, flags) == -1) {
107         close(fd);
108         PROFILER_LOG_ERROR(LOG_CORE, "%s: set fd_cloexec failed!", __func__);
109         return false;
110     }
111     if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
112         // 进程正在运行,加锁失败
113         close(fd);
114         printf("%s is running, please don't start it again.\n", processName.c_str());
115         PROFILER_LOG_ERROR(LOG_CORE, "%s is running, please don't start it again.", processName.c_str());
116         return true;
117     }
118     std::string pidStr = std::to_string(getpid());
119     auto nbytes = write(fd, pidStr.data(), pidStr.size());
120     lockFileFd = fd;
121     CHECK_TRUE(static_cast<size_t>(nbytes) == pidStr.size(), false, "write pid FAILED!");
122     return false;
123 }
124 
IsProcessExist(const std::string& processName, int& pid)125 bool IsProcessExist(const std::string& processName, int& pid)
126 {
127     DIR* dir = opendir("/proc");
128     CHECK_NOTNULL(dir, false, "open /proc dir failed");
129     struct dirent* ptr;
130     int pidValue = INVALID_PID;
131     while ((ptr = readdir(dir)) != nullptr) {
132         if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
133             continue;
134         }
135         if ((!isdigit(*ptr->d_name)) || ptr->d_type != DT_DIR) {
136             continue;
137         }
138         char filePath[FILE_PATH_SIZE] = {0};
139         int len = snprintf_s(filePath, FILE_PATH_SIZE, FILE_PATH_SIZE - 1, "/proc/%s/cmdline", ptr->d_name);
140         if (len < 0) {
141             PROFILER_LOG_WARN(LOG_CORE, "maybe, the contents of cmdline had be cut off");
142             continue;
143         }
144         FILE* fp = fopen(filePath, "r");
145         if (fp == nullptr) {
146             PROFILER_LOG_DEBUG(LOG_CORE, "open file failed! %s", filePath);
147             continue;
148         }
149         char buf[BUFFER_SIZE] = {0};
150         if (fgets(buf, sizeof(buf) - 1, fp) == nullptr) {
151             fclose(fp);
152             continue;
153         }
154         std::string str(buf);
155         size_t found = str.rfind("/");
156         std::string fullProcess;
157         if (found != std::string::npos) {
158             fullProcess = str.substr(found + 1);
159         } else {
160             fullProcess = str;
161         }
162         if (fullProcess == processName) {
163             pidValue = atoi(ptr->d_name);
164             fclose(fp);
165             break;
166         }
167         fclose(fp);
168     }
169     closedir(dir);
170     if (pidValue != INVALID_PID) {
171         pid = pidValue;
172     }
173     return pidValue != INVALID_PID;
174 }
175 
CloseStdio()176 static void CloseStdio()
177 {
178     close(STDIN_FILENO);
179     close(STDOUT_FILENO);
180     close(STDERR_FILENO);
181 }
182 
StartProcess(const std::string& processBin, std::vector<char*>& argv)183 int StartProcess(const std::string& processBin, std::vector<char*>& argv)
184 {
185     if (argv.size() > MAX_CMD_ARGV || argv.size() < 1) {
186         PROFILER_LOG_ERROR(LOG_CORE, "%s: param invalid", __func__);
187         return -1;
188     }
189     // check whitelist
190     if (!CheckWhiteList(processBin)) {
191         PROFILER_LOG_ERROR(LOG_CORE, "%s: command not in whitelist!", __func__);
192         return -1;
193     }
194     for (auto& item : argv) {
195         std::string itemStr(item);
196         if (!CheckCmdLineArgValid(itemStr)) {
197             PROFILER_LOG_ERROR(LOG_CORE, "%s: command arg invalid : %s", __func__, itemStr.c_str());
198             return -1;
199         }
200     }
201     int pid = fork();
202     if (pid == 0) {
203         CloseStdio();
204         argv.push_back(nullptr); // last item in argv must be NULL
205         int retval = execv(processBin.data(), argv.data());
206         if (retval == -1 && errno == EXECVP_ERRNO) {
207             printf("warning: %s does not exist!\n", processBin.c_str());
208             PROFILER_LOG_WARN(LOG_CORE, "warning: %s does not exist!", processBin.c_str());
209         }
210         _exit(EXIT_FAILURE);
211     }
212 
213     return pid;
214 }
215 
KillProcess(int pid)216 int KillProcess(int pid)
217 {
218     if (pid == -1) {
219         return -1;
220     }
221     int stat;
222     kill(pid, SIGTERM);
223     if (waitpid(pid, &stat, 0) == -1) {
224         if (errno != EINTR) {
225             stat = -1;
226         }
227     }
228     return stat;
229 }
230 
PrintMallinfoLog(const std::string& mallInfoPrefix, const struct mallinfo2& mi)231 void PrintMallinfoLog(const std::string& mallInfoPrefix, const struct mallinfo2& mi)
232 {
233 #ifdef HOOK_ENABLE
234     std::string mallinfoLog = mallInfoPrefix;
235     mallinfoLog += "arena = " + std::to_string(mi.arena) + ", ordblks = " + std::to_string(mi.ordblks);
236     mallinfoLog += ", smblks = " + std::to_string(mi.smblks) + ", hblks = " + std::to_string(mi.hblks);
237     mallinfoLog += ", hblkhd = " + std::to_string(mi.hblkhd) + ", usmblks = " + std::to_string(mi.usmblks);
238     mallinfoLog +=
239         ", fsmblks = " + std::to_string(mi.fsmblks) + ", uordblks = " + std::to_string(mi.uordblks);
240     mallinfoLog +=
241         ", fordblks = " + std::to_string(mi.fordblks) + ", keepcost = " + std::to_string(mi.keepcost);
242     PROFILER_LOG_INFO(LOG_CORE, "%s", mallinfoLog.c_str());
243 #endif  // HOOK_ENABLE
244 }
245 
GetDeveloperMode()246 bool GetDeveloperMode()
247 {
248     bool developerMode = OHOS::system::GetBoolParameter("const.security.developermode.state", true);
249     if (!developerMode) {
250         PROFILER_LOG_INFO(LOG_CORE, "It is not developer mode!");
251     }
252     return developerMode;
253 }
254 
CustomFdClose(int& fd)255 inline int CustomFdClose(int& fd)
256 {
257     int ret = close(fd);
258     if (ret == 0) {
259         fd = -1;
260     }
261     return ret;
262 }
263 
CustomFdFclose(FILE** fp)264 inline int CustomFdFclose(FILE** fp)
265 {
266     int ret = fclose(*fp);
267     if (ret == 0) {
268         *fp = nullptr;
269     }
270     return ret;
271 }
272 
CustomPopen(const std::vector<std::string>& command, const char* type, int fds[], volatile pid_t& childPid, bool needUnblock)273 FILE* CustomPopen(const std::vector<std::string>& command, const char* type, int fds[],
274                   volatile pid_t& childPid, bool needUnblock)
275 {
276     PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
277     if (command.size() < MIN_CMD_ARGV || command.size() > MAX_CMD_ARGV || type == nullptr || strlen(type) != 1) {
278         PROFILER_LOG_ERROR(LOG_CORE, "%s: param invalid", __func__);
279         return nullptr;
280     }
281 
282     // only allow "r" or "w"
283     if ((type[0] != 'r' && type[0] != 'w')) {
284         errno = EINVAL;
285         return  nullptr;
286     }
287     // check whitelist
288     if (!CheckWhiteList(command[0])) {
289         PROFILER_LOG_ERROR(LOG_CORE, "%s: command not in whitelist!", __func__);
290         return nullptr;
291     }
292     // check cmd arg valid
293     for (auto& item : command) {
294         if (!CheckCmdLineArgValid(item)) {
295             PROFILER_LOG_ERROR(LOG_CORE, "%s: command arg invalid : %s", __func__, item.c_str());
296             return nullptr;
297         }
298     }
299     CHECK_TRUE(pipe(fds) == 0, nullptr, "Pipe open failed!");
300     pid_t pid = fork();
301     if (pid == -1) {
302         perror("fork");
303         exit(1);
304     }
305 
306     if (pid == 0) {
307         // execve : the last argv must be nullptr.
308         std::vector<char*> argv(command.size() + 1, nullptr);
309         for (size_t i = 0, cmdSize = command.size(); i < cmdSize; i++) {
310             argv[i] = const_cast<char*>(command[i].data());
311         }
312 
313         if (strncmp(type, "r", strlen(type)) == 0) {
314             CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "CustomFdClose failed!");
315             dup2(fds[WRITE], STDOUT_FILENO); // Redirect stdout to pipe
316             CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "CustomFdClose failed!");
317         } else {
318             CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "CustomFdClose failed!");
319             dup2(fds[READ], STDIN_FILENO); // Redirect stdin to pipe
320             CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "CustomFdClose failed!");
321         }
322 
323         setpgid(pid, pid);
324         // exe path = argv[0]; exe name = argv[1]
325         if (execv(argv[0], &argv[1]) == -1) {
326             PROFILER_LOG_ERROR(LOG_CORE, "execv failed {%s:%s}", __func__, strerror(errno));
327             exit(EXIT_FAILURE);
328         }
329     }
330 
331     if (!needUnblock) {
332         if (strncmp(type, "r", strlen(type)) == 0) {
333             // Close the WRITE end of the pipe since parent's fd is read-only
334             CHECK_TRUE(CustomFdClose(fds[WRITE]) == 0, nullptr, "%s %d CustomFdClose failed! errno(%s)\n",
335                 __func__, __LINE__, strerror(errno));
336         } else {
337             // Close the READ end of the pipe since parent's fd is write-only
338             CHECK_TRUE(CustomFdClose(fds[READ]) == 0, nullptr, "%s %d CustomFdClose failed! errno(%s)\n",
339                 __func__, __LINE__, strerror(errno));
340         }
341     }
342 
343     // Make sure the parent pipe reads and writes exist;CustomPUnblock will use.
344     childPid = pid;
345     if (strncmp(type, "r", strlen(type)) == 0) {
346         PROFILER_LOG_DEBUG(LOG_CORE, "END %s fds[READ]: success!", __func__);
347         return fdopen(fds[READ], "r");
348     }
349 
350     PROFILER_LOG_DEBUG(LOG_CORE, "END %s fds[WRITE]: success!", __func__);
351     return fdopen(fds[WRITE], "w");
352 }
353 
IsNumeric(const std::string& str)354 bool IsNumeric(const std::string& str)
355 {
356     std::istringstream iss(str);
357     int number;
358     char trailingCharacter;
359     if (!(iss >> number)) {
360         return false;
361     }
362     if (iss >> trailingCharacter) {
363         return false;
364     }
365     return true;
366 }
367 
CustomPclose(FILE* fp, int fds[], volatile pid_t& childPid, bool needUnblock)368 int CustomPclose(FILE* fp, int fds[], volatile pid_t& childPid, bool needUnblock)
369 {
370     PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
371     CHECK_NOTNULL(fp, -1, "NOTE %s: fp is null", __func__);
372 
373     int stat = 0;
374 
375     if (needUnblock) {
376         PROFILER_LOG_DEBUG(LOG_CORE, "NOTE Kill Endless Loop Child %d.", childPid);
377         kill(childPid, SIGKILL);
378     }
379 
380     while (waitpid(childPid, &stat, 0) == -1) {
381         PROFILER_LOG_ERROR(LOG_CORE, "%s: %s.", __func__, strerror(errno));
382         if (errno == EINTR) {
383             continue;
384         }
385         break;
386     }
387 
388     if (needUnblock) {
389         if (fileno(fp) == fds[READ]) {
390             fds[READ] = -1;
391             if (CustomFdClose(fds[WRITE]) != 0) {
392                 PROFILER_LOG_ERROR(LOG_CORE, "CustomFdClose failed!");
393                 CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!");
394                 return -1;
395             }
396         } else if (fileno(fp) == fds[WRITE]) {
397             fds[WRITE] = -1;
398             if (CustomFdClose(fds[READ]) != 0) {
399                 PROFILER_LOG_ERROR(LOG_CORE, "CustomFdClose failed!");
400                 CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!");
401                 return -1;
402             }
403         } else {
404             PROFILER_LOG_INFO(LOG_CORE, "%s: Can't find fp in fds[READ/WRITE].", __func__);
405         }
406     }
407 
408     CHECK_TRUE(CustomFdFclose(&fp) == 0, -1, "CustomFdFclose failed!");
409 
410     PROFILER_LOG_DEBUG(LOG_CORE, "END %s: success!", __func__);
411     return stat;
412 }
413 
414 // IF pipe fds is block, before release other threads, you need call CustomPUnblock
CustomPUnblock(int fds[])415 int CustomPUnblock(int fds[])
416 {
417     PROFILER_LOG_DEBUG(LOG_CORE, "BEGN %s: ready!", __func__);
418 
419     CHECK_TRUE(fds[READ] != -1 && fds[WRITE] != -1, -1, "END fds[READ/WRITE]=-1");
420 
421     int stat = fcntl(fds[READ], F_GETFL);
422     CHECK_TRUE(stat != -1, -1, "END fcntl(F_GETFL) failed!");
423 
424     if (!(stat & O_NONBLOCK)) {
425         PROFILER_LOG_DEBUG(LOG_CORE, "NOTE %s: ready!Unblock r_fd and close all", __func__);
426         const char* eof = "\n\0";
427         write(fds[WRITE], eof, strlen(eof) + 1);
428         fcntl(fds[READ], F_SETFL, O_NONBLOCK);
429     }
430     PROFILER_LOG_DEBUG(LOG_CORE, "END %s: success!", __func__);
431     return 0;
432 }
433 
GetServicePort()434 int GetServicePort()
435 {
436     const std::string portRangePath = "/proc/sys/net/ipv4/ip_local_port_range";
437     std::ifstream file(portRangePath.c_str());
438     CHECK_TRUE(file.is_open(), -1, "Open file failed! filePath:%s", portRangePath.c_str());
439 
440     std::string rangeStr;
441     copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(rangeStr));
442 
443     int minPort;
444     int maxPort;
445     std::istringstream istr(rangeStr);
446     istr >> minPort >> maxPort;
447     const int offset = 3168; // To be compatible with previously used port 50051;
448     int port = (minPort + maxPort) / 2 + offset;
449     PROFILER_LOG_DEBUG(LOG_CORE, "Service port is: %d", port);
450     return port;
451 }
452 
SplitString(const std::string& str, const std::string &sep, std::vector<std::string>& ret)453 void SplitString(const std::string& str, const std::string &sep, std::vector<std::string>& ret)
454 {
455     if (str.empty()) {
456         PROFILER_LOG_ERROR(LOG_CORE, "The string splited is empty!");
457         return;
458     }
459     std::string::size_type beginPos = str.find_first_not_of(sep);
460     std::string::size_type findPos = 0;
461     while (beginPos != std::string::npos) {
462         findPos = str.find(sep, beginPos);
463         std::string tmp;
464         if (findPos != std::string::npos) {
465             tmp = str.substr(beginPos, findPos - beginPos);
466             beginPos = findPos + sep.length();
467         } else {
468             tmp = str.substr(beginPos);
469             beginPos = findPos;
470         }
471         if (!tmp.empty()) {
472             ret.push_back(tmp);
473             tmp.clear();
474         }
475     }
476 }
477 
CheckApplicationPermission(int pid, const std::string& processName)478 bool CheckApplicationPermission(int pid, const std::string& processName)
479 {
480     std::string bundleName;
481     if (pid > 0) {
482         std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
483         if (!LoadStringFromFile(filePath, bundleName)) {
484             PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!");
485             return false;
486         }
487         bundleName.resize(strlen(bundleName.c_str()));
488     } else {
489         bundleName = processName;
490     }
491     auto pos = bundleName.find(":");
492     if (pos != std::string::npos) {
493         bundleName = bundleName.substr(0, pos);
494     }
495     CHECK_TRUE(!bundleName.empty(), false, "Pid or process name is illegal!");
496 
497     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
498     CHECK_NOTNULL(sam, false, "GetSystemAbilityManager failed!");
499     sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
500     CHECK_NOTNULL(remoteObject, false, "Get BundleMgr SA failed!");
501     sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject);
502     AppExecFwk::ApplicationInfo appInfo;
503     bool ret = proxy->GetApplicationInfo(bundleName, AppExecFwk::GET_APPLICATION_INFO_WITH_DISABLE,
504                                          AppExecFwk::Constants::ANY_USERID, appInfo);
505     if (!ret) {
506         PROFILER_LOG_ERROR(LOG_CORE, "GetApplicationInfo failed!");
507         return false;
508     }
509     return appInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG;
510 }
CheckApplicationEncryped(int pid, const std::string& processName)511 bool CheckApplicationEncryped(int pid, const std::string& processName)
512 {
513     std::string bundleName;
514     if (pid > 0) {
515         std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline";
516         if (!LoadStringFromFile(filePath, bundleName)) {
517             PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!");
518             return false;
519         }
520         bundleName.resize(strlen(bundleName.c_str()));
521     } else {
522         bundleName = processName;
523     }
524     auto pos = bundleName.find(":");
525     if (pos != std::string::npos) {
526         bundleName = bundleName.substr(0, pos);
527     }
528     CHECK_TRUE(!bundleName.empty(), false, "Pid or process name is illegal!");
529     sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
530     CHECK_NOTNULL(sam, false, "GetSystemAbilityManager failed!");
531     sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
532     CHECK_NOTNULL(remoteObject, false, "Get BundleMgr SA failed!");
533     sptr<BundleMgrProxy> proxy = iface_cast<BundleMgrProxy>(remoteObject);
534     AppExecFwk::ApplicationInfo appInfo;
535     bool ret = proxy->GetApplicationInfo(bundleName, AppExecFwk::ApplicationFlag::GET_BASIC_APPLICATION_INFO,
536                                          AppExecFwk::Constants::ANY_USERID, appInfo);
537     CHECK_TRUE(ret, false, "%s:%s GetApplicationInfo failed!", __func__, bundleName.c_str());
538     bool isEncrypted = (appInfo.applicationReservedFlag &
539                         static_cast<uint32_t>(AppExecFwk::ApplicationReservedFlag::ENCRYPTED_APPLICATION)) != 0;
540     PROFILER_LOG_INFO(LOG_CORE, "%s: check application encryped.%d : %s", __func__, isEncrypted, bundleName.c_str());
541     return isEncrypted;
542 }
543 
VerifyPath(const std::string& filePath, const std::vector<std::string>& validPaths)544 bool VerifyPath(const std::string& filePath, const std::vector<std::string>& validPaths)
545 {
546     if (validPaths.size() == 0) {
547         return true;
548     }
549 
550     for (const std::string& path : validPaths) {
551         if (filePath.rfind(path, 0) == 0) {
552             return true;
553         }
554     }
555     return false;
556 }
557 
RealPath(std::string &filePath)558 const char* RealPath(std::string &filePath)
559 {
560     if (filePath.size() > 0 && (filePath.back() == '/' || filePath.back() == '.')) {
561         return nullptr;
562     }
563     if (filePath.find('.') == std::string::npos) {
564         return filePath.c_str();
565     }
566     std::vector<std::string> paths;
567     SplitString(filePath, "/", paths);
568     std::vector<std::string> validPaths;
569     for (std::string& pathName: paths) {
570         if (pathName == "..") {
571             if (validPaths.size() == 0) {
572                 return nullptr;
573             } else {
574                 validPaths.pop_back();
575             }
576         } else {
577             validPaths.emplace_back(pathName);
578         }
579     }
580     filePath = "/";
581     for (const std::string &pathName : validPaths) {
582         filePath += pathName;
583         filePath += "/";
584     }
585     filePath.pop_back();
586     return filePath.c_str();
587 }
588 
ReadFile(const std::string &filePath, const std::vector<std::string>& validPaths, std::string& fileContent)589 bool ReadFile(const std::string &filePath, const std::vector<std::string>& validPaths, std::string& fileContent)
590 {
591     std::string pathName = filePath;
592     const char* realFilePath = RealPath(pathName);
593     CHECK_NOTNULL(realFilePath, false, "Fail to realPath: %s", filePath.c_str());
594 
595     std::string realFilePathStr(realFilePath);
596     CHECK_TRUE(VerifyPath(realFilePathStr, validPaths), false, "Fail to VerifyPath: %s", realFilePathStr.c_str());
597 
598     std::ifstream fileStream(realFilePathStr, std::ios::in);
599     CHECK_TRUE(fileStream.is_open(), false, "Fail to open file %s", realFilePathStr.c_str());
600 
601     std::istreambuf_iterator<char> firstIt = { fileStream };
602     std::string content(firstIt, {});
603     fileContent = content;
604     return true;
605 }
606 
IsUserMode()607 bool IsUserMode()
608 {
609     std::string debugMode = "0";
610     debugMode = OHOS::system::GetParameter("const.debuggable", debugMode);
611     if (debugMode != "0") {
612         PROFILER_LOG_INFO(LOG_CORE, "It is not user mode!");
613     }
614     return debugMode == "0";
615 }
616 
GetErrorMsg()617 std::string GetErrorMsg()
618 {
619     const int bufSize = 256;
620     char buffer[bufSize] = { 0 };
621     strerror_r(errno, buffer, bufSize);
622     std::string errorMsg(buffer);
623     return errorMsg;
624 }
625 
GetTimeStr()626 std::string GetTimeStr()
627 {
628     time_t now = time(nullptr);
629     struct tm tmTime;
630     localtime_r(&now, &tmTime);
631 
632     char buffer[32] = {0};
633     // 1900: count of years
634     (void)sprintf_s(buffer, sizeof(buffer), "%04d%02d%02d_%02d%02d%02d", tmTime.tm_year + 1900, tmTime.tm_mon + 1,
635         tmTime.tm_mday, tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec);
636     std::string timeStr(buffer);
637     return timeStr;
638 }
639 
640 // get clockid by str, return CLOCK_REALTIME as default
GetClockId(const std::string& clockIdStr)641 clockid_t GetClockId(const std::string& clockIdStr)
642 {
643     clockid_t clockId = CLOCK_REALTIME;
644     auto iter = clockIdMap.find(clockIdStr);
645     if (iter != clockIdMap.end()) {
646         clockId = iter->second;
647     }
648     return clockId;
649 }
650 
GetClockStr(const int32_t clockId)651 std::string GetClockStr(const int32_t clockId)
652 {
653     std::string ret = "realtime";
654     for (const auto& [str, id] : clockIdMap) {
655         if (id == clockId) {
656             ret = str;
657             break;
658         }
659     }
660     return ret;
661 }
662 
AdaptSandboxPath(std::string& filePath, int pid)663 void AdaptSandboxPath(std::string& filePath, int pid)
664 {
665     if (filePath.find("/data/storage") == 0 && access(filePath.c_str(), F_OK) != 0) {
666         filePath = "/proc/" + std::to_string(pid) + "/root" + filePath;
667     }
668 }
669 
GetCurrentUserId(int32_t& userId)670 bool GetCurrentUserId(int32_t& userId)
671 {
672     std::vector<int32_t> activeIds;
673     int32_t ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(activeIds);
674     if (ret != 0) {
675         PROFILER_LOG_ERROR(LOG_CORE, "QueryActiveOsAccountIds failed ret:%d", ret);
676         return false;
677     }
678 
679     if (activeIds.empty()) {
680         PROFILER_LOG_ERROR(LOG_CORE, "QueryActiveOsAccountIds activeIds empty");
681         return false;
682     }
683     userId = activeIds[0];
684     PROFILER_LOG_INFO(LOG_CORE, "QueryActiveOsAccountIds userId[0]:%d", userId);
685     return true;
686 }
687 
GetPackageUid(const std::string& name)688 int32_t GetPackageUid(const std::string& name)
689 {
690     int32_t userId = 0;
691     if (!GetCurrentUserId(userId)) {
692         PROFILER_LOG_ERROR(LOG_CORE, "Failed to get current user id");
693         return EC_INVALID_VALUE;
694     }
695     auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
696     if (manager == nullptr) {
697         PROFILER_LOG_ERROR(LOG_CORE, "systemAbilityManager is nullptr");
698         return EC_INVALID_VALUE;
699     }
700     sptr<IRemoteObject> remoteObject = manager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
701     if (remoteObject == nullptr) {
702         PROFILER_LOG_ERROR(LOG_CORE, "failed to get service id");
703         return EC_INVALID_VALUE;
704     }
705     sptr<AppExecFwk::IBundleMgr> mgr = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
706     if (mgr == nullptr) {
707         PROFILER_LOG_ERROR(LOG_CORE, "mgr is nullptr");
708         return EC_INVALID_VALUE;
709     }
710     int32_t uid = mgr->GetUidByBundleName(name, userId);
711     PROFILER_LOG_INFO(LOG_CORE, "pkgname is: %s, uid is : %d", name.c_str(), uid);
712     return uid;
713 }
714 
IsBetaVersion()715 bool IsBetaVersion()
716 {
717     int ret = static_cast<int>(FindParameter(KEY_HIVIEW_USER_TYPE.c_str()));
718     if (ret == -1) {
719         PROFILER_LOG_INFO(LOG_CORE, "user type is not exist");
720         return true;
721     }
722     std::string userType = OHOS::system::GetParameter(KEY_HIVIEW_USER_TYPE, "");
723     PROFILER_LOG_INFO(LOG_CORE, "user type is:%s", userType.c_str());
724     return userType == "beta";
725 }
726 
CheckNotExistsFilePath(const std::string& filePath)727 std::pair<bool, std::string> CheckNotExistsFilePath(const std::string& filePath)
728 {
729     size_t pos = filePath.rfind('/');
730     std::string pathDir = "";
731     if (pos != std::string::npos) {
732         pathDir = filePath.substr(0, pos);
733     } else {
734         pathDir = ".";
735     }
736     std::unique_ptr<char[]> pathDirRealPath = std::make_unique<char[]>(PATH_MAX);
737     if ((pathDir.length() >= PATH_MAX - 1) || (realpath(pathDir.c_str(), pathDirRealPath.get()) == nullptr)) {
738         PROFILER_LOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, pathDir.c_str(), errno);
739         return {false, ""};
740     }
741     if (access(pathDir.c_str(), F_OK) != 0) {
742         PROFILER_LOG_ERROR(LOG_CORE, "%s:Fail to access path: %s", __func__, pathDir.c_str());
743         return {false, ""};
744     }
745     return {true, std::string(pathDirRealPath.get()) + "/" + filePath.substr(pos + 1)};
746 }
747 
CheckWhiteList(const std::string& cmdPath)748 bool CheckWhiteList(const std::string& cmdPath)
749 {
750     if (cmdPath.empty()) {
751         PROFILER_LOG_ERROR(LOG_CORE, "cmd is empty {%s}", __func__);
752         return false;
753     }
754 
755     if (CMD_WHITE_LIST.find(cmdPath) == CMD_WHITE_LIST.end() ||
756         cmdPath.find_first_of("|;&${}<>'\\!\n~?*%[]^") != std::string::npos) {
757         PROFILER_LOG_ERROR(LOG_CORE, "cmd %s:is illegal {%s}", cmdPath.c_str(), __func__);
758         return false;
759     }
760     return true;
761 }
762 
CheckCmdLineArgValid(const std::string& cmdLine)763 bool CheckCmdLineArgValid(const std::string& cmdLine)
764 {
765     if (cmdLine.empty()) {
766         PROFILER_LOG_ERROR(LOG_CORE, "cmdLine is empty {%s}", __func__);
767         return false;
768     }
769 
770     if (cmdLine.find_first_of("|;&${}<>'\\!\n~?*%[]^") != std::string::npos) {
771         PROFILER_LOG_ERROR(LOG_CORE, "cmdLine %s is illegal {%s}", cmdLine.c_str(), __func__);
772         return false;
773     }
774     return true;
775 }
776 } // namespace COMMON
777