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_define.h"
30 #include "dfx_log.h"
31 #include "dfx_util.h"
32 #include "faultloggerd_socket.h"
33 #include "file_util.h"
34
35 #define FAULTLOGGER_DAEMON_RESP "RESP:COMPLETE"
36 static const int32_t SOCKET_TIMEOUT = 5;
37
GetSocketConnectionName()38 static std::string GetSocketConnectionName()
39 {
40 std::string content;
41 OHOS::HiviewDFX::LoadStringFromFile(PROC_SELF_CMDLINE_PATH, content);
42 if (content.find("processdump") != std::string::npos) {
43 return std::string(SERVER_CRASH_SOCKET_NAME);
44 }
45 return std::string(SERVER_SOCKET_NAME);
46 }
47
RequestFileDescriptor(int32_t type)48 int32_t RequestFileDescriptor(int32_t type)
49 {
50 struct FaultLoggerdRequest request;
51 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
52 request.type = type;
53 request.pid = getpid();
54 request.tid = gettid();
55 request.uid = getuid();
56 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
57 return RequestFileDescriptorEx(&request);
58 }
59
RequestLogFileDescriptor(struct FaultLoggerdRequest * request)60 int32_t RequestLogFileDescriptor(struct FaultLoggerdRequest *request)
61 {
62 request->clientType = (int32_t)FaultLoggerClientType::LOG_FILE_DES_CLIENT;
63 return RequestFileDescriptorEx(request);
64 }
65
RequestFileDescriptorEx(const struct FaultLoggerdRequest * request)66 int32_t RequestFileDescriptorEx(const struct FaultLoggerdRequest *request)
67 {
68 if (request == nullptr) {
69 DFXLOG_ERROR("nullptr request");
70 return -1;
71 }
72
73 int sockfd;
74 std::string name = GetSocketConnectionName();
75 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
76 DFXLOG_ERROR("StartConnect failed");
77 return -1;
78 }
79
80 write(sockfd, request, sizeof(struct FaultLoggerdRequest));
81 int fd = ReadFileDescriptorFromSocket(sockfd);
82 DFXLOG_DEBUG("RequestFileDescriptorEx(%d).\n", fd);
83 close(sockfd);
84 return fd;
85 }
86
CheckReadResp(int sockfd)87 static bool CheckReadResp(int sockfd)
88 {
89 char ControlBuffer[SOCKET_BUFFER_SIZE] = {0};
90 (void)memset_s(&ControlBuffer, sizeof(ControlBuffer), 0, SOCKET_BUFFER_SIZE);
91
92 ssize_t nread = read(sockfd, ControlBuffer, sizeof(ControlBuffer) - 1);
93 if (nread != static_cast<ssize_t>(strlen(FAULTLOGGER_DAEMON_RESP))) {
94 DFXLOG_ERROR("nread: %d.", nread);
95 return false;
96 }
97 return true;
98 }
99
RequestFileDescriptorByCheck(const struct FaultLoggerdRequest * request)100 static int32_t RequestFileDescriptorByCheck(const struct FaultLoggerdRequest *request)
101 {
102 int32_t fd = -1;
103 if (request == nullptr) {
104 DFXLOG_ERROR("nullptr request");
105 return -1;
106 }
107
108 int sockfd = -1;
109 do {
110 std::string name = GetSocketConnectionName();
111 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
112 DFXLOG_ERROR("StartConnect failed");
113 break;
114 }
115
116 write(sockfd, request, sizeof(struct FaultLoggerdRequest));
117
118 if (!CheckReadResp(sockfd)) {
119 break;
120 }
121
122 int data = 12345;
123 if (!SendMsgIovToSocket(sockfd, reinterpret_cast<void *>(&data), sizeof(data))) {
124 DFXLOG_ERROR("%s :: Failed to sendmsg.", __func__);
125 break;
126 }
127
128 fd = ReadFileDescriptorFromSocket(sockfd);
129 DFXLOG_DEBUG("RequestFileDescriptorByCheck(%d).\n", fd);
130 } while (false);
131 close(sockfd);
132 return fd;
133 }
134
SendUidToServer(int sockfd)135 static int SendUidToServer(int sockfd)
136 {
137 int mRsp = (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
138
139 int data = 12345;
140 if (!SendMsgIovToSocket(sockfd, reinterpret_cast<void *>(&data), sizeof(data))) {
141 DFXLOG_ERROR("%s :: Failed to sendmsg.", __func__);
142 return mRsp;
143 }
144
145 char recvbuf[SOCKET_BUFFER_SIZE] = {'\0'};
146 ssize_t count = recv(sockfd, recvbuf, sizeof(recvbuf), 0);
147 if (count < 0) {
148 DFXLOG_ERROR("%s :: Failed to recv.", __func__);
149 return mRsp;
150 }
151
152 mRsp = atoi(recvbuf);
153 return mRsp;
154 }
155
CheckConnectStatus()156 bool CheckConnectStatus()
157 {
158 int sockfd = -1;
159 std::string name = GetSocketConnectionName();
160 if (StartConnect(sockfd, name.c_str(), -1)) {
161 close(sockfd);
162 return true;
163 }
164 return false;
165 }
166
SendRequestToServer(const FaultLoggerdRequest & request)167 static int SendRequestToServer(const FaultLoggerdRequest &request)
168 {
169 int sockfd = -1;
170 int resRsp = (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
171 do {
172 std::string name = GetSocketConnectionName();
173 if (!StartConnect(sockfd, name.c_str(), -1)) {
174 DFXLOG_ERROR("StartConnect failed.");
175 break;
176 }
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 DFXLOG_INFO("RequestSdkDump :: type(%d), pid(%d), tid(%d).", type, pid, tid);
217 if (pid <= 0 || tid < 0) {
218 return -1;
219 }
220
221 struct FaultLoggerdRequest request;
222 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
223 request.sigCode = type;
224 request.pid = pid;
225 request.tid = tid;
226 request.callerPid = getpid();
227 request.callerTid = syscall(SYS_gettid);
228 request.clientType = (int32_t)FaultLoggerClientType::SDK_DUMP_CLIENT;
229 request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
230
231 return SendRequestToServer(request);
232 }
233
RequestPrintTHilog(const char * msg,int length)234 int RequestPrintTHilog(const char *msg, int length)
235 {
236 if (length >= LOG_BUF_LEN) {
237 return -1;
238 }
239
240 struct FaultLoggerdRequest request;
241 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
242 request.clientType = (int32_t)FaultLoggerClientType::PRINT_T_HILOG_CLIENT;
243 request.pid = getpid();
244 request.uid = getuid();
245 int sockfd = -1;
246 do {
247 std::string name = GetSocketConnectionName();
248 if (!StartConnect(sockfd, name.c_str(), -1)) {
249 DFXLOG_ERROR("StartConnect failed");
250 break;
251 }
252
253 if (write(sockfd, &request, sizeof(struct FaultLoggerdRequest)) != static_cast<long>(sizeof(request))) {
254 break;
255 }
256
257 if (!CheckReadResp(sockfd)) {
258 break;
259 }
260
261 int nwrite = write(sockfd, msg, strlen(msg));
262 if (nwrite != static_cast<long>(strlen(msg))) {
263 DFXLOG_ERROR("nwrite: %d.", nwrite);
264 break;
265 }
266 close(sockfd);
267 return 0;
268 } while (false);
269 close(sockfd);
270 return -1;
271 }
272
RequestPipeFd(int32_t pid,int32_t pipeType)273 int32_t RequestPipeFd(int32_t pid, int32_t pipeType)
274 {
275 if (pipeType < static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_BUF) ||
276 pipeType > static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_WRITE_RES)) {
277 DFXLOG_ERROR("%s :: pipeType(%d) failed.", __func__, pipeType);
278 return -1;
279 }
280 struct FaultLoggerdRequest request;
281 (void)memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest));
282 request.pipeType = pipeType;
283 request.pid = pid;
284 request.callerPid = getpid();
285 request.callerTid = syscall(SYS_gettid);
286 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT;
287 if ((pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_BUF)) ||
288 (pipeType == static_cast<int32_t>(FaultLoggerPipeType::PIPE_FD_READ_RES))) {
289 return RequestFileDescriptorByCheck(&request);
290 }
291 return RequestFileDescriptorEx(&request);
292 }
293
RequestDelPipeFd(int32_t pid)294 int32_t RequestDelPipeFd(int32_t pid)
295 {
296 struct FaultLoggerdRequest request;
297 (void)memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest));
298 request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE;
299 request.pid = pid;
300 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT;
301
302 int sockfd;
303 std::string name = GetSocketConnectionName();
304 if (!StartConnect(sockfd, name.c_str(), SOCKET_TIMEOUT)) {
305 DFXLOG_ERROR("StartConnect failed");
306 return -1;
307 }
308
309 write(sockfd, &request, sizeof(struct FaultLoggerdRequest));
310 close(sockfd);
311 return 0;
312 }
313