1 /*
2  * Copyright (c) 2021-2024 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 
16 #include "fault_logger_daemon.h"
17 
18 #include <algorithm>
19 #include <cerrno>
20 #include <csignal>
21 #include <cstring>
22 #include <ctime>
23 #include <dirent.h>
24 #include <fcntl.h>
25 #include <fstream>
26 #include <securec.h>
27 #include <sstream>
28 #include <unistd.h>
29 #include <vector>
30 
31 #include <sys/epoll.h>
32 #include <sys/socket.h>
33 #include <sys/stat.h>
34 #include <sys/syscall.h>
35 #include <sys/types.h>
36 #include <sys/un.h>
37 #include <sys/wait.h>
38 
39 #include "dfx_define.h"
40 #include "dfx_exception.h"
41 #include "dfx_log.h"
42 #include "dfx_trace.h"
43 #include "dfx_util.h"
44 #include "string_printf.h"
45 #include "directory_ex.h"
46 #include "fault_logger_config.h"
47 #include "faultloggerd_socket.h"
48 #ifndef is_ohos_lite
49 #include "parameters.h"
50 #endif
51 #ifndef HISYSEVENT_DISABLE
52 #include "hisysevent.h"
53 #endif
54 
55 namespace OHOS {
56 namespace HiviewDFX {
57 std::shared_ptr<FaultLoggerConfig> faultLoggerConfig_;
58 std::shared_ptr<FaultLoggerPipeMap> faultLoggerPipeMap_;
59 
60 namespace {
61 constexpr int32_t MAX_CONNECTION = 30;
62 constexpr int32_t REQUEST_BUF_SIZE = 2048;
63 constexpr int32_t MAX_EPOLL_EVENT = 1024;
64 const int32_t FAULTLOG_FILE_PROP = 0640;
65 
66 static constexpr uint32_t ROOT_UID = 0;
67 static constexpr uint32_t BMS_UID = 1000;
68 static constexpr uint32_t HIVIEW_UID = 1201;
69 static constexpr uint32_t HIDUMPER_SERVICE_UID = 1212;
70 static constexpr uint32_t FOUNDATION_UID = 5523;
71 static const std::string FAULTLOGGERD_TAG = "FaultLoggerd";
72 static const std::string DAEMON_RESP = "RESP:COMPLETE";
73 static const int DAEMON_REMOVE_FILE_TIME_S = 60;
74 
GetRequestTypeName(int32_t type)75 static std::string GetRequestTypeName(int32_t type)
76 {
77     switch (type) {
78         case (int32_t)FaultLoggerType::CPP_CRASH:
79             return "cppcrash";
80         case (int32_t)FaultLoggerType::CPP_STACKTRACE: // change the name to nativestack ?
81             return "stacktrace";
82         case (int32_t)FaultLoggerType::JS_STACKTRACE:
83             return "jsstack";
84         case (int32_t)FaultLoggerType::JS_HEAP_SNAPSHOT:
85         case (int32_t)FaultLoggerType::JS_RAW_SNAPSHOT:
86             return "jsheap";
87         case (int32_t)FaultLoggerType::JS_HEAP_LEAK_LIST:
88             return "leaklist";
89         case (int32_t)FaultLoggerType::LEAK_STACKTRACE:
90             return "leakstack";
91         case (int32_t)FaultLoggerType::FFRT_CRASH_LOG:
92             return "ffrtlog";
93         case (int32_t)FaultLoggerType::JIT_CODE_LOG:
94             return "jitcode";
95         default:
96             return "unsupported";
97     }
98 }
99 
CheckCallerUID(uint32_t callerUid)100 static bool CheckCallerUID(uint32_t callerUid)
101 {
102     // If caller's is BMS / root or caller's uid/pid is validate, just return true
103     if ((callerUid == BMS_UID) ||
104         (callerUid == ROOT_UID) ||
105         (callerUid == HIVIEW_UID) ||
106         (callerUid == HIDUMPER_SERVICE_UID) ||
107         (callerUid == FOUNDATION_UID)) {
108         return true;
109     }
110     DFXLOGW("%{public}s :: CheckCallerUID :: Caller Uid(%{public}d) is unexpectly.\n",
111         FAULTLOGGERD_TAG.c_str(), callerUid);
112     return false;
113 }
114 }
115 
ReportExceptionToSysEvent(CrashDumpException& exception)116 static void ReportExceptionToSysEvent(CrashDumpException& exception)
117 {
118 #ifndef HISYSEVENT_DISABLE
119     std::string errMessage;
120     if (exception.error == CRASH_DUMP_LOCAL_REPORT) {
121         std::ifstream rfile;
122         if (strlen(exception.message) == 0) {
123             return;
124         }
125         rfile.open(exception.message, std::ios::binary | std::ios::ate);
126         if (!rfile.is_open()) {
127             return;
128         }
129         std::streamsize size = rfile.tellg();
130         rfile.seekg(0, std::ios::beg);
131         std::vector<char> buf(size);
132         rfile.read(buf.data(), size);
133         errMessage = std::string(buf.begin(), buf.end());
134     } else {
135         errMessage = exception.message;
136     }
137     HiSysEventWrite(
138         HiSysEvent::Domain::RELIABILITY,
139         "CPP_CRASH_EXCEPTION",
140         HiSysEvent::EventType::FAULT,
141         "PID", exception.pid,
142         "UID", exception.uid,
143         "HAPPEN_TIME", exception.time,
144         "ERROR_CODE", exception.error,
145         "ERROR_MSG", errMessage);
146 #endif
147 }
148 
FaultLoggerDaemon()149 FaultLoggerDaemon::FaultLoggerDaemon()
150 {
151 #ifndef is_ohos_lite
152     isBeta_ = OHOS::system::GetParameter("const.logsystem.versiontype", "false") == "beta";
153 #endif
154 }
155 
StartServer()156 int32_t FaultLoggerDaemon::StartServer()
157 {
158     if (!CreateSockets()) {
159         DFXLOGE("%{public}s :: Failed to create faultloggerd sockets.", FAULTLOGGERD_TAG.c_str());
160         CleanupSockets();
161         return -1;
162     }
163 
164     if (!InitEnvironment()) {
165         DFXLOGE("%{public}s :: Failed to init environment.", FAULTLOGGERD_TAG.c_str());
166         CleanupSockets();
167         return -1;
168     }
169 
170     if (!CreateEventFd()) {
171         DFXLOGE("%{public}s :: Failed to create eventFd.", FAULTLOGGERD_TAG.c_str());
172         CleanupSockets();
173         return -1;
174     }
175     RemoveTempFileIfNeed();
176     // loop in WaitForRequest
177     WaitForRequest();
178     CleanupEventFd();
179     CleanupSockets();
180     return 0;
181 }
182 
HandleAccept(int32_t epollFd, int32_t socketFd)183 void FaultLoggerDaemon::HandleAccept(int32_t epollFd, int32_t socketFd)
184 {
185     DFX_TRACE_SCOPED("HandleAccept");
186     struct sockaddr_un clientAddr;
187     socklen_t clientAddrSize = static_cast<socklen_t>(sizeof(clientAddr));
188 
189     int connectionFd = OHOS_TEMP_FAILURE_RETRY(accept(socketFd,
190         reinterpret_cast<struct sockaddr *>(&clientAddr), &clientAddrSize));
191     if (connectionFd < 0) {
192         DFXLOGW("%{public}s :: Failed to accept connection", FAULTLOGGERD_TAG.c_str());
193         return;
194     }
195 
196     AddEvent(eventFd_, connectionFd, EPOLLIN);
197     connectionMap_[connectionFd] = socketFd;
198 }
199 
200 #ifdef FAULTLOGGERD_FUZZER
HandleStaticForFuzzer(int32_t type, uint32_t callerUid)201 bool FaultLoggerDaemon::HandleStaticForFuzzer(int32_t type, uint32_t callerUid)
202 {
203     std::string str = GetRequestTypeName(type);
204     bool ret = CheckCallerUID(callerUid);
205     if (str == "unsupported" || !ret) {
206         return false;
207     } else {
208         return true;
209     }
210 }
211 
HandleRequestForFuzzer(int32_t epollFd, int32_t connectionFd, const FaultLoggerdRequest *requestConst, FaultLoggerdRequest *request)212 void FaultLoggerDaemon::HandleRequestForFuzzer(int32_t epollFd, int32_t connectionFd,
213                                                const FaultLoggerdRequest *requestConst, FaultLoggerdRequest *request)
214 {
215     if (faultLoggerConfig_ == nullptr) {
216         faultLoggerConfig_ = std::make_shared<FaultLoggerConfig>(LOG_FILE_NUMBER, LOG_FILE_SIZE,
217             LOG_FILE_PATH, DEBUG_LOG_FILE_PATH);
218     }
219     HandleRequest(epollFd, connectionFd);
220     HandleLogFileDesClientRequest(connectionFd, requestConst);
221     HandlePrintTHilogClientRequest(connectionFd, request);
222     HandlePermissionRequest(connectionFd, request);
223     HandleSdkDumpRequest(connectionFd, request);
224     HandleExceptionRequest(connectionFd, request);
225 }
226 #endif
227 
CheckReadRequest(ssize_t nread, ssize_t size)228 static bool CheckReadRequest(ssize_t nread, ssize_t size)
229 {
230     if (nread < 0) {
231         DFXLOGE("%{public}s :: Failed to read message", FAULTLOGGERD_TAG.c_str());
232         return false;
233     } else if (nread == 0) {
234         DFXLOGE("%{public}s :: Read null from request socket", FAULTLOGGERD_TAG.c_str());
235         return false;
236     } else if (nread != static_cast<long>(size)) {
237         return false;
238     }
239     return true;
240 }
241 
HandleRequestByClientType(int32_t connectionFd, FaultLoggerdRequest* request)242 void FaultLoggerDaemon::HandleRequestByClientType(int32_t connectionFd, FaultLoggerdRequest* request)
243 {
244     switch (request->clientType) {
245         case static_cast<int32_t>(FaultLoggerClientType::DEFAULT_CLIENT):
246             HandleDefaultClientRequest(connectionFd, request);
247             break;
248         case static_cast<int32_t>(FaultLoggerClientType::LOG_FILE_DES_CLIENT):
249             HandleLogFileDesClientRequest(connectionFd, request);
250             break;
251         case static_cast<int32_t>(FaultLoggerClientType::PRINT_T_HILOG_CLIENT):
252             HandlePrintTHilogClientRequest(connectionFd, request);
253             break;
254         case static_cast<int32_t>(FaultLoggerClientType::PERMISSION_CLIENT):
255             HandlePermissionRequest(connectionFd, request);
256             break;
257         case static_cast<int32_t>(FaultLoggerClientType::SDK_DUMP_CLIENT):
258             HandleSdkDumpRequest(connectionFd, request);
259             break;
260         case static_cast<int32_t>(FaultLoggerClientType::PIPE_FD_CLIENT):
261             HandlePipeFdClientRequest(connectionFd, request);
262             break;
263         case static_cast<int32_t>(FaultLoggerClientType::REPORT_EXCEPTION_CLIENT):
264             HandleExceptionRequest(connectionFd, request);
265             break;
266         default:
267             DFXLOGE("%{public}s :: unknown clientType(%{public}d).\n", FAULTLOGGERD_TAG.c_str(), request->clientType);
268             break;
269         }
270 }
271 
HandleRequest(int32_t epollFd, int32_t connectionFd)272 void FaultLoggerDaemon::HandleRequest(int32_t epollFd, int32_t connectionFd)
273 {
274     if (epollFd < 0 || connectionFd < 3) { // 3: not allow fd = 0,1,2 because they are reserved by system
275         DFXLOGE("%{public}s :: HandleRequest recieved invalid fd parmeters.", FAULTLOGGERD_TAG.c_str());
276         return;
277     }
278 
279     std::vector<uint8_t> buf(REQUEST_BUF_SIZE, 0);
280     do {
281         ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, buf.data(), REQUEST_BUF_SIZE));
282         if (CheckReadRequest(nread, sizeof(FaultLoggerdStatsRequest))) {
283             HandleDumpStats(connectionFd, reinterpret_cast<FaultLoggerdStatsRequest *>(buf.data()));
284             break;
285         }
286         if (!CheckReadRequest(nread, sizeof(FaultLoggerdRequest))) {
287             break;
288         }
289         auto request = reinterpret_cast<FaultLoggerdRequest *>(buf.data());
290         if (!CheckRequestCredential(connectionFd, request)) {
291             break;
292         }
293         DFXLOGD("%{public}s :: clientType(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->clientType);
294         HandleRequestByClientType(connectionFd, request);
295     } while (false);
296     DelEvent(eventFd_, connectionFd, EPOLLIN);
297     connectionMap_.erase(connectionFd);
298 }
299 
InitEnvironment()300 bool FaultLoggerDaemon::InitEnvironment()
301 {
302     faultLoggerConfig_ = std::make_shared<FaultLoggerConfig>(LOG_FILE_NUMBER, LOG_FILE_SIZE,
303         LOG_FILE_PATH, DEBUG_LOG_FILE_PATH);
304     faultLoggerPipeMap_ = std::make_shared<FaultLoggerPipeMap>();
305 
306     if (!OHOS::ForceCreateDirectory(faultLoggerConfig_->GetLogFilePath())) {
307         DFXLOGE("%{public}s :: Failed to ForceCreateDirectory GetLogFilePath", FAULTLOGGERD_TAG.c_str());
308         return false;
309     }
310 
311     signal(SIGCHLD, SIG_IGN);
312     signal(SIGPIPE, SIG_IGN);
313     return true;
314 }
315 
HandleDefaultClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)316 void FaultLoggerDaemon::HandleDefaultClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)
317 {
318     DFX_TRACE_SCOPED("HandleDefaultClientRequest");
319     int fd = CreateFileForRequest(request->type, request->pid, request->tid, request->time);
320     if (fd < 0) {
321         DFXLOGE("[%{public}d]: %{public}s :: Failed to create log file, errno(%{public}d)", __LINE__,
322             FAULTLOGGERD_TAG.c_str(), errno);
323         return;
324     }
325     RecordFileCreation(request->type, request->pid);
326     SendFileDescriptorToSocket(connectionFd, fd);
327 
328     close(fd);
329 }
330 
HandleLogFileDesClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)331 void FaultLoggerDaemon::HandleLogFileDesClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)
332 {
333     int fd = CreateFileForRequest(request->type, request->pid, request->tid, request->time);
334     if (fd < 0) {
335         DFXLOGE("[%{public}d]: %{public}s :: Failed to create log file, errno(%{public}d)", __LINE__,
336             FAULTLOGGERD_TAG.c_str(), errno);
337         return;
338     }
339     SendFileDescriptorToSocket(connectionFd, fd);
340 
341     close(fd);
342 }
343 
HandleExceptionRequest(int32_t connectionFd, FaultLoggerdRequest * request)344 void FaultLoggerDaemon::HandleExceptionRequest(int32_t connectionFd, FaultLoggerdRequest * request)
345 {
346     if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd,
347         DAEMON_RESP.c_str(), DAEMON_RESP.length())) != static_cast<ssize_t>(DAEMON_RESP.length())) {
348         DFXLOGE("[%{public}d]: %{public}s :: Failed to write DAEMON_RESP.", __LINE__, FAULTLOGGERD_TAG.c_str());
349     }
350 
351     CrashDumpException exception;
352     (void)memset_s(&exception, sizeof(CrashDumpException), 0, sizeof(CrashDumpException));
353     ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, &exception, sizeof(CrashDumpException)));
354     exception.message[LINE_BUF_SIZE - 1] = '\0';
355     if (!CheckReadRequest(nread, sizeof(CrashDumpException))) {
356         return;
357     }
358 
359     ReportExceptionToSysEvent(exception);
360 }
361 
HandleReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)362 void FaultLoggerDaemon::HandleReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
363     FaultLoggerPipe2* faultLoggerPipe)
364 {
365     FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
366     if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
367         return;
368     }
369     if ((faultLoggerPipe->faultLoggerPipeBuf_) != nullptr) {
370         fd = faultLoggerPipe->faultLoggerPipeBuf_->GetReadFd();
371     }
372 }
373 
HandleWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)374 void FaultLoggerDaemon::HandleWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)
375 {
376     if ((faultLoggerPipe->faultLoggerPipeBuf_) != nullptr) {
377         fd = faultLoggerPipe->faultLoggerPipeBuf_->GetWriteFd();
378     }
379 }
380 
HandleReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)381 void FaultLoggerDaemon::HandleReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
382     FaultLoggerPipe2* faultLoggerPipe)
383 {
384     FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
385     if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
386         return;
387     }
388     if ((faultLoggerPipe->faultLoggerPipeRes_) != nullptr) {
389         fd = faultLoggerPipe->faultLoggerPipeRes_->GetReadFd();
390     }
391 }
392 
HandleWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)393 void FaultLoggerDaemon::HandleWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)
394 {
395     if ((faultLoggerPipe->faultLoggerPipeRes_) != nullptr) {
396         fd = faultLoggerPipe->faultLoggerPipeRes_->GetWriteFd();
397     }
398 }
399 
HandleDelete(FaultLoggerdRequest* request)400 void FaultLoggerDaemon::HandleDelete(FaultLoggerdRequest* request)
401 {
402     faultLoggerPipeMap_->Del(request->pid);
403 }
404 
HandleJsonReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)405 void FaultLoggerDaemon::HandleJsonReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
406     FaultLoggerPipe2* faultLoggerPipe)
407 {
408     FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
409     if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
410         return;
411     }
412     if ((faultLoggerPipe->faultLoggerJsonPipeBuf_) != nullptr) {
413         fd = faultLoggerPipe->faultLoggerJsonPipeBuf_->GetReadFd();
414     }
415 }
416 
HandleJsonWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)417 void FaultLoggerDaemon::HandleJsonWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)
418 {
419     if ((faultLoggerPipe->faultLoggerJsonPipeBuf_) != nullptr) {
420         fd = faultLoggerPipe->faultLoggerJsonPipeBuf_->GetWriteFd();
421     }
422 }
423 
HandleJsonReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)424 void FaultLoggerDaemon::HandleJsonReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
425     FaultLoggerPipe2* faultLoggerPipe)
426 {
427     FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
428     if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
429         return;
430     }
431     if ((faultLoggerPipe->faultLoggerJsonPipeRes_) != nullptr) {
432         fd = faultLoggerPipe->faultLoggerJsonPipeRes_->GetReadFd();
433     }
434 }
435 
HandleJsonWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)436 void FaultLoggerDaemon::HandleJsonWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)
437 {
438     if ((faultLoggerPipe->faultLoggerJsonPipeRes_) != nullptr) {
439         fd = faultLoggerPipe->faultLoggerJsonPipeRes_->GetWriteFd();
440     }
441 }
442 
HandleRequestByPipeType(int& fd, int32_t connectionFd, FaultLoggerdRequest* request, FaultLoggerPipe2* faultLoggerPipe)443 void FaultLoggerDaemon::HandleRequestByPipeType(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
444                                                 FaultLoggerPipe2* faultLoggerPipe)
445 {
446     switch (request->pipeType) {
447         case (int32_t)FaultLoggerPipeType::PIPE_FD_READ_BUF: {
448             HandleReadBuf(fd, connectionFd, request, faultLoggerPipe);
449             break;
450         }
451         case (int32_t)FaultLoggerPipeType::PIPE_FD_WRITE_BUF: {
452             HandleWriteBuf(fd, faultLoggerPipe);
453             break;
454         }
455         case (int32_t)FaultLoggerPipeType::PIPE_FD_READ_RES: {
456             HandleReadRes(fd, connectionFd, request, faultLoggerPipe);
457             break;
458         }
459         case (int32_t)FaultLoggerPipeType::PIPE_FD_WRITE_RES: {
460             HandleWriteRes(fd, faultLoggerPipe);
461             break;
462         }
463         case (int32_t)FaultLoggerPipeType::PIPE_FD_DELETE: {
464             HandleDelete(request);
465             return;
466         }
467         case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF: {
468             HandleJsonReadBuf(fd, connectionFd, request, faultLoggerPipe);
469             break;
470         }
471         case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_WRITE_BUF: {
472             HandleJsonWriteBuf(fd, faultLoggerPipe);
473             break;
474         }
475         case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_READ_RES: {
476             HandleJsonReadRes(fd, connectionFd, request, faultLoggerPipe);
477             break;
478         }
479         case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES: {
480             HandleJsonWriteRes(fd, faultLoggerPipe);
481             break;
482         }
483         default:
484             DFXLOGE("%{public}s :: unknown pipeType(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->pipeType);
485             return;
486     }
487 }
488 
HandlePipeFdClientRequest(int32_t connectionFd, FaultLoggerdRequest * request)489 void FaultLoggerDaemon::HandlePipeFdClientRequest(int32_t connectionFd, FaultLoggerdRequest * request)
490 {
491     DFX_TRACE_SCOPED("HandlePipeFdClientRequest");
492     DFXLOGD("%{public}s :: pid(%{public}d), pipeType(%{public}d).", FAULTLOGGERD_TAG.c_str(),
493         request->pid, request->pipeType);
494     int fd = -1;
495     FaultLoggerPipe2* faultLoggerPipe = faultLoggerPipeMap_->Get(request->pid);
496     if (faultLoggerPipe == nullptr) {
497         DFXLOGE("%{public}s :: cannot find pipe fd for pid(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->pid);
498         return;
499     }
500     HandleRequestByPipeType(fd, connectionFd, request, faultLoggerPipe);
501     if (fd < 0) {
502         DFXLOGE("%{public}s :: Failed to get pipe fd, pipeType(%{public}d)",
503             FAULTLOGGERD_TAG.c_str(), request->pipeType);
504         return;
505     }
506     SendFileDescriptorToSocket(connectionFd, fd);
507 }
508 
HandlePrintTHilogClientRequest(int32_t const connectionFd, FaultLoggerdRequest * request)509 void FaultLoggerDaemon::HandlePrintTHilogClientRequest(int32_t const connectionFd, FaultLoggerdRequest * request)
510 {
511     char buf[LINE_BUF_SIZE] = {0};
512 
513     if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd,
514         DAEMON_RESP.c_str(), DAEMON_RESP.length())) != static_cast<ssize_t>(DAEMON_RESP.length())) {
515         DFXLOGE("[%{public}d]: %{public}s :: Failed to write DAEMON_RESP.", __LINE__, FAULTLOGGERD_TAG.c_str());
516     }
517 
518     int nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, buf, sizeof(buf) - 1));
519     if (nread < 0) {
520         DFXLOGE("%{public}s :: Failed to read message, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
521     } else if (nread == 0) {
522         DFXLOGE("%{public}s :: HandlePrintTHilogClientRequest :: Read null from request socket",
523             FAULTLOGGERD_TAG.c_str());
524     } else {
525         DFXLOGE("%{public}s", buf);
526     }
527 }
528 
SecurityCheck(int32_t connectionFd, FaultLoggerdRequest * request)529 FaultLoggerCheckPermissionResp FaultLoggerDaemon::SecurityCheck(int32_t connectionFd, FaultLoggerdRequest * request)
530 {
531     FaultLoggerCheckPermissionResp resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
532 
533     struct ucred rcred;
534     do {
535         int optval = 1;
536         if (OHOS_TEMP_FAILURE_RETRY(setsockopt(connectionFd,
537             SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval))) == -1) {
538             DFXLOGE("%{public}s :: setsockopt SO_PASSCRED error, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
539             break;
540         }
541 
542         if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd, DAEMON_RESP.c_str(), DAEMON_RESP.length())) !=
543             static_cast<ssize_t>(DAEMON_RESP.length())) {
544             DFXLOGE("%{public}s :: Failed to write DAEMON_RESP, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
545             break;
546         }
547 
548         if (!RecvMsgCredFromSocket(connectionFd, &rcred)) {
549             DFXLOGE("%{public}s :: Recv msg ucred error, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
550             break;
551         }
552 
553         request->uid = rcred.uid;
554         request->callerPid = static_cast<int32_t>(rcred.pid);
555 
556         auto it = connectionMap_.find(connectionFd);
557         if (it == connectionMap_.end()) {
558             break;
559         }
560 
561         if (it->second == sdkdumpSocketFd_) {
562             resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS;
563             break;
564         }
565 
566         bool res = CheckCallerUID(request->uid);
567         if (res) {
568             resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS;
569         }
570     } while (false);
571 
572     return resCheckPermission;
573 }
574 
HandlePermissionRequest(int32_t connectionFd, FaultLoggerdRequest * request)575 void FaultLoggerDaemon::HandlePermissionRequest(int32_t connectionFd, FaultLoggerdRequest * request)
576 {
577     FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
578     if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS == resSecurityCheck) {
579         OHOS_TEMP_FAILURE_RETRY(send(connectionFd, "1", strlen("1"), 0));
580     }
581     if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT == resSecurityCheck) {
582         OHOS_TEMP_FAILURE_RETRY(send(connectionFd, "2", strlen("2"), 0));
583     }
584 }
585 
HandleSdkDumpRequest(int32_t connectionFd, FaultLoggerdRequest * request)586 void FaultLoggerDaemon::HandleSdkDumpRequest(int32_t connectionFd, FaultLoggerdRequest * request)
587 {
588     DFX_TRACE_SCOPED("HandleSdkDumpRequest");
589     DFXLOGI("Receive dump request for pid:%{public}d tid:%{public}d.", request->pid, request->tid);
590     FaultLoggerSdkDumpResp resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_PASS;
591     FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
592 
593     /*
594     *           all     threads my user, local pid             my user, remote pid     other user's process
595     * 3rd       Y       Y(in signal_handler local)     Y(in signal_handler loacl)      N
596     * system    Y       Y(in signal_handler local)     Y(in signal_handler loacl)      Y(in signal_handler remote)
597     * root      Y       Y(in signal_handler local)     Y(in signal_handler loacl)      Y(in signal_handler remote)
598     */
599 
600     /*
601     * 1. pid != 0 && tid != 0:    means we want dump a thread, so we send signal to a thread.
602         Main thread stack is tid's stack, we need ignore other thread info.
603     * 2. pid != 0 && tid == 0:    means we want dump a process, so we send signal to process.
604         Main thead stack is pid's stack, we need other tread info.
605     */
606 
607     /*
608      * in signal_handler we need to check caller pid and tid(which is send to signal handler by SYS_rt_sig.).
609      * 1. caller pid == signal pid, means we do back trace in ourself process, means local backtrace.
610      *      |- we do all tid back trace in signal handler's local unwind.
611      * 2. pid != signal pid, means we do remote back trace.
612      */
613 
614     /*
615      * in local back trace, all unwind stack will save to signal_handler global var.(mutex lock in signal handler.)
616      * in remote back trace, all unwind stack will save to file, and read in dump_catcher, then return.
617      */
618 
619     do {
620         if ((request->pid <= 0) || (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT == resSecurityCheck)) {
621             DFXLOGE("%{public}s :: HandleSdkDumpRequest :: pid(%{public}d) or resSecurityCheck(%{public}d) fail.\n", \
622                 FAULTLOGGERD_TAG.c_str(), request->pid, (int)resSecurityCheck);
623             resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_REJECT;
624             break;
625         }
626         DFXLOGI("Sdk dump pid(%{public}d) request pass permission verification.", request->pid);
627         if (IsCrashed(request->pid)) {
628             resSdkDump = FaultLoggerSdkDumpResp::SDK_PROCESS_CRASHED;
629             DFXLOGW("%{public}s :: pid(%{public}d) has been crashed, break.\n",
630                 FAULTLOGGERD_TAG.c_str(), request->pid);
631             break;
632         }
633         if (faultLoggerPipeMap_->Check(request->pid, request->time)) {
634             resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_REPEAT;
635             DFXLOGE("%{public}s :: pid(%{public}d) is dumping, break.\n", FAULTLOGGERD_TAG.c_str(), request->pid);
636             break;
637         }
638         faultLoggerPipeMap_->Set(request->pid, request->time, request->isJson);
639 
640 #pragma clang diagnostic push
641 #pragma clang diagnostic ignored "-Winitializer-overrides"
642         // defined in out/hi3516dv300/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/signal.h
643         siginfo_t si {0};
644         si.si_signo = SIGDUMP;
645         si.si_errno = 0;
646         si.si_value.sival_int = request->tid;
647         if (request->tid == 0 && sizeof(void *) == 8) { // 8 : platform 64
648             si.si_value.sival_ptr = reinterpret_cast<void *>(request->endTime | (1ULL << 63)); // 63 : platform 64
649         }
650         si.si_code = request->sigCode;
651         si.si_pid = request->callerPid;
652         si.si_uid = static_cast<uid_t>(request->callerTid);
653 #pragma clang diagnostic pop
654         /*
655          * means we need dump all the threads in a process
656          * --------
657          * Accroding to the linux manual, A process-directed signal may be delivered to any one of the
658          * threads that does not currently have the signal blocked.
659          */
660         if (syscall(SYS_rt_sigqueueinfo, request->pid, si.si_signo, &si) != 0) {
661             DFXLOGE("Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", si.si_signo, errno);
662             resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_NOPROC;
663         }
664     } while (false);
665     auto retMsg = std::to_string(resSdkDump);
666     if (OHOS_TEMP_FAILURE_RETRY(send(connectionFd, retMsg.data(), retMsg.length(), 0)) !=
667         static_cast<ssize_t>(retMsg.length())) {
668         DFXLOGE("Failed to send result message to client, errno(%{public}d).", errno);
669     }
670 }
671 
RecordFileCreation(int32_t type, int32_t pid)672 void FaultLoggerDaemon::RecordFileCreation(int32_t type, int32_t pid)
673 {
674     if (type == static_cast<int32_t>(FaultLoggerType::CPP_CRASH)) {
675         ClearTimeOutRecords();
676         crashTimeMap_[pid] = time(nullptr);
677     }
678 }
679 
ClearTimeOutRecords()680 void FaultLoggerDaemon::ClearTimeOutRecords()
681 {
682     constexpr int validTime = 8;
683     auto currentTime = time(nullptr);
684     for (auto it = crashTimeMap_.begin(); it != crashTimeMap_.end();) {
685         if ((it->second + validTime) <= currentTime) {
686             crashTimeMap_.erase(it++);
687         } else {
688             it++;
689         }
690     }
691 }
692 
IsCrashed(int32_t pid)693 bool FaultLoggerDaemon::IsCrashed(int32_t pid)
694 {
695     DFX_TRACE_SCOPED("IsCrashed");
696     ClearTimeOutRecords();
697     return crashTimeMap_.find(pid) != crashTimeMap_.end();
698 }
699 
CreateFileForRequest(int32_t type, int32_t pid, int32_t tid, uint64_t time) const700 int32_t FaultLoggerDaemon::CreateFileForRequest(int32_t type, int32_t pid, int32_t tid, uint64_t time) const
701 {
702     RemoveTempFileIfNeed();
703     std::string typeStr = GetRequestTypeName(type);
704     if (typeStr == "unsupported") {
705         DFXLOGE("Unsupported request type(%{public}d)", type);
706         return -1;
707     }
708 
709     std::string folderPath = "";
710     folderPath = faultLoggerConfig_->GetLogFilePath();
711 
712     if (time == 0) {
713         time = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>\
714             (std::chrono::system_clock::now().time_since_epoch()).count());
715     }
716 
717     std::string ss = folderPath + "/" + typeStr + "-" + std::to_string(pid);
718     if (type == FaultLoggerType::JS_HEAP_SNAPSHOT || type == FaultLoggerType::JS_RAW_SNAPSHOT) {
719         ss += "-" + std::to_string(tid);
720     }
721     ss += "-" + std::to_string(time);
722     if (type == FaultLoggerType::JS_RAW_SNAPSHOT) {
723         ss += ".rawheap";
724     }
725     const std::string path = ss;
726     DFXLOGI("%{public}s :: file path(%{public}s).\n", FAULTLOGGERD_TAG.c_str(), path.c_str());
727     if (!VerifyFilePath(path, VALID_FILE_PATH)) {
728         DFXLOGE("%{public}s :: Open %{public}s fail, please check it under valid path.\n",
729             FAULTLOGGERD_TAG.c_str(), path.c_str());
730         return -1;
731     }
732     int32_t fd = OHOS_TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CREAT, FAULTLOG_FILE_PROP));
733     if (fd != -1) {
734         if (!ChangeModeFile(path, FAULTLOG_FILE_PROP)) {
735             DFXLOGE("%{public}s :: Failed to ChangeMode CreateFileForRequest", FAULTLOGGERD_TAG.c_str());
736         }
737     }
738     return fd;
739 }
740 
RemoveTempFileIfNeed() const741 void FaultLoggerDaemon::RemoveTempFileIfNeed() const
742 {
743     int maxFileCount = 50;
744     int currentLogCounts = 0;
745 
746     std::string logFilePath = faultLoggerConfig_->GetLogFilePath();
747     std::vector<std::string> files;
748     OHOS::GetDirFiles(logFilePath, files);
749     constexpr uint64_t maxFileSize = 1lu << 31; // 2GB
750     if (!isBeta_ && OHOS::GetFolderSize(logFilePath) > maxFileSize) {
751         DFXLOGE("%{public}s :: current file size is over limit, clear all files", FAULTLOGGERD_TAG.c_str());
752         std::for_each(files.begin(), files.end(), OHOS::RemoveFile);
753         return;
754     }
755     currentLogCounts = (int)files.size();
756     maxFileCount = faultLoggerConfig_->GetLogFileMaxNumber();
757     if (currentLogCounts < maxFileCount) {
758         return;
759     }
760 
761     std::sort(files.begin(), files.end(),
762         [](const std::string& lhs, const std::string& rhs) -> int {
763         auto lhsSplitPos = lhs.find_last_of("-");
764         auto rhsSplitPos = rhs.find_last_of("-");
765         if (lhsSplitPos == std::string::npos || rhsSplitPos == std::string::npos) {
766             return lhs.compare(rhs) > 0;
767         }
768 
769         return lhs.substr(lhsSplitPos).compare(rhs.substr(rhsSplitPos)) > 0;
770     });
771 
772     time_t currentTime = static_cast<time_t>(time(nullptr));
773     if (currentTime <= 0) {
774         DFXLOGE("%{public}s :: currentTime is less than zero CreateFileForRequest", FAULTLOGGERD_TAG.c_str());
775     }
776 
777     constexpr int deleteNum = 1;
778     int startIndex = maxFileCount > deleteNum ? maxFileCount - deleteNum : maxFileCount;
779     for (unsigned int index = (unsigned int)startIndex; index < files.size(); index++) {
780         struct stat st;
781         int err = stat(files[index].c_str(), &st);
782         if (err != 0) {
783             DFXLOGE("%{public}s :: Get log stat failed, errno(%{public}d).", FAULTLOGGERD_TAG.c_str(), errno);
784         } else {
785             if ((currentTime - st.st_mtime) <= DAEMON_REMOVE_FILE_TIME_S) {
786                 continue;
787             }
788         }
789 
790         OHOS::RemoveFile(files[index]);
791         DFXLOGD("%{public}s :: Now we rm file(%{public}s) as max log number exceeded.", \
792             FAULTLOGGERD_TAG.c_str(), files[index].c_str());
793     }
794 }
795 
AddEvent(int32_t epollFd, int32_t addFd, uint32_t event)796 void FaultLoggerDaemon::AddEvent(int32_t epollFd, int32_t addFd, uint32_t event)
797 {
798     epoll_event ev;
799     ev.events = event;
800     ev.data.fd = addFd;
801     int ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, addFd, &ev);
802     if (ret < 0) {
803         DFXLOGW("%{public}s :: Failed to epoll ctl add Fd(%{public}d), errno(%{public}d)",
804             FAULTLOGGERD_TAG.c_str(), addFd, errno);
805     }
806 }
807 
DelEvent(int32_t epollFd, int32_t delFd, uint32_t event)808 void FaultLoggerDaemon::DelEvent(int32_t epollFd, int32_t delFd, uint32_t event)
809 {
810     epoll_event ev;
811     ev.events = event;
812     ev.data.fd = delFd;
813     int ret = epoll_ctl(epollFd, EPOLL_CTL_DEL, delFd, &ev);
814     if (ret < 0) {
815         DFXLOGW("%{public}s :: Failed to epoll ctl del Fd(%{public}d), errno(%{public}d)",
816             FAULTLOGGERD_TAG.c_str(), delFd, errno);
817     }
818     close(delFd);
819 }
820 
CheckRequestCredential(int32_t connectionFd, FaultLoggerdRequest* request)821 bool FaultLoggerDaemon::CheckRequestCredential(int32_t connectionFd, FaultLoggerdRequest* request)
822 {
823     if (request == nullptr) {
824         return false;
825     }
826 
827     auto it = connectionMap_.find(connectionFd);
828     if (it == connectionMap_.end()) {
829         DFXLOGE("%{public}s : Failed to find fd:%{public}d, map size:%{public}zu", FAULTLOGGERD_TAG.c_str(),
830             connectionFd, connectionMap_.size());
831         return false;
832     }
833 
834     if (it->second == crashSocketFd_ || it->second == sdkdumpSocketFd_) {
835         // only processdump use this socket
836         return true;
837     }
838 
839     struct ucred creds = {};
840     socklen_t credSize = sizeof(creds);
841     int err = getsockopt(connectionFd, SOL_SOCKET, SO_PEERCRED, &creds, &credSize);
842     if (err != 0) {
843         DFXLOGE("%{public}s :: Failed to CheckRequestCredential, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
844         return false;
845     }
846 
847     if (CheckCallerUID(creds.uid)) {
848         return true;
849     }
850 
851     bool isCredentialMatched = (creds.pid == request->pid);
852     if (request->clientType == (int32_t)REPORT_EXCEPTION_CLIENT) {
853         isCredentialMatched = (creds.uid == request->uid);   /* check uid when report exception */
854     }
855     if (!isCredentialMatched) {
856         DFXLOGW("Failed to check request credential request:%{public}d:" \
857             "%{public}d cred:%{public}d:%{public}d fd:%{public}d:%{public}d",
858             request->pid, request->uid, creds.pid, creds.uid, it->second, crashSocketFd_);
859     }
860     return isCredentialMatched;
861 }
862 
CreateSockets()863 bool FaultLoggerDaemon::CreateSockets()
864 {
865     if (!StartListen(defaultSocketFd_, SERVER_SOCKET_NAME, MAX_CONNECTION)) {
866         return false;
867     }
868 
869     if (!StartListen(crashSocketFd_, SERVER_CRASH_SOCKET_NAME, MAX_CONNECTION)) {
870         close(defaultSocketFd_);
871         defaultSocketFd_ = -1;
872         return false;
873     }
874 #ifndef is_ohos_lite
875     if (!StartListen(sdkdumpSocketFd_, SERVER_SDKDUMP_SOCKET_NAME, MAX_CONNECTION)) {
876         close(defaultSocketFd_);
877         defaultSocketFd_ = -1;
878         close(crashSocketFd_);
879         crashSocketFd_ = -1;
880         return false;
881     }
882 #endif
883     return true;
884 }
885 
CleanupSockets()886 void FaultLoggerDaemon::CleanupSockets()
887 {
888     if (defaultSocketFd_ >= 0) {
889         close(defaultSocketFd_);
890         defaultSocketFd_ = -1;
891     }
892 
893     if (crashSocketFd_ >= 0) {
894         close(crashSocketFd_);
895         crashSocketFd_ = -1;
896     }
897 
898     if (sdkdumpSocketFd_ >= 0) {
899         close(sdkdumpSocketFd_);
900         sdkdumpSocketFd_ = -1;
901     }
902 }
903 
CreateEventFd()904 bool FaultLoggerDaemon::CreateEventFd()
905 {
906     eventFd_ = epoll_create(MAX_EPOLL_EVENT);
907     if (eventFd_ < 0) {
908         return false;
909     }
910     return true;
911 }
912 
WaitForRequest()913 void FaultLoggerDaemon::WaitForRequest()
914 {
915     AddEvent(eventFd_, defaultSocketFd_, EPOLLIN);
916     AddEvent(eventFd_, crashSocketFd_, EPOLLIN);
917     AddEvent(eventFd_, sdkdumpSocketFd_, EPOLLIN);
918     epoll_event events[MAX_CONNECTION];
919     DFXLOGD("%{public}s :: %{public}s: start epoll wait.", FAULTLOGGERD_TAG.c_str(), __func__);
920     do {
921         int epollNum = OHOS_TEMP_FAILURE_RETRY(epoll_wait(eventFd_, events, MAX_CONNECTION, -1));
922         if (epollNum < 0) {
923             DFXLOGE("%{public}s :: %{public}s: epoll wait error, errno(%{public}d).",
924                 FAULTLOGGERD_TAG.c_str(), __func__, errno);
925             continue;
926         }
927         for (int i = 0; i < epollNum; i++) {
928             if (!(events[i].events & EPOLLIN)) {
929                 DFXLOGW("%{public}s :: %{public}s: epoll event(%{public}d) error.",
930                     FAULTLOGGERD_TAG.c_str(), __func__, events[i].events);
931                 continue;
932             }
933 
934             int fd = events[i].data.fd;
935             if (fd == defaultSocketFd_ || fd == crashSocketFd_ || fd == sdkdumpSocketFd_) {
936                 HandleAccept(eventFd_, fd);
937             } else {
938                 HandleRequest(eventFd_, fd);
939             }
940         }
941     } while (true);
942 }
943 
CleanupEventFd()944 void FaultLoggerDaemon::CleanupEventFd()
945 {
946     DelEvent(eventFd_, defaultSocketFd_, EPOLLIN);
947     DelEvent(eventFd_, crashSocketFd_, EPOLLIN);
948     DelEvent(eventFd_, sdkdumpSocketFd_, EPOLLIN);
949 
950     if (eventFd_ > 0) {
951         close(eventFd_);
952         eventFd_ = -1;
953     }
954 }
955 
GetElfName(FaultLoggerdStatsRequest* request)956 std::string GetElfName(FaultLoggerdStatsRequest* request)
957 {
958     if (request == nullptr || strlen(request->callerElf) > NAME_BUF_LEN) {
959         return "";
960     }
961 
962     std::string ss = StringPrintf("%s(%p)", request->callerElf, reinterpret_cast<void *>(request->offset));
963     return ss;
964 }
965 
HandleDumpStats(int32_t connectionFd, FaultLoggerdStatsRequest* request)966 void FaultLoggerDaemon::HandleDumpStats(int32_t connectionFd, FaultLoggerdStatsRequest* request)
967 {
968     DFXLOGI("%{public}s :: %{public}s: HandleDumpStats", FAULTLOGGERD_TAG.c_str(), __func__);
969     size_t index = 0;
970     bool hasRecord = false;
971     for (index = 0; index < stats_.size(); index++) {
972         if (stats_[index].pid == request->pid) {
973             hasRecord = true;
974             break;
975         }
976     }
977 
978     DumpStats stats;
979     if (request->type == PROCESS_DUMP && !hasRecord) {
980         stats.pid = request->pid;
981         stats.signalTime = request->signalTime;
982         stats.processdumpStartTime = request->processdumpStartTime;
983         stats.processdumpFinishTime = request->processdumpFinishTime;
984         stats.targetProcessName = request->targetProcess;
985         stats_.emplace_back(stats);
986     } else if (request->type == DUMP_CATCHER && hasRecord) {
987         stats_[index].requestTime = request->requestTime;
988         stats_[index].dumpCatcherFinishTime = request->dumpCatcherFinishTime;
989         stats_[index].callerElfName = GetElfName(request);
990         stats_[index].callerProcessName = request->callerProcess;
991         stats_[index].result = request->result;
992         stats_[index].summary = request->summary;
993         ReportDumpStats(stats_[index]);
994         stats_.erase(stats_.begin() + index);
995     } else if (request->type == DUMP_CATCHER) {
996         stats.pid = request->pid;
997         stats.requestTime = request->requestTime;
998         stats.dumpCatcherFinishTime = request->dumpCatcherFinishTime;
999         stats.callerElfName = GetElfName(request);
1000         stats.result = request->result;
1001         stats.callerProcessName = request->callerProcess;
1002         stats.summary = request->summary;
1003         stats.targetProcessName = request->targetProcess;
1004         ReportDumpStats(stats);
1005     }
1006     RemoveTimeoutDumpStats();
1007 }
1008 
RemoveTimeoutDumpStats()1009 void FaultLoggerDaemon::RemoveTimeoutDumpStats()
1010 {
1011     const uint64_t timeout = 10000;
1012     uint64_t now = GetTimeMilliSeconds();
1013     for (auto it = stats_.begin(); it != stats_.end();) {
1014         if (((now > it->signalTime) && (now - it->signalTime > timeout)) ||
1015             (now <= it->signalTime)) {
1016             it = stats_.erase(it);
1017         } else {
1018             ++it;
1019         }
1020     }
1021 }
1022 
ReportDumpStats(const DumpStats& stat)1023 void FaultLoggerDaemon::ReportDumpStats(const DumpStats& stat)
1024 {
1025 #ifndef HISYSEVENT_DISABLE
1026     HiSysEventWrite(
1027         HiSysEvent::Domain::HIVIEWDFX,
1028         "DUMP_CATCHER_STATS",
1029         HiSysEvent::EventType::STATISTIC,
1030         "CALLER_PROCESS_NAME", stat.callerProcessName,
1031         "CALLER_FUNC_NAME", stat.callerElfName,
1032         "TARGET_PROCESS_NAME", stat.targetProcessName,
1033         "RESULT", stat.result,
1034         "SUMMARY", stat.summary, // we need to parse summary when interface return false
1035         "PID", stat.pid,
1036         "REQUEST_TIME", stat.requestTime,
1037         "OVERALL_TIME", stat.dumpCatcherFinishTime - stat.requestTime,
1038         "SIGNAL_TIME", stat.signalTime - stat.requestTime,
1039         "DUMPER_START_TIME", stat.processdumpStartTime - stat.signalTime,
1040         "UNWIND_TIME", stat.processdumpFinishTime - stat.processdumpStartTime);
1041 #endif
1042 }
1043 } // namespace HiviewDFX
1044 } // namespace OHOS
1045