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