• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
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 <securec.h>
26 #include <sstream>
27 #include <unistd.h>
28 #include <vector>
29 
30 #include <sys/epoll.h>
31 #include <sys/socket.h>
32 #include <sys/stat.h>
33 #include <sys/syscall.h>
34 #include <sys/types.h>
35 #include <sys/un.h>
36 #include <sys/wait.h>
37 
38 #include "dfx_define.h"
39 #include "dfx_log.h"
40 #include "dfx_util.h"
41 #include "directory_ex.h"
42 #include "fault_logger_config.h"
43 #include "fault_logger_pipe.h"
44 #include "faultloggerd_socket.h"
45 
46 namespace OHOS {
47 namespace HiviewDFX {
48 std::shared_ptr<FaultLoggerConfig> faultLoggerConfig_;
49 std::shared_ptr<FaultLoggerPipeMap> faultLoggerPipeMap_;
50 
51 namespace {
52 constexpr int32_t MAX_CONNECTION = 30;
53 constexpr int32_t REQUEST_BUF_SIZE = 1024;
54 constexpr int32_t MAX_EPOLL_EVENT = 1024;
55 const int32_t FAULTLOG_FILE_PROP = 0640;
56 
57 static constexpr uint32_t ROOT_UID = 0;
58 static constexpr uint32_t BMS_UID = 1000;
59 static constexpr uint32_t HIVIEW_UID = 1201;
60 static constexpr uint32_t HIDUMPER_SERVICE_UID = 1212;
61 static constexpr uint32_t FOUNDATION_UID = 5523;
62 static const std::string FAULTLOGGERD_TAG = "FaultLoggerd";
63 static const std::string DAEMON_RESP = "RESP:COMPLETE";
64 static const int DAEMON_REMOVE_FILE_TIME_S = 60;
65 
GetRequestTypeName(int32_t type)66 static std::string GetRequestTypeName(int32_t type)
67 {
68     switch (type) {
69         case (int32_t)FaultLoggerType::CPP_CRASH:
70             return "cppcrash";
71         case (int32_t)FaultLoggerType::CPP_STACKTRACE: // change the name to nativestack ?
72             return "stacktrace";
73         case (int32_t)FaultLoggerType::JS_STACKTRACE:
74             return "jsstack";
75         case (int32_t)FaultLoggerType::JS_HEAP_SNAPSHOT:
76             return "jsheap";
77         default:
78             return "unsupported";
79     }
80 }
81 
CheckCallerUID(uint32_t callerUid)82 static bool CheckCallerUID(uint32_t callerUid)
83 {
84     // If caller's is BMS / root or caller's uid/pid is validate, just return true
85     if ((callerUid == BMS_UID) ||
86         (callerUid == ROOT_UID) ||
87         (callerUid == HIVIEW_UID) ||
88         (callerUid == HIDUMPER_SERVICE_UID) ||
89         (callerUid == FOUNDATION_UID)) {
90         return true;
91     }
92     DFXLOG_WARN("%s :: CheckCallerUID :: Caller Uid(%d) is unexpectly.\n", FAULTLOGGERD_TAG.c_str(), callerUid);
93     return false;
94 }
95 }
96 
FaultLoggerDaemon()97 FaultLoggerDaemon::FaultLoggerDaemon()
98 {
99 }
100 
StartServer()101 int32_t FaultLoggerDaemon::StartServer()
102 {
103     if (!CreateSockets()) {
104         DFXLOG_ERROR("%s :: Failed to create faultloggerd sockets.", FAULTLOGGERD_TAG.c_str());
105         CleanupSockets();
106         return -1;
107     }
108 
109     if (!InitEnvironment()) {
110         DFXLOG_ERROR("%s :: Failed to init environment.", FAULTLOGGERD_TAG.c_str());
111         CleanupSockets();
112         return -1;
113     }
114 
115     if (!CreateEventFd()) {
116         DFXLOG_ERROR("%s :: Failed to create eventFd.", FAULTLOGGERD_TAG.c_str());
117         CleanupSockets();
118         return -1;
119     }
120 
121     // loop in WaitForRequest
122     WaitForRequest();
123 
124     CleanupEventFd();
125     CleanupSockets();
126     return 0;
127 }
128 
HandleAccept(int32_t epollFd,int32_t socketFd)129 void FaultLoggerDaemon::HandleAccept(int32_t epollFd, int32_t socketFd)
130 {
131     struct sockaddr_un clientAddr;
132     socklen_t clientAddrSize = static_cast<socklen_t>(sizeof(clientAddr));
133 
134     int connectionFd = accept(socketFd, reinterpret_cast<struct sockaddr *>(&clientAddr), &clientAddrSize);
135     if (connectionFd < 0) {
136         DFXLOG_WARN("%s :: Failed to accept connection", FAULTLOGGERD_TAG.c_str());
137         return;
138     }
139 
140     AddEvent(eventFd_, connectionFd, EPOLLIN);
141     connectionMap_.insert(std::pair<int32_t, int32_t>(connectionFd, socketFd));
142 }
143 
HandleRequest(int32_t epollFd,int32_t connectionFd)144 void FaultLoggerDaemon::HandleRequest(int32_t epollFd, int32_t connectionFd)
145 {
146     if (epollFd < 0 || connectionFd < 0) {
147         DFXLOG_ERROR("%s :: HandleRequest recieved invalid fd parmeters.", FAULTLOGGERD_TAG.c_str());
148         return;
149     }
150     char buf[REQUEST_BUF_SIZE] = {0};
151 
152     do {
153         ssize_t nread = read(connectionFd, buf, sizeof(buf));
154         if (nread < 0) {
155             DFXLOG_ERROR("%s :: Failed to read message", FAULTLOGGERD_TAG.c_str());
156             break;
157         } else if (nread == 0) {
158             DFXLOG_ERROR("%s :: HandleRequest :: Read null from request socket", FAULTLOGGERD_TAG.c_str());
159             break;
160         } else if (nread != static_cast<long>(sizeof(FaultLoggerdRequest))) {
161             DFXLOG_ERROR("%s :: Unmatched request length", FAULTLOGGERD_TAG.c_str());
162             break;
163         }
164 
165         auto request = reinterpret_cast<FaultLoggerdRequest *>(buf);
166         if (!CheckRequestCredential(connectionFd, request)) {
167             break;
168         }
169 
170         DFXLOG_DEBUG("%s :: clientType(%d).\n", FAULTLOGGERD_TAG.c_str(), request->clientType);
171         switch (request->clientType) {
172             case static_cast<int32_t>(FaultLoggerClientType::DEFAULT_CLIENT):
173                 HandleDefaultClientRequest(connectionFd, request);
174                 break;
175             case static_cast<int32_t>(FaultLoggerClientType::LOG_FILE_DES_CLIENT):
176                 HandleLogFileDesClientRequest(connectionFd, request);
177                 break;
178             case static_cast<int32_t>(FaultLoggerClientType::PRINT_T_HILOG_CLIENT):
179                 HandlePrintTHilogClientRequest(connectionFd, request);
180                 break;
181             case static_cast<int32_t>(FaultLoggerClientType::PERMISSION_CLIENT):
182                 HandlePermissionRequest(connectionFd, request);
183                 break;
184             case static_cast<int32_t>(FaultLoggerClientType::SDK_DUMP_CLIENT):
185                 HandleSdkDumpRequest(connectionFd, request);
186                 break;
187             case static_cast<int32_t>(FaultLoggerClientType::PIPE_FD_CLIENT):
188                 HandlePipeFdClientRequest(connectionFd, request);
189                 break;
190             default:
191                 DFXLOG_ERROR("%s :: unknown clientType(%d).\n", FAULTLOGGERD_TAG.c_str(), request->clientType);
192                 break;
193         }
194     } while (false);
195 
196     DelEvent(eventFd_, connectionFd, EPOLLIN);
197     connectionMap_.erase(connectionFd);
198 }
199 
InitEnvironment()200 bool FaultLoggerDaemon::InitEnvironment()
201 {
202     faultLoggerConfig_ = std::make_shared<FaultLoggerConfig>(LOG_FILE_NUMBER, LOG_FILE_SIZE,
203         LOG_FILE_PATH, DEBUG_LOG_FILE_PATH);
204     faultLoggerPipeMap_ = std::make_shared<FaultLoggerPipeMap>();
205 
206     if (!OHOS::ForceCreateDirectory(faultLoggerConfig_->GetLogFilePath())) {
207         DFXLOG_ERROR("%s :: Failed to ForceCreateDirectory GetLogFilePath", FAULTLOGGERD_TAG.c_str());
208         return false;
209     }
210 
211     if (!OHOS::ForceCreateDirectory(faultLoggerConfig_->GetDebugLogFilePath())) {
212         DFXLOG_ERROR("%s :: Failed to ForceCreateDirectory GetDebugLogFilePath", FAULTLOGGERD_TAG.c_str());
213         return false;
214     }
215 
216     signal(SIGCHLD, SIG_IGN);
217     signal(SIGPIPE, SIG_IGN);
218     return true;
219 }
220 
HandleDefaultClientRequest(int32_t connectionFd,const FaultLoggerdRequest * request)221 void FaultLoggerDaemon::HandleDefaultClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)
222 {
223     RemoveTempFileIfNeed();
224 
225     int fd = CreateFileForRequest(request->type, request->pid, request->time, false);
226     if (fd < 0) {
227         DFXLOG_ERROR("%s :: Failed to create log file, errno(%d)", FAULTLOGGERD_TAG.c_str(), errno);
228         return;
229     }
230     SendFileDescriptorToSocket(connectionFd, fd);
231 
232     close(fd);
233 }
234 
HandleLogFileDesClientRequest(int32_t connectionFd,const FaultLoggerdRequest * request)235 void FaultLoggerDaemon::HandleLogFileDesClientRequest(int32_t connectionFd, const FaultLoggerdRequest * request)
236 {
237     int fd = CreateFileForRequest(request->type, request->pid, request->time, true);
238     if (fd < 0) {
239         DFXLOG_ERROR("%s :: Failed to create log file, errno(%d)", FAULTLOGGERD_TAG.c_str(), errno);
240         return;
241     }
242     SendFileDescriptorToSocket(connectionFd, fd);
243 
244     close(fd);
245 }
246 
HandlePipeFdClientRequest(int32_t connectionFd,FaultLoggerdRequest * request)247 void FaultLoggerDaemon::HandlePipeFdClientRequest(int32_t connectionFd, FaultLoggerdRequest * request)
248 {
249     DFXLOG_DEBUG("%s :: pid(%d), pipeType(%d).\n", FAULTLOGGERD_TAG.c_str(), request->pid, request->pipeType);
250     int fd = -1;
251 
252     FaultLoggerPipe2* faultLoggerPipe = faultLoggerPipeMap_->Get(request->pid);
253     if (faultLoggerPipe == nullptr) {
254         DFXLOG_ERROR("%s :: cannot find pipe fd for pid(%d).\n", FAULTLOGGERD_TAG.c_str(), request->pid);
255         return;
256     }
257 
258     switch (request->pipeType) {
259         case (int32_t)FaultLoggerPipeType::PIPE_FD_READ_BUF: {
260             FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
261             if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
262                 return;
263             }
264             fd = faultLoggerPipe->faultLoggerPipeBuf_->GetReadFd();
265             break;
266         }
267         case (int32_t)FaultLoggerPipeType::PIPE_FD_WRITE_BUF: {
268             fd = faultLoggerPipe->faultLoggerPipeBuf_->GetWriteFd();
269             break;
270         }
271         case (int32_t)FaultLoggerPipeType::PIPE_FD_READ_RES: {
272             FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
273             if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS != resSecurityCheck) {
274                 return;
275             }
276             fd = faultLoggerPipe->faultLoggerPipeRes_->GetReadFd();
277             break;
278         }
279         case (int32_t)FaultLoggerPipeType::PIPE_FD_WRITE_RES: {
280             fd = faultLoggerPipe->faultLoggerPipeRes_->GetWriteFd();
281             break;
282         }
283         case (int32_t)FaultLoggerPipeType::PIPE_FD_DELETE: {
284             faultLoggerPipeMap_->Del(request->pid);
285             return;
286         }
287         default:
288             DFXLOG_ERROR("%s :: unknown pipeType(%d).\n", FAULTLOGGERD_TAG.c_str(), request->pipeType);
289             return;
290     }
291 
292     if (fd < 0) {
293         DFXLOG_ERROR("%s :: Failed to get pipe fd", FAULTLOGGERD_TAG.c_str());
294         return;
295     }
296     SendFileDescriptorToSocket(connectionFd, fd);
297 }
298 
HandlePrintTHilogClientRequest(int32_t const connectionFd,FaultLoggerdRequest * request)299 void FaultLoggerDaemon::HandlePrintTHilogClientRequest(int32_t const connectionFd, FaultLoggerdRequest * request)
300 {
301     char buf[LOG_BUF_LEN] = {0};
302 
303     if (write(connectionFd, DAEMON_RESP.c_str(), DAEMON_RESP.length()) != static_cast<ssize_t>(DAEMON_RESP.length())) {
304         DFXLOG_ERROR("%s :: Failed to write DAEMON_RESP.", FAULTLOGGERD_TAG.c_str());
305     }
306 
307     int nread = read(connectionFd, buf, sizeof(buf) - 1);
308     if (nread < 0) {
309         DFXLOG_ERROR("%s :: Failed to read message, errno(%d)", FAULTLOGGERD_TAG.c_str(), errno);
310     } else if (nread == 0) {
311         DFXLOG_ERROR("%s :: HandlePrintTHilogClientRequest :: Read null from request socket", FAULTLOGGERD_TAG.c_str());
312     } else {
313         DFXLOG_ERROR("%s", buf);
314     }
315 }
316 
SecurityCheck(int32_t connectionFd,FaultLoggerdRequest * request)317 FaultLoggerCheckPermissionResp FaultLoggerDaemon::SecurityCheck(int32_t connectionFd, FaultLoggerdRequest * request)
318 {
319     FaultLoggerCheckPermissionResp resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
320 
321     struct ucred rcred;
322     do {
323         int optval = 1;
324         if (setsockopt(connectionFd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) {
325             DFXLOG_ERROR("%s :: setsockopt SO_PASSCRED error, errno(%d)", FAULTLOGGERD_TAG.c_str(), errno);
326             break;
327         }
328 
329         if (write(connectionFd, DAEMON_RESP.c_str(), DAEMON_RESP.length()) !=
330             static_cast<ssize_t>(DAEMON_RESP.length())) {
331             DFXLOG_ERROR("%s :: Failed to write DAEMON_RESP, errno(%d)", FAULTLOGGERD_TAG.c_str(), errno);
332         }
333 
334         if (!RecvMsgCredFromSocket(connectionFd, &rcred)) {
335             DFXLOG_ERROR("%s :: Recv msg ucred error.", FAULTLOGGERD_TAG.c_str());
336             break;
337         }
338 
339         request->uid = rcred.uid;
340         request->callerPid = static_cast<int32_t>(rcred.pid);
341         bool res = CheckCallerUID(request->uid);
342         if (res) {
343             resCheckPermission = FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS;
344         }
345     } while (false);
346 
347     return resCheckPermission;
348 }
349 
HandlePermissionRequest(int32_t connectionFd,FaultLoggerdRequest * request)350 void FaultLoggerDaemon::HandlePermissionRequest(int32_t connectionFd, FaultLoggerdRequest * request)
351 {
352     FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
353     if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS == resSecurityCheck) {
354         send(connectionFd, "1", strlen("1"), 0);
355     }
356     if (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT == resSecurityCheck) {
357         send(connectionFd, "2", strlen("2"), 0);
358     }
359 }
360 
HandleSdkDumpRequest(int32_t connectionFd,FaultLoggerdRequest * request)361 void FaultLoggerDaemon::HandleSdkDumpRequest(int32_t connectionFd, FaultLoggerdRequest * request)
362 {
363     DFXLOG_INFO("Receive dump request for pid:%d tid:%d.", request->pid, request->tid);
364     FaultLoggerSdkDumpResp resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_PASS;
365     FaultLoggerCheckPermissionResp resSecurityCheck = SecurityCheck(connectionFd, request);
366 
367     /*
368     *           all     threads my user, local pid             my user, remote pid     other user's process
369     * 3rd       Y       Y(in signal_handler local)     Y(in signal_handler loacl)      N
370     * system    Y       Y(in signal_handler local)     Y(in signal_handler loacl)      Y(in signal_handler remote)
371     * root      Y       Y(in signal_handler local)     Y(in signal_handler loacl)      Y(in signal_handler remote)
372     */
373 
374     /*
375     * 1. pid != 0 && tid != 0:    means we want dump a thread, so we send signal to a thread.
376         Main thread stack is tid's stack, we need ignore other thread info.
377     * 2. pid != 0 && tid == 0:    means we want dump a process, so we send signal to process.
378         Main thead stack is pid's stack, we need other tread info.
379     */
380 
381     /*
382      * in signal_handler we need to check caller pid and tid(which is send to signal handler by SYS_rt_sig.).
383      * 1. caller pid == signal pid, means we do back trace in ourself process, means local backtrace.
384      *      |- we do all tid back trace in signal handler's local unwind.
385      * 2. pid != signal pid, means we do remote back trace.
386      */
387 
388     /*
389      * in local back trace, all unwind stack will save to signal_handler global var.(mutex lock in signal handler.)
390      * in remote back trace, all unwind stack will save to file, and read in dump_catcher, then return.
391      */
392 
393     do {
394         if ((request->pid <= 0) || (FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT == resSecurityCheck)) {
395             DFXLOG_ERROR("%s :: HandleSdkDumpRequest :: pid(%d) or resSecurityCheck(%d) fail.\n", \
396                 FAULTLOGGERD_TAG.c_str(), request->pid, (int)resSecurityCheck);
397             resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_REJECT;
398             break;
399         }
400 
401         if (faultLoggerPipeMap_->Check(request->pid, request->time)) {
402             resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_REPEAT;
403             DFXLOG_ERROR("%s :: pid(%d) is dumping, break.\n", FAULTLOGGERD_TAG.c_str(), request->pid);
404             break;
405         }
406         faultLoggerPipeMap_->Set(request->pid, request->time);
407 
408 #pragma clang diagnostic push
409 #pragma clang diagnostic ignored "-Winitializer-overrides"
410         // defined in out/hi3516dv300/obj/third_party/musl/intermidiates/linux/musl_src_ported/include/signal.h
411         siginfo_t si = {
412             .si_signo = SIGDUMP,
413             .si_errno = 0,
414             .si_code = request->sigCode,
415             .si_value.sival_int = request->tid,
416             .si_pid = request->callerPid,
417             .si_uid = static_cast<uid_t>(request->callerTid)
418         };
419 #pragma clang diagnostic pop
420         // means we need dump all the threads in a process.
421         if (request->tid == 0) {
422             if (syscall(SYS_rt_sigqueueinfo, request->pid, si.si_signo, &si) != 0) {
423                 DFXLOG_ERROR("Failed to SYS_rt_sigqueueinfo signal(%d), errno(%d).", si.si_signo, errno);
424                 resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_NOPROC;
425                 break;
426             }
427         } else {
428             // means we need dump a specified thread
429             if (syscall(SYS_rt_tgsigqueueinfo, request->pid, request->tid, si.si_signo, &si) != 0) {
430                 DFXLOG_ERROR("Failed to SYS_rt_tgsigqueueinfo signal(%d), errno(%d).", si.si_signo, errno);
431                 resSdkDump = FaultLoggerSdkDumpResp::SDK_DUMP_NOPROC;
432                 break;
433             }
434         }
435     } while (false);
436 
437     switch (resSdkDump) {
438         case FaultLoggerSdkDumpResp::SDK_DUMP_REJECT:
439             send(connectionFd, "2", strlen("2"), 0);
440             break;
441         case FaultLoggerSdkDumpResp::SDK_DUMP_REPEAT:
442             send(connectionFd, "3", strlen("3"), 0);
443             break;
444         case FaultLoggerSdkDumpResp::SDK_DUMP_NOPROC:
445             send(connectionFd, "4", strlen("4"), 0);
446             break;
447         default:
448             send(connectionFd, "1", strlen("1"), 0);
449             break;
450     }
451 }
452 
CreateFileForRequest(int32_t type,int32_t pid,uint64_t time,bool debugFlag) const453 int32_t FaultLoggerDaemon::CreateFileForRequest(int32_t type, int32_t pid, uint64_t time, bool debugFlag) const
454 {
455     std::string typeStr = GetRequestTypeName(type);
456     if (typeStr == "unsupported") {
457         DFXLOG_ERROR("Unsupported request type(%d)", type);
458         return -1;
459     }
460 
461     std::string filePath = "";
462     if (debugFlag == false) {
463         filePath = faultLoggerConfig_->GetLogFilePath();
464     } else {
465         filePath = faultLoggerConfig_->GetDebugLogFilePath();
466     }
467 
468     if (time == 0) {
469         time = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>\
470             (std::chrono::system_clock::now().time_since_epoch()).count());
471     }
472 
473     std::stringstream crashTime;
474     crashTime << "-" << time;
475     const std::string path = filePath + "/" + typeStr + "-" + std::to_string(pid) + crashTime.str();
476     DFXLOG_INFO("%s :: file path(%s).\n", FAULTLOGGERD_TAG.c_str(), path.c_str());
477     if (!VerifyFilePath(path, VALID_FILE_PATH)) {
478         DFXLOG_ERROR("%s :: Open %s fail, please check it under valid path.\n", FAULTLOGGERD_TAG.c_str(), path.c_str());
479         return -1;
480     }
481     int32_t fd = OHOS_TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CREAT, FAULTLOG_FILE_PROP));
482     if (fd != -1) {
483         if (!ChangeModeFile(path, FAULTLOG_FILE_PROP)) {
484             DFXLOG_ERROR("%s :: Failed to ChangeMode CreateFileForRequest", FAULTLOGGERD_TAG.c_str());
485         }
486     }
487     return fd;
488 }
489 
RemoveTempFileIfNeed()490 void FaultLoggerDaemon::RemoveTempFileIfNeed()
491 {
492     int maxFileCount = 50;
493     int currentLogCounts = 0;
494 
495     std::vector<std::string> files;
496     OHOS::GetDirFiles(faultLoggerConfig_->GetLogFilePath(), files);
497     currentLogCounts = (int)files.size();
498 
499     maxFileCount = faultLoggerConfig_->GetLogFileMaxNumber();
500     if (currentLogCounts < maxFileCount) {
501         return;
502     }
503 
504     std::sort(files.begin(), files.end(),
505         [](const std::string& lhs, const std::string& rhs) -> int
506     {
507         auto lhsSplitPos = lhs.find_last_of("-");
508         auto rhsSplitPos = rhs.find_last_of("-");
509         if (lhsSplitPos == std::string::npos || rhsSplitPos == std::string::npos) {
510             return lhs.compare(rhs) > 0;
511         }
512 
513         return lhs.substr(lhsSplitPos).compare(rhs.substr(rhsSplitPos)) > 0;
514     });
515 
516     time_t currentTime = static_cast<time_t>(time(nullptr));
517     if (currentTime <= 0) {
518         DFXLOG_ERROR("%s :: currentTime is less than zero CreateFileForRequest", FAULTLOGGERD_TAG.c_str());
519     }
520 
521     int startIndex = maxFileCount / 2;
522     for (unsigned int index = (unsigned int)startIndex; index < files.size(); index++) {
523         struct stat st;
524         int err = stat(files[index].c_str(), &st);
525         if (err != 0) {
526             DFXLOG_ERROR("%s :: Get log stat failed, errno(%d).", FAULTLOGGERD_TAG.c_str(), errno);
527         } else {
528             if ((currentTime - st.st_mtime) <= DAEMON_REMOVE_FILE_TIME_S) {
529                 continue;
530             }
531         }
532 
533         OHOS::RemoveFile(files[index]);
534         DFXLOG_DEBUG("%s :: Now we rm file(%s) as max log number exceeded.", \
535             FAULTLOGGERD_TAG.c_str(), files[index].c_str());
536     }
537 }
538 
AddEvent(int32_t epollFd,int32_t addFd,uint32_t event)539 void FaultLoggerDaemon::AddEvent(int32_t epollFd, int32_t addFd, uint32_t event)
540 {
541     epoll_event ev;
542     ev.events = event;
543     ev.data.fd = addFd;
544     int ret = epoll_ctl(epollFd, EPOLL_CTL_ADD, addFd, &ev);
545     if (ret < 0) {
546         DFXLOG_WARN("%s :: Failed to epoll ctl add Fd(%d), errno(%d)", FAULTLOGGERD_TAG.c_str(), addFd, errno);
547     }
548 }
549 
DelEvent(int32_t epollFd,int32_t delFd,uint32_t event)550 void FaultLoggerDaemon::DelEvent(int32_t epollFd, int32_t delFd, uint32_t event)
551 {
552     epoll_event ev;
553     ev.events = event;
554     ev.data.fd = delFd;
555     int ret = epoll_ctl(epollFd, EPOLL_CTL_DEL, delFd, &ev);
556     if (ret < 0) {
557         DFXLOG_WARN("%s :: Failed to epoll ctl del Fd(%d), errno(%d)", FAULTLOGGERD_TAG.c_str(), delFd, errno);
558     }
559     close(delFd);
560 }
561 
CheckRequestCredential(int32_t connectionFd,FaultLoggerdRequest * request)562 bool FaultLoggerDaemon::CheckRequestCredential(int32_t connectionFd, FaultLoggerdRequest* request)
563 {
564     if (request == nullptr) {
565         return false;
566     }
567 
568     auto it = connectionMap_.find(connectionFd);
569     if (it == connectionMap_.end()) {
570         return false;
571     }
572 
573     if (it->second == crashSocketFd_) {
574         // only processdump use this socket
575         return true;
576     }
577 
578     struct ucred creds = {};
579     socklen_t credSize = sizeof(creds);
580     int err = getsockopt(connectionFd, SOL_SOCKET, SO_PEERCRED, &creds, &credSize);
581     if (err != 0) {
582         DFXLOG_ERROR("%s :: Failed to CheckRequestCredential, errno(%d)", FAULTLOGGERD_TAG.c_str(), errno);
583         return false;
584     }
585 
586     if (CheckCallerUID(creds.uid)) {
587         return true;
588     }
589 
590     bool isCredentialMatched = (creds.pid == request->pid);
591     if (!isCredentialMatched) {
592         DFXLOG_WARN("Failed to check request credential request:%d:%d cred:%d:%d",
593             request->pid, request->uid, creds.pid, creds.uid);
594     }
595     return isCredentialMatched;
596 }
597 
CreateSockets()598 bool FaultLoggerDaemon::CreateSockets()
599 {
600     if (!StartListen(defaultSocketFd_, SERVER_SOCKET_NAME, MAX_CONNECTION)) {
601         return false;
602     }
603 
604     if (!StartListen(crashSocketFd_, SERVER_CRASH_SOCKET_NAME, MAX_CONNECTION)) {
605         close(defaultSocketFd_);
606         defaultSocketFd_ = -1;
607         return false;
608     }
609 
610     return true;
611 }
612 
CleanupSockets()613 void FaultLoggerDaemon::CleanupSockets()
614 {
615     if (defaultSocketFd_ >= 0) {
616         close(defaultSocketFd_);
617         defaultSocketFd_ = -1;
618     }
619 
620     if (crashSocketFd_ >= 0) {
621         close(crashSocketFd_);
622         crashSocketFd_ = -1;
623     }
624 }
625 
CreateEventFd()626 bool FaultLoggerDaemon::CreateEventFd()
627 {
628     eventFd_ = epoll_create(MAX_EPOLL_EVENT);
629     if (eventFd_ < 0) {
630         return false;
631     }
632     return true;
633 }
634 
WaitForRequest()635 void FaultLoggerDaemon::WaitForRequest()
636 {
637     AddEvent(eventFd_, defaultSocketFd_, EPOLLIN);
638     AddEvent(eventFd_, crashSocketFd_, EPOLLIN);
639     epoll_event events[MAX_CONNECTION];
640     DFXLOG_DEBUG("%s :: %s: start epoll wait.", FAULTLOGGERD_TAG.c_str(), __func__);
641     do {
642         int epollNum = epoll_wait(eventFd_, events, MAX_CONNECTION, -1);
643         if (epollNum < 0) {
644             if (errno != EINTR) {
645                 DFXLOG_ERROR("%s :: %s: epoll wait error, errno(%d).", FAULTLOGGERD_TAG.c_str(), __func__, errno);
646             }
647             continue;
648         }
649         for (int i = 0; i < epollNum; i++) {
650             if (!(events[i].events & EPOLLIN)) {
651                 DFXLOG_WARN("%s :: %s: epoll event(%d) error.", FAULTLOGGERD_TAG.c_str(), __func__, events[i].events);
652                 continue;
653             }
654 
655             int fd = events[i].data.fd;
656             if (fd == defaultSocketFd_ || fd == crashSocketFd_) {
657                 HandleAccept(eventFd_, fd);
658             } else {
659                 HandleRequest(eventFd_, fd);
660             }
661         }
662     } while (true);
663 }
664 
CleanupEventFd()665 void FaultLoggerDaemon::CleanupEventFd()
666 {
667     DelEvent(eventFd_, defaultSocketFd_, EPOLLIN);
668     DelEvent(eventFd_, crashSocketFd_, EPOLLIN);
669 
670     if (eventFd_ > 0) {
671         close(eventFd_);
672         eventFd_ = -1;
673     }
674 }
675 } // namespace HiviewDFX
676 } // namespace OHOS
677