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 #include "file_util.h"
35
36 #define FAULTLOGGER_DAEMON_RESP "RESP:COMPLETE"
37 static const int32_t SOCKET_TIMEOUT = 5;
38
GetSocketConnectionName()39 static std::string GetSocketConnectionName()
40 {
41 char content[NAME_BUF_LEN];
42 GetProcessName(content, sizeof(content));
43 if (std::string(content).find("processdump") != std::string::npos) {
44 return std::string(SERVER_CRASH_SOCKET_NAME);
45 }
46 return std::string(SERVER_SOCKET_NAME);
47 }
48
RequestFileDescriptor(int32_t type)49 int32_t RequestFileDescriptor(int32_t type)
50 {
51 struct FaultLoggerdRequest request;
52 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
53 request.type = type;
54 request.pid = getpid();
55 request.tid = gettid();
56 request.uid = getuid();
57 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
58 return RequestFileDescriptorEx(&request);
59 }
60
RequestLogFileDescriptor(struct FaultLoggerdRequest * request)61 int32_t RequestLogFileDescriptor(struct FaultLoggerdRequest *request)
62 {
63 request->clientType = (int32_t)FaultLoggerClientType::LOG_FILE_DES_CLIENT;
64 return RequestFileDescriptorEx(request);
65 }
66
RequestFileDescriptorEx(const struct FaultLoggerdRequest * request)67 int32_t RequestFileDescriptorEx(const struct FaultLoggerdRequest *request)
68 {
69 if (request == nullptr) {
70 DFXLOG_ERROR("nullptr request");
71 return -1;
72 }
73
74 int sockfd;
75 std::string name = GetSocketConnectionName();
76 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
77 DFXLOG_ERROR("StartConnect failed");
78 return -1;
79 }
80
81 write(sockfd, request, sizeof(struct FaultLoggerdRequest));
82 int fd = ReadFileDescriptorFromSocket(sockfd);
83 DFXLOG_DEBUG("RequestFileDescriptorEx(%d).\n", fd);
84 close(sockfd);
85 return fd;
86 }
87
CheckReadResp(int sockfd)88 static bool CheckReadResp(int sockfd)
89 {
90 char ControlBuffer[SOCKET_BUFFER_SIZE] = {0};
91 (void)memset_s(&ControlBuffer, sizeof(ControlBuffer), 0, SOCKET_BUFFER_SIZE);
92
93 ssize_t nread = 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("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 failed");
114 break;
115 }
116
117 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).\n", 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 = 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(), -1)) {
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 (!StartConnect(sockfd, name.c_str(), -1)) {
175 DFXLOG_ERROR("StartConnect failed.");
176 break;
177 }
178 if (write(sockfd, &request, sizeof(struct FaultLoggerdRequest)) != static_cast<long>(sizeof(request))) {
179 DFXLOG_ERROR("write failed.");
180 break;
181 }
182
183 if (!CheckReadResp(sockfd)) {
184 break;
185 }
186 resRsp = SendUidToServer(sockfd);
187 } while (false);
188
189 close(sockfd);
190 DFXLOG_INFO("SendRequestToServer :: resRsp(%d).", resRsp);
191 return resRsp;
192 }
193
RequestCheckPermission(int32_t pid)194 bool RequestCheckPermission(int32_t pid)
195 {
196 DFXLOG_INFO("RequestCheckPermission :: %d.", pid);
197 if (pid <= 0) {
198 return false;
199 }
200
201 struct FaultLoggerdRequest request;
202 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
203
204 request.pid = pid;
205 request.clientType = (int32_t)FaultLoggerClientType::PERMISSION_CLIENT;
206
207 bool ret = false;
208 if (SendRequestToServer(request) == (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS) {
209 ret = true;
210 }
211 return ret;
212 }
213
RequestSdkDump(int32_t type,int32_t pid,int32_t tid)214 int RequestSdkDump(int32_t type, int32_t pid, int32_t tid)
215 {
216 return RequestSdkDumpJson(type, pid, tid, false);
217 }
218
RequestSdkDumpJson(int32_t type,int32_t pid,int32_t tid,bool isJson)219 int RequestSdkDumpJson(int32_t type, int32_t pid, int32_t tid, bool isJson)
220 {
221 DFXLOG_INFO("RequestSdkDumpJson :: type(%d), pid(%d), tid(%d).", type, pid, tid);
222 if (pid <= 0 || tid < 0) {
223 return -1;
224 }
225
226 struct FaultLoggerdRequest request;
227 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
228 request.isJson = isJson;
229 request.sigCode = type;
230 request.pid = pid;
231 request.tid = tid;
232 request.callerPid = getpid();
233 request.callerTid = syscall(SYS_gettid);
234 request.clientType = (int32_t)FaultLoggerClientType::SDK_DUMP_CLIENT;
235 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
236
237 return SendRequestToServer(request);
238 }
239
RequestPrintTHilog(const char * msg,int length)240 int RequestPrintTHilog(const char *msg, int length)
241 {
242 if (length >= LINE_BUF_SIZE) {
243 return -1;
244 }
245
246 struct FaultLoggerdRequest request;
247 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
248 request.clientType = (int32_t)FaultLoggerClientType::PRINT_T_HILOG_CLIENT;
249 request.pid = getpid();
250 request.uid = getuid();
251 int sockfd = -1;
252 do {
253 std::string name = GetSocketConnectionName();
254 if (!StartConnect(sockfd, name.c_str(), -1)) {
255 DFXLOG_ERROR("StartConnect failed");
256 break;
257 }
258
259 if (write(sockfd, &request, sizeof(struct FaultLoggerdRequest)) != static_cast<long>(sizeof(request))) {
260 break;
261 }
262
263 if (!CheckReadResp(sockfd)) {
264 break;
265 }
266
267 int nwrite = write(sockfd, msg, strlen(msg));
268 if (nwrite != static_cast<long>(strlen(msg))) {
269 DFXLOG_ERROR("nwrite: %d.", nwrite);
270 break;
271 }
272 close(sockfd);
273 return 0;
274 } while (false);
275 close(sockfd);
276 return -1;
277 }
278
RequestPipeFd(int32_t pid,int32_t pipeType)279 int32_t RequestPipeFd(int32_t pid, int32_t pipeType)
280 {
281 if (pipeType < static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_BUF) ||
282 pipeType > static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_DELETE)) {
283 DFXLOG_ERROR("%s :: pipeType(%d) failed.", __func__, pipeType);
284 return -1;
285 }
286 struct FaultLoggerdRequest request;
287 (void)memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest));
288
289 if ((pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF)) ||
290 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_RES))) {
291 request.isJson = true;
292 } else {
293 request.isJson = false;
294 }
295 request.pipeType = pipeType;
296 request.pid = pid;
297 request.callerPid = getpid();
298 request.callerTid = syscall(SYS_gettid);
299 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT;
300 if ((pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_BUF)) ||
301 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_RES)) ||
302 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_BUF)) ||
303 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_JSON_READ_RES))) {
304 return RequestFileDescriptorByCheck(&request);
305 }
306 return RequestFileDescriptorEx(&request);
307 }
308
RequestDelPipeFd(int32_t pid)309 int32_t RequestDelPipeFd(int32_t pid)
310 {
311 struct FaultLoggerdRequest request;
312 (void)memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest));
313 request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE;
314 request.pid = pid;
315 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT;
316
317 int sockfd;
318 std::string name = GetSocketConnectionName();
319 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
320 DFXLOG_ERROR("StartConnect failed");
321 return -1;
322 }
323
324 write(sockfd, &request, sizeof(struct FaultLoggerdRequest));
325 close(sockfd);
326 return 0;
327 }
328