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 #include "faultloggerd_client.h"
16
17 #include <cstdint>
18
19 #include <securec.h>
20 #include <sys/un.h>
21
22 #include "dfx_cutil.h"
23 #include "dfx_define.h"
24 #include "dfx_log.h"
25 #include "dfx_socket_request.h"
26 #include "dfx_util.h"
27 #include "faultloggerd_socket.h"
28
29 using namespace OHOS::HiviewDFX;
30 namespace {
31 constexpr const char* const FAULTLOGGERD_CLIENT_TAG = "FAULT_LOGGERD_CLIENT";
32 constexpr int32_t SDKDUMP_SOCKET_TIMEOUT = 1;
33 constexpr int32_t COREDUMP_SOCKET_TIMEOUT = 5;
34 constexpr int32_t CRASHDUMP_SOCKET_TIMEOUT = 3;
GetSocketName()35 std::string GetSocketName()
36 {
37 char content[NAME_BUF_LEN];
38 GetProcessName(content, sizeof(content));
39 return strcmp(content, "processdump") == 0 ? SERVER_CRASH_SOCKET_NAME : SERVER_SOCKET_NAME;
40 }
41
FillRequestHeadData(RequestDataHead & head,FaultLoggerClientType clientType)42 void FillRequestHeadData(RequestDataHead& head, FaultLoggerClientType clientType)
43 {
44 head.clientType = clientType;
45 head.clientPid = getpid();
46 }
47
SendRequestToServer(const char * socketName,const SocketRequestData & socketRequestData,int32_t timeout,SocketFdData * socketFdData=nullptr,bool signalSafely=false)48 int32_t SendRequestToServer(const char* socketName, const SocketRequestData& socketRequestData, int32_t timeout,
49 SocketFdData* socketFdData = nullptr, bool signalSafely = false)
50 {
51 FaultLoggerdSocket faultLoggerdSocket(signalSafely);
52 int32_t retCode{ResponseCode::DEFAULT_ERROR_CODE};
53 if (!faultLoggerdSocket.CreateSocketFileDescriptor(timeout)) {
54 return ResponseCode::CONNECT_FAILED;
55 }
56 if (!faultLoggerdSocket.StartConnect(socketName)) {
57 retCode = ResponseCode::CONNECT_FAILED;
58 } else {
59 retCode = socketFdData ? faultLoggerdSocket.RequestFdsFromServer(socketRequestData, *socketFdData) :
60 faultLoggerdSocket.RequestServer(socketRequestData);
61 }
62 faultLoggerdSocket.CloseSocketFileDescriptor();
63 return retCode;
64 }
65
RequestFileDescriptor(const struct FaultLoggerdRequest & request)66 int32_t RequestFileDescriptor(const struct FaultLoggerdRequest &request)
67 {
68 int32_t fd{-1};
69 SocketRequestData socketRequestData = {&request, sizeof(request)};
70 SocketFdData socketFdData = {&fd, 1};
71 switch (request.type) {
72 case FFRT_CRASH_LOG:
73 SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, CRASHDUMP_SOCKET_TIMEOUT,
74 &socketFdData, true);
75 return fd;
76 case CPP_CRASH:
77 case CPP_STACKTRACE:
78 case LEAK_STACKTRACE:
79 case JIT_CODE_LOG:
80 SendRequestToServer(SERVER_CRASH_SOCKET_NAME, socketRequestData, CRASHDUMP_SOCKET_TIMEOUT, &socketFdData);
81 return fd;
82 default:
83 SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, CRASHDUMP_SOCKET_TIMEOUT, &socketFdData);
84 return fd;
85 }
86 }
87 }
88
RequestFileDescriptor(int32_t type)89 int32_t RequestFileDescriptor(int32_t type)
90 {
91 struct FaultLoggerdRequest request{};
92 FillRequestHeadData(request.head, FaultLoggerClientType::LOG_FILE_DES_CLIENT);
93 request.type = type;
94 request.pid = request.head.clientPid;
95 request.tid = gettid();
96 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
97 return RequestFileDescriptor(request);
98 }
99
RequestFileDescriptorEx(struct FaultLoggerdRequest * request)100 int32_t RequestFileDescriptorEx(struct FaultLoggerdRequest* request)
101 {
102 if (request == nullptr) {
103 DFXLOGE("%{public}s.%{public}s :: RequestFileDescriptorEx nullptr.", FAULTLOGGERD_CLIENT_TAG, __func__);
104 return -1;
105 }
106 FillRequestHeadData(request->head, FaultLoggerClientType::LOG_FILE_DES_CLIENT);
107 return RequestFileDescriptor(*request);
108 }
109
RequestSdkDump(int32_t pid,int32_t tid,int (& pipeReadFd)[2],bool isJson,int timeout)110 int32_t RequestSdkDump(int32_t pid, int32_t tid, int (&pipeReadFd)[2], bool isJson, int timeout)
111 {
112 #ifndef is_ohos_lite
113 DFXLOGI("%{public}s.%{public}s :: pid: %{public}d, tid: %{public}d, isJson: %{public}d.",
114 FAULTLOGGERD_CLIENT_TAG, __func__, pid, tid, isJson);
115 if (pid <= 0 || tid < 0) {
116 return ResponseCode::DEFAULT_ERROR_CODE;
117 }
118 struct SdkDumpRequestData request{};
119 FillRequestHeadData(request.head, FaultLoggerClientType::SDK_DUMP_CLIENT);
120 request.sigCode = isJson ? DUMP_TYPE_REMOTE_JSON : DUMP_TYPE_REMOTE;
121 request.pid = pid;
122 request.tid = tid;
123 request.callerTid = gettid();
124 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
125 request.endTime = GetAbsTimeMilliSeconds() + static_cast<uint64_t>(timeout);
126 SocketRequestData socketRequestData = {&request, sizeof(request)};
127 SocketFdData socketFdData = {pipeReadFd, PIPE_NUM_SZ};
128 return SendRequestToServer(SERVER_SDKDUMP_SOCKET_NAME, socketRequestData, SDKDUMP_SOCKET_TIMEOUT, &socketFdData);
129 #else
130 return ResponseCode::DEFAULT_ERROR_CODE;
131 #endif
132 }
133
RequestLitePerfPipeFd(int32_t pipeType,int (& pipeFd)[2],int timeout)134 int32_t RequestLitePerfPipeFd(int32_t pipeType, int (&pipeFd)[2], int timeout)
135 {
136 #ifndef is_ohos_lite
137 if (pipeType < FaultLoggerPipeType::PIPE_FD_READ || pipeType > FaultLoggerPipeType::PIPE_FD_DELETE) {
138 DFXLOGE("%{public}s.%{public}s :: pipeType: %{public}d failed.", FAULTLOGGERD_CLIENT_TAG, __func__, pipeType);
139 return ResponseCode::DEFAULT_ERROR_CODE;
140 }
141 DFXLOGI("%{public}s.%{public}s :: pipeType: %{public}d.", FAULTLOGGERD_CLIENT_TAG, __func__, pipeType);
142 LitePerfFdRequestData request{};
143 FillRequestHeadData(request.head, FaultLoggerClientType::PIPE_FD_LITEPERF_CLIENT);
144 request.pipeType = static_cast<int8_t>(pipeType);
145 request.pid = getpid();
146 request.uid = getuid();
147 request.timeout = timeout;
148 SocketRequestData socketRequestData = {&request, sizeof(request)};
149 SocketFdData socketFdData = {pipeFd, PIPE_NUM_SZ};
150 return SendRequestToServer(GetSocketName().c_str(), socketRequestData, CRASHDUMP_SOCKET_TIMEOUT, &socketFdData);
151 #else
152 return ResponseCode::DEFAULT_ERROR_CODE;
153 #endif
154 }
155
RequestLitePerfDelPipeFd()156 int32_t RequestLitePerfDelPipeFd()
157 {
158 #ifndef is_ohos_lite
159 LitePerfFdRequestData request{};
160 FillRequestHeadData(request.head, FaultLoggerClientType::PIPE_FD_LITEPERF_CLIENT);
161 request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE;
162 request.pid = getpid();
163 request.uid = getuid();
164 return SendRequestToServer(GetSocketName().c_str(), {&request, sizeof(request)}, SDKDUMP_SOCKET_TIMEOUT);
165 #else
166 return ResponseCode::DEFAULT_ERROR_CODE;
167 #endif
168 }
169
RequestPipeFd(int32_t pid,int32_t pipeType,int (& pipeFd)[2])170 int32_t RequestPipeFd(int32_t pid, int32_t pipeType, int (&pipeFd)[2])
171 {
172 #ifndef is_ohos_lite
173 if (pipeType < FaultLoggerPipeType::PIPE_FD_READ || pipeType > FaultLoggerPipeType::PIPE_FD_DELETE) {
174 DFXLOGE("%{public}s.%{public}s :: pipeType: %{public}d failed.", FAULTLOGGERD_CLIENT_TAG, __func__, pipeType);
175 return ResponseCode::DEFAULT_ERROR_CODE;
176 }
177 PipFdRequestData request{};
178 FillRequestHeadData(request.head, FaultLoggerClientType::PIPE_FD_CLIENT);
179 request.pipeType = static_cast<int8_t>(pipeType);
180 request.pid = pid;
181 SocketRequestData socketRequestData = {&request, sizeof(request)};
182 SocketFdData socketFdData = {pipeFd, PIPE_NUM_SZ};
183 return SendRequestToServer(GetSocketName().c_str(), socketRequestData, CRASHDUMP_SOCKET_TIMEOUT, &socketFdData);
184 #else
185 return ResponseCode::DEFAULT_ERROR_CODE;
186 #endif
187 }
188
RequestDelPipeFd(int32_t pid)189 int32_t RequestDelPipeFd(int32_t pid)
190 {
191 #ifndef is_ohos_lite
192 PipFdRequestData request{};
193 FillRequestHeadData(request.head, FaultLoggerClientType::PIPE_FD_CLIENT);
194 request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE;
195 request.pid = pid;
196 return SendRequestToServer(GetSocketName().c_str(), {&request, sizeof(request)}, SDKDUMP_SOCKET_TIMEOUT);
197 #else
198 return ResponseCode::DEFAULT_ERROR_CODE;
199 #endif
200 }
201
ReportDumpStats(struct FaultLoggerdStatsRequest * request)202 int32_t ReportDumpStats(struct FaultLoggerdStatsRequest *request)
203 {
204 if (request == nullptr) {
205 return ResponseCode::DEFAULT_ERROR_CODE;
206 }
207 int32_t retCode{ResponseCode::REQUEST_SUCCESS};
208 #ifndef HISYSEVENT_DISABLE
209 FillRequestHeadData(request->head, FaultLoggerClientType::DUMP_STATS_CLIENT);
210 FaultLoggerdSocket faultLoggerdSocket;
211 if (!faultLoggerdSocket.CreateSocketFileDescriptor(SDKDUMP_SOCKET_TIMEOUT)) {
212 return ResponseCode::CONNECT_FAILED;
213 }
214 if (!faultLoggerdSocket.StartConnect(GetSocketName().c_str())) {
215 retCode = ResponseCode::CONNECT_FAILED;
216 } else if (!faultLoggerdSocket.SendMsgToSocket(request, sizeof (FaultLoggerdStatsRequest))) {
217 retCode = ResponseCode::SEND_DATA_FAILED;
218 }
219 faultLoggerdSocket.CloseSocketFileDescriptor();
220 #endif
221 return retCode;
222 }
223
SaveCoredumpToFileTimeout(int32_t targetPid,int timeout)224 std::string SaveCoredumpToFileTimeout(int32_t targetPid, int timeout)
225 {
226 #ifndef is_ohos_lite
227 DFXLOGI("%{public}s.%{public}s :: pid: %{public}d.", FAULTLOGGERD_CLIENT_TAG, __func__, targetPid);
228 if (targetPid <= 0) {
229 return "";
230 }
231
232 struct CoreDumpRequestData request{};
233 FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_CLIENT);
234 request.pid = targetPid;
235 request.endTime = GetAbsTimeMilliSeconds() + static_cast<uint64_t>(timeout);
236 request.coredumpAction = CoreDumpAction::DO_CORE_DUMP;
237
238 SocketRequestData socketRequestData = {&request, sizeof(request)};
239 FaultLoggerdSocket faultLoggerdSocket;
240 int32_t retCode{ResponseCode::DEFAULT_ERROR_CODE};
241 if (!faultLoggerdSocket.CreateSocketFileDescriptor(COREDUMP_SOCKET_TIMEOUT)) {
242 DFXLOGE("%{public}s create socket fail", __func__);
243 return "";
244 }
245 if (!faultLoggerdSocket.StartConnect(SERVER_SOCKET_NAME)) {
246 retCode = ResponseCode::CONNECT_FAILED;
247 } else {
248 retCode = faultLoggerdSocket.RequestServer(socketRequestData);
249 }
250 if (retCode != ResponseCode::REQUEST_SUCCESS) {
251 DFXLOGE("%{public}s connect server fail, retCode : %{public}d", __func__, retCode);
252 return "";
253 }
254 DFXLOGI("%{public}s connect request retCode : %{public}d", __func__, retCode);
255 CoreDumpResult coredumpResult = {"", ResponseCode::RECEIVE_DATA_FAILED};
256 faultLoggerdSocket.GetMsgFromSocket(&coredumpResult, sizeof(coredumpResult));
257
258 DFXLOGI("%{public}s has received retCode : %{public}d and filename: %{public}s", __func__,
259 coredumpResult.retCode, coredumpResult.fileName);
260 return coredumpResult.fileName;
261 #else
262 return "";
263 #endif
264 }
265
CancelCoredump(int32_t targetPid)266 int32_t CancelCoredump(int32_t targetPid)
267 {
268 #ifndef is_ohos_lite
269 DFXLOGI("%{public}s.%{public}s :: pid: %{public}d.", FAULTLOGGERD_CLIENT_TAG, __func__, targetPid);
270 if (targetPid <= 0) {
271 return ResponseCode::DEFAULT_ERROR_CODE;
272 }
273
274 struct CoreDumpRequestData request{};
275 FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_CLIENT);
276 request.pid = targetPid;
277 request.coredumpAction = CoreDumpAction::CANCEL_CORE_DUMP;
278
279 SocketRequestData socketRequestData = {&request, sizeof(request)};
280 int32_t retCode =
281 SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, COREDUMP_SOCKET_TIMEOUT);
282
283 DFXLOGI("%{public}s has received retcode : %{public}d %{public}d", __func__, retCode, __LINE__);
284 return retCode;
285 #else
286 return ResponseCode::DEFAULT_ERROR_CODE;
287 #endif
288 }
289
StartCoredumpCb(int32_t targetPid,int32_t processDumpPid)290 int32_t StartCoredumpCb(int32_t targetPid, int32_t processDumpPid)
291 {
292 #ifndef is_ohos_lite
293 DFXLOGI("%{public}s.%{public}s :: targetpid: %{public}d, processDumpPid: %{public}d.",
294 FAULTLOGGERD_CLIENT_TAG, __func__, targetPid, processDumpPid);
295 if (targetPid <= 0 || processDumpPid <= 0) {
296 return ResponseCode::DEFAULT_ERROR_CODE;
297 }
298
299 struct CoreDumpStatusData request{};
300 FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_PROCESS_DUMP_CLIENT);
301 request.pid = targetPid;
302 request.processDumpPid = processDumpPid;
303 request.coredumpStatus = CoreDumpStatus::CORE_DUMP_START;
304
305 SocketRequestData socketRequestData = {&request, sizeof(request)};
306 int32_t retCode =
307 SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, COREDUMP_SOCKET_TIMEOUT);
308
309 DFXLOGI("%{public}s has received retcode : %{public}d %{public}d", __func__, retCode, __LINE__);
310 return retCode;
311 #else
312 return ResponseCode::DEFAULT_ERROR_CODE;
313 #endif
314 }
315
FinishCoredumpCb(int32_t targetPid,std::string & fileName,int32_t ret)316 int32_t FinishCoredumpCb(int32_t targetPid, std::string& fileName, int32_t ret)
317 {
318 #ifndef is_ohos_lite
319 DFXLOGI("%{public}s.%{public}s :: targetpid: %{public}d.",
320 FAULTLOGGERD_CLIENT_TAG, __func__, targetPid);
321 if (targetPid <= 0) {
322 return ResponseCode::DEFAULT_ERROR_CODE;
323 }
324
325 struct CoreDumpStatusData request{};
326 FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_PROCESS_DUMP_CLIENT);
327 request.pid = targetPid;
328 request.coredumpStatus = CoreDumpStatus::CORE_DUMP_END;
329 request.retCode = ret;
330 if (strncpy_s(request.fileName, sizeof(request.fileName), fileName.c_str(), sizeof(request.fileName) - 1) != 0) {
331 DFXLOGE("%{public}s :: strncpy failed.", __func__);
332 return ResponseCode::DEFAULT_ERROR_CODE;
333 }
334
335 SocketRequestData socketRequestData = {&request, sizeof(request)};
336 int32_t retCode =
337 SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, COREDUMP_SOCKET_TIMEOUT);
338
339 DFXLOGI("%{public}s has received retcode : %{public}d %{public}d", __func__, retCode, __LINE__);
340 return retCode;
341 #else
342 return ResponseCode::DEFAULT_ERROR_CODE;
343 #endif
344 }