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