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