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 ¶ms)
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