• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "faultlogger.h"
16 
17 #include <climits>
18 #include <cstdint>
19 #include <ctime>
20 #ifdef UNIT_TEST
21 #include <fstream>
22 #include <iostream>
23 #include <cstring>
24 #endif
25 #include <memory>
26 #include <regex>
27 #include <string>
28 #include <vector>
29 #include <fstream>
30 
31 #include <fcntl.h>
32 #include <sys/stat.h>
33 #include <sys/syscall.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 
37 #include <cerrno>
38 #include <future>
39 #include <thread>
40 #include <unistd.h>
41 #include <sys/select.h>
42 
43 #include "accesstoken_kit.h"
44 #include "bundle_mgr_client.h"
45 #include "common_utils.h"
46 #include "constants.h"
47 #include "crash_exception.h"
48 #include "event.h"
49 #include "event_publish.h"
50 #include "faultlog_formatter.h"
51 #include "faultlog_info.h"
52 #include "faultlog_query_result_inner.h"
53 #include "faultlog_util.h"
54 #include "faultlogger_adapter.h"
55 #include "ffrt.h"
56 #include "file_util.h"
57 #include "hisysevent.h"
58 #include "hiview_global.h"
59 #include "ipc_skeleton.h"
60 #include "json/json.h"
61 #include "log_analyzer.h"
62 #include "hiview_logger.h"
63 #include "parameter_ex.h"
64 #include "plugin_factory.h"
65 #include "process_status.h"
66 #include "securec.h"
67 #include "string_util.h"
68 #include "sys_event_dao.h"
69 #include "time_util.h"
70 #include "dfx_bundle_util.h"
71 #include "freeze_json_generator.h"
72 #include "freeze_json_util.h"
73 
74 namespace OHOS {
75 namespace HiviewDFX {
76 REGISTER(Faultlogger);
77 DEFINE_LOG_LABEL(0xD002D11, "Faultlogger");
78 using namespace FaultLogger;
79 using namespace OHOS::AppExecFwk;
80 namespace {
81 constexpr char FILE_SEPERATOR[] = "******";
82 constexpr uint32_t MAX_TIMESTR_LEN = 256;
83 constexpr uint32_t DUMP_MAX_NUM = 100;
84 constexpr int32_t MAX_QUERY_NUM = 100;
85 constexpr int MIN_APP_UID = 10000;
86 constexpr int DUMP_PARSE_CMD = 0;
87 constexpr int DUMP_PARSE_FILE_NAME = 1;
88 constexpr int DUMP_PARSE_TIME = 2;
89 constexpr int DUMP_START_PARSE_MODULE_NAME = 3;
90 constexpr uint32_t MAX_NAME_LENGTH = 4096;
91 constexpr char TEMP_LOG_PATH[] = "/data/log/faultlog/temp";
92 constexpr time_t FORTYEIGHT_HOURS = 48 * 60 * 60;
93 constexpr int READ_HILOG_BUFFER_SIZE = 1024;
94 constexpr char APP_CRASH_TYPE[] = "APP_CRASH";
95 constexpr char APP_FREEZE_TYPE[] = "APP_FREEZE";
96 constexpr char APP_HICOLLIE_TYPE[] = "APP_HICOLLIE";
97 constexpr char LIFECYCLE_TIMEOUT[] = "LIFECYCLE_TIMEOUT";
98 constexpr int REPORT_HILOG_LINE = 100;
99 constexpr const char STACK_ERROR_MESSAGE[] = "Cannot get SourceMap info, dump raw stack:";
InitDumpRequest()100 DumpRequest InitDumpRequest()
101 {
102     DumpRequest request;
103     request.requestDetail = false;
104     request.requestList = false;
105     request.fileName = "";
106     request.moduleName = "";
107     request.time = -1;
108     request.compatFlag = false;
109     return request;
110 }
111 
IsLogNameValid(const std::string & name)112 bool IsLogNameValid(const std::string& name)
113 {
114     const int32_t idxOfType = 0;
115     const int32_t idxOfMoudle = 1;
116     const int32_t idxOfUid = 2;
117     const int32_t idxOfTime = 3;
118     const int32_t expectedVecSize = 4;
119     const size_t tailWithMillSecLen = 7u;
120     if (name.empty() || name.size() > MAX_NAME_LENGTH) {
121         HIVIEW_LOGI("invalid log name.");
122         return false;
123     }
124 
125     std::vector<std::string> out;
126     StringUtil::SplitStr(name, "-", out, true, false);
127     if (out.size() != expectedVecSize) {
128         return false;
129     }
130 
131     std::regex reType("^[a-z]+$");
132     if (!std::regex_match(out[idxOfType], reType)) {
133         HIVIEW_LOGI("invalid type.");
134         return false;
135     }
136 
137     if (!IsModuleNameValid(out[idxOfMoudle])) {
138         HIVIEW_LOGI("invalid module name.");
139         return false;
140     }
141 
142     std::regex reDigits("^[0-9]*$");
143     if (!std::regex_match(out[idxOfUid], reDigits)) {
144         HIVIEW_LOGI("invalid uid.");
145         return false;
146     }
147 
148     if (StringUtil::EndWith(out[idxOfTime], ".log") && out[idxOfTime].length() > tailWithMillSecLen) {
149         out[idxOfTime] = out[idxOfTime].substr(0, out[idxOfTime].length() - tailWithMillSecLen);
150     }
151 
152     if (!std::regex_match(out[idxOfTime], reDigits)) {
153         HIVIEW_LOGI("invalid digits.");
154         return false;
155     }
156     return true;
157 }
158 
FillDumpRequest(DumpRequest & request,int status,const std::string & item)159 bool FillDumpRequest(DumpRequest &request, int status, const std::string &item)
160 {
161     switch (status) {
162         case DUMP_PARSE_FILE_NAME:
163             if (!IsLogNameValid(item)) {
164                 return false;
165             }
166             request.fileName = item;
167             break;
168         case DUMP_PARSE_TIME:
169             if (item.size() == 14) { // 14 : BCD time size
170                 request.time = TimeUtil::StrToTimeStamp(item, "%Y%m%d%H%M%S");
171             } else {
172                 StringUtil::ConvertStringTo<time_t>(item, request.time);
173             }
174             break;
175         case DUMP_START_PARSE_MODULE_NAME:
176             if (!IsModuleNameValid(item)) {
177                 return false;
178             }
179             request.moduleName = item;
180             break;
181         default:
182             HIVIEW_LOGI("Unknown status.");
183             break;
184     }
185     return true;
186 }
187 
GetSummaryFromSectionMap(int32_t type,const std::map<std::string,std::string> & maps)188 std::string GetSummaryFromSectionMap(int32_t type, const std::map<std::string, std::string>& maps)
189 {
190     std::string key = "";
191     switch (type) {
192         case CPP_CRASH:
193             key = "KEY_THREAD_INFO";
194             break;
195         default:
196             break;
197     }
198 
199     if (key.empty()) {
200         return "";
201     }
202 
203     auto value = maps.find(key);
204     if (value == maps.end()) {
205         return "";
206     }
207     return value->second;
208 }
209 
ParseJsErrorSummary(std::string & summary,std::string & name,std::string & message,std::string & stack)210 void ParseJsErrorSummary(std::string& summary, std::string& name, std::string& message, std::string& stack)
211 {
212     std::string leftStr = StringUtil::GetLeftSubstr(summary, "Error message:");
213     std::string rightStr = StringUtil::GetRightSubstr(summary, "Error message:");
214     name = StringUtil::GetRightSubstr(leftStr, "Error name:");
215     stack = StringUtil::GetRightSubstr(rightStr, "Stacktrace:");
216     leftStr = StringUtil::GetLeftSubstr(rightStr, "Stacktrace:");
217     do {
218         if (leftStr.find("Error code:") != std::string::npos) {
219             leftStr = StringUtil::GetLeftSubstr(leftStr, "Error code:");
220             break;
221         }
222         if (leftStr.find("SourceCode:") != std::string::npos) {
223             leftStr = StringUtil::GetLeftSubstr(leftStr, "SourceCode:");
224             break;
225         }
226     } while (false);
227     message = leftStr;
228 }
229 
FillJsErrorParams(std::string summary,Json::Value & params)230 void FillJsErrorParams(std::string summary, Json::Value &params)
231 {
232     Json::Value exception;
233     std::string name = "";
234     std::string message = "";
235     std::string stack = "";
236     do {
237         if (summary == "") {
238             break;
239         }
240         ParseJsErrorSummary(summary, name, message, stack);
241         name.erase(name.find_last_not_of("\n") + 1);
242         message.erase(message.find_last_not_of("\n") + 1);
243         if (stack.size() > 1) {
244             stack.erase(0, 1);
245             if ((stack.size() >= strlen(STACK_ERROR_MESSAGE)) &&
246                 (strcmp(STACK_ERROR_MESSAGE, stack.substr(0, strlen(STACK_ERROR_MESSAGE)).c_str()) == 0)) {
247                 stack.erase(0, strlen(STACK_ERROR_MESSAGE) + 1);
248             }
249         }
250     } while (false);
251     exception["name"] = name;
252     exception["message"] = message;
253     exception["stack"] = stack;
254     params["exception"] = exception;
255 }
256 
IsSystemProcess(const std::string & processName,int32_t uid)257 static bool IsSystemProcess(const std::string &processName, int32_t uid)
258 {
259     std::string sysBin = "/system/bin";
260     std::string venBin = "/vendor/bin";
261     return (uid < MIN_APP_USERID ||
262             (processName.compare(0, sysBin.length(), sysBin) == 0) ||
263             (processName.compare(0, venBin.length(), venBin) == 0));
264 }
265 
ProcessKernelSnapshot(FaultLogInfo & info)266 void ProcessKernelSnapshot(FaultLogInfo& info)
267 {
268     if (info.reason.find("CppCrashKernelSnapshot") == std::string::npos) {
269         return;
270     }
271 
272     info.dumpLogToFautlogger = false;
273     info.reportToAppEvent = false;
274     info.logPath = GetCppCrashTempLogName(info);
275 }
276 } // namespace
277 
278 class Faultlogger::FaultloggerListener : public EventListener {
279 public:
280     explicit FaultloggerListener(Faultlogger& faultlogger);
~FaultloggerListener()281     ~FaultloggerListener() {}
282     void OnUnorderedEvent(const Event &msg) override;
283     std::string GetListenerName() override;
284 
285 private:
286     Faultlogger& faultlogger_;
287 };
288 
AddPublicInfo(FaultLogInfo & info)289 void Faultlogger::AddPublicInfo(FaultLogInfo &info)
290 {
291     info.sectionMap["DEVICE_INFO"] = Parameter::GetString("const.product.name", "Unknown");
292     if (info.sectionMap.find("BUILD_INFO") == info.sectionMap.end()) {
293         info.sectionMap["BUILD_INFO"] = Parameter::GetString("const.product.software.version", "Unknown");
294     }
295     info.sectionMap["UID"] = std::to_string(info.id);
296     info.sectionMap["PID"] = std::to_string(info.pid);
297     info.module = RegulateModuleNameIfNeed(info.module);
298     info.sectionMap["MODULE"] = info.module;
299     AddBundleInfo(info);
300     AddForegroundInfo(info);
301 
302     if (info.reason.empty()) {
303         info.reason = info.sectionMap["REASON"];
304     } else {
305         info.sectionMap["REASON"] = info.reason;
306     }
307 
308     if (info.summary.empty()) {
309         info.summary = GetSummaryFromSectionMap(info.faultLogType, info.sectionMap);
310     } else {
311         info.sectionMap["SUMMARY"] = info.summary;
312     }
313 
314     UpdateTerminalThreadStack(info);
315 
316     // parse fingerprint by summary or temp log for native crash
317     AnalysisFaultlog(info, info.parsedLogInfo);
318     info.sectionMap.insert(info.parsedLogInfo.begin(), info.parsedLogInfo.end());
319     info.parsedLogInfo.clear();
320 }
321 
AddBundleInfo(FaultLogInfo & info)322 void Faultlogger::AddBundleInfo(FaultLogInfo& info)
323 {
324     DfxBundleInfo bundleInfo;
325     if (info.id < MIN_APP_USERID || !GetDfxBundleInfo(info.module, bundleInfo)) {
326         return;
327     }
328 
329     if (!bundleInfo.versionName.empty()) {
330         info.sectionMap["VERSION"] = bundleInfo.versionName;
331         info.sectionMap["VERSION_CODE"] = std::to_string(bundleInfo.versionCode);
332     }
333 
334     info.sectionMap["PRE_INSTALL"] = bundleInfo.isPreInstalled ? "Yes" : "No";
335 }
336 
AddForegroundInfo(FaultLogInfo & info)337 void Faultlogger::AddForegroundInfo(FaultLogInfo& info)
338 {
339     if (!info.sectionMap["FOREGROUND"].empty() || info.id < MIN_APP_USERID) {
340         return;
341     }
342 
343     if (UCollectUtil::ProcessStatus::GetInstance().GetProcessState(info.pid) == UCollectUtil::FOREGROUND) {
344         info.sectionMap["FOREGROUND"] = "Yes";
345     } else if (UCollectUtil::ProcessStatus::GetInstance().GetProcessState(info.pid) == UCollectUtil::BACKGROUND) {
346         int64_t lastFgTime = static_cast<int64_t>(UCollectUtil::ProcessStatus::GetInstance()
347                                                   .GetProcessLastForegroundTime(info.pid));
348         info.sectionMap["FOREGROUND"] = lastFgTime > info.time ? "Yes" : "No";
349     }
350 }
351 
UpdateTerminalThreadStack(FaultLogInfo & info)352 void Faultlogger::UpdateTerminalThreadStack(FaultLogInfo& info)
353 {
354     if (info.sectionMap.count("TERMINAL_THREAD_STACK") == 0) {
355         return;
356     }
357     auto threadStack = info.sectionMap["TERMINAL_THREAD_STACK"];
358     if (threadStack.empty()) {
359         return;
360     }
361     // Replace the '\n' in the string with a line break character
362     info.parsedLogInfo["TERMINAL_THREAD_STACK"] = StringUtil::ReplaceStr(threadStack, "\\n", "\n");
363 }
364 
AddCppCrashInfo(FaultLogInfo & info)365 void Faultlogger::AddCppCrashInfo(FaultLogInfo& info)
366 {
367     if (!info.registers.empty()) {
368         info.sectionMap["KEY_THREAD_REGISTERS"] = info.registers;
369     }
370 
371     info.sectionMap["APPEND_ORIGIN_LOG"] = GetCppCrashTempLogName(info);
372 
373     std::string log;
374     GetHilog(info.pid, log);
375     info.sectionMap["HILOG"] = log;
376 }
377 
AddDebugSignalInfo(FaultLogInfo & info) const378 void Faultlogger::AddDebugSignalInfo(FaultLogInfo& info) const
379 {
380     info.reportToAppEvent = false;
381     info.dumpLogToFautlogger = false;
382     info.logPath = GetDebugSignalTempLogName(info);
383 }
384 
VerifiedDumpPermission()385 bool Faultlogger::VerifiedDumpPermission()
386 {
387     using namespace Security::AccessToken;
388     auto tokenId = IPCSkeleton::GetCallingTokenID();
389     if (AccessTokenKit::VerifyAccessToken(tokenId, "ohos.permission.DUMP") != PermissionState::PERMISSION_GRANTED) {
390         return false;
391     }
392     return true;
393 }
394 
Dump(int fd,const std::vector<std::string> & cmds)395 void Faultlogger::Dump(int fd, const std::vector<std::string> &cmds)
396 {
397     if (!VerifiedDumpPermission()) {
398         dprintf(fd, "dump operation is not permitted.\n");
399         return;
400     }
401     auto request = InitDumpRequest();
402     int32_t status = DUMP_PARSE_CMD;
403     for (auto it = cmds.begin(); it != cmds.end(); it++) {
404         if ((*it) == "-f") {
405             status = DUMP_PARSE_FILE_NAME;
406             continue;
407         } else if ((*it) == "-l") {
408             request.requestList = true;
409             continue;
410         } else if ((*it) == "-t") {
411             status = DUMP_PARSE_TIME;
412             continue;
413         } else if ((*it) == "-m") {
414             status = DUMP_START_PARSE_MODULE_NAME;
415             continue;
416         } else if ((*it) == "-d") {
417             request.requestDetail = true;
418             continue;
419         } else if ((*it) == "Faultlogger") {
420             // skip first params
421             request.compatFlag = true;
422             continue;
423         } else if ((*it) == "-LogSuffixWithMs") {
424             // skip first params
425             request.compatFlag = false;
426             continue;
427         } else if ((!(*it).empty()) && ((*it).at(0) == '-')) {
428             dprintf(fd, "Unknown command.\n");
429             return;
430         }
431 
432         if (!FillDumpRequest(request, status, *it)) {
433             dprintf(fd, "invalid parameters.\n");
434             return;
435         }
436         status = DUMP_PARSE_CMD;
437     }
438 
439     if (status != DUMP_PARSE_CMD) {
440         dprintf(fd, "empty parameters.\n");
441         return;
442     }
443 
444     HIVIEW_LOGI("DumpRequest: detail:%d, list:%d, file:%s, name:%s, time:%lld",
445         request.requestDetail, request.requestList, request.fileName.c_str(), request.moduleName.c_str(),
446         static_cast<long long>(request.time));
447     Dump(fd, request);
448 }
449 
Dump(int fd,const DumpRequest & request) const450 void Faultlogger::Dump(int fd, const DumpRequest &request) const
451 {
452     if (!request.fileName.empty()) {
453         std::string content;
454         if (mgr_->GetFaultLogContent(request.fileName, content)) {
455             dprintf(fd, "%s\n", content.c_str());
456         } else {
457             dprintf(fd, "Fail to dump the log.\n");
458         }
459         return;
460     }
461     auto fileList = mgr_->GetFaultLogFileList(request.moduleName, request.time, -1, 0, DUMP_MAX_NUM);
462     if (fileList.empty()) {
463         dprintf(fd, "No fault log exist.\n");
464         return;
465     }
466     dprintf(fd, "Fault log list:\n");
467     dprintf(fd, "%s\n", FILE_SEPERATOR);
468     std::map<std::string, std::string> fileNameMap;
469     const size_t tailWithMillsecLen = 7;
470     for (auto &file : fileList) {
471         std::string fileName = FileUtil::ExtractFileName(file);
472         if (fileName.length() <= tailWithMillsecLen) {
473             continue;
474         }
475         if (!request.compatFlag && StringUtil::EndWith(fileName, ".log") == false) {
476             continue;
477         } else if (request.compatFlag && StringUtil::EndWith(fileName, ".log")) {
478             if (fileNameMap[fileName.substr(0, fileName.length() - tailWithMillsecLen)].compare(fileName) < 0) {
479                 fileNameMap[fileName.substr(0, fileName.length() - tailWithMillsecLen)] = fileName;
480             }
481             continue;
482         }
483         fileNameMap[fileName] = fileName;
484     }
485     for (auto it = fileNameMap.begin(); it != fileNameMap.end(); ++it) {
486         dprintf(fd, "%s\n", it->first.c_str());
487         if (request.requestDetail) {
488             std::string content;
489             std::string fullFileName = "/data/log/faultlog/faultlogger/" + it->second;
490             if (FileUtil::LoadStringFromFile(fullFileName, content)) {
491                 dprintf(fd, "%s\n", content.c_str());
492             } else {
493                 dprintf(fd, "Fail to dump detail log.\n");
494             }
495             dprintf(fd, "%s\n", FILE_SEPERATOR);
496         }
497     }
498     dprintf(fd, "%s\n", FILE_SEPERATOR);
499 }
500 
JudgmentRateLimiting(std::shared_ptr<Event> event)501 bool Faultlogger::JudgmentRateLimiting(std::shared_ptr<Event> event)
502 {
503     int interval = 60; // 60s time interval
504     auto sysEvent = std::static_pointer_cast<SysEvent>(event);
505     long pid = sysEvent->GetPid();
506     std::string eventPid = std::to_string(pid);
507 
508     std::time_t now = std::time(nullptr);
509     for (auto it = eventTagTime_.begin(); it != eventTagTime_.end();) {
510         if ((now - it->second) >= interval) {
511             it = eventTagTime_.erase(it);
512             continue;
513         }
514         ++it;
515     }
516 
517     auto it = eventTagTime_.find(eventPid);
518     if (it != eventTagTime_.end()) {
519         if ((now - it->second) < interval) {
520             HIVIEW_LOGW("event: id:0x%{public}d, eventName:%{public}s pid:%{public}s. \
521                 interval:%{public}d There's not enough interval",
522                 sysEvent->eventId_, sysEvent->eventName_.c_str(), eventPid.c_str(), interval);
523             return false;
524         }
525     }
526     eventTagTime_[eventPid] = now;
527     HIVIEW_LOGI("event: id:0x%{public}d, eventName:%{public}s pid:%{public}s. \
528         interval:%{public}d normal interval",
529         sysEvent->eventId_, sysEvent->eventName_.c_str(), eventPid.c_str(), interval);
530     return true;
531 }
532 
IsInterestedPipelineEvent(std::shared_ptr<Event> event)533 bool Faultlogger::IsInterestedPipelineEvent(std::shared_ptr<Event> event)
534 {
535     if (!hasInit_ || event == nullptr) {
536         return false;
537     }
538 
539     if (event->eventName_ != "PROCESS_EXIT" &&
540         event->eventName_ != "JS_ERROR" &&
541         event->eventName_ != "CJ_ERROR" &&
542         event->eventName_ != "RUST_PANIC"  &&
543         event->eventName_ != "ADDR_SANITIZER") {
544         return false;
545     }
546 
547     return true;
548 }
549 
IsDebugSignal(const FaultLogInfo & info)550 static bool IsDebugSignal(const FaultLogInfo& info)
551 {
552     return info.faultLogType == FaultLogType::ADDR_SANITIZER && info.reason.find("DEBUG SIGNAL") != std::string::npos;
553 }
554 
FillFaultLogInfo(SysEvent & sysEvent) const555 FaultLogInfo Faultlogger::FillFaultLogInfo(SysEvent &sysEvent) const
556 {
557     FaultLogInfo info;
558     info.time = static_cast<int64_t>(sysEvent.happenTime_);
559     info.id = sysEvent.GetUid();
560     info.pid = sysEvent.GetPid();
561     if (sysEvent.eventName_ == "JS_ERROR") {
562         info.faultLogType = FaultLogType::JS_CRASH;
563     } else if (sysEvent.eventName_ == "CJ_ERROR") {
564         info.faultLogType = FaultLogType::CJ_ERROR;
565     } else if (sysEvent.eventName_ == "RUST_PANIC") {
566         info.faultLogType = FaultLogType::RUST_PANIC;
567     } else {
568         info.faultLogType = FaultLogType::ADDR_SANITIZER;
569     }
570     if (info.faultLogType == FaultLogType::JS_CRASH || info.faultLogType == FaultLogType::CJ_ERROR) {
571         info.module = sysEvent.GetEventValue("PACKAGE_NAME");
572     } else {
573         info.module = sysEvent.GetEventValue("MODULE");
574     }
575     info.reason = sysEvent.GetEventValue("REASON");
576     auto summary = sysEvent.GetEventValue("SUMMARY");
577     if (info.faultLogType == FaultLogType::ADDR_SANITIZER) {
578         if (info.reason.find("DEBUG SIGNAL") != std::string::npos) {
579             info.pid = sysEvent.GetEventIntValue("PID");
580             info.time = sysEvent.GetEventIntValue("HAPPEN_TIME");
581             AddDebugSignalInfo(info);
582         } else {
583             info.sanitizerType = sysEvent.GetEventValue("FAULT_TYPE");
584             info.logPath = GetSanitizerTempLogName(info.pid, sysEvent.GetEventIntValue("HAPPEN_TIME"));
585             summary = "";
586         }
587     }
588     info.summary = StringUtil::UnescapeJsonStringValue(summary);
589     info.sectionMap = sysEvent.GetKeyValuePairs();
590     uint64_t secTime = sysEvent.happenTime_ / TimeUtil::SEC_TO_MILLISEC;
591     char strBuff[MAX_TIMESTR_LEN] = {0};
592     if (snprintf_s(strBuff, sizeof(strBuff), sizeof(strBuff) - 1, "%s.%03lu",
593             TimeUtil::TimestampFormatToDate(secTime, "%Y-%m-%d %H:%M:%S").c_str(),
594             sysEvent.happenTime_ % TimeUtil::SEC_TO_MILLISEC) < 0) {
595         HIVIEW_LOGE("fill faultlog info timestamp snprintf fail!");
596         info.sectionMap["TIMESTAMP"] = "1970-01-01 00:00:00.000";
597     } else {
598         info.sectionMap["TIMESTAMP"] = std::string(strBuff);
599     }
600     HIVIEW_LOGI("eventName:%{public}s, time %{public}" PRId64 ", uid %{public}d, pid %{public}d, "
601                 "module: %{public}s, reason: %{public}s",
602                 sysEvent.eventName_.c_str(), info.time, info.id, info.pid,
603                 info.module.c_str(), info.reason.c_str());
604     return info;
605 }
606 
UpdateSysEvent(SysEvent & sysEvent,FaultLogInfo & info)607 static void UpdateSysEvent(SysEvent &sysEvent, FaultLogInfo &info)
608 {
609     sysEvent.SetEventValue("FAULT_TYPE", std::to_string(info.faultLogType));
610     sysEvent.SetEventValue("MODULE", info.module);
611     sysEvent.SetEventValue("LOG_PATH", info.logPath);
612     // DEBUG SIGNAL does not need to update HAPPEN_TIME
613     if (!IsDebugSignal(info)) {
614         sysEvent.SetEventValue("HAPPEN_TIME", sysEvent.happenTime_);
615     }
616     sysEvent.SetEventValue("tz_", TimeUtil::GetTimeZone());
617     sysEvent.SetEventValue("VERSION", info.sectionMap["VERSION"]);
618     sysEvent.SetEventValue("VERSION_CODE", info.sectionMap["VERSION_CODE"]);
619     sysEvent.SetEventValue("PRE_INSTALL", info.sectionMap["PRE_INSTALL"]);
620     sysEvent.SetEventValue("FOREGROUND", info.sectionMap["FOREGROUND"]);
621     std::map<std::string, std::string> eventInfos;
622     if (AnalysisFaultlog(info, eventInfos)) {
623         auto pName = sysEvent.GetEventValue("PNAME");
624         if (pName.empty()) {
625             sysEvent.SetEventValue("PNAME", std::string("/"));
626         }
627         sysEvent.SetEventValue("FIRST_FRAME", eventInfos["FIRST_FRAME"].empty() ? "/" :
628                                 StringUtil::EscapeJsonStringValue(eventInfos["FIRST_FRAME"]));
629         sysEvent.SetEventValue("SECOND_FRAME", eventInfos["SECOND_FRAME"].empty() ? "/" :
630                                 StringUtil::EscapeJsonStringValue(eventInfos["SECOND_FRAME"]));
631         sysEvent.SetEventValue("LAST_FRAME", eventInfos["LAST_FRAME"].empty() ? "/" :
632                                 StringUtil::EscapeJsonStringValue(eventInfos["LAST_FRAME"]));
633     }
634     std::string fingerPrint;
635     if (info.faultLogType == FaultLogType::ADDR_SANITIZER) {
636         fingerPrint = sysEvent.GetEventValue("FINGERPRINT");
637     }
638     if (fingerPrint.empty()) {
639         sysEvent.SetEventValue("FINGERPRINT", eventInfos["FINGERPRINT"]);
640     }
641 }
642 
OnEvent(std::shared_ptr<Event> & event)643 bool Faultlogger::OnEvent(std::shared_ptr<Event> &event)
644 {
645     if (!hasInit_ || event == nullptr) {
646         return false;
647     }
648     if (event->eventName_ != "JS_ERROR" && event->eventName_ != "CJ_ERROR" && event->eventName_ != "RUST_PANIC"
649         && event->eventName_ != "ADDR_SANITIZER") {
650         return true;
651     }
652     if (event->rawData_ == nullptr) {
653         return false;
654     }
655     auto sysEvent = std::static_pointer_cast<SysEvent>(event);
656     FaultLogInfo info = FillFaultLogInfo(*sysEvent);
657     AddFaultLog(info);
658     UpdateSysEvent(*sysEvent, info);
659     if (!info.reportToAppEvent) {
660         return true;
661     }
662     if (info.faultLogType == FaultLogType::JS_CRASH || info.faultLogType == FaultLogType::CJ_ERROR) {
663         ReportJsOrCjErrorToAppEvent(sysEvent, static_cast<FaultLogType>(info.faultLogType));
664     }
665     // DEBUG FD is used for debugging and is not reported to the application.
666     // The kernel writes a special reason field to prevent reporting.
667     if (info.faultLogType == FaultLogType::ADDR_SANITIZER) {
668         ReportSanitizerToAppEvent(sysEvent);
669     }
670     return true;
671 }
672 
CanProcessEvent(std::shared_ptr<Event> event)673 bool Faultlogger::CanProcessEvent(std::shared_ptr<Event> event)
674 {
675     return true;
676 }
677 
FillHilog(const std::string & hilogStr,Json::Value & hilog) const678 void Faultlogger::FillHilog(const std::string &hilogStr, Json::Value &hilog) const
679 {
680     if (hilogStr.empty()) {
681         HIVIEW_LOGE("Get hilog is empty");
682         return;
683     }
684     std::stringstream logStream(hilogStr);
685     std::string oneLine;
686     for (int count = 0; count < REPORT_HILOG_LINE && getline(logStream, oneLine); count++) {
687         hilog.append(oneLine);
688     }
689 }
690 
ReportJsOrCjErrorToAppEvent(std::shared_ptr<SysEvent> sysEvent,FaultLogType faultType) const691 void Faultlogger::ReportJsOrCjErrorToAppEvent(std::shared_ptr<SysEvent> sysEvent, FaultLogType faultType) const
692 {
693     std::string summary = StringUtil::UnescapeJsonStringValue(sysEvent->GetEventValue("SUMMARY"));
694     HIVIEW_LOGD("ReportAppEvent:summary:%{public}s.", summary.c_str());
695 
696     Json::Value params;
697     params["time"] = sysEvent->happenTime_;
698     if (faultType == FaultLogType::JS_CRASH) {
699         params["crash_type"] = "JsError";
700     } else {
701         params["crash_type"] = "CjError";
702     }
703     std::string foreground = sysEvent->GetEventValue("FOREGROUND");
704     params["foreground"] = (foreground == "Yes") ? true : false;
705     Json::Value externalLog(Json::arrayValue);
706     std::string logPath = sysEvent->GetEventValue("LOG_PATH");
707     if (!logPath.empty()) {
708         externalLog.append(logPath);
709     }
710     params["external_log"] = externalLog;
711     params["bundle_version"] = sysEvent->GetEventValue("VERSION");
712     params["bundle_name"] = sysEvent->GetEventValue("PACKAGE_NAME");
713     params["pid"] = sysEvent->GetPid();
714     params["uid"] = sysEvent->GetUid();
715     params["uuid"] = sysEvent->GetEventValue("FINGERPRINT");
716     params["app_running_unique_id"] = sysEvent->GetEventValue("APP_RUNNING_UNIQUE_ID");
717     FillJsErrorParams(summary, params);
718     std::string log;
719     Json::Value hilog(Json::arrayValue);
720     GetHilog(sysEvent->GetPid(), log);
721     FillHilog(log, hilog);
722     params["hilog"] = hilog;
723     std::string paramsStr = Json::FastWriter().write(params);
724     HIVIEW_LOGD("ReportAppEvent: uid:%{public}d, json:%{public}s.",
725         sysEvent->GetUid(), paramsStr.c_str());
726 #ifdef UNITTEST
727     std::string outputFilePath = (faultType == FaultLogType::JS_CRASH) ?
728         "/data/test_jsError_info" : "/data/test_cjError_info";
729     if (!FileUtil::FileExists(outputFilePath)) {
730         int fd = TEMP_FAILURE_RETRY(open(outputFilePath.c_str(), O_CREAT | O_RDWR | O_APPEND, DEFAULT_LOG_FILE_MODE));
731         if (fd != -1) {
732             close(fd);
733         }
734     }
735     FileUtil::SaveStringToFile(outputFilePath, paramsStr, false);
736 #else
737     EventPublish::GetInstance().PushEvent(sysEvent->GetUid(), APP_CRASH_TYPE, HiSysEvent::EventType::FAULT, paramsStr);
738 #endif
739 }
740 
ReportSanitizerToAppEvent(std::shared_ptr<SysEvent> sysEvent) const741 void Faultlogger::ReportSanitizerToAppEvent(std::shared_ptr<SysEvent> sysEvent) const
742 {
743     std::string summary = StringUtil::UnescapeJsonStringValue(sysEvent->GetEventValue("SUMMARY"));
744     HIVIEW_LOGD("ReportSanitizerAppEvent:summary:%{public}s.", summary.c_str());
745 
746     Json::Value params;
747     params["time"] = sysEvent->happenTime_;
748     params["type"] = sysEvent->GetEventValue("REASON");
749     Json::Value externalLog(Json::arrayValue);
750     std::string logPath = sysEvent->GetEventValue("LOG_PATH");
751     if (!logPath.empty()) {
752         externalLog.append(logPath);
753     }
754     params["external_log"] = externalLog;
755     params["bundle_version"] = sysEvent->GetEventValue("VERSION");
756     params["bundle_name"] = sysEvent->GetEventValue("MODULE");
757     params["pid"] = sysEvent->GetPid();
758     params["uid"] = sysEvent->GetUid();
759     std::string paramsStr = Json::FastWriter().write(params);
760     HIVIEW_LOGD("ReportSanitizerAppEvent: uid:%{public}d, json:%{public}s.",
761         sysEvent->GetUid(), paramsStr.c_str());
762     EventPublish::GetInstance().PushEvent(sysEvent->GetUid(), "ADDRESS_SANITIZER",
763         HiSysEvent::EventType::FAULT, paramsStr);
764 }
765 
ReadyToLoad()766 bool Faultlogger::ReadyToLoad()
767 {
768     return true;
769 }
770 
OnLoad()771 void Faultlogger::OnLoad()
772 {
773     auto context = GetHiviewContext();
774     if (context == nullptr) {
775         HIVIEW_LOGE("GetHiviewContext failed.");
776         return;
777     }
778     mgr_ = std::make_unique<FaultLogManager>(context->GetSharedWorkLoop());
779     mgr_->Init();
780     hasInit_ = true;
781     workLoop_ = context->GetSharedWorkLoop();
782 #ifndef UNITTEST
783     FaultloggerAdapter::StartService(this);
784 
785     eventListener_ = std::make_shared<FaultloggerListener>(*this);
786     context->RegisterUnorderedEventListener(eventListener_);
787 #endif
788 }
789 
AddFaultLog(FaultLogInfo & info)790 void Faultlogger::AddFaultLog(FaultLogInfo& info)
791 {
792     if (!hasInit_) {
793         return;
794     }
795 
796     if ((info.faultLogType <= FaultLogType::ALL) || (info.faultLogType > FaultLogType::CJ_ERROR)) {
797         HIVIEW_LOGW("Unsupported fault type");
798         return;
799     }
800 
801     if (info.reason.find("CppCrashKernelSnapshot") != std::string::npos) {
802         HIVIEW_LOGI("Skip cpp crash kernel snapshot fault %{public}d", info.pid);
803         return;
804     }
805 
806     AddFaultLogIfNeed(info, nullptr);
807 }
808 
QuerySelfFaultLog(int32_t id,int32_t pid,int32_t faultType,int32_t maxNum)809 std::unique_ptr<FaultLogQueryResultInner> Faultlogger::QuerySelfFaultLog(int32_t id,
810     int32_t pid, int32_t faultType, int32_t maxNum)
811 {
812     if (!hasInit_) {
813         return nullptr;
814     }
815 
816     if ((faultType < FaultLogType::ALL) || (faultType > FaultLogType::APP_FREEZE)) {
817         HIVIEW_LOGW("Unsupported fault type");
818         return nullptr;
819     }
820 
821     if (maxNum < 0 || maxNum > MAX_QUERY_NUM) {
822         maxNum = MAX_QUERY_NUM;
823     }
824 
825     std::string name = "";
826     if (id >= MIN_APP_UID) {
827         name = GetApplicationNameById(id);
828     }
829 
830     if (name.empty()) {
831         name = CommonUtils::GetProcNameByPid(pid);
832     }
833     return std::make_unique<FaultLogQueryResultInner>(mgr_->GetFaultInfoList(name, id, faultType, maxNum));
834 }
835 
FaultlogLimit(const std::string & logPath,int32_t faultType) const836 void Faultlogger::FaultlogLimit(const std::string &logPath, int32_t faultType) const
837 {
838     std::ifstream logReadFile(logPath);
839     std::string readContent(std::istreambuf_iterator<char>(logReadFile), (std::istreambuf_iterator<char>()));
840     bool modified = false;
841     if (faultType == FaultLogType::CPP_CRASH) {
842         size_t pos = readContent.find("HiLog:");
843         if (pos == std::string::npos) {
844             HIVIEW_LOGW("No Hilog Found In Crash Log");
845         } else {
846             readContent.resize(pos);
847             modified = true;
848         }
849         // The CppCrash file size is limited to 1 MB after reporting CppCrash to AppEvent
850         constexpr size_t maxLogSize = 1024 * 1024;
851         auto fileLen = readContent.length();
852         if (fileLen > maxLogSize) {
853             readContent.resize(maxLogSize);
854             readContent += "\nThe cpp crash log length is " + std::to_string(fileLen) +
855                 ", which exceeesd the limit of " + std::to_string(maxLogSize) + " and is truncated.\n";
856             modified = true;
857         }
858     }
859 
860     if (modified) {
861         std::ofstream logWriteFile(logPath);
862         logWriteFile << readContent;
863         logWriteFile.close();
864     }
865 }
866 
AddFaultLogIfNeed(FaultLogInfo & info,std::shared_ptr<Event> event)867 void Faultlogger::AddFaultLogIfNeed(FaultLogInfo& info, std::shared_ptr<Event> event)
868 {
869     if (!IsValidPath(info.logPath)) {
870         HIVIEW_LOGE("The log path is incorrect, and the current log path is: %{public}s.", info.logPath.c_str());
871         return;
872     }
873     HIVIEW_LOGI("Start saving Faultlog of Process:%{public}d, Name:%{public}s, Reason:%{public}s.",
874         info.pid, info.module.c_str(), info.reason.c_str());
875     info.sectionMap["PROCESS_NAME"] = info.module; // save process name
876     // Non system processes use UID to pass events to applications
877     bool isSystemProcess = IsSystemProcess(info.module, info.id);
878     if (!isSystemProcess && info.sectionMap["SCBPROCESS"] != "Yes") {
879         std::string appName = GetApplicationNameById(info.id);
880         if (!appName.empty()) {
881             info.module = appName; // if bundle name is not empty, replace module name by it.
882         }
883     }
884 
885     HIVIEW_LOGD("nameProc %{public}s", info.module.c_str());
886     if ((info.module.empty()) || (!IsModuleNameValid(info.module))) {
887         HIVIEW_LOGW("Invalid module name %{public}s", info.module.c_str());
888         return;
889     }
890     AddPublicInfo(info);
891     // Internal reserved fields, avoid illegal privilege escalation to access files
892     info.sectionMap.erase("APPEND_ORIGIN_LOG");
893     if (info.faultLogType == FaultLogType::CPP_CRASH) {
894         AddCppCrashInfo(info);
895     } else if (info.faultLogType == FaultLogType::APP_FREEZE) {
896         info.sectionMap["STACK"] = GetThreadStack(info.logPath, info.pid);
897     }
898 
899     ProcessKernelSnapshot(info);
900     if (info.dumpLogToFautlogger) {
901         mgr_->SaveFaultLogToFile(info);
902     }
903     if (info.faultLogType != FaultLogType::JS_CRASH && info.faultLogType != FaultLogType::CJ_ERROR
904         && info.faultLogType != FaultLogType::RUST_PANIC && info.faultLogType != FaultLogType::ADDR_SANITIZER) {
905         mgr_->SaveFaultInfoToRawDb(info);
906     }
907     HIVIEW_LOGI("\nSave Faultlog of Process:%{public}d\n"
908                 "ModuleName:%{public}s\n"
909                 "Reason:%{public}s\n",
910                 info.pid, info.module.c_str(), info.reason.c_str());
911 
912     if (!isSystemProcess && info.reportToAppEvent) {
913         ReportEventToAppEvent(info);
914     }
915 
916     if (info.dumpLogToFautlogger &&
917         ((info.faultLogType == FaultLogType::CPP_CRASH) || (info.faultLogType == FaultLogType::APP_FREEZE)) &&
918         IsFaultLogLimit()) {
919         FaultlogLimit(info.logPath, info.faultLogType);
920     }
921 }
922 
StartBootScan()923 void Faultlogger::StartBootScan()
924 {
925     std::vector<std::string> files;
926     time_t now = time(nullptr);
927     FileUtil::GetDirFiles(TEMP_LOG_PATH, files);
928     for (const auto& file : files) {
929         // if file type is not cppcrash, skip!
930         if (file.find("cppcrash") == std::string::npos) {
931             HIVIEW_LOGI("Skip this file(%{public}s) that the type is not cppcrash.", file.c_str());
932             continue;
933         }
934         time_t lastAccessTime = GetFileLastAccessTimeStamp(file);
935         if ((now > lastAccessTime) && (now - lastAccessTime > FORTYEIGHT_HOURS)) {
936             HIVIEW_LOGI("Skip this file(%{public}s) that were created 48 hours ago.", file.c_str());
937             continue;
938         }
939         auto info = ParseFaultLogInfoFromFile(file, true);
940         if (info.summary.find("#00") == std::string::npos) {
941             HIVIEW_LOGI("Skip this file(%{public}s) which stack is empty.", file.c_str());
942             HiSysEventWrite(HiSysEvent::Domain::RELIABILITY, "CPP_CRASH_NO_LOG", HiSysEvent::EventType::FAULT,
943                 "PID", info.pid,
944                 "UID", info.id,
945                 "PROCESS_NAME", info.module,
946                 "HAPPEN_TIME", std::to_string(info.time)
947             );
948             if (remove(file.c_str()) != 0) {
949                 HIVIEW_LOGE("Failed to remove file(%{public}s) which stack is empty", file.c_str());
950             }
951             continue;
952         }
953         if (mgr_->IsProcessedFault(info.pid, info.id, info.faultLogType)) {
954             HIVIEW_LOGI("Skip processed fault.(%{public}d:%{public}d) ", info.pid, info.id);
955             continue;
956         }
957         AddFaultLog(info);
958     }
959 }
960 
ReportCppCrashToAppEvent(const FaultLogInfo & info) const961 void Faultlogger::ReportCppCrashToAppEvent(const FaultLogInfo& info) const
962 {
963     std::string stackInfo;
964     GetStackInfo(info, stackInfo);
965     if (stackInfo.length() == 0) {
966         HIVIEW_LOGE("stackInfo is empty");
967         return;
968     }
969     HIVIEW_LOGI("report cppcrash to appevent, pid:%{public}d len:%{public}zu", info.pid, stackInfo.length());
970 #ifdef UNIT_TEST
971     std::string outputFilePath = "/data/test_cppcrash_info_" + std::to_string(info.pid);
972     std::ofstream outFile(outputFilePath);
973     outFile << stackInfo << std::endl;
974     outFile.close();
975 #endif
976     EventPublish::GetInstance().PushEvent(info.id, APP_CRASH_TYPE, HiSysEvent::EventType::FAULT, stackInfo);
977 }
978 
GetStackInfo(const FaultLogInfo & info,std::string & stackInfo) const979 void Faultlogger::GetStackInfo(const FaultLogInfo& info, std::string& stackInfo) const
980 {
981     if (info.pipeFd == nullptr || *(info.pipeFd) == -1) {
982         HIVIEW_LOGE("invalid fd");
983         return;
984     }
985     ssize_t nread = -1;
986     char *buffer = new char[MAX_PIPE_SIZE];
987     nread = TEMP_FAILURE_RETRY(read(*info.pipeFd, buffer, MAX_PIPE_SIZE));
988     if (nread <= 0) {
989         HIVIEW_LOGE("read pipe failed");
990         delete []buffer;
991         return;
992     }
993     std::string stackInfoOriginal(buffer, nread);
994     delete []buffer;
995     Json::Reader reader;
996     Json::Value stackInfoObj;
997     if (!reader.parse(stackInfoOriginal, stackInfoObj)) {
998         HIVIEW_LOGE("parse stackInfo failed");
999         return;
1000     }
1001     stackInfoObj["bundle_name"] = info.module;
1002     Json::Value externalLog;
1003     externalLog.append(info.logPath);
1004     stackInfoObj["external_log"] = externalLog;
1005     if (info.sectionMap.count("VERSION") == 1) {
1006         stackInfoObj["bundle_version"] = info.sectionMap.at("VERSION");
1007     }
1008     if (info.sectionMap.count("FOREGROUND") == 1) {
1009         stackInfoObj["foreground"] = (info.sectionMap.at("FOREGROUND") == "Yes") ? true : false;
1010     }
1011     if (info.sectionMap.count("FINGERPRINT") == 1) {
1012         stackInfoObj["uuid"] = info.sectionMap.at("FINGERPRINT");
1013     }
1014     if (info.sectionMap.count("HILOG") == 1) {
1015         Json::Value hilog(Json::arrayValue);
1016         auto hilogStr = info.sectionMap.at("HILOG");
1017         FillHilog(hilogStr, hilog);
1018         stackInfoObj["hilog"] = hilog;
1019     }
1020     stackInfo.append(Json::FastWriter().write(stackInfoObj));
1021 }
1022 
DoGetHilogProcess(int32_t pid,int writeFd)1023 int Faultlogger::DoGetHilogProcess(int32_t pid, int writeFd)
1024 {
1025     HIVIEW_LOGD("Start do get hilog process, pid:%{public}d", pid);
1026     if (writeFd < 0 || dup2(writeFd, STDOUT_FILENO) == -1 ||
1027         dup2(writeFd, STDERR_FILENO) == -1) {
1028         HIVIEW_LOGE("dup2 writeFd fail");
1029         return -1;
1030     }
1031 
1032     int ret = -1;
1033     ret = execl("/system/bin/hilog", "hilog", "-z", "1000", "-P", std::to_string(pid).c_str(), nullptr);
1034     if (ret < 0) {
1035         HIVIEW_LOGE("execl %{public}d, errno: %{public}d", ret, errno);
1036         return ret;
1037     }
1038     return 0;
1039 }
1040 
ReadHilog(int fd,std::string & log)1041 bool Faultlogger::ReadHilog(int fd, std::string& log)
1042 {
1043     fd_set readFds;
1044     constexpr int readTimeout = 5;
1045     struct timeval timeout = {0};
1046     time_t startTime = time(nullptr);
1047     bool isReadDone = false;
1048     while (!isReadDone) {
1049         time_t now = time(nullptr);
1050         if (now >= startTime + readTimeout) {
1051             HIVIEW_LOGI("read hilog timeout.");
1052             isReadDone = true;
1053             return false;
1054         }
1055         timeout.tv_sec = startTime + readTimeout - now;
1056         timeout.tv_usec = 0;
1057 
1058         FD_ZERO(&readFds);
1059         FD_SET(fd, &readFds);
1060         int ret = select(fd + 1, &readFds, nullptr, nullptr, &timeout);
1061         if (ret <= 0) {
1062             HIVIEW_LOGE("select failed: %{public}d, errno: %{public}d", ret, errno);
1063             if (errno == EINTR) {
1064                 continue;
1065             }
1066             isReadDone = true;
1067             return false;
1068         }
1069 
1070         char buffer[READ_HILOG_BUFFER_SIZE] = {0};
1071         ssize_t nread = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer) - 1));
1072         if (nread == 0) {
1073             HIVIEW_LOGI("read hilog finished");
1074             isReadDone = true;
1075             break;
1076         } else if (nread < 0) {
1077             HIVIEW_LOGI("read failed. errno: %{public}d", errno);
1078             isReadDone = true;
1079             break;
1080         }
1081         log.append(buffer);
1082     }
1083     return true;
1084 }
1085 
GetHilog(int32_t pid,std::string & log) const1086 bool Faultlogger::GetHilog(int32_t pid, std::string& log) const
1087 {
1088     if (Parameter::IsOversea() && !Parameter::IsBetaVersion()) {
1089         HIVIEW_LOGI("Do not get hilog in oversea commercial version.");
1090         return false;
1091     }
1092     int fds[2] = {-1, -1}; // 2: one read pipe, one write pipe
1093     if (pipe(fds) != 0) {
1094         HIVIEW_LOGE("Failed to create pipe for get log.");
1095         return false;
1096     }
1097     int childPid = fork();
1098     if (childPid < 0) {
1099         HIVIEW_LOGE("fork fail");
1100         return false;
1101     } else if (childPid == 0) {
1102         syscall(SYS_close, fds[0]);
1103         int rc = DoGetHilogProcess(pid, fds[1]);
1104         syscall(SYS_close, fds[1]);
1105         _exit(rc);
1106     } else {
1107         syscall(SYS_close, fds[1]);
1108         // read log from fds[0]
1109         HIVIEW_LOGI("read hilog start");
1110         ReadHilog(fds[0], log);
1111         syscall(SYS_close, fds[0]);
1112 
1113         if (TEMP_FAILURE_RETRY(waitpid(childPid, nullptr, 0)) != childPid) {
1114             HIVIEW_LOGE("waitpid fail, pid: %{public}d, errno: %{public}d", childPid, errno);
1115             return false;
1116         }
1117         HIVIEW_LOGI("get hilog waitpid %{public}d success", childPid);
1118         return true;
1119     }
1120     return false;
1121 }
1122 
GetDightStrArr(const std::string & target)1123 std::list<std::string> GetDightStrArr(const std::string& target)
1124 {
1125     std::list<std::string> ret;
1126     std::string temp = "";
1127     for (size_t i = 0, len = target.size(); i < len; i++) {
1128         if (target[i] >= '0' && target[i] <= '9') {
1129             temp += target[i];
1130             continue;
1131         }
1132         if (temp.size() != 0) {
1133             ret.push_back(temp);
1134             temp = "";
1135         }
1136     }
1137     if (temp.size() != 0) {
1138         ret.push_back(temp);
1139     }
1140     ret.push_back("0");
1141     return ret;
1142 }
1143 
GetMemoryStrByPid(long pid) const1144 std::string Faultlogger::GetMemoryStrByPid(long pid) const
1145 {
1146     if (pid <= 0) {
1147         return "";
1148     }
1149     unsigned long long rss = 0; // statm col = 2 *4
1150     unsigned long long vss = 0; // statm col = 1 *4
1151     unsigned long long sysFreeMem = 0; // meminfo row=2
1152     unsigned long long sysAvailMem = 0; // meminfo row=3
1153     unsigned long long sysTotalMem = 0; // meminfo row=1
1154     std::ifstream statmStream("/proc/" + std::to_string(pid) + "/statm");
1155     if (statmStream) {
1156         std::string statmLine;
1157         std::getline(statmStream, statmLine);
1158         HIVIEW_LOGI("/proc/%{public}ld/statm : %{public}s", pid, statmLine.c_str());
1159         statmStream.close();
1160         std::list<std::string> numStrArr = GetDightStrArr(statmLine);
1161         if (numStrArr.size() > 1) {
1162             auto it = numStrArr.begin();
1163             unsigned long long multiples = 4;
1164             vss = multiples * static_cast<unsigned long long>(std::atoll(it->c_str()));
1165             it++;
1166             rss = multiples * static_cast<unsigned long long>(std::atoll(it->c_str()));
1167         }
1168         HIVIEW_LOGI("GET FreezeJson rss=%{public}llu, vss=%{public}llu.", rss, vss);
1169     } else {
1170         HIVIEW_LOGE("Fail to open /proc/%{public}ld/statm", pid);
1171     }
1172 
1173     std::ifstream meminfoStream("/proc/meminfo");
1174     if (meminfoStream) {
1175         constexpr int decimalBase = 10;
1176         std::string meminfoLine;
1177         std::getline(meminfoStream, meminfoLine);
1178         sysTotalMem = strtoull(GetDightStrArr(meminfoLine).front().c_str(), nullptr, decimalBase);
1179         std::getline(meminfoStream, meminfoLine);
1180         sysFreeMem = strtoull(GetDightStrArr(meminfoLine).front().c_str(), nullptr, decimalBase);
1181         std::getline(meminfoStream, meminfoLine);
1182         sysAvailMem = strtoull(GetDightStrArr(meminfoLine).front().c_str(), nullptr, decimalBase);
1183         meminfoStream.close();
1184         HIVIEW_LOGI("GET FreezeJson sysFreeMem=%{public}llu, sysAvailMem=%{public}llu, sysTotalMem=%{public}llu.",
1185             sysFreeMem, sysAvailMem, sysTotalMem);
1186     } else {
1187         HIVIEW_LOGE("Fail to open /proc/meminfo");
1188     }
1189 
1190     FreezeJsonMemory freezeJsonMemory = FreezeJsonMemory::Builder().InitRss(rss).InitVss(vss).
1191         InitSysFreeMem(sysFreeMem).InitSysAvailMem(sysAvailMem).InitSysTotalMem(sysTotalMem).Build();
1192     return freezeJsonMemory.JsonStr();
1193 }
1194 
GetFreezeJsonCollector(const FaultLogInfo & info) const1195 FreezeJsonUtil::FreezeJsonCollector Faultlogger::GetFreezeJsonCollector(const FaultLogInfo& info) const
1196 {
1197     FreezeJsonUtil::FreezeJsonCollector collector = {0};
1198     std::string jsonFilePath = FreezeJsonUtil::GetFilePath(info.pid, info.id, info.time);
1199     if (!FileUtil::FileExists(jsonFilePath)) {
1200         HIVIEW_LOGE("Not Exist FreezeJsonFile: %{public}s.", jsonFilePath.c_str());
1201         return collector;
1202     }
1203     FreezeJsonUtil::LoadCollectorFromFile(jsonFilePath, collector);
1204     HIVIEW_LOGI("load FreezeJsonFile.");
1205     FreezeJsonUtil::DelFile(jsonFilePath);
1206 
1207     FreezeJsonException exception = FreezeJsonException::Builder()
1208         .InitName(collector.stringId)
1209         .InitMessage(collector.message)
1210         .Build();
1211     collector.exception = exception.JsonStr();
1212 
1213     std::list<std::string> hilogList;
1214     std::string hilogStr;
1215     GetHilog(collector.pid, hilogStr);
1216     if (hilogStr.length() == 0) {
1217         HIVIEW_LOGE("Get FreezeJson hilog is empty!");
1218     } else {
1219         std::stringstream hilogStream(hilogStr);
1220         std::string oneLine;
1221         int count = 0;
1222         while (++count <= REPORT_HILOG_LINE && std::getline(hilogStream, oneLine)) {
1223             hilogList.push_back(StringUtil::EscapeJsonStringValue(oneLine));
1224         }
1225     }
1226     collector.hilog = FreezeJsonUtil::GetStrByList(hilogList);
1227 
1228     collector.memory = GetMemoryStrByPid(collector.pid);
1229 
1230     if (info.sectionMap.count("FOREGROUND") == 1) {
1231         std::string foreground = info.sectionMap.at("FOREGROUND");
1232         collector.foreground = (foreground == "Yes");
1233     }
1234 
1235     if (info.sectionMap.count("VERSION") == 1) {
1236         collector.version = info.sectionMap.at("VERSION");
1237     }
1238 
1239     if (info.sectionMap.count("FINGERPRINT") == 1) {
1240         collector.uuid = info.sectionMap.at("FINGERPRINT");
1241     }
1242 
1243     return collector;
1244 }
1245 
ReportAppFreezeToAppEvent(const FaultLogInfo & info,bool isAppHicollie) const1246 void Faultlogger::ReportAppFreezeToAppEvent(const FaultLogInfo& info, bool isAppHicollie) const
1247 {
1248     HIVIEW_LOGI("Start to report freezeJson !!!");
1249 
1250     FreezeJsonUtil::FreezeJsonCollector collector = GetFreezeJsonCollector(info);
1251     std::list<std::string> externalLogList;
1252     externalLogList.push_back(info.logPath);
1253     std::string externalLog = FreezeJsonUtil::GetStrByList(externalLogList);
1254 
1255     FreezeJsonParams freezeJsonParams = FreezeJsonParams::Builder()
1256         .InitTime(collector.timestamp)
1257         .InitUuid(collector.uuid)
1258         .InitFreezeType(isAppHicollie ? "AppHicollie" : "AppFreeze")
1259         .InitForeground(collector.foreground)
1260         .InitBundleVersion(collector.version)
1261         .InitBundleName(collector.package_name)
1262         .InitProcessName(collector.process_name)
1263         .InitExternalLog(externalLog)
1264         .InitPid(collector.pid)
1265         .InitUid(collector.uid)
1266         .InitAppRunningUniqueId(collector.appRunningUniqueId)
1267         .InitException(collector.exception)
1268         .InitHilog(collector.hilog)
1269         .InitEventHandler(collector.event_handler)
1270         .InitEventHandlerSize3s(collector.event_handler_3s_size)
1271         .InitEventHandlerSize6s(collector.event_handler_6s_size)
1272         .InitPeerBinder(collector.peer_binder)
1273         .InitThreads(collector.stack)
1274         .InitMemory(collector.memory)
1275         .Build();
1276     EventPublish::GetInstance().PushEvent(info.id, isAppHicollie ? APP_HICOLLIE_TYPE : APP_FREEZE_TYPE,
1277         HiSysEvent::EventType::FAULT, freezeJsonParams.JsonStr());
1278     HIVIEW_LOGI("Report FreezeJson Successfully!");
1279 }
1280 
ReportEventToAppEvent(const FaultLogInfo & info)1281 void Faultlogger::ReportEventToAppEvent(const FaultLogInfo& info)
1282 {
1283     if (FreezeJsonUtil::IsAppHicollie(info.reason)) {
1284         ReportAppFreezeToAppEvent(info, true);
1285         return;
1286     }
1287 
1288     switch (info.faultLogType) {
1289         case FaultLogType::CPP_CRASH:
1290             CheckFaultLogAsync(info);
1291             ReportCppCrashToAppEvent(info);
1292             break;
1293         case FaultLogType::APP_FREEZE:
1294             ReportAppFreezeToAppEvent(info);
1295             break;
1296         default:
1297             break;
1298     }
1299 }
1300 /*
1301  * return value: 0 means fault log invalid; 1 means fault log valid.
1302  */
CheckFaultLog(FaultLogInfo info)1303 bool Faultlogger::CheckFaultLog(FaultLogInfo info)
1304 {
1305     int32_t err = CrashExceptionCode::CRASH_ESUCCESS;
1306     if (!CheckFaultSummaryValid(info.summary)) {
1307         err = CrashExceptionCode::CRASH_LOG_ESUMMARYLOS;
1308     }
1309     ReportCrashException(info.module, info.pid, info.id, err);
1310 
1311     return (err == CrashExceptionCode::CRASH_ESUCCESS);
1312 }
1313 
CheckFaultLogAsync(const FaultLogInfo & info)1314 void Faultlogger::CheckFaultLogAsync(const FaultLogInfo& info)
1315 {
1316     if (workLoop_ != nullptr) {
1317         auto task = [this, info] {
1318             CheckFaultLog(info);
1319         };
1320         workLoop_->AddTimerEvent(nullptr, nullptr, task, 0, false);
1321     }
1322 }
1323 
AddBootScanEvent()1324 void Faultlogger::AddBootScanEvent()
1325 {
1326     if (workLoop_ == nullptr) {
1327         HIVIEW_LOGE("workLoop_ is nullptr.");
1328         return;
1329     }
1330     // some crash happened before hiview start, ensure every crash event is added into eventdb
1331     auto task = [this] {
1332         StartBootScan();
1333     };
1334     workLoop_->AddTimerEvent(nullptr, nullptr, task, 10, false); // delay 10 seconds
1335 }
1336 
FaultloggerListener(Faultlogger & faultlogger)1337 Faultlogger::FaultloggerListener::FaultloggerListener(Faultlogger& faultlogger) : faultlogger_(faultlogger)
1338 {
1339     AddListenerInfo(Event::MessageType::PLUGIN_MAINTENANCE);
1340 }
1341 
OnUnorderedEvent(const Event & msg)1342 void Faultlogger::FaultloggerListener::OnUnorderedEvent(const Event &msg)
1343 {
1344 #ifndef UNITTEST
1345     if (msg.messageType_ != Event::MessageType::PLUGIN_MAINTENANCE ||
1346         msg.eventId_ != Event::EventId::PLUGIN_LOADED) {
1347         HIVIEW_LOGE("messageType_(%{public}u), eventId_(%{public}u).", msg.messageType_, msg.eventId_);
1348         return;
1349     }
1350     faultlogger_.AddBootScanEvent();
1351 #endif
1352 }
1353 
GetListenerName()1354 std::string Faultlogger::FaultloggerListener::GetListenerName()
1355 {
1356     return "Faultlogger";
1357 }
1358 } // namespace HiviewDFX
1359 } // namespace OHOS
1360