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