• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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