1 /*
2 * Copyright (c) 2021-2022 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 <sys/socket.h>
23 #include <sys/syscall.h>
24 #include <sys/time.h>
25 #include <sys/un.h>
26 #include <unistd.h>
27 #include "dfx_define.h"
28 #include "dfx_log.h"
29 #include "faultloggerd_socket.h"
30
31 static const int32_t SOCKET_TIMEOUT = 5;
32
ReadStringFromFile(const char * path,char * buf,size_t len)33 bool ReadStringFromFile(const char *path, char *buf, size_t len)
34 {
35 if ((len <= 1) || (buf == nullptr) || (path == nullptr)) {
36 return false;
37 }
38
39 char realPath[PATH_MAX];
40 if (realpath(path, realPath) == nullptr) {
41 return false;
42 }
43
44 FILE *fp = fopen(realPath, "r");
45 if (fp == nullptr) {
46 // log failure
47 return false;
48 }
49
50 char *ptr = buf;
51 for (size_t i = 0; i < len; i++) {
52 int c = getc(fp);
53 if (c == EOF) {
54 *ptr++ = 0x00;
55 break;
56 } else {
57 *ptr++ = c;
58 }
59 }
60 fclose(fp);
61 return false;
62 }
63
FillRequest(int32_t type,FaultLoggerdRequest * request)64 void FillRequest(int32_t type, FaultLoggerdRequest *request)
65 {
66 if (request == nullptr) {
67 DfxLogError("nullptr request");
68 return;
69 }
70
71 struct timeval time;
72 (void)gettimeofday(&time, nullptr);
73
74 request->type = type;
75 request->pid = getpid();
76 request->tid = gettid();
77 request->uid = getuid();
78 request->time = (static_cast<uint64_t>(time.tv_sec) * 1000) + // 1000 : second to millsecond convert ratio
79 (static_cast<uint64_t>(time.tv_usec) / 1000); // 1000 : microsecond to millsecond convert ratio
80 ReadStringFromFile("/proc/self/cmdline", request->module, sizeof(request->module));
81 }
82
RequestFileDescriptor(int32_t type)83 int32_t RequestFileDescriptor(int32_t type)
84 {
85 struct FaultLoggerdRequest request;
86 errno_t err = memset_s(&request, sizeof(request), 0, sizeof(request));
87 if (err != EOK) {
88 DfxLogError("%s :: memset_s request failed..", __func__);
89 }
90 FillRequest(type, &request);
91 return RequestFileDescriptorEx(&request);
92 }
93
RequestLogFileDescriptor(struct FaultLoggerdRequest * request)94 int32_t RequestLogFileDescriptor(struct FaultLoggerdRequest *request)
95 {
96 request->clientType = (int32_t)FaultLoggerClientType::LOG_FILE_DES_CLIENT;
97 return RequestFileDescriptorEx(request);
98 }
99
RequestPipeFd(int32_t pid,int32_t pipeType)100 int32_t RequestPipeFd(int32_t pid, int32_t pipeType)
101 {
102 struct FaultLoggerdRequest request;
103 if (memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest)) != 0) {
104 DfxLogError("%s :: memset_s request failed..", __func__);
105 }
106 request.pipeType = pipeType;
107 request.pid = pid;
108 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT;
109 return RequestFileDescriptorEx(&request);
110 }
111
RequestDelPipeFd(int32_t pid)112 int32_t RequestDelPipeFd(int32_t pid)
113 {
114 struct FaultLoggerdRequest request;
115 if (memset_s(&request, sizeof(request), 0, sizeof(struct FaultLoggerdRequest)) != 0) {
116 DfxLogError("%s :: memset_s request failed..", __func__);
117 }
118 request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE;
119 request.pid = pid;
120 request.clientType = (int32_t)FaultLoggerClientType::PIPE_FD_CLIENT;
121
122 int sockfd;
123 if (!StartConnect(sockfd, FAULTLOGGERD_SOCK_PATH, SOCKET_TIMEOUT)) {
124 DfxLogError("StartConnect failed");
125 return -1;
126 }
127
128 write(sockfd, &request, sizeof(struct FaultLoggerdRequest));
129 close(sockfd);
130 return 0;
131 }
132
RequestFileDescriptorEx(const struct FaultLoggerdRequest * request)133 int32_t RequestFileDescriptorEx(const struct FaultLoggerdRequest *request)
134 {
135 if (request == nullptr) {
136 DfxLogError("nullptr request");
137 return -1;
138 }
139
140 int sockfd;
141 if (!StartConnect(sockfd, FAULTLOGGERD_SOCK_PATH, SOCKET_TIMEOUT)) {
142 DfxLogError("StartConnect failed");
143 return -1;
144 }
145
146 write(sockfd, request, sizeof(struct FaultLoggerdRequest));
147 int fd = ReadFileDescriptorFromSocket(sockfd);
148 DfxLogDebug("RequestFileDescriptorEx(%d).\n", fd);
149 close(sockfd);
150 return fd;
151 }
152
SendUidToServer(int sockfd)153 static int SendUidToServer(int sockfd)
154 {
155 int mRsp = (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_REJECT;
156
157 int data = 12345;
158 if (!SendMsgIovToSocket(sockfd, reinterpret_cast<void *>(&data), sizeof(data))) {
159 DfxLogError("%s :: Failed to sendmsg.", __func__);
160 return mRsp;
161 }
162
163 char recvbuf[SOCKET_BUFFER_SIZE] = {'\0'};
164 ssize_t count = recv(sockfd, recvbuf, sizeof(recvbuf), 0);
165 if (count < 0) {
166 DfxLogError("%s :: Failed to recv.", __func__);
167 return mRsp;
168 }
169
170 mRsp = atoi(recvbuf);
171 return mRsp;
172 }
173
CheckConnectStatus()174 bool CheckConnectStatus()
175 {
176 int sockfd = -1;
177 if (StartConnect(sockfd, FAULTLOGGERD_SOCK_PATH, -1)) {
178 close(sockfd);
179 return true;
180 }
181 return false;
182 }
183
SendRequestToServer(const FaultLoggerdRequest & request)184 static int SendRequestToServer(const FaultLoggerdRequest &request)
185 {
186 int sockfd = -1;
187 int resRsp = (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS;
188 do {
189 if (!StartConnect(sockfd, FAULTLOGGERD_SOCK_PATH, -1)) {
190 DfxLogError("StartConnect failed.");
191 break;
192 }
193
194 if (write(sockfd, &request, sizeof(struct FaultLoggerdRequest)) != static_cast<long>(sizeof(request))) {
195 break;
196 }
197
198 char ControlBuffer[SOCKET_BUFFER_SIZE];
199 errno_t err = memset_s(&ControlBuffer, sizeof(ControlBuffer), 0, SOCKET_BUFFER_SIZE);
200 if (err != EOK) {
201 DfxLogError("memset_s failed, err = %d.", (int)err);
202 break;
203 }
204
205 int nread = read(sockfd, ControlBuffer, sizeof(ControlBuffer) - 1);
206 if (nread != (ssize_t)strlen(FAULTLOGGER_DAEMON_RESP)) {
207 DfxLogError("nread: %d.", nread);
208 break;
209 }
210 resRsp = SendUidToServer(sockfd);
211 } while (false);
212
213 close(sockfd);
214 DfxLogInfo("SendRequestToServer :: resRsp(%d).", resRsp);
215 return resRsp;
216 }
217
RequestCheckPermission(int32_t pid)218 bool RequestCheckPermission(int32_t pid)
219 {
220 DfxLogInfo("RequestCheckPermission :: %d.", pid);
221 if (pid <= 0) {
222 return false;
223 }
224
225 struct FaultLoggerdRequest request;
226 errno_t err = memset_s(&request, sizeof(request), 0, sizeof(request));
227 if (err != EOK) {
228 DfxLogError("%s :: memset_s request failed..", __func__);
229 }
230
231 request.pid = pid;
232 request.clientType = (int32_t)FaultLoggerClientType::PERMISSION_CLIENT;
233
234 bool ret = false;
235 if (SendRequestToServer(request) == (int)FaultLoggerCheckPermissionResp::CHECK_PERMISSION_PASS) {
236 ret = true;
237 }
238 return ret;
239 }
240
RequestSdkDump(int32_t type,int32_t pid,int32_t tid)241 int RequestSdkDump(int32_t type, int32_t pid, int32_t tid)
242 {
243 DfxLogInfo("RequestSdkDump :: type(%d), pid(%d), tid(%d).", type, pid, tid);
244 if (pid <= 0 || tid < 0) {
245 return false;
246 }
247
248 struct FaultLoggerdRequest request;
249 errno_t err = memset_s(&request, sizeof(request), 0, sizeof(request));
250 if (err != EOK) {
251 DfxLogError("%s :: memset_s request failed..", __func__);
252 }
253 request.sigCode = type;
254 request.pid = pid;
255 request.tid = tid;
256 request.callerPid = getpid();
257 request.callerTid = syscall(SYS_gettid);
258 request.clientType = (int32_t)FaultLoggerClientType::SDK_DUMP_CLIENT;
259
260 return SendRequestToServer(request);
261 }
262
RequestPrintTHilog(const char * msg,int length)263 void RequestPrintTHilog(const char *msg, int length)
264 {
265 if (length >= LOG_BUF_LEN) {
266 return;
267 }
268
269 struct FaultLoggerdRequest request;
270 errno_t err = memset_s(&request, sizeof(request), 0, sizeof(request));
271 if (err != EOK) {
272 DfxLogError("%s :: memset_s request failed..", __func__);
273 }
274 request.clientType = (int32_t)FaultLoggerClientType::PRINT_T_HILOG_CLIENT;
275
276 int sockfd = -1;
277 do {
278 if (!StartConnect(sockfd, FAULTLOGGERD_SOCK_PATH, -1)) {
279 DfxLogError("StartConnect failed");
280 break;
281 }
282
283 if (write(sockfd, &request, sizeof(struct FaultLoggerdRequest)) != static_cast<long>(sizeof(request))) {
284 break;
285 }
286
287 char ControlBuffer[SOCKET_BUFFER_SIZE];
288 errno_t ret = memset_s(&ControlBuffer, sizeof(ControlBuffer), 0, SOCKET_BUFFER_SIZE);
289 if (ret != EOK) {
290 DfxLogError("memset_s failed, err = %d.", (int)ret);
291 break;
292 }
293 if (read(sockfd, ControlBuffer, sizeof(ControlBuffer) - 1) != \
294 static_cast<long>(strlen(FAULTLOGGER_DAEMON_RESP))) {
295 break;
296 }
297
298 int nwrite = write(sockfd, msg, strlen(msg));
299 if (nwrite != static_cast<long>(strlen(msg))) {
300 DfxLogError("nwrite: %d.", nwrite);
301 break;
302 }
303 } while (false);
304 close(sockfd);
305 }
306
307