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 <climits>
18 #include <cstdint>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <securec.h>
22 #include <unistd.h>
23
24 #include <sys/socket.h>
25 #include <sys/syscall.h>
26 #include <sys/un.h>
27 #include <sys/stat.h>
28
29 #include "dfx_cutil.h"
30 #include "dfx_define.h"
31 #include "dfx_log.h"
32 #include "dfx_util.h"
33 #include "faultloggerd_socket.h"
34
35 static const int32_t SOCKET_TIMEOUT = 5;
36
GetSocketConnectionName()37 static std::string GetSocketConnectionName()
38 {
39 char content[NAME_BUF_LEN];
40 GetProcessName(content, sizeof(content));
41 if (std::string(content).find("processdump") != std::string::npos) {
42 return std::string(SERVER_CRASH_SOCKET_NAME);
43 }
44 return std::string(SERVER_SOCKET_NAME);
45 }
46
RequestFileDescriptor(int32_t type)47 int32_t RequestFileDescriptor(int32_t type)
48 {
49 struct FaultLoggerdRequest request;
50 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
51 request.type = type;
52 request.pid = getprocpid();
53 request.tid = getproctid();
54 request.uid = getuid();
55 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
56 return RequestFileDescriptorEx(&request);
57 }
58
RequestLogFileDescriptor(struct FaultLoggerdRequest * request)59 int32_t RequestLogFileDescriptor(struct FaultLoggerdRequest *request)
60 {
61 if (request == nullptr) {
62 DFXLOG_ERROR("%s", "nullptr request");
63 return -1;
64 }
65 request->clientType = (int32_t)FaultLoggerClientType::LOG_FILE_DES_CLIENT;
66 return RequestFileDescriptorEx(request);
67 }
68
RequestFileDescriptorEx(const struct FaultLoggerdRequest * request)69 int32_t RequestFileDescriptorEx(const struct FaultLoggerdRequest *request)
70 {
71 if (request == nullptr) {
72 DFXLOG_ERROR("%s", "nullptr request");
73 return -1;
74 }
75
76 int sockfd;
77 std::string name = GetSocketConnectionName();
78 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
79 DFXLOG_ERROR("StartConnect(%d) failed", sockfd);
80 return -1;
81 }
82
83 OHOS_TEMP_FAILURE_RETRY(write(sockfd, request, sizeof(struct FaultLoggerdRequest)));
84 int fd = ReadFileDescriptorFromSocket(sockfd);
85 DFXLOG_DEBUG("RequestFileDescriptorEx(%d).", fd);
86 close(sockfd);
87 return fd;
88 }
89
CheckReadResp(int sockfd)90 static bool CheckReadResp(int sockfd)
91 {
92 char ControlBuffer[SOCKET_BUFFER_SIZE] = {0};
93 ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(sockfd, ControlBuffer, sizeof(ControlBuffer) - 1));
94 if (nread != static_cast<ssize_t>(strlen(FAULTLOGGER_DAEMON_RESP))) {
95 DFXLOG_ERROR("nread: %zd.", nread);
96 return false;
97 }
98 return true;
99 }
100
RequestFileDescriptorByCheck(const struct FaultLoggerdRequest * request)101 static int32_t RequestFileDescriptorByCheck(const struct FaultLoggerdRequest *request)
102 {
103 int32_t fd = -1;
104 if (request == nullptr) {
105 DFXLOG_ERROR("%s", "nullptr request");
106 return -1;
107 }
108
109 int sockfd = -1;
110 do {
111 std::string name = GetSocketConnectionName();
112 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
113 DFXLOG_ERROR("StartConnect(%d) failed", sockfd);
114 return fd;
115 }
116
117 OHOS_TEMP_FAILURE_RETRY(write(sockfd, request, sizeof(struct FaultLoggerdRequest)));
118
119 if (!CheckReadResp(sockfd)) {
120 break;
121 }
122
123 int data = 12345;
124 if (!SendMsgIovToSocket(sockfd, reinterpret_cast<void *>(&data), sizeof(data))) {
125 DFXLOG_ERROR("%s :: Failed to sendmsg.", __func__);
126 break;
127 }
128
129 fd = ReadFileDescriptorFromSocket(sockfd);
130 DFXLOG_DEBUG("RequestFileDescriptorByCheck(%d).", fd);
131 } while (false);
132 close(sockfd);
133 return fd;
134 }
135
SendUidToServer(int sockfd)136 static int SendUidToServer(int sockfd)
137 {
138 int mRsp = (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
139
140 int data = 12345;
141 if (!SendMsgIovToSocket(sockfd, reinterpret_cast<void *>(&data), sizeof(data))) {
142 DFXLOG_ERROR("%s :: Failed to sendmsg.", __func__);
143 return mRsp;
144 }
145
146 char recvbuf[SOCKET_BUFFER_SIZE] = {'\0'};
147 ssize_t count = OHOS_TEMP_FAILURE_RETRY(recv(sockfd, recvbuf, sizeof(recvbuf), 0));
148 if (count < 0) {
149 DFXLOG_ERROR("%s :: Failed to recv.", __func__);
150 return mRsp;
151 }
152
153 mRsp = atoi(recvbuf);
154 return mRsp;
155 }
156
CheckConnectStatus()157 bool CheckConnectStatus()
158 {
159 int sockfd = -1;
160 std::string name = GetSocketConnectionName();
161 if (StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
162 close(sockfd);
163 return true;
164 }
165 return false;
166 }
167
SendRequestToServer(const FaultLoggerdRequest & request)168 static int SendRequestToServer(const FaultLoggerdRequest &request)
169 {
170 int sockfd = -1;
171 int resRsp = (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
172 do {
173 std::string name = GetSocketConnectionName();
174 if (request.clientType == FaultLoggerClientType::SDK_DUMP_CLIENT) {
175 name = std::string(SERVER_SDKDUMP_SOCKET_NAME);
176 }
177
178 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
179 DFXLOG_ERROR("StartConnect(%d) failed", sockfd);
180 return resRsp;
181 }
182 if (OHOS_TEMP_FAILURE_RETRY(write(sockfd, &request,
183 sizeof(struct FaultLoggerdRequest))) != static_cast<long>(sizeof(request))) {
184 DFXLOG_ERROR("%s", "write failed.");
185 break;
186 }
187
188 if (!CheckReadResp(sockfd)) {
189 break;
190 }
191 resRsp = SendUidToServer(sockfd);
192 } while (false);
193
194 close(sockfd);
195 DFXLOG_INFO("SendRequestToServer :: resRsp(%d).", resRsp);
196 return resRsp;
197 }
198
RequestCheckPermission(int32_t pid)199 bool RequestCheckPermission(int32_t pid)
200 {
201 DFXLOG_INFO("RequestCheckPermission :: %d.", pid);
202 if (pid <= 0) {
203 return false;
204 }
205
206 struct FaultLoggerdRequest request;
207 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
208
209 request.pid = pid;
210 request.clientType = (int32_t)FaultLoggerClientType::PERMISSION_CLIENT;
211
212 bool ret = false;
213 if (SendRequestToServer(request) == (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS) {
214 ret = true;
215 }
216 return ret;
217 }
218
RequestSdkDump(int32_t pid,int32_t tid,int timeout)219 int RequestSdkDump(int32_t pid, int32_t tid, int timeout)
220 {
221 return RequestSdkDumpJson(pid, tid, false, timeout);
222 }
223
RequestSdkDumpJson(int32_t pid,int32_t tid,bool isJson,int timeout)224 int RequestSdkDumpJson(int32_t pid, int32_t tid, bool isJson, int timeout)
225 {
226 DFXLOG_INFO("RequestSdkDumpJson :: pid(%d), tid(%d).", pid, tid);
227 if (pid <= 0 || tid < 0) {
228 return -1;
229 }
230
231 struct FaultLoggerdRequest request;
232 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
233 request.isJson = isJson;
234 request.sigCode = DUMP_TYPE_REMOTE;
235 request.pid = pid;
236 request.tid = tid;
237 request.callerPid = getprocpid();
238 request.callerTid = getproctid();
239 request.clientType = (int32_t)FaultLoggerClientType::SDK_DUMP_CLIENT;
240 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
241 request.endTime = GetAbsTimeMilliSeconds() + static_cast<uint64_t>(timeout);
242
243 return SendRequestToServer(request);
244 }
245
RequestPrintTHilog(const char * msg,int length)246 int RequestPrintTHilog(const char *msg, int length)
247 {
248 if (length >= LINE_BUF_SIZE) {
249 return -1;
250 }
251
252 struct FaultLoggerdRequest request;
253 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
254 request.clientType = (int32_t)FaultLoggerClientType::PRINT_T_HILOG_CLIENT;
255 request.pid = getprocpid();
256 request.uid = getuid();
257 int sockfd = -1;
258 do {
259 std::string name = GetSocketConnectionName();
260 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
261 DFXLOG_ERROR("StartConnect(%d) failed", sockfd);
262 return -1;
263 }
264
265 if (OHOS_TEMP_FAILURE_RETRY(write(sockfd, &request,
266 sizeof(struct FaultLoggerdRequest))) != static_cast<long>(sizeof(request))) {
267 break;
268 }
269
270 if (!CheckReadResp(sockfd)) {
271 break;
272 }
273
274 int nwrite = OHOS_TEMP_FAILURE_RETRY(write(sockfd, msg, strlen(msg)));
275 if (nwrite != static_cast<long>(strlen(msg))) {
276 DFXLOG_ERROR("nwrite: %d.", nwrite);
277 break;
278 }
279 close(sockfd);
280 return 0;
281 } while (false);
282 close(sockfd);
283 return -1;
284 }
285
RequestPipeFd(int32_t pid,int32_t pipeType)286 int32_t RequestPipeFd(int32_t pid, int32_t pipeType)
287 {
288 if (pipeType < static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_BUF) ||
289 pipeType > static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_DELETE)) {
290 DFXLOG_ERROR("%s :: pipeType(%d) failed.", __func__, pipeType);
291 return -1;
292 }
293 struct FaultLoggerdRequest request;
294 (void)memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest));
295
296 if ((pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF)) ||
297 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_RES))) {
298 request.isJson = true;
299 } else {
300 request.isJson = false;
301 }
302 request.pipeType = pipeType;
303 request.pid = pid;
304 request.callerPid = getprocpid();
305 request.callerTid = getproctid();
306 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT;
307 if ((pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_BUF)) ||
308 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_RES)) ||
309 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF)) ||
310 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_RES))) {
311 return RequestFileDescriptorByCheck(&request);
312 }
313 return RequestFileDescriptorEx(&request);
314 }
315
RequestDelPipeFd(int32_t pid)316 int32_t RequestDelPipeFd(int32_t pid)
317 {
318 struct FaultLoggerdRequest request;
319 (void)memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest));
320 request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE;
321 request.pid = pid;
322 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT;
323
324 int sockfd;
325 std::string name = GetSocketConnectionName();
326 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
327 DFXLOG_ERROR("StartConnect(%d) failed", sockfd);
328 return -1;
329 }
330
331 OHOS_TEMP_FAILURE_RETRY(write(sockfd, &request, sizeof(struct FaultLoggerdRequest)));
332 close(sockfd);
333 return 0;
334 }
335
ReportDumpStats(const struct FaultLoggerdStatsRequest * request)336 int ReportDumpStats(const struct FaultLoggerdStatsRequest *request)
337 {
338 int sockfd = -1;
339 std::string name = GetSocketConnectionName();
340 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
341 DFXLOG_ERROR("%s", "ReportDumpCatcherStats: failed to connect to faultloggerd");
342 return -1;
343 }
344
345 if (OHOS_TEMP_FAILURE_RETRY(write(sockfd, request,
346 sizeof(struct FaultLoggerdStatsRequest))) != static_cast<long int>(sizeof(struct FaultLoggerdStatsRequest))) {
347 DFXLOG_ERROR("%s", "ReportDumpCatcherStats: failed to write stats.");
348 close(sockfd);
349 return -1;
350 }
351 close(sockfd);
352 return 0;
353 }
354