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 }