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 <unistd.h>
24
25 #include "dfx_define.h"
26 #include "dfx_exception.h"
27 #include "dfx_socket_request.h"
28 #include "errno.h"
29 #include "string.h"
30
31 #ifndef DFX_SIGNAL_LIBC
32 #include "dfx_log.h"
33 #else
34 #include "musl_log.h"
35 #endif
36
37 #ifdef LOG_DOMAIN
38 #undef LOG_DOMAIN
39 #define LOG_DOMAIN 0xD002D11
40 #endif
41
42 #ifdef LOG_TAG
43 #undef LOG_TAG
44 #define LOG_TAG "DfxSignalHandlerException"
45 #endif
46
47 static const int TIME_OUT = 2; /* seconds */
48 static const char FAULTLOGGERD_SOCKET_NAME[] = "/dev/unix/socket/faultloggerd.server";
49
ConnectSocket(const char * path,const int timeout)50 static int ConnectSocket(const char* path, const int timeout)
51 {
52 int fd = -1;
53 if ((fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
54 DFXLOG_ERROR("Failed to create a socket, errno(%d).", errno);
55 return -1;
56 }
57
58 do {
59 if (timeout > 0) {
60 struct timeval timev = {
61 timeout,
62 0
63 };
64 void* pTimev = &timev;
65 if (OHOS_TEMP_FAILURE_RETRY(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
66 (const void*)(pTimev), sizeof(timev))) != 0) {
67 DFXLOG_ERROR("setsockopt SO_RCVTIMEO error, errno(%d).", errno);
68 syscall(SYS_close, fd);
69 fd = -1;
70 break;
71 }
72 }
73 struct sockaddr_un server;
74 (void)memset(&server, 0, sizeof(server));
75 server.sun_family = AF_LOCAL;
76 (void)strncpy(server.sun_path, path, sizeof(server.sun_path) - 1);
77 int len = sizeof(server.sun_family) + strlen(server.sun_path);
78 int connected = OHOS_TEMP_FAILURE_RETRY(connect(fd, (struct sockaddr*)(&server), len));
79 if (connected < 0) {
80 DFXLOG_ERROR("Failed to connect to faultloggerd socket, errno = %d.", errno);
81 syscall(SYS_close, fd);
82 fd = -1;
83 break;
84 }
85 } while (false);
86 return fd;
87 }
88
CheckReadResp(int fd)89 static bool CheckReadResp(int fd)
90 {
91 char controlBuffer[MAX_FUNC_NAME_LEN] = {0};
92 ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(fd, controlBuffer, sizeof(controlBuffer) - 1));
93 if (nread != (ssize_t)(strlen(FAULTLOGGER_DAEMON_RESP))) {
94 DFXLOG_ERROR("Failed to read expected length, nread: %zd, errno(%d).", nread, errno);
95 return false;
96 }
97 return true;
98 }
99
ReportException(struct CrashDumpException exception)100 int ReportException(struct CrashDumpException exception)
101 {
102 struct FaultLoggerdRequest request;
103 (void)memset(&request, 0, sizeof(struct FaultLoggerdRequest));
104 request.clientType = (int32_t)REPORT_EXCEPTION_CLIENT;
105 request.pid = exception.pid;
106 request.uid = (uint32_t)(exception.uid);
107 int ret = -1;
108 int fd = ConnectSocket(FAULTLOGGERD_SOCKET_NAME, TIME_OUT); // connect timeout
109 if (fd == -1) {
110 DFXLOG_ERROR("Failed to connect socket.");
111 return ret;
112 }
113 do {
114 if (OHOS_TEMP_FAILURE_RETRY(write(fd, &request, sizeof(request))) != (long)sizeof(request)) {
115 DFXLOG_ERROR("Failed to write request message to socket, errno(%d).", errno);
116 break;
117 }
118
119 if (!CheckReadResp(fd)) {
120 DFXLOG_ERROR("Failed to receive socket responces.");
121 break;
122 }
123
124 if (OHOS_TEMP_FAILURE_RETRY(write(fd, &exception,
125 sizeof(exception))) != (long)sizeof(exception)) {
126 DFXLOG_ERROR("Failed to write exception message to socket, errno(%d).", errno);
127 break;
128 }
129
130 ret = 0;
131 } while (false);
132 syscall(SYS_close, fd);
133 return ret;
134 }