• 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 
16 /* This files is writer log to file module on process dump module. */
17 
18 #include "faultloggerd_socket.h"
19 
20 #include <cstddef>
21 #include <cstdio>
22 #include <securec.h>
23 #include <sys/socket.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 "init_socket.h"
30 
StartConnect(int & sockfd,const char * path,const int timeout)31 bool StartConnect(int& sockfd, const char* path, const int timeout)
32 {
33     bool ret = false;
34     if ((sockfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) {
35         DfxLogError("%s :: Failed to socket\n", __func__);
36         return ret;
37     }
38 
39     do {
40         if (timeout > 0) {
41             struct timeval timev = {
42                 timeout,
43                 0
44             };
45             void* pTimev = &timev;
46             if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, \
47                 static_cast<const char*>(pTimev), sizeof(timev)) != 0) {
48                     DfxLogError("setsockopt SO_RCVTIMEO error");
49             }
50         }
51 
52         struct sockaddr_un server;
53         errno_t err = memset_s(&server, sizeof(server), 0, sizeof(server));
54         if (err != EOK) {
55             DfxLogError("%s :: memset_s failed, err = %d.", __func__, (int)err);
56             break;
57         }
58         server.sun_family = AF_LOCAL;
59         err = strncpy_s(server.sun_path, sizeof(server.sun_path), path, sizeof(server.sun_path) - 1);
60         if (err != EOK) {
61             DfxLogError("%s :: strncpy failed, err = %d.", __func__, (int)err);
62             break;
63         }
64 
65         int len = static_cast<int>(offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path) + 1);
66         int connected = connect(sockfd, reinterpret_cast<struct sockaddr *>(&server), len);
67         if (connected < 0) {
68             DfxLogError("%s :: connect failed, errno = %d.", __func__, errno);
69             break;
70         }
71 
72         ret = true;
73     } while (false);
74 
75     if (!ret) {
76         close(sockfd);
77     }
78     return ret;
79 }
80 
GetServerSocket(int & sockfd,const char * path)81 static bool GetServerSocket(int& sockfd, const char* path)
82 {
83     sockfd = OHOS_TEMP_FAILURE_RETRY(socket(AF_LOCAL, SOCK_STREAM, 0));
84     if (sockfd < 0) {
85         DfxLogError("%s :: Failed to create socket", __func__);
86         return false;
87     }
88 
89     struct sockaddr_un server;
90     errno_t err = memset_s(&server, sizeof(server), 0, sizeof(server));
91     if (err != EOK) {
92         DfxLogError("%s :: memset_s failed, err = %d.", __func__, (int)err);
93         return false;
94     }
95     server.sun_family = AF_LOCAL;
96     if (strncpy_s(server.sun_path, sizeof(server.sun_path), path, sizeof(server.sun_path) - 1) != 0) {
97         DfxLogError("%s :: strncpy failed.", __func__);
98         return false;
99     }
100 
101     unlink(path);
102 
103     int optval = 1;
104     int ret = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
105     if (ret < 0) {
106         return false;
107     }
108 
109     if (bind(sockfd, (struct sockaddr *)&server,
110         offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path)) < 0) {
111         DfxLogError("%s :: Failed to bind socket", __func__);
112         return false;
113     }
114 
115     return true;
116 }
117 
StartListen(int & sockfd,const char * name,const int listenCnt)118 bool StartListen(int& sockfd, const char* name, const int listenCnt)
119 {
120     if (name == nullptr) {
121         return false;
122     }
123     sockfd = GetControlSocket(name);
124     if (sockfd < 0) {
125         DfxLogWarn("%s :: Failed to get socket fd by cfg", __func__);
126 
127         if (GetServerSocket(sockfd, FAULTLOGGERD_SOCK_PATH) == false) {
128             DfxLogError("%s :: Failed to get socket fd by path", __func__);
129             return false;
130         }
131     }
132 
133     if (listen(sockfd, listenCnt) < 0) {
134         DfxLogError("%s :: Failed to listen socket", __func__);
135         close(sockfd);
136         sockfd = -1;
137         return false;
138     }
139     DfxLogInfo("%s :: success to listen socket", __func__);
140     return true;
141 }
142 
RecvMsgFromSocket(int sockfd,unsigned char * data,size_t & len)143 static bool RecvMsgFromSocket(int sockfd, unsigned char* data, size_t& len)
144 {
145     bool ret = false;
146     if ((sockfd < 0) || (data == nullptr)) {
147         return ret;
148     }
149 
150     do {
151         struct msghdr msgh = { 0 };
152         char msgBuffer[SOCKET_BUFFER_SIZE] = { 0 };
153         struct iovec iov = {
154             .iov_base = msgBuffer,
155             .iov_len = sizeof(msgBuffer)
156         };
157         msgh.msg_iov = &iov;
158         msgh.msg_iovlen = 1;
159 
160         char ctlBuffer[SOCKET_BUFFER_SIZE] = { 0 };
161         msgh.msg_control = ctlBuffer;
162         msgh.msg_controllen = sizeof(ctlBuffer);
163 
164         if (recvmsg(sockfd, &msgh, 0) < 0) {
165             DfxLogError("%s :: Failed to recv message\n", __func__);
166             break;
167         }
168 
169         struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh);
170         if (cmsg == nullptr) {
171             DfxLogError("%s :: Invalid message\n", __func__);
172             break;
173         }
174 
175         len = cmsg->cmsg_len - sizeof(struct cmsghdr);
176         if (memcpy_s(data, len, CMSG_DATA(cmsg), len) != 0) {
177             DfxLogError("%s :: memcpy error\n", __func__);
178             break;
179         }
180 
181         ret = true;
182     } while (false);
183     return ret;
184 }
185 
RecvMsgCredFromSocket(int sockfd,struct ucred * pucred)186 bool RecvMsgCredFromSocket(int sockfd, struct ucred* pucred)
187 {
188     bool ret = false;
189     if ((sockfd < 0) || (pucred == nullptr)) {
190         return ret;
191     }
192 
193     do {
194         struct msghdr msgh = { 0 };
195         union {
196             char buf[CMSG_SPACE(sizeof(struct ucred))];
197 
198             /* Space large enough to hold a 'ucred' structure */
199             struct cmsghdr align;
200         } controlMsg;
201 
202         msgh.msg_name = nullptr;
203         msgh.msg_namelen = 0;
204 
205         int data;
206         struct iovec iov = {
207             .iov_base = &data,
208             .iov_len = sizeof(data)
209         };
210         msgh.msg_iov = &iov;
211         msgh.msg_iovlen = 1;
212 
213         msgh.msg_control = controlMsg.buf;
214         msgh.msg_controllen = sizeof(controlMsg.buf);
215 
216         if (recvmsg(sockfd, &msgh, 0) < 0) {
217             DfxLogError("%s :: Failed to recv message\n", __func__);
218             break;
219         }
220 
221         struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh);
222         if (cmsg == nullptr) {
223             DfxLogError("%s :: Invalid message\n", __func__);
224             break;
225         }
226 
227         if (memcpy_s(pucred, sizeof(struct ucred), CMSG_DATA(cmsg), sizeof(struct ucred)) != 0) {
228             DfxLogError("%s :: memcpy error\n", __func__);
229             break;
230         }
231 
232         ret = true;
233     } while (false);
234     return ret;
235 }
236 
SendMsgIovToSocket(int sockfd,void * iovBase,const int iovLen)237 bool SendMsgIovToSocket(int sockfd, void *iovBase, const int iovLen)
238 {
239     if ((sockfd < 0) || (iovBase == nullptr) || (iovLen == 0)) {
240         return false;
241     }
242 
243     struct msghdr msgh = { 0 };
244     msgh.msg_name = nullptr;
245     msgh.msg_namelen = 0;
246 
247     struct iovec iov;
248     iov.iov_base = iovBase;
249     iov.iov_len = iovLen;
250     msgh.msg_iov = &iov;
251     msgh.msg_iovlen = 1;
252 
253     msgh.msg_control = nullptr;
254     msgh.msg_controllen = 0;
255 
256     if (sendmsg(sockfd, &msgh, 0) < 0) {
257         DfxLogError("%s :: Failed to send message.", __func__);
258         return false;
259     }
260     return true;
261 }
262 
SendMsgCtlToSocket(int sockfd,const void * cmsg,const int cmsgLen)263 static bool SendMsgCtlToSocket(int sockfd, const void *cmsg, const int cmsgLen)
264 {
265     if ((sockfd < 0) || (cmsg == nullptr) || (cmsgLen == 0)) {
266         return false;
267     }
268 
269     struct msghdr msgh = { 0 };
270     char iovBase[] = "";
271     struct iovec iov = {
272         .iov_base = reinterpret_cast<void *>(iovBase),
273         .iov_len = 1
274     };
275     msgh.msg_iov = &iov;
276     msgh.msg_iovlen = 1;
277 
278     int controlBufLen = CMSG_SPACE(static_cast<unsigned int>(cmsgLen));
279     char controlBuf[controlBufLen];
280     msgh.msg_control = controlBuf;
281     msgh.msg_controllen = sizeof(controlBuf);
282 
283     struct cmsghdr *cmsgh = CMSG_FIRSTHDR(&msgh);
284     if (cmsgh != nullptr) {
285         cmsgh->cmsg_level = SOL_SOCKET;
286         cmsgh->cmsg_type = SCM_RIGHTS;
287         cmsgh->cmsg_len = CMSG_LEN(cmsgLen);
288     }
289     if (memcpy_s(CMSG_DATA(cmsgh), cmsgLen, cmsg, cmsgLen) != 0) {
290         DfxLogError("%s :: memcpy error\n", __func__);
291     }
292 
293     if (sendmsg(sockfd, &msgh, 0) < 0) {
294         DfxLogError("%s :: Failed to send message", __func__);
295         return false;
296     }
297     return true;
298 }
299 
SendFileDescriptorToSocket(int sockfd,int fd)300 bool SendFileDescriptorToSocket(int sockfd, int fd)
301 {
302     return SendMsgCtlToSocket(sockfd, reinterpret_cast<void *>(&fd), sizeof(fd));
303 }
304 
ReadFileDescriptorFromSocket(int sockfd)305 int ReadFileDescriptorFromSocket(int sockfd)
306 {
307     size_t len = sizeof(int);
308     unsigned char data[len + 1];
309     if (!RecvMsgFromSocket(sockfd, data, len)) {
310         DfxLogError("%s :: Failed to recv message", __func__);
311         return -1;
312     }
313 
314     if (len != sizeof(int)) {
315         DfxLogError("%s :: data is null or len is %d", __func__, len);
316         return -1;
317     }
318     int fd = *(reinterpret_cast<int *>(data));
319     DfxLogDebug("%s :: fd: %d", __func__, fd);
320     return fd;
321 }