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