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