1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License.
5800b99b8Sopenharmony_ci * You may obtain a copy of the License at
6800b99b8Sopenharmony_ci *
7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8800b99b8Sopenharmony_ci *
9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and
13800b99b8Sopenharmony_ci * limitations under the License.
14800b99b8Sopenharmony_ci */
15800b99b8Sopenharmony_ci
16800b99b8Sopenharmony_ci#include "fault_logger_daemon.h"
17800b99b8Sopenharmony_ci
18800b99b8Sopenharmony_ci#include <algorithm>
19800b99b8Sopenharmony_ci#include <cerrno>
20800b99b8Sopenharmony_ci#include <csignal>
21800b99b8Sopenharmony_ci#include <cstring>
22800b99b8Sopenharmony_ci#include <ctime>
23800b99b8Sopenharmony_ci#include <dirent.h>
24800b99b8Sopenharmony_ci#include <fcntl.h>
25800b99b8Sopenharmony_ci#include <fstream>
26800b99b8Sopenharmony_ci#include <securec.h>
27800b99b8Sopenharmony_ci#include <sstream>
28800b99b8Sopenharmony_ci#include <unistd.h>
29800b99b8Sopenharmony_ci#include <vector>
30800b99b8Sopenharmony_ci
31800b99b8Sopenharmony_ci#include <sys/epoll.h>
32800b99b8Sopenharmony_ci#include <sys/socket.h>
33800b99b8Sopenharmony_ci#include <sys/stat.h>
34800b99b8Sopenharmony_ci#include <sys/syscall.h>
35800b99b8Sopenharmony_ci#include <sys/types.h>
36800b99b8Sopenharmony_ci#include <sys/un.h>
37800b99b8Sopenharmony_ci#include <sys/wait.h>
38800b99b8Sopenharmony_ci
39800b99b8Sopenharmony_ci#include "dfx_define.h"
40800b99b8Sopenharmony_ci#include "dfx_exception.h"
41800b99b8Sopenharmony_ci#include "dfx_log.h"
42800b99b8Sopenharmony_ci#include "dfx_trace.h"
43800b99b8Sopenharmony_ci#include "dfx_util.h"
44800b99b8Sopenharmony_ci#include "string_printf.h"
45800b99b8Sopenharmony_ci#include "directory_ex.h"
46800b99b8Sopenharmony_ci#include "fault_logger_config.h"
47800b99b8Sopenharmony_ci#include "faultloggerd_socket.h"
48800b99b8Sopenharmony_ci#ifndef is_ohos_lite
49800b99b8Sopenharmony_ci#include "parameters.h"
50800b99b8Sopenharmony_ci#endif
51800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE
52800b99b8Sopenharmony_ci#include "hisysevent.h"
53800b99b8Sopenharmony_ci#endif
54800b99b8Sopenharmony_ci
55800b99b8Sopenharmony_cinamespace OHOS {
56800b99b8Sopenharmony_cinamespace HiviewDFX {
57800b99b8Sopenharmony_cistd::shared_ptr<FaultLoggerConfig> faultLoggerConfig_;
58800b99b8Sopenharmony_cistd::shared_ptr<FaultLoggerPipeMap> faultLoggerPipeMap_;
59800b99b8Sopenharmony_ci
60800b99b8Sopenharmony_cinamespace {
61800b99b8Sopenharmony_ciconstexpr int32_t MAX_CONNECTION = 30;
62800b99b8Sopenharmony_ciconstexpr int32_t REQUEST_BUF_SIZE = 2048;
63800b99b8Sopenharmony_ciconstexpr int32_t MAX_EPOLL_EVENT = 1024;
64800b99b8Sopenharmony_ciconst int32_t FAULTLOG_FILE_PROP = 0640;
65800b99b8Sopenharmony_ci
66800b99b8Sopenharmony_cistatic constexpr uint32_t ROOT_UID = 0;
67800b99b8Sopenharmony_cistatic constexpr uint32_t BMS_UID = 1000;
68800b99b8Sopenharmony_cistatic constexpr uint32_t HIVIEW_UID = 1201;
69800b99b8Sopenharmony_cistatic constexpr uint32_t HIDUMPER_SERVICE_UID = 1212;
70800b99b8Sopenharmony_cistatic constexpr uint32_t FOUNDATION_UID = 5523;
71800b99b8Sopenharmony_cistatic const std::string FAULTLOGGERD_TAG = "FaultLoggerd";
72800b99b8Sopenharmony_cistatic const std::string DAEMON_RESP = "RESP:COMPLETE";
73800b99b8Sopenharmony_cistatic const int DAEMON_REMOVE_FILE_TIME_S = 60;
74800b99b8Sopenharmony_ci
75800b99b8Sopenharmony_cistatic std::string GetRequestTypeName(int32_t type)
76800b99b8Sopenharmony_ci{
77800b99b8Sopenharmony_ci    switch (type) {
78800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::CPP_CRASH:
79800b99b8Sopenharmony_ci            return "cppcrash";
80800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::CPP_STACKTRACE: // change the name to nativestack ?
81800b99b8Sopenharmony_ci            return "stacktrace";
82800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::JS_STACKTRACE:
83800b99b8Sopenharmony_ci            return "jsstack";
84800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::JS_HEAP_SNAPSHOT:
85800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::JS_RAW_SNAPSHOT:
86800b99b8Sopenharmony_ci            return "jsheap";
87800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::JS_HEAP_LEAK_LIST:
88800b99b8Sopenharmony_ci            return "leaklist";
89800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::LEAK_STACKTRACE:
90800b99b8Sopenharmony_ci            return "leakstack";
91800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::FFRT_CRASH_LOG:
92800b99b8Sopenharmony_ci            return "ffrtlog";
93800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerType::JIT_CODE_LOG:
94800b99b8Sopenharmony_ci            return "jitcode";
95800b99b8Sopenharmony_ci        default:
96800b99b8Sopenharmony_ci            return "unsupported";
97800b99b8Sopenharmony_ci    }
98800b99b8Sopenharmony_ci}
99800b99b8Sopenharmony_ci
100800b99b8Sopenharmony_cistatic bool CheckCallerUID(uint32_t callerUid)
101800b99b8Sopenharmony_ci{
102800b99b8Sopenharmony_ci    // If caller's is BMS / root or caller's uid/pid is validate, just return true
103800b99b8Sopenharmony_ci    if ((callerUid == BMS_UID) ||
104800b99b8Sopenharmony_ci        (callerUid == ROOT_UID) ||
105800b99b8Sopenharmony_ci        (callerUid == HIVIEW_UID) ||
106800b99b8Sopenharmony_ci        (callerUid == HIDUMPER_SERVICE_UID) ||
107800b99b8Sopenharmony_ci        (callerUid == FOUNDATION_UID)) {
108800b99b8Sopenharmony_ci        return true;
109800b99b8Sopenharmony_ci    }
110800b99b8Sopenharmony_ci    DFXLOGW("%{public}s :: CheckCallerUID :: Caller Uid(%{public}d) is unexpectly.\n",
111800b99b8Sopenharmony_ci        FAULTLOGGERD_TAG.c_str(), callerUid);
112800b99b8Sopenharmony_ci    return false;
113800b99b8Sopenharmony_ci}
114800b99b8Sopenharmony_ci}
115800b99b8Sopenharmony_ci
116800b99b8Sopenharmony_cistatic void ReportExceptionToSysEvent(CrashDumpException& exception)
117800b99b8Sopenharmony_ci{
118800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE
119800b99b8Sopenharmony_ci    std::string errMessage;
120800b99b8Sopenharmony_ci    if (exception.error == CRASH_DUMP_LOCAL_REPORT) {
121800b99b8Sopenharmony_ci        std::ifstream rfile;
122800b99b8Sopenharmony_ci        if (strlen(exception.message) == 0) {
123800b99b8Sopenharmony_ci            return;
124800b99b8Sopenharmony_ci        }
125800b99b8Sopenharmony_ci        rfile.open(exception.message, std::ios::binary | std::ios::ate);
126800b99b8Sopenharmony_ci        if (!rfile.is_open()) {
127800b99b8Sopenharmony_ci            return;
128800b99b8Sopenharmony_ci        }
129800b99b8Sopenharmony_ci        std::streamsize size = rfile.tellg();
130800b99b8Sopenharmony_ci        rfile.seekg(0, std::ios::beg);
131800b99b8Sopenharmony_ci        std::vector<char> buf(size);
132800b99b8Sopenharmony_ci        rfile.read(buf.data(), size);
133800b99b8Sopenharmony_ci        errMessage = std::string(buf.begin(), buf.end());
134800b99b8Sopenharmony_ci    } else {
135800b99b8Sopenharmony_ci        errMessage = exception.message;
136800b99b8Sopenharmony_ci    }
137800b99b8Sopenharmony_ci    HiSysEventWrite(
138800b99b8Sopenharmony_ci        HiSysEvent::Domain::RELIABILITY,
139800b99b8Sopenharmony_ci        "CPP_CRASH_EXCEPTION",
140800b99b8Sopenharmony_ci        HiSysEvent::EventType::FAULT,
141800b99b8Sopenharmony_ci        "PID", exception.pid,
142800b99b8Sopenharmony_ci        "UID", exception.uid,
143800b99b8Sopenharmony_ci        "HAPPEN_TIME", exception.time,
144800b99b8Sopenharmony_ci        "ERROR_CODE", exception.error,
145800b99b8Sopenharmony_ci        "ERROR_MSG", errMessage);
146800b99b8Sopenharmony_ci#endif
147800b99b8Sopenharmony_ci}
148800b99b8Sopenharmony_ci
149800b99b8Sopenharmony_ciFaultLoggerDaemon::FaultLoggerDaemon()
150800b99b8Sopenharmony_ci{
151800b99b8Sopenharmony_ci#ifndef is_ohos_lite
152800b99b8Sopenharmony_ci    isBeta_ = OHOS::system::GetParameter("const.logsystem.versiontype", "false") == "beta";
153800b99b8Sopenharmony_ci#endif
154800b99b8Sopenharmony_ci}
155800b99b8Sopenharmony_ci
156800b99b8Sopenharmony_ciint32_t FaultLoggerDaemon::StartServer()
157800b99b8Sopenharmony_ci{
158800b99b8Sopenharmony_ci    if (!CreateSockets()) {
159800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to create faultloggerd sockets.", FAULTLOGGERD_TAG.c_str());
160800b99b8Sopenharmony_ci        CleanupSockets();
161800b99b8Sopenharmony_ci        return -1;
162800b99b8Sopenharmony_ci    }
163800b99b8Sopenharmony_ci
164800b99b8Sopenharmony_ci    if (!InitEnvironment()) {
165800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to init environment.", FAULTLOGGERD_TAG.c_str());
166800b99b8Sopenharmony_ci        CleanupSockets();
167800b99b8Sopenharmony_ci        return -1;
168800b99b8Sopenharmony_ci    }
169800b99b8Sopenharmony_ci
170800b99b8Sopenharmony_ci    if (!CreateEventFd()) {
171800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to create eventFd.", FAULTLOGGERD_TAG.c_str());
172800b99b8Sopenharmony_ci        CleanupSockets();
173800b99b8Sopenharmony_ci        return -1;
174800b99b8Sopenharmony_ci    }
175800b99b8Sopenharmony_ci    RemoveTempFileIfNeed();
176800b99b8Sopenharmony_ci    // loop in WaitForRequest
177800b99b8Sopenharmony_ci    WaitForRequest();
178800b99b8Sopenharmony_ci    CleanupEventFd();
179800b99b8Sopenharmony_ci    CleanupSockets();
180800b99b8Sopenharmony_ci    return 0;
181800b99b8Sopenharmony_ci}
182800b99b8Sopenharmony_ci
183800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleAccept(int32_t epollFd, int32_t socketFd)
184800b99b8Sopenharmony_ci{
185800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("HandleAccept");
186800b99b8Sopenharmony_ci    struct sockaddr_un clientAddr;
187800b99b8Sopenharmony_ci    socklen_t clientAddrSize = static_cast<socklen_t>(sizeof(clientAddr));
188800b99b8Sopenharmony_ci
189800b99b8Sopenharmony_ci    int connectionFd = OHOS_TEMP_FAILURE_RETRY(accept(socketFd,
190800b99b8Sopenharmony_ci        reinterpret_cast<struct sockaddr *>(&clientAddr), &clientAddrSize));
191800b99b8Sopenharmony_ci    if (connectionFd < 0) {
192800b99b8Sopenharmony_ci        DFXLOGW("%{public}s :: Failed to accept connection", FAULTLOGGERD_TAG.c_str());
193800b99b8Sopenharmony_ci        return;
194800b99b8Sopenharmony_ci    }
195800b99b8Sopenharmony_ci
196800b99b8Sopenharmony_ci    AddEvent(eventFd_, connectionFd, EPOLLIN);
197800b99b8Sopenharmony_ci    connectionMap_[connectionFd] = socketFd;
198800b99b8Sopenharmony_ci}
199800b99b8Sopenharmony_ci
200800b99b8Sopenharmony_ci#ifdef FAULTLOGGERD_FUZZER
201800b99b8Sopenharmony_cibool FaultLoggerDaemon::HandleStaticForFuzzer(int32_t type, uint32_t callerUid)
202800b99b8Sopenharmony_ci{
203800b99b8Sopenharmony_ci    std::string str = GetRequestTypeName(type);
204800b99b8Sopenharmony_ci    bool ret = CheckCallerUID(callerUid);
205800b99b8Sopenharmony_ci    if (str == "unsupported" || !ret) {
206800b99b8Sopenharmony_ci        return false;
207800b99b8Sopenharmony_ci    } else {
208800b99b8Sopenharmony_ci        return true;
209800b99b8Sopenharmony_ci    }
210800b99b8Sopenharmony_ci}
211800b99b8Sopenharmony_ci
212800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleRequestForFuzzer(int32_t epollFd, int32_t connectionFd,
213800b99b8Sopenharmony_ci                                               const FaultLoggerdRequest *requestConst, FaultLoggerdRequest *request)
214800b99b8Sopenharmony_ci{
215800b99b8Sopenharmony_ci    if (faultLoggerConfig_ == nullptr) {
216800b99b8Sopenharmony_ci        faultLoggerConfig_ = std::make_shared<FaultLoggerConfig>(LOG_FILE_NUMBER, LOG_FILE_SIZE,
217800b99b8Sopenharmony_ci            LOG_FILE_PATH, DEBUG_LOG_FILE_PATH);
218800b99b8Sopenharmony_ci    }
219800b99b8Sopenharmony_ci    HandleRequest(epollFd, connectionFd);
220800b99b8Sopenharmony_ci    HandleLogFileDesClientRequest(connectionFd, requestConst);
221800b99b8Sopenharmony_ci    HandlePrintTHilogClientRequest(connectionFd, request);
222800b99b8Sopenharmony_ci    HandlePermissionRequest(connectionFd, request);
223800b99b8Sopenharmony_ci    HandleSdkDumpRequest(connectionFd, request);
224800b99b8Sopenharmony_ci    HandleExceptionRequest(connectionFd, request);
225800b99b8Sopenharmony_ci}
226800b99b8Sopenharmony_ci#endif
227800b99b8Sopenharmony_ci
228800b99b8Sopenharmony_cistatic bool CheckReadRequest(ssize_t nread, ssize_t size)
229800b99b8Sopenharmony_ci{
230800b99b8Sopenharmony_ci    if (nread < 0) {
231800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to read message", FAULTLOGGERD_TAG.c_str());
232800b99b8Sopenharmony_ci        return false;
233800b99b8Sopenharmony_ci    } else if (nread == 0) {
234800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Read null from request socket", FAULTLOGGERD_TAG.c_str());
235800b99b8Sopenharmony_ci        return false;
236800b99b8Sopenharmony_ci    } else if (nread != static_cast<long>(size)) {
237800b99b8Sopenharmony_ci        return false;
238800b99b8Sopenharmony_ci    }
239800b99b8Sopenharmony_ci    return true;
240800b99b8Sopenharmony_ci}
241800b99b8Sopenharmony_ci
242800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleRequestByClientType(int32_t connectionFd, FaultLoggerdRequest* request)
243800b99b8Sopenharmony_ci{
244800b99b8Sopenharmony_ci    switch (request->clientType) {
245800b99b8Sopenharmony_ci        case static_cast<int32_t>(FaultLoggerClientType::DEFAULT_CLIENT):
246800b99b8Sopenharmony_ci            HandleDefaultClientRequest(connectionFd, request);
247800b99b8Sopenharmony_ci            break;
248800b99b8Sopenharmony_ci        case static_cast<int32_t>(FaultLoggerClientType::LOG_FILE_DES_CLIENT):
249800b99b8Sopenharmony_ci            HandleLogFileDesClientRequest(connectionFd, request);
250800b99b8Sopenharmony_ci            break;
251800b99b8Sopenharmony_ci        case static_cast<int32_t>(FaultLoggerClientType::PRINT_T_HILOG_CLIENT):
252800b99b8Sopenharmony_ci            HandlePrintTHilogClientRequest(connectionFd, request);
253800b99b8Sopenharmony_ci            break;
254800b99b8Sopenharmony_ci        case static_cast<int32_t>(FaultLoggerClientType::PERMISSION_CLIENT):
255800b99b8Sopenharmony_ci            HandlePermissionRequest(connectionFd, request);
256800b99b8Sopenharmony_ci            break;
257800b99b8Sopenharmony_ci        case static_cast<int32_t>(FaultLoggerClientType::SDK_DUMP_CLIENT):
258800b99b8Sopenharmony_ci            HandleSdkDumpRequest(connectionFd, request);
259800b99b8Sopenharmony_ci            break;
260800b99b8Sopenharmony_ci        case static_cast<int32_t>(FaultLoggerClientType::PIPE_FD_CLIENT):
261800b99b8Sopenharmony_ci            HandlePipeFdClientRequest(connectionFd, request);
262800b99b8Sopenharmony_ci            break;
263800b99b8Sopenharmony_ci        case static_cast<int32_t>(FaultLoggerClientType::REPORT_EXCEPTION_CLIENT):
264800b99b8Sopenharmony_ci            HandleExceptionRequest(connectionFd, request);
265800b99b8Sopenharmony_ci            break;
266800b99b8Sopenharmony_ci        default:
267800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: unknown clientType(%{public}d).\n", FAULTLOGGERD_TAG.c_str(), request->clientType);
268800b99b8Sopenharmony_ci            break;
269800b99b8Sopenharmony_ci        }
270800b99b8Sopenharmony_ci}
271800b99b8Sopenharmony_ci
272800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleRequest(int32_t epollFd, int32_t connectionFd)
273800b99b8Sopenharmony_ci{
274800b99b8Sopenharmony_ci    if (epollFd < 0 || connectionFd < 3) { // 3: not allow fd = 0,1,2 because they are reserved by system
275800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: HandleRequest recieved invalid fd parmeters.", FAULTLOGGERD_TAG.c_str());
276800b99b8Sopenharmony_ci        return;
277800b99b8Sopenharmony_ci    }
278800b99b8Sopenharmony_ci
279800b99b8Sopenharmony_ci    std::vector<uint8_t> buf(REQUEST_BUF_SIZE, 0);
280800b99b8Sopenharmony_ci    do {
281800b99b8Sopenharmony_ci        ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, buf.data(), REQUEST_BUF_SIZE));
282800b99b8Sopenharmony_ci        if (CheckReadRequest(nread, sizeof(FaultLoggerdStatsRequest))) {
283800b99b8Sopenharmony_ci            HandleDumpStats(connectionFd, reinterpret_cast<FaultLoggerdStatsRequest *>(buf.data()));
284800b99b8Sopenharmony_ci            break;
285800b99b8Sopenharmony_ci        }
286800b99b8Sopenharmony_ci        if (!CheckReadRequest(nread, sizeof(FaultLoggerdRequest))) {
287800b99b8Sopenharmony_ci            break;
288800b99b8Sopenharmony_ci        }
289800b99b8Sopenharmony_ci        auto request = reinterpret_cast<FaultLoggerdRequest *>(buf.data());
290800b99b8Sopenharmony_ci        if (!CheckRequestCredential(connectionFd, request)) {
291800b99b8Sopenharmony_ci            break;
292800b99b8Sopenharmony_ci        }
293800b99b8Sopenharmony_ci        DFXLOGD("%{public}s :: clientType(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->clientType);
294800b99b8Sopenharmony_ci        HandleRequestByClientType(connectionFd, request);
295800b99b8Sopenharmony_ci    } while (false);
296800b99b8Sopenharmony_ci    DelEvent(eventFd_, connectionFd, EPOLLIN);
297800b99b8Sopenharmony_ci    connectionMap_.erase(connectionFd);
298800b99b8Sopenharmony_ci}
299800b99b8Sopenharmony_ci
300800b99b8Sopenharmony_cibool FaultLoggerDaemon::InitEnvironment()
301800b99b8Sopenharmony_ci{
302800b99b8Sopenharmony_ci    faultLoggerConfig_ = std::make_shared<FaultLoggerConfig>(LOG_FILE_NUMBER, LOG_FILE_SIZE,
303800b99b8Sopenharmony_ci        LOG_FILE_PATH, DEBUG_LOG_FILE_PATH);
304800b99b8Sopenharmony_ci    faultLoggerPipeMap_ = std::make_shared<FaultLoggerPipeMap>();
305800b99b8Sopenharmony_ci
306800b99b8Sopenharmony_ci    if (!OHOS::ForceCreateDirectory(faultLoggerConfig_->GetLogFilePath())) {
307800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to ForceCreateDirectory GetLogFilePath", FAULTLOGGERD_TAG.c_str());
308800b99b8Sopenharmony_ci        return false;
309800b99b8Sopenharmony_ci    }
310800b99b8Sopenharmony_ci
311800b99b8Sopenharmony_ci    signal(SIGCHLD, SIG_IGN);
312800b99b8Sopenharmony_ci    signal(SIGPIPE, SIG_IGN);
313800b99b8Sopenharmony_ci    return true;
314800b99b8Sopenharmony_ci}
315800b99b8Sopenharmony_ci
316800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleDefaultClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)
317800b99b8Sopenharmony_ci{
318800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("HandleDefaultClientRequest");
319800b99b8Sopenharmony_ci    int fd = CreateFileForRequest(request->type, request->pid, request->tid, request->time);
320800b99b8Sopenharmony_ci    if (fd < 0) {
321800b99b8Sopenharmony_ci        DFXLOGE("[%{public}d]: %{public}s :: Failed to create log file, errno(%{public}d)", __LINE__,
322800b99b8Sopenharmony_ci            FAULTLOGGERD_TAG.c_str(), errno);
323800b99b8Sopenharmony_ci        return;
324800b99b8Sopenharmony_ci    }
325800b99b8Sopenharmony_ci    RecordFileCreation(request->type, request->pid);
326800b99b8Sopenharmony_ci    SendFileDescriptorToSocket(connectionFd, fd);
327800b99b8Sopenharmony_ci
328800b99b8Sopenharmony_ci    close(fd);
329800b99b8Sopenharmony_ci}
330800b99b8Sopenharmony_ci
331800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleLogFileDesClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)
332800b99b8Sopenharmony_ci{
333800b99b8Sopenharmony_ci    int fd = CreateFileForRequest(request->type, request->pid, request->tid, request->time);
334800b99b8Sopenharmony_ci    if (fd < 0) {
335800b99b8Sopenharmony_ci        DFXLOGE("[%{public}d]: %{public}s :: Failed to create log file, errno(%{public}d)", __LINE__,
336800b99b8Sopenharmony_ci            FAULTLOGGERD_TAG.c_str(), errno);
337800b99b8Sopenharmony_ci        return;
338800b99b8Sopenharmony_ci    }
339800b99b8Sopenharmony_ci    SendFileDescriptorToSocket(connectionFd, fd);
340800b99b8Sopenharmony_ci
341800b99b8Sopenharmony_ci    close(fd);
342800b99b8Sopenharmony_ci}
343800b99b8Sopenharmony_ci
344800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleExceptionRequest(int32_t connectionFd, FaultLoggerdRequest * request)
345800b99b8Sopenharmony_ci{
346800b99b8Sopenharmony_ci    if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd,
347800b99b8Sopenharmony_ci        DAEMON_RESP.c_str(), DAEMON_RESP.length())) != static_cast<ssize_t>(DAEMON_RESP.length())) {
348800b99b8Sopenharmony_ci        DFXLOGE("[%{public}d]: %{public}s :: Failed to write DAEMON_RESP.", __LINE__, FAULTLOGGERD_TAG.c_str());
349800b99b8Sopenharmony_ci    }
350800b99b8Sopenharmony_ci
351800b99b8Sopenharmony_ci    CrashDumpException exception;
352800b99b8Sopenharmony_ci    (void)memset_s(&exception, sizeof(CrashDumpException), 0, sizeof(CrashDumpException));
353800b99b8Sopenharmony_ci    ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, &exception, sizeof(CrashDumpException)));
354800b99b8Sopenharmony_ci    exception.message[LINE_BUF_SIZE - 1] = '\0';
355800b99b8Sopenharmony_ci    if (!CheckReadRequest(nread, sizeof(CrashDumpException))) {
356800b99b8Sopenharmony_ci        return;
357800b99b8Sopenharmony_ci    }
358800b99b8Sopenharmony_ci
359800b99b8Sopenharmony_ci    ReportExceptionToSysEvent(exception);
360800b99b8Sopenharmony_ci}
361800b99b8Sopenharmony_ci
362800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
363800b99b8Sopenharmony_ci    FaultLoggerPipe2* faultLoggerPipe)
364800b99b8Sopenharmony_ci{
365800b99b8Sopenharmony_ci    FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
366800b99b8Sopenharmony_ci    if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
367800b99b8Sopenharmony_ci        return;
368800b99b8Sopenharmony_ci    }
369800b99b8Sopenharmony_ci    if ((faultLoggerPipe->faultLoggerPipeBuf_) != nullptr) {
370800b99b8Sopenharmony_ci        fd = faultLoggerPipe->faultLoggerPipeBuf_->GetReadFd();
371800b99b8Sopenharmony_ci    }
372800b99b8Sopenharmony_ci}
373800b99b8Sopenharmony_ci
374800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)
375800b99b8Sopenharmony_ci{
376800b99b8Sopenharmony_ci    if ((faultLoggerPipe->faultLoggerPipeBuf_) != nullptr) {
377800b99b8Sopenharmony_ci        fd = faultLoggerPipe->faultLoggerPipeBuf_->GetWriteFd();
378800b99b8Sopenharmony_ci    }
379800b99b8Sopenharmony_ci}
380800b99b8Sopenharmony_ci
381800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
382800b99b8Sopenharmony_ci    FaultLoggerPipe2* faultLoggerPipe)
383800b99b8Sopenharmony_ci{
384800b99b8Sopenharmony_ci    FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
385800b99b8Sopenharmony_ci    if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
386800b99b8Sopenharmony_ci        return;
387800b99b8Sopenharmony_ci    }
388800b99b8Sopenharmony_ci    if ((faultLoggerPipe->faultLoggerPipeRes_) != nullptr) {
389800b99b8Sopenharmony_ci        fd = faultLoggerPipe->faultLoggerPipeRes_->GetReadFd();
390800b99b8Sopenharmony_ci    }
391800b99b8Sopenharmony_ci}
392800b99b8Sopenharmony_ci
393800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)
394800b99b8Sopenharmony_ci{
395800b99b8Sopenharmony_ci    if ((faultLoggerPipe->faultLoggerPipeRes_) != nullptr) {
396800b99b8Sopenharmony_ci        fd = faultLoggerPipe->faultLoggerPipeRes_->GetWriteFd();
397800b99b8Sopenharmony_ci    }
398800b99b8Sopenharmony_ci}
399800b99b8Sopenharmony_ci
400800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleDelete(FaultLoggerdRequest* request)
401800b99b8Sopenharmony_ci{
402800b99b8Sopenharmony_ci    faultLoggerPipeMap_->Del(request->pid);
403800b99b8Sopenharmony_ci}
404800b99b8Sopenharmony_ci
405800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleJsonReadBuf(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
406800b99b8Sopenharmony_ci    FaultLoggerPipe2* faultLoggerPipe)
407800b99b8Sopenharmony_ci{
408800b99b8Sopenharmony_ci    FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
409800b99b8Sopenharmony_ci    if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
410800b99b8Sopenharmony_ci        return;
411800b99b8Sopenharmony_ci    }
412800b99b8Sopenharmony_ci    if ((faultLoggerPipe->faultLoggerJsonPipeBuf_) != nullptr) {
413800b99b8Sopenharmony_ci        fd = faultLoggerPipe->faultLoggerJsonPipeBuf_->GetReadFd();
414800b99b8Sopenharmony_ci    }
415800b99b8Sopenharmony_ci}
416800b99b8Sopenharmony_ci
417800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleJsonWriteBuf(int& fd, FaultLoggerPipe2* faultLoggerPipe)
418800b99b8Sopenharmony_ci{
419800b99b8Sopenharmony_ci    if ((faultLoggerPipe->faultLoggerJsonPipeBuf_) != nullptr) {
420800b99b8Sopenharmony_ci        fd = faultLoggerPipe->faultLoggerJsonPipeBuf_->GetWriteFd();
421800b99b8Sopenharmony_ci    }
422800b99b8Sopenharmony_ci}
423800b99b8Sopenharmony_ci
424800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleJsonReadRes(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
425800b99b8Sopenharmony_ci    FaultLoggerPipe2* faultLoggerPipe)
426800b99b8Sopenharmony_ci{
427800b99b8Sopenharmony_ci    FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
428800b99b8Sopenharmony_ci    if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
429800b99b8Sopenharmony_ci        return;
430800b99b8Sopenharmony_ci    }
431800b99b8Sopenharmony_ci    if ((faultLoggerPipe->faultLoggerJsonPipeRes_) != nullptr) {
432800b99b8Sopenharmony_ci        fd = faultLoggerPipe->faultLoggerJsonPipeRes_->GetReadFd();
433800b99b8Sopenharmony_ci    }
434800b99b8Sopenharmony_ci}
435800b99b8Sopenharmony_ci
436800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleJsonWriteRes(int& fd, FaultLoggerPipe2* faultLoggerPipe)
437800b99b8Sopenharmony_ci{
438800b99b8Sopenharmony_ci    if ((faultLoggerPipe->faultLoggerJsonPipeRes_) != nullptr) {
439800b99b8Sopenharmony_ci        fd = faultLoggerPipe->faultLoggerJsonPipeRes_->GetWriteFd();
440800b99b8Sopenharmony_ci    }
441800b99b8Sopenharmony_ci}
442800b99b8Sopenharmony_ci
443800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleRequestByPipeType(int& fd, int32_t connectionFd, FaultLoggerdRequest* request,
444800b99b8Sopenharmony_ci                                                FaultLoggerPipe2* faultLoggerPipe)
445800b99b8Sopenharmony_ci{
446800b99b8Sopenharmony_ci    switch (request->pipeType) {
447800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_READ_BUF: {
448800b99b8Sopenharmony_ci            HandleReadBuf(fd, connectionFd, request, faultLoggerPipe);
449800b99b8Sopenharmony_ci            break;
450800b99b8Sopenharmony_ci        }
451800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_WRITE_BUF: {
452800b99b8Sopenharmony_ci            HandleWriteBuf(fd, faultLoggerPipe);
453800b99b8Sopenharmony_ci            break;
454800b99b8Sopenharmony_ci        }
455800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_READ_RES: {
456800b99b8Sopenharmony_ci            HandleReadRes(fd, connectionFd, request, faultLoggerPipe);
457800b99b8Sopenharmony_ci            break;
458800b99b8Sopenharmony_ci        }
459800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_WRITE_RES: {
460800b99b8Sopenharmony_ci            HandleWriteRes(fd, faultLoggerPipe);
461800b99b8Sopenharmony_ci            break;
462800b99b8Sopenharmony_ci        }
463800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_DELETE: {
464800b99b8Sopenharmony_ci            HandleDelete(request);
465800b99b8Sopenharmony_ci            return;
466800b99b8Sopenharmony_ci        }
467800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF: {
468800b99b8Sopenharmony_ci            HandleJsonReadBuf(fd, connectionFd, request, faultLoggerPipe);
469800b99b8Sopenharmony_ci            break;
470800b99b8Sopenharmony_ci        }
471800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_WRITE_BUF: {
472800b99b8Sopenharmony_ci            HandleJsonWriteBuf(fd, faultLoggerPipe);
473800b99b8Sopenharmony_ci            break;
474800b99b8Sopenharmony_ci        }
475800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_READ_RES: {
476800b99b8Sopenharmony_ci            HandleJsonReadRes(fd, connectionFd, request, faultLoggerPipe);
477800b99b8Sopenharmony_ci            break;
478800b99b8Sopenharmony_ci        }
479800b99b8Sopenharmony_ci        case (int32_t)FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES: {
480800b99b8Sopenharmony_ci            HandleJsonWriteRes(fd, faultLoggerPipe);
481800b99b8Sopenharmony_ci            break;
482800b99b8Sopenharmony_ci        }
483800b99b8Sopenharmony_ci        default:
484800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: unknown pipeType(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->pipeType);
485800b99b8Sopenharmony_ci            return;
486800b99b8Sopenharmony_ci    }
487800b99b8Sopenharmony_ci}
488800b99b8Sopenharmony_ci
489800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandlePipeFdClientRequest(int32_t connectionFd, FaultLoggerdRequest * request)
490800b99b8Sopenharmony_ci{
491800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("HandlePipeFdClientRequest");
492800b99b8Sopenharmony_ci    DFXLOGD("%{public}s :: pid(%{public}d), pipeType(%{public}d).", FAULTLOGGERD_TAG.c_str(),
493800b99b8Sopenharmony_ci        request->pid, request->pipeType);
494800b99b8Sopenharmony_ci    int fd = -1;
495800b99b8Sopenharmony_ci    FaultLoggerPipe2* faultLoggerPipe = faultLoggerPipeMap_->Get(request->pid);
496800b99b8Sopenharmony_ci    if (faultLoggerPipe == nullptr) {
497800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: cannot find pipe fd for pid(%{public}d).", FAULTLOGGERD_TAG.c_str(), request->pid);
498800b99b8Sopenharmony_ci        return;
499800b99b8Sopenharmony_ci    }
500800b99b8Sopenharmony_ci    HandleRequestByPipeType(fd, connectionFd, request, faultLoggerPipe);
501800b99b8Sopenharmony_ci    if (fd < 0) {
502800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to get pipe fd, pipeType(%{public}d)",
503800b99b8Sopenharmony_ci            FAULTLOGGERD_TAG.c_str(), request->pipeType);
504800b99b8Sopenharmony_ci        return;
505800b99b8Sopenharmony_ci    }
506800b99b8Sopenharmony_ci    SendFileDescriptorToSocket(connectionFd, fd);
507800b99b8Sopenharmony_ci}
508800b99b8Sopenharmony_ci
509800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandlePrintTHilogClientRequest(int32_t const connectionFd, FaultLoggerdRequest * request)
510800b99b8Sopenharmony_ci{
511800b99b8Sopenharmony_ci    char buf[LINE_BUF_SIZE] = {0};
512800b99b8Sopenharmony_ci
513800b99b8Sopenharmony_ci    if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd,
514800b99b8Sopenharmony_ci        DAEMON_RESP.c_str(), DAEMON_RESP.length())) != static_cast<ssize_t>(DAEMON_RESP.length())) {
515800b99b8Sopenharmony_ci        DFXLOGE("[%{public}d]: %{public}s :: Failed to write DAEMON_RESP.", __LINE__, FAULTLOGGERD_TAG.c_str());
516800b99b8Sopenharmony_ci    }
517800b99b8Sopenharmony_ci
518800b99b8Sopenharmony_ci    int nread = OHOS_TEMP_FAILURE_RETRY(read(connectionFd, buf, sizeof(buf) - 1));
519800b99b8Sopenharmony_ci    if (nread < 0) {
520800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to read message, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
521800b99b8Sopenharmony_ci    } else if (nread == 0) {
522800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: HandlePrintTHilogClientRequest :: Read null from request socket",
523800b99b8Sopenharmony_ci            FAULTLOGGERD_TAG.c_str());
524800b99b8Sopenharmony_ci    } else {
525800b99b8Sopenharmony_ci        DFXLOGE("%{public}s", buf);
526800b99b8Sopenharmony_ci    }
527800b99b8Sopenharmony_ci}
528800b99b8Sopenharmony_ci
529800b99b8Sopenharmony_ciFaultLoggerCheckPermissionResp FaultLoggerDaemon::SecurityCheck(int32_t connectionFd, FaultLoggerdRequest * request)
530800b99b8Sopenharmony_ci{
531800b99b8Sopenharmony_ci    FaultLoggerCheckPermissionResp resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
532800b99b8Sopenharmony_ci
533800b99b8Sopenharmony_ci    struct ucred rcred;
534800b99b8Sopenharmony_ci    do {
535800b99b8Sopenharmony_ci        int optval = 1;
536800b99b8Sopenharmony_ci        if (OHOS_TEMP_FAILURE_RETRY(setsockopt(connectionFd,
537800b99b8Sopenharmony_ci            SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval))) == -1) {
538800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: setsockopt SO_PASSCRED error, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
539800b99b8Sopenharmony_ci            break;
540800b99b8Sopenharmony_ci        }
541800b99b8Sopenharmony_ci
542800b99b8Sopenharmony_ci        if (OHOS_TEMP_FAILURE_RETRY(write(connectionFd, DAEMON_RESP.c_str(), DAEMON_RESP.length())) !=
543800b99b8Sopenharmony_ci            static_cast<ssize_t>(DAEMON_RESP.length())) {
544800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: Failed to write DAEMON_RESP, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
545800b99b8Sopenharmony_ci            break;
546800b99b8Sopenharmony_ci        }
547800b99b8Sopenharmony_ci
548800b99b8Sopenharmony_ci        if (!RecvMsgCredFromSocket(connectionFd, &rcred)) {
549800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: Recv msg ucred error, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
550800b99b8Sopenharmony_ci            break;
551800b99b8Sopenharmony_ci        }
552800b99b8Sopenharmony_ci
553800b99b8Sopenharmony_ci        request->uid = rcred.uid;
554800b99b8Sopenharmony_ci        request->callerPid = static_cast<int32_t>(rcred.pid);
555800b99b8Sopenharmony_ci
556800b99b8Sopenharmony_ci        auto it = connectionMap_.find(connectionFd);
557800b99b8Sopenharmony_ci        if (it == connectionMap_.end()) {
558800b99b8Sopenharmony_ci            break;
559800b99b8Sopenharmony_ci        }
560800b99b8Sopenharmony_ci
561800b99b8Sopenharmony_ci        if (it->second == sdkdumpSocketFd_) {
562800b99b8Sopenharmony_ci            resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS;
563800b99b8Sopenharmony_ci            break;
564800b99b8Sopenharmony_ci        }
565800b99b8Sopenharmony_ci
566800b99b8Sopenharmony_ci        bool res = CheckCallerUID(request->uid);
567800b99b8Sopenharmony_ci        if (res) {
568800b99b8Sopenharmony_ci            resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS;
569800b99b8Sopenharmony_ci        }
570800b99b8Sopenharmony_ci    } while (false);
571800b99b8Sopenharmony_ci
572800b99b8Sopenharmony_ci    return resCheckPermission;
573800b99b8Sopenharmony_ci}
574800b99b8Sopenharmony_ci
575800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandlePermissionRequest(int32_t connectionFd, FaultLoggerdRequest * request)
576800b99b8Sopenharmony_ci{
577800b99b8Sopenharmony_ci    FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
578800b99b8Sopenharmony_ci    if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS == resSecurityCheck) {
579800b99b8Sopenharmony_ci        OHOS_TEMP_FAILURE_RETRY(send(connectionFd, "1", strlen("1"), 0));
580800b99b8Sopenharmony_ci    }
581800b99b8Sopenharmony_ci    if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT == resSecurityCheck) {
582800b99b8Sopenharmony_ci        OHOS_TEMP_FAILURE_RETRY(send(connectionFd, "2", strlen("2"), 0));
583800b99b8Sopenharmony_ci    }
584800b99b8Sopenharmony_ci}
585800b99b8Sopenharmony_ci
586800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleSdkDumpRequest(int32_t connectionFd, FaultLoggerdRequest * request)
587800b99b8Sopenharmony_ci{
588800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("HandleSdkDumpRequest");
589800b99b8Sopenharmony_ci    DFXLOGI("Receive dump request for pid:%{public}d tid:%{public}d.", request->pid, request->tid);
590800b99b8Sopenharmony_ci    FaultLoggerSdkDumpResp resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_PASS;
591800b99b8Sopenharmony_ci    FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
592800b99b8Sopenharmony_ci
593800b99b8Sopenharmony_ci    /*
594800b99b8Sopenharmony_ci    *           all     threads my user, local pid             my user, remote pid     other user's process
595800b99b8Sopenharmony_ci    * 3rd       Y       Y(in signal_handler local)     Y(in signal_handler loacl)      N
596800b99b8Sopenharmony_ci    * system    Y       Y(in signal_handler local)     Y(in signal_handler loacl)      Y(in signal_handler remote)
597800b99b8Sopenharmony_ci    * root      Y       Y(in signal_handler local)     Y(in signal_handler loacl)      Y(in signal_handler remote)
598800b99b8Sopenharmony_ci    */
599800b99b8Sopenharmony_ci
600800b99b8Sopenharmony_ci    /*
601800b99b8Sopenharmony_ci    * 1. pid != 0 && tid != 0:    means we want dump a thread, so we send signal to a thread.
602800b99b8Sopenharmony_ci        Main thread stack is tid's stack, we need ignore other thread info.
603800b99b8Sopenharmony_ci    * 2. pid != 0 && tid == 0:    means we want dump a process, so we send signal to process.
604800b99b8Sopenharmony_ci        Main thead stack is pid's stack, we need other tread info.
605800b99b8Sopenharmony_ci    */
606800b99b8Sopenharmony_ci
607800b99b8Sopenharmony_ci    /*
608800b99b8Sopenharmony_ci     * in signal_handler we need to check caller pid and tid(which is send to signal handler by SYS_rt_sig.).
609800b99b8Sopenharmony_ci     * 1. caller pid == signal pid, means we do back trace in ourself process, means local backtrace.
610800b99b8Sopenharmony_ci     *      |- we do all tid back trace in signal handler's local unwind.
611800b99b8Sopenharmony_ci     * 2. pid != signal pid, means we do remote back trace.
612800b99b8Sopenharmony_ci     */
613800b99b8Sopenharmony_ci
614800b99b8Sopenharmony_ci    /*
615800b99b8Sopenharmony_ci     * in local back trace, all unwind stack will save to signal_handler global var.(mutex lock in signal handler.)
616800b99b8Sopenharmony_ci     * in remote back trace, all unwind stack will save to file, and read in dump_catcher, then return.
617800b99b8Sopenharmony_ci     */
618800b99b8Sopenharmony_ci
619800b99b8Sopenharmony_ci    do {
620800b99b8Sopenharmony_ci        if ((request->pid <= 0) || (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT == resSecurityCheck)) {
621800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: HandleSdkDumpRequest :: pid(%{public}d) or resSecurityCheck(%{public}d) fail.\n", \
622800b99b8Sopenharmony_ci                FAULTLOGGERD_TAG.c_str(), request->pid, (int)resSecurityCheck);
623800b99b8Sopenharmony_ci            resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_REJECT;
624800b99b8Sopenharmony_ci            break;
625800b99b8Sopenharmony_ci        }
626800b99b8Sopenharmony_ci        DFXLOGI("Sdk dump pid(%{public}d) request pass permission verification.", request->pid);
627800b99b8Sopenharmony_ci        if (IsCrashed(request->pid)) {
628800b99b8Sopenharmony_ci            resSdkDump = FaultLoggerSdkDumpResp::SDK_PROCESS_CRASHED;
629800b99b8Sopenharmony_ci            DFXLOGW("%{public}s :: pid(%{public}d) has been crashed, break.\n",
630800b99b8Sopenharmony_ci                FAULTLOGGERD_TAG.c_str(), request->pid);
631800b99b8Sopenharmony_ci            break;
632800b99b8Sopenharmony_ci        }
633800b99b8Sopenharmony_ci        if (faultLoggerPipeMap_->Check(request->pid, request->time)) {
634800b99b8Sopenharmony_ci            resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_REPEAT;
635800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: pid(%{public}d) is dumping, break.\n", FAULTLOGGERD_TAG.c_str(), request->pid);
636800b99b8Sopenharmony_ci            break;
637800b99b8Sopenharmony_ci        }
638800b99b8Sopenharmony_ci        faultLoggerPipeMap_->Set(request->pid, request->time, request->isJson);
639800b99b8Sopenharmony_ci
640800b99b8Sopenharmony_ci#pragma clang diagnostic push
641800b99b8Sopenharmony_ci#pragma clang diagnostic ignored "-Winitializer-overrides"
642800b99b8Sopenharmony_ci        // defined in out/hi3516dv300/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/signal.h
643800b99b8Sopenharmony_ci        siginfo_t si {0};
644800b99b8Sopenharmony_ci        si.si_signo = SIGDUMP;
645800b99b8Sopenharmony_ci        si.si_errno = 0;
646800b99b8Sopenharmony_ci        si.si_value.sival_int = request->tid;
647800b99b8Sopenharmony_ci        if (request->tid == 0 && sizeof(void *) == 8) { // 8 : platform 64
648800b99b8Sopenharmony_ci            si.si_value.sival_ptr = reinterpret_cast<void *>(request->endTime | (1ULL << 63)); // 63 : platform 64
649800b99b8Sopenharmony_ci        }
650800b99b8Sopenharmony_ci        si.si_code = request->sigCode;
651800b99b8Sopenharmony_ci        si.si_pid = request->callerPid;
652800b99b8Sopenharmony_ci        si.si_uid = static_cast<uid_t>(request->callerTid);
653800b99b8Sopenharmony_ci#pragma clang diagnostic pop
654800b99b8Sopenharmony_ci        /*
655800b99b8Sopenharmony_ci         * means we need dump all the threads in a process
656800b99b8Sopenharmony_ci         * --------
657800b99b8Sopenharmony_ci         * Accroding to the linux manual, A process-directed signal may be delivered to any one of the
658800b99b8Sopenharmony_ci         * threads that does not currently have the signal blocked.
659800b99b8Sopenharmony_ci         */
660800b99b8Sopenharmony_ci        if (syscall(SYS_rt_sigqueueinfo, request->pid, si.si_signo, &si) != 0) {
661800b99b8Sopenharmony_ci            DFXLOGE("Failed to SYS_rt_sigqueueinfo signal(%{public}d), errno(%{public}d).", si.si_signo, errno);
662800b99b8Sopenharmony_ci            resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_NOPROC;
663800b99b8Sopenharmony_ci        }
664800b99b8Sopenharmony_ci    } while (false);
665800b99b8Sopenharmony_ci    auto retMsg = std::to_string(resSdkDump);
666800b99b8Sopenharmony_ci    if (OHOS_TEMP_FAILURE_RETRY(send(connectionFd, retMsg.data(), retMsg.length(), 0)) !=
667800b99b8Sopenharmony_ci        static_cast<ssize_t>(retMsg.length())) {
668800b99b8Sopenharmony_ci        DFXLOGE("Failed to send result message to client, errno(%{public}d).", errno);
669800b99b8Sopenharmony_ci    }
670800b99b8Sopenharmony_ci}
671800b99b8Sopenharmony_ci
672800b99b8Sopenharmony_civoid FaultLoggerDaemon::RecordFileCreation(int32_t type, int32_t pid)
673800b99b8Sopenharmony_ci{
674800b99b8Sopenharmony_ci    if (type == static_cast<int32_t>(FaultLoggerType::CPP_CRASH)) {
675800b99b8Sopenharmony_ci        ClearTimeOutRecords();
676800b99b8Sopenharmony_ci        crashTimeMap_[pid] = time(nullptr);
677800b99b8Sopenharmony_ci    }
678800b99b8Sopenharmony_ci}
679800b99b8Sopenharmony_ci
680800b99b8Sopenharmony_civoid FaultLoggerDaemon::ClearTimeOutRecords()
681800b99b8Sopenharmony_ci{
682800b99b8Sopenharmony_ci    constexpr int validTime = 8;
683800b99b8Sopenharmony_ci    auto currentTime = time(nullptr);
684800b99b8Sopenharmony_ci    for (auto it = crashTimeMap_.begin(); it != crashTimeMap_.end();) {
685800b99b8Sopenharmony_ci        if ((it->second + validTime) <= currentTime) {
686800b99b8Sopenharmony_ci            crashTimeMap_.erase(it++);
687800b99b8Sopenharmony_ci        } else {
688800b99b8Sopenharmony_ci            it++;
689800b99b8Sopenharmony_ci        }
690800b99b8Sopenharmony_ci    }
691800b99b8Sopenharmony_ci}
692800b99b8Sopenharmony_ci
693800b99b8Sopenharmony_cibool FaultLoggerDaemon::IsCrashed(int32_t pid)
694800b99b8Sopenharmony_ci{
695800b99b8Sopenharmony_ci    DFX_TRACE_SCOPED("IsCrashed");
696800b99b8Sopenharmony_ci    ClearTimeOutRecords();
697800b99b8Sopenharmony_ci    return crashTimeMap_.find(pid) != crashTimeMap_.end();
698800b99b8Sopenharmony_ci}
699800b99b8Sopenharmony_ci
700800b99b8Sopenharmony_ciint32_t FaultLoggerDaemon::CreateFileForRequest(int32_t type, int32_t pid, int32_t tid, uint64_t time) const
701800b99b8Sopenharmony_ci{
702800b99b8Sopenharmony_ci    RemoveTempFileIfNeed();
703800b99b8Sopenharmony_ci    std::string typeStr = GetRequestTypeName(type);
704800b99b8Sopenharmony_ci    if (typeStr == "unsupported") {
705800b99b8Sopenharmony_ci        DFXLOGE("Unsupported request type(%{public}d)", type);
706800b99b8Sopenharmony_ci        return -1;
707800b99b8Sopenharmony_ci    }
708800b99b8Sopenharmony_ci
709800b99b8Sopenharmony_ci    std::string folderPath = "";
710800b99b8Sopenharmony_ci    folderPath = faultLoggerConfig_->GetLogFilePath();
711800b99b8Sopenharmony_ci
712800b99b8Sopenharmony_ci    if (time == 0) {
713800b99b8Sopenharmony_ci        time = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>\
714800b99b8Sopenharmony_ci            (std::chrono::system_clock::now().time_since_epoch()).count());
715800b99b8Sopenharmony_ci    }
716800b99b8Sopenharmony_ci
717800b99b8Sopenharmony_ci    std::string ss = folderPath + "/" + typeStr + "-" + std::to_string(pid);
718800b99b8Sopenharmony_ci    if (type == FaultLoggerType::JS_HEAP_SNAPSHOT || type == FaultLoggerType::JS_RAW_SNAPSHOT) {
719800b99b8Sopenharmony_ci        ss += "-" + std::to_string(tid);
720800b99b8Sopenharmony_ci    }
721800b99b8Sopenharmony_ci    ss += "-" + std::to_string(time);
722800b99b8Sopenharmony_ci    if (type == FaultLoggerType::JS_RAW_SNAPSHOT) {
723800b99b8Sopenharmony_ci        ss += ".rawheap";
724800b99b8Sopenharmony_ci    }
725800b99b8Sopenharmony_ci    const std::string path = ss;
726800b99b8Sopenharmony_ci    DFXLOGI("%{public}s :: file path(%{public}s).\n", FAULTLOGGERD_TAG.c_str(), path.c_str());
727800b99b8Sopenharmony_ci    if (!VerifyFilePath(path, VALID_FILE_PATH)) {
728800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Open %{public}s fail, please check it under valid path.\n",
729800b99b8Sopenharmony_ci            FAULTLOGGERD_TAG.c_str(), path.c_str());
730800b99b8Sopenharmony_ci        return -1;
731800b99b8Sopenharmony_ci    }
732800b99b8Sopenharmony_ci    int32_t fd = OHOS_TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CREAT, FAULTLOG_FILE_PROP));
733800b99b8Sopenharmony_ci    if (fd != -1) {
734800b99b8Sopenharmony_ci        if (!ChangeModeFile(path, FAULTLOG_FILE_PROP)) {
735800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: Failed to ChangeMode CreateFileForRequest", FAULTLOGGERD_TAG.c_str());
736800b99b8Sopenharmony_ci        }
737800b99b8Sopenharmony_ci    }
738800b99b8Sopenharmony_ci    return fd;
739800b99b8Sopenharmony_ci}
740800b99b8Sopenharmony_ci
741800b99b8Sopenharmony_civoid FaultLoggerDaemon::RemoveTempFileIfNeed() const
742800b99b8Sopenharmony_ci{
743800b99b8Sopenharmony_ci    int maxFileCount = 50;
744800b99b8Sopenharmony_ci    int currentLogCounts = 0;
745800b99b8Sopenharmony_ci
746800b99b8Sopenharmony_ci    std::string logFilePath = faultLoggerConfig_->GetLogFilePath();
747800b99b8Sopenharmony_ci    std::vector<std::string> files;
748800b99b8Sopenharmony_ci    OHOS::GetDirFiles(logFilePath, files);
749800b99b8Sopenharmony_ci    constexpr uint64_t maxFileSize = 1lu << 31; // 2GB
750800b99b8Sopenharmony_ci    if (!isBeta_ && OHOS::GetFolderSize(logFilePath) > maxFileSize) {
751800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: current file size is over limit, clear all files", FAULTLOGGERD_TAG.c_str());
752800b99b8Sopenharmony_ci        std::for_each(files.begin(), files.end(), OHOS::RemoveFile);
753800b99b8Sopenharmony_ci        return;
754800b99b8Sopenharmony_ci    }
755800b99b8Sopenharmony_ci    currentLogCounts = (int)files.size();
756800b99b8Sopenharmony_ci    maxFileCount = faultLoggerConfig_->GetLogFileMaxNumber();
757800b99b8Sopenharmony_ci    if (currentLogCounts < maxFileCount) {
758800b99b8Sopenharmony_ci        return;
759800b99b8Sopenharmony_ci    }
760800b99b8Sopenharmony_ci
761800b99b8Sopenharmony_ci    std::sort(files.begin(), files.end(),
762800b99b8Sopenharmony_ci        [](const std::string& lhs, const std::string& rhs) -> int {
763800b99b8Sopenharmony_ci        auto lhsSplitPos = lhs.find_last_of("-");
764800b99b8Sopenharmony_ci        auto rhsSplitPos = rhs.find_last_of("-");
765800b99b8Sopenharmony_ci        if (lhsSplitPos == std::string::npos || rhsSplitPos == std::string::npos) {
766800b99b8Sopenharmony_ci            return lhs.compare(rhs) > 0;
767800b99b8Sopenharmony_ci        }
768800b99b8Sopenharmony_ci
769800b99b8Sopenharmony_ci        return lhs.substr(lhsSplitPos).compare(rhs.substr(rhsSplitPos)) > 0;
770800b99b8Sopenharmony_ci    });
771800b99b8Sopenharmony_ci
772800b99b8Sopenharmony_ci    time_t currentTime = static_cast<time_t>(time(nullptr));
773800b99b8Sopenharmony_ci    if (currentTime <= 0) {
774800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: currentTime is less than zero CreateFileForRequest", FAULTLOGGERD_TAG.c_str());
775800b99b8Sopenharmony_ci    }
776800b99b8Sopenharmony_ci
777800b99b8Sopenharmony_ci    constexpr int deleteNum = 1;
778800b99b8Sopenharmony_ci    int startIndex = maxFileCount > deleteNum ? maxFileCount - deleteNum : maxFileCount;
779800b99b8Sopenharmony_ci    for (unsigned int index = (unsigned int)startIndex; index < files.size(); index++) {
780800b99b8Sopenharmony_ci        struct stat st;
781800b99b8Sopenharmony_ci        int err = stat(files[index].c_str(), &st);
782800b99b8Sopenharmony_ci        if (err != 0) {
783800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: Get log stat failed, errno(%{public}d).", FAULTLOGGERD_TAG.c_str(), errno);
784800b99b8Sopenharmony_ci        } else {
785800b99b8Sopenharmony_ci            if ((currentTime - st.st_mtime) <= DAEMON_REMOVE_FILE_TIME_S) {
786800b99b8Sopenharmony_ci                continue;
787800b99b8Sopenharmony_ci            }
788800b99b8Sopenharmony_ci        }
789800b99b8Sopenharmony_ci
790800b99b8Sopenharmony_ci        OHOS::RemoveFile(files[index]);
791800b99b8Sopenharmony_ci        DFXLOGD("%{public}s :: Now we rm file(%{public}s) as max log number exceeded.", \
792800b99b8Sopenharmony_ci            FAULTLOGGERD_TAG.c_str(), files[index].c_str());
793800b99b8Sopenharmony_ci    }
794800b99b8Sopenharmony_ci}
795800b99b8Sopenharmony_ci
796800b99b8Sopenharmony_civoid FaultLoggerDaemon::AddEvent(int32_t epollFd, int32_t addFd, uint32_t event)
797800b99b8Sopenharmony_ci{
798800b99b8Sopenharmony_ci    epoll_event ev;
799800b99b8Sopenharmony_ci    ev.events = event;
800800b99b8Sopenharmony_ci    ev.data.fd = addFd;
801800b99b8Sopenharmony_ci    int ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, addFd, &ev);
802800b99b8Sopenharmony_ci    if (ret < 0) {
803800b99b8Sopenharmony_ci        DFXLOGW("%{public}s :: Failed to epoll ctl add Fd(%{public}d), errno(%{public}d)",
804800b99b8Sopenharmony_ci            FAULTLOGGERD_TAG.c_str(), addFd, errno);
805800b99b8Sopenharmony_ci    }
806800b99b8Sopenharmony_ci}
807800b99b8Sopenharmony_ci
808800b99b8Sopenharmony_civoid FaultLoggerDaemon::DelEvent(int32_t epollFd, int32_t delFd, uint32_t event)
809800b99b8Sopenharmony_ci{
810800b99b8Sopenharmony_ci    epoll_event ev;
811800b99b8Sopenharmony_ci    ev.events = event;
812800b99b8Sopenharmony_ci    ev.data.fd = delFd;
813800b99b8Sopenharmony_ci    int ret = epoll_ctl(epollFd, EPOLL_CTL_DEL, delFd, &ev);
814800b99b8Sopenharmony_ci    if (ret < 0) {
815800b99b8Sopenharmony_ci        DFXLOGW("%{public}s :: Failed to epoll ctl del Fd(%{public}d), errno(%{public}d)",
816800b99b8Sopenharmony_ci            FAULTLOGGERD_TAG.c_str(), delFd, errno);
817800b99b8Sopenharmony_ci    }
818800b99b8Sopenharmony_ci    close(delFd);
819800b99b8Sopenharmony_ci}
820800b99b8Sopenharmony_ci
821800b99b8Sopenharmony_cibool FaultLoggerDaemon::CheckRequestCredential(int32_t connectionFd, FaultLoggerdRequest* request)
822800b99b8Sopenharmony_ci{
823800b99b8Sopenharmony_ci    if (request == nullptr) {
824800b99b8Sopenharmony_ci        return false;
825800b99b8Sopenharmony_ci    }
826800b99b8Sopenharmony_ci
827800b99b8Sopenharmony_ci    auto it = connectionMap_.find(connectionFd);
828800b99b8Sopenharmony_ci    if (it == connectionMap_.end()) {
829800b99b8Sopenharmony_ci        DFXLOGE("%{public}s : Failed to find fd:%{public}d, map size:%{public}zu", FAULTLOGGERD_TAG.c_str(),
830800b99b8Sopenharmony_ci            connectionFd, connectionMap_.size());
831800b99b8Sopenharmony_ci        return false;
832800b99b8Sopenharmony_ci    }
833800b99b8Sopenharmony_ci
834800b99b8Sopenharmony_ci    if (it->second == crashSocketFd_ || it->second == sdkdumpSocketFd_) {
835800b99b8Sopenharmony_ci        // only processdump use this socket
836800b99b8Sopenharmony_ci        return true;
837800b99b8Sopenharmony_ci    }
838800b99b8Sopenharmony_ci
839800b99b8Sopenharmony_ci    struct ucred creds = {};
840800b99b8Sopenharmony_ci    socklen_t credSize = sizeof(creds);
841800b99b8Sopenharmony_ci    int err = getsockopt(connectionFd, SOL_SOCKET, SO_PEERCRED, &creds, &credSize);
842800b99b8Sopenharmony_ci    if (err != 0) {
843800b99b8Sopenharmony_ci        DFXLOGE("%{public}s :: Failed to CheckRequestCredential, errno(%{public}d)", FAULTLOGGERD_TAG.c_str(), errno);
844800b99b8Sopenharmony_ci        return false;
845800b99b8Sopenharmony_ci    }
846800b99b8Sopenharmony_ci
847800b99b8Sopenharmony_ci    if (CheckCallerUID(creds.uid)) {
848800b99b8Sopenharmony_ci        return true;
849800b99b8Sopenharmony_ci    }
850800b99b8Sopenharmony_ci
851800b99b8Sopenharmony_ci    bool isCredentialMatched = (creds.pid == request->pid);
852800b99b8Sopenharmony_ci    if (request->clientType == (int32_t)REPORT_EXCEPTION_CLIENT) {
853800b99b8Sopenharmony_ci        isCredentialMatched = (creds.uid == request->uid);   /* check uid when report exception */
854800b99b8Sopenharmony_ci    }
855800b99b8Sopenharmony_ci    if (!isCredentialMatched) {
856800b99b8Sopenharmony_ci        DFXLOGW("Failed to check request credential request:%{public}d:" \
857800b99b8Sopenharmony_ci            "%{public}d cred:%{public}d:%{public}d fd:%{public}d:%{public}d",
858800b99b8Sopenharmony_ci            request->pid, request->uid, creds.pid, creds.uid, it->second, crashSocketFd_);
859800b99b8Sopenharmony_ci    }
860800b99b8Sopenharmony_ci    return isCredentialMatched;
861800b99b8Sopenharmony_ci}
862800b99b8Sopenharmony_ci
863800b99b8Sopenharmony_cibool FaultLoggerDaemon::CreateSockets()
864800b99b8Sopenharmony_ci{
865800b99b8Sopenharmony_ci    if (!StartListen(defaultSocketFd_, SERVER_SOCKET_NAME, MAX_CONNECTION)) {
866800b99b8Sopenharmony_ci        return false;
867800b99b8Sopenharmony_ci    }
868800b99b8Sopenharmony_ci
869800b99b8Sopenharmony_ci    if (!StartListen(crashSocketFd_, SERVER_CRASH_SOCKET_NAME, MAX_CONNECTION)) {
870800b99b8Sopenharmony_ci        close(defaultSocketFd_);
871800b99b8Sopenharmony_ci        defaultSocketFd_ = -1;
872800b99b8Sopenharmony_ci        return false;
873800b99b8Sopenharmony_ci    }
874800b99b8Sopenharmony_ci#ifndef is_ohos_lite
875800b99b8Sopenharmony_ci    if (!StartListen(sdkdumpSocketFd_, SERVER_SDKDUMP_SOCKET_NAME, MAX_CONNECTION)) {
876800b99b8Sopenharmony_ci        close(defaultSocketFd_);
877800b99b8Sopenharmony_ci        defaultSocketFd_ = -1;
878800b99b8Sopenharmony_ci        close(crashSocketFd_);
879800b99b8Sopenharmony_ci        crashSocketFd_ = -1;
880800b99b8Sopenharmony_ci        return false;
881800b99b8Sopenharmony_ci    }
882800b99b8Sopenharmony_ci#endif
883800b99b8Sopenharmony_ci    return true;
884800b99b8Sopenharmony_ci}
885800b99b8Sopenharmony_ci
886800b99b8Sopenharmony_civoid FaultLoggerDaemon::CleanupSockets()
887800b99b8Sopenharmony_ci{
888800b99b8Sopenharmony_ci    if (defaultSocketFd_ >= 0) {
889800b99b8Sopenharmony_ci        close(defaultSocketFd_);
890800b99b8Sopenharmony_ci        defaultSocketFd_ = -1;
891800b99b8Sopenharmony_ci    }
892800b99b8Sopenharmony_ci
893800b99b8Sopenharmony_ci    if (crashSocketFd_ >= 0) {
894800b99b8Sopenharmony_ci        close(crashSocketFd_);
895800b99b8Sopenharmony_ci        crashSocketFd_ = -1;
896800b99b8Sopenharmony_ci    }
897800b99b8Sopenharmony_ci
898800b99b8Sopenharmony_ci    if (sdkdumpSocketFd_ >= 0) {
899800b99b8Sopenharmony_ci        close(sdkdumpSocketFd_);
900800b99b8Sopenharmony_ci        sdkdumpSocketFd_ = -1;
901800b99b8Sopenharmony_ci    }
902800b99b8Sopenharmony_ci}
903800b99b8Sopenharmony_ci
904800b99b8Sopenharmony_cibool FaultLoggerDaemon::CreateEventFd()
905800b99b8Sopenharmony_ci{
906800b99b8Sopenharmony_ci    eventFd_ = epoll_create(MAX_EPOLL_EVENT);
907800b99b8Sopenharmony_ci    if (eventFd_ < 0) {
908800b99b8Sopenharmony_ci        return false;
909800b99b8Sopenharmony_ci    }
910800b99b8Sopenharmony_ci    return true;
911800b99b8Sopenharmony_ci}
912800b99b8Sopenharmony_ci
913800b99b8Sopenharmony_civoid FaultLoggerDaemon::WaitForRequest()
914800b99b8Sopenharmony_ci{
915800b99b8Sopenharmony_ci    AddEvent(eventFd_, defaultSocketFd_, EPOLLIN);
916800b99b8Sopenharmony_ci    AddEvent(eventFd_, crashSocketFd_, EPOLLIN);
917800b99b8Sopenharmony_ci    AddEvent(eventFd_, sdkdumpSocketFd_, EPOLLIN);
918800b99b8Sopenharmony_ci    epoll_event events[MAX_CONNECTION];
919800b99b8Sopenharmony_ci    DFXLOGD("%{public}s :: %{public}s: start epoll wait.", FAULTLOGGERD_TAG.c_str(), __func__);
920800b99b8Sopenharmony_ci    do {
921800b99b8Sopenharmony_ci        int epollNum = OHOS_TEMP_FAILURE_RETRY(epoll_wait(eventFd_, events, MAX_CONNECTION, -1));
922800b99b8Sopenharmony_ci        if (epollNum < 0) {
923800b99b8Sopenharmony_ci            DFXLOGE("%{public}s :: %{public}s: epoll wait error, errno(%{public}d).",
924800b99b8Sopenharmony_ci                FAULTLOGGERD_TAG.c_str(), __func__, errno);
925800b99b8Sopenharmony_ci            continue;
926800b99b8Sopenharmony_ci        }
927800b99b8Sopenharmony_ci        for (int i = 0; i < epollNum; i++) {
928800b99b8Sopenharmony_ci            if (!(events[i].events & EPOLLIN)) {
929800b99b8Sopenharmony_ci                DFXLOGW("%{public}s :: %{public}s: epoll event(%{public}d) error.",
930800b99b8Sopenharmony_ci                    FAULTLOGGERD_TAG.c_str(), __func__, events[i].events);
931800b99b8Sopenharmony_ci                continue;
932800b99b8Sopenharmony_ci            }
933800b99b8Sopenharmony_ci
934800b99b8Sopenharmony_ci            int fd = events[i].data.fd;
935800b99b8Sopenharmony_ci            if (fd == defaultSocketFd_ || fd == crashSocketFd_ || fd == sdkdumpSocketFd_) {
936800b99b8Sopenharmony_ci                HandleAccept(eventFd_, fd);
937800b99b8Sopenharmony_ci            } else {
938800b99b8Sopenharmony_ci                HandleRequest(eventFd_, fd);
939800b99b8Sopenharmony_ci            }
940800b99b8Sopenharmony_ci        }
941800b99b8Sopenharmony_ci    } while (true);
942800b99b8Sopenharmony_ci}
943800b99b8Sopenharmony_ci
944800b99b8Sopenharmony_civoid FaultLoggerDaemon::CleanupEventFd()
945800b99b8Sopenharmony_ci{
946800b99b8Sopenharmony_ci    DelEvent(eventFd_, defaultSocketFd_, EPOLLIN);
947800b99b8Sopenharmony_ci    DelEvent(eventFd_, crashSocketFd_, EPOLLIN);
948800b99b8Sopenharmony_ci    DelEvent(eventFd_, sdkdumpSocketFd_, EPOLLIN);
949800b99b8Sopenharmony_ci
950800b99b8Sopenharmony_ci    if (eventFd_ > 0) {
951800b99b8Sopenharmony_ci        close(eventFd_);
952800b99b8Sopenharmony_ci        eventFd_ = -1;
953800b99b8Sopenharmony_ci    }
954800b99b8Sopenharmony_ci}
955800b99b8Sopenharmony_ci
956800b99b8Sopenharmony_cistd::string GetElfName(FaultLoggerdStatsRequest* request)
957800b99b8Sopenharmony_ci{
958800b99b8Sopenharmony_ci    if (request == nullptr || strlen(request->callerElf) > NAME_BUF_LEN) {
959800b99b8Sopenharmony_ci        return "";
960800b99b8Sopenharmony_ci    }
961800b99b8Sopenharmony_ci
962800b99b8Sopenharmony_ci    std::string ss = StringPrintf("%s(%p)", request->callerElf, reinterpret_cast<void *>(request->offset));
963800b99b8Sopenharmony_ci    return ss;
964800b99b8Sopenharmony_ci}
965800b99b8Sopenharmony_ci
966800b99b8Sopenharmony_civoid FaultLoggerDaemon::HandleDumpStats(int32_t connectionFd, FaultLoggerdStatsRequest* request)
967800b99b8Sopenharmony_ci{
968800b99b8Sopenharmony_ci    DFXLOGI("%{public}s :: %{public}s: HandleDumpStats", FAULTLOGGERD_TAG.c_str(), __func__);
969800b99b8Sopenharmony_ci    size_t index = 0;
970800b99b8Sopenharmony_ci    bool hasRecord = false;
971800b99b8Sopenharmony_ci    for (index = 0; index < stats_.size(); index++) {
972800b99b8Sopenharmony_ci        if (stats_[index].pid == request->pid) {
973800b99b8Sopenharmony_ci            hasRecord = true;
974800b99b8Sopenharmony_ci            break;
975800b99b8Sopenharmony_ci        }
976800b99b8Sopenharmony_ci    }
977800b99b8Sopenharmony_ci
978800b99b8Sopenharmony_ci    DumpStats stats;
979800b99b8Sopenharmony_ci    if (request->type == PROCESS_DUMP && !hasRecord) {
980800b99b8Sopenharmony_ci        stats.pid = request->pid;
981800b99b8Sopenharmony_ci        stats.signalTime = request->signalTime;
982800b99b8Sopenharmony_ci        stats.processdumpStartTime = request->processdumpStartTime;
983800b99b8Sopenharmony_ci        stats.processdumpFinishTime = request->processdumpFinishTime;
984800b99b8Sopenharmony_ci        stats.targetProcessName = request->targetProcess;
985800b99b8Sopenharmony_ci        stats_.emplace_back(stats);
986800b99b8Sopenharmony_ci    } else if (request->type == DUMP_CATCHER && hasRecord) {
987800b99b8Sopenharmony_ci        stats_[index].requestTime = request->requestTime;
988800b99b8Sopenharmony_ci        stats_[index].dumpCatcherFinishTime = request->dumpCatcherFinishTime;
989800b99b8Sopenharmony_ci        stats_[index].callerElfName = GetElfName(request);
990800b99b8Sopenharmony_ci        stats_[index].callerProcessName = request->callerProcess;
991800b99b8Sopenharmony_ci        stats_[index].result = request->result;
992800b99b8Sopenharmony_ci        stats_[index].summary = request->summary;
993800b99b8Sopenharmony_ci        ReportDumpStats(stats_[index]);
994800b99b8Sopenharmony_ci        stats_.erase(stats_.begin() + index);
995800b99b8Sopenharmony_ci    } else if (request->type == DUMP_CATCHER) {
996800b99b8Sopenharmony_ci        stats.pid = request->pid;
997800b99b8Sopenharmony_ci        stats.requestTime = request->requestTime;
998800b99b8Sopenharmony_ci        stats.dumpCatcherFinishTime = request->dumpCatcherFinishTime;
999800b99b8Sopenharmony_ci        stats.callerElfName = GetElfName(request);
1000800b99b8Sopenharmony_ci        stats.result = request->result;
1001800b99b8Sopenharmony_ci        stats.callerProcessName = request->callerProcess;
1002800b99b8Sopenharmony_ci        stats.summary = request->summary;
1003800b99b8Sopenharmony_ci        stats.targetProcessName = request->targetProcess;
1004800b99b8Sopenharmony_ci        ReportDumpStats(stats);
1005800b99b8Sopenharmony_ci    }
1006800b99b8Sopenharmony_ci    RemoveTimeoutDumpStats();
1007800b99b8Sopenharmony_ci}
1008800b99b8Sopenharmony_ci
1009800b99b8Sopenharmony_civoid FaultLoggerDaemon::RemoveTimeoutDumpStats()
1010800b99b8Sopenharmony_ci{
1011800b99b8Sopenharmony_ci    const uint64_t timeout = 10000;
1012800b99b8Sopenharmony_ci    uint64_t now = GetTimeMilliSeconds();
1013800b99b8Sopenharmony_ci    for (auto it = stats_.begin(); it != stats_.end();) {
1014800b99b8Sopenharmony_ci        if (((now > it->signalTime) && (now - it->signalTime > timeout)) ||
1015800b99b8Sopenharmony_ci            (now <= it->signalTime)) {
1016800b99b8Sopenharmony_ci            it = stats_.erase(it);
1017800b99b8Sopenharmony_ci        } else {
1018800b99b8Sopenharmony_ci            ++it;
1019800b99b8Sopenharmony_ci        }
1020800b99b8Sopenharmony_ci    }
1021800b99b8Sopenharmony_ci}
1022800b99b8Sopenharmony_ci
1023800b99b8Sopenharmony_civoid FaultLoggerDaemon::ReportDumpStats(const DumpStats& stat)
1024800b99b8Sopenharmony_ci{
1025800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE
1026800b99b8Sopenharmony_ci    HiSysEventWrite(
1027800b99b8Sopenharmony_ci        HiSysEvent::Domain::HIVIEWDFX,
1028800b99b8Sopenharmony_ci        "DUMP_CATCHER_STATS",
1029800b99b8Sopenharmony_ci        HiSysEvent::EventType::STATISTIC,
1030800b99b8Sopenharmony_ci        "CALLER_PROCESS_NAME", stat.callerProcessName,
1031800b99b8Sopenharmony_ci        "CALLER_FUNC_NAME", stat.callerElfName,
1032800b99b8Sopenharmony_ci        "TARGET_PROCESS_NAME", stat.targetProcessName,
1033800b99b8Sopenharmony_ci        "RESULT", stat.result,
1034800b99b8Sopenharmony_ci        "SUMMARY", stat.summary, // we need to parse summary when interface return false
1035800b99b8Sopenharmony_ci        "PID", stat.pid,
1036800b99b8Sopenharmony_ci        "REQUEST_TIME", stat.requestTime,
1037800b99b8Sopenharmony_ci        "OVERALL_TIME", stat.dumpCatcherFinishTime - stat.requestTime,
1038800b99b8Sopenharmony_ci        "SIGNAL_TIME", stat.signalTime - stat.requestTime,
1039800b99b8Sopenharmony_ci        "DUMPER_START_TIME", stat.processdumpStartTime - stat.signalTime,
1040800b99b8Sopenharmony_ci        "UNWIND_TIME", stat.processdumpFinishTime - stat.processdumpStartTime);
1041800b99b8Sopenharmony_ci#endif
1042800b99b8Sopenharmony_ci}
1043800b99b8Sopenharmony_ci} // namespace HiviewDFX
1044800b99b8Sopenharmony_ci} // namespace OHOS
1045