1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dfx_signalhandler_exception.h"
17
18 #include <stdio.h>
19 #include <sys/syscall.h>
20 #include <sys/socket.h>
21 #include <sys/time.h>
22 #include <sys/un.h>
23 #include <securec.h>
24 #include <unistd.h>
25
26 #include "dfx_define.h"
27 #include "dfx_exception.h"
28 #include "errno.h"
29 #include "string.h"
30 #include "dfx_log.h"
31
32 #ifdef LOG_DOMAIN
33 #undef LOG_DOMAIN
34 #define LOG_DOMAIN 0xD002D11
35 #endif
36
37 #ifdef LOG_TAG
38 #undef LOG_TAG
39 #define LOG_TAG "DfxSignalHandlerException"
40 #endif
41
42 static const int TIME_OUT = 2; /* socket connecet timeout 2 seconds */
43 const char * const FAULTLOGGERD_SOCKET_NAME = "/dev/unix/socket/faultloggerd.server";
44
ConnectSocket(const char * path,const int timeout)45 static int ConnectSocket(const char* path, const int timeout)
46 {
47 int fd = -1;
48 if ((fd = syscall(SYS_socket, AF_LOCAL, SOCK_STREAM, 0)) < 0) {
49 DFXLOGE("Failed to create a socket, errno(%{public}d).", errno);
50 return -1;
51 }
52
53 do {
54 if (timeout > 0) {
55 struct timeval timev = {
56 timeout,
57 0
58 };
59 void* pTimev = &timev;
60 if (OHOS_TEMP_FAILURE_RETRY(syscall(SYS_setsockopt, fd, SOL_SOCKET, SO_RCVTIMEO,
61 (const void*)(pTimev), sizeof(timev))) != 0) {
62 DFXLOGE("setsockopt SO_RCVTIMEO error, errno(%{public}d).", errno);
63 syscall(SYS_close, fd);
64 fd = -1;
65 break;
66 }
67 }
68 struct sockaddr_un server;
69 (void)memset_s(&server, sizeof(server), 0, sizeof(server));
70 server.sun_family = AF_LOCAL;
71 if (strcpy_s(server.sun_path, sizeof(server.sun_path), path) != EOK) {
72 DFXLOGE("server sun_path strcpy fail.");
73 }
74 int len = sizeof(server.sun_family) + strlen(server.sun_path);
75 int connected = OHOS_TEMP_FAILURE_RETRY(connect(fd, (struct sockaddr*)(&server), len));
76 if (connected < 0) {
77 DFXLOGE("Failed to connect to faultloggerd socket, errno = %{public}d.", errno);
78 syscall(SYS_close, fd);
79 fd = -1;
80 break;
81 }
82 } while (false);
83 return fd;
84 }
85
ReportException(struct CrashDumpException * exception)86 int ReportException(struct CrashDumpException* exception)
87 {
88 if (exception == NULL) {
89 return -1;
90 }
91 exception->head.clientType = REPORT_EXCEPTION_CLIENT;
92 exception->head.clientPid = getpid();
93 int ret = -1;
94 int fd = ConnectSocket(FAULTLOGGERD_SOCKET_NAME, TIME_OUT); // connect timeout
95 if (fd == -1) {
96 DFXLOGE("Failed to connect socket.");
97 return ret;
98 }
99 do {
100 if (OHOS_TEMP_FAILURE_RETRY(write(fd, exception, sizeof(struct CrashDumpException))) !=
101 (long)sizeof(struct CrashDumpException)) {
102 DFXLOGE("Failed to write request message to socket, errno(%{public}d).", errno);
103 break;
104 }
105 ret = 0;
106 } while (false);
107 syscall(SYS_close, fd);
108 return ret;
109 }
110