• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "faultloggerd_socket.h"
17 
18 #include <cstddef>
19 #include <cstdio>
20 #include <string>
21 
22 #include <securec.h>
23 #include <unistd.h>
24 
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <sys/un.h>
29 
30 #include "dfx_define.h"
31 #include "dfx_log.h"
32 #include "init_socket.h"
33 
34 namespace {
35 constexpr int SOCKET_BUFFER_SIZE = 32;
36 }
37 
StartConnect(int32_t sockFd,const char * socketName,uint32_t timeout)38 bool StartConnect(int32_t sockFd, const char* socketName, uint32_t timeout)
39 {
40     if (UNLIKELY(sockFd < 0 || socketName == nullptr)) {
41         return false;
42     }
43     if (timeout > 0) {
44         struct timeval timev = { timeout, 0 };
45         if (OHOS_TEMP_FAILURE_RETRY(setsockopt(sockFd, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev))) != 0) {
46             DFXLOGE("setsockopt(%{public}d) SO_RCVTIMEO error, errno(%{public}d).", sockFd, errno);
47         }
48         if (OHOS_TEMP_FAILURE_RETRY(setsockopt(sockFd, SOL_SOCKET, SO_SNDTIMEO, &timev, sizeof(timev))) != 0) {
49             DFXLOGE("setsockopt(%{public}d) SO_SNDTIMEO error, errno(%{public}d).", sockFd, errno);
50         }
51     }
52 
53     struct sockaddr_un server{0};
54     server.sun_family = AF_LOCAL;
55     std::string fullPath = std::string(FAULTLOGGERD_SOCK_BASE_PATH) + std::string(socketName);
56     errno_t err = strncpy_s(server.sun_path, sizeof(server.sun_path), fullPath.c_str(), sizeof(server.sun_path) - 1);
57     if (err != EOK) {
58         DFXLOGE("%{public}s :: strncpy failed, err = %{public}d.", __func__, (int)err);
59         return false;
60     }
61 
62     int len = static_cast<int>(offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path) + 1);
63     int connected = OHOS_TEMP_FAILURE_RETRY(connect(sockFd, reinterpret_cast<struct sockaddr *>(&server), len));
64     if (connected < 0) {
65         DFXLOGE("%{public}s :: connect failed, errno = %{public}d.", __func__, errno);
66         return false;
67     }
68     return true;
69 }
70 
CreateSocketFd()71 int32_t CreateSocketFd()
72 {
73     int32_t socketFd = socket(AF_LOCAL, SOCK_STREAM, 0);
74     if (socketFd < 0) {
75         DFXLOGE("%{public}s :: Failed to create socket, errno(%{public}d)", __func__, errno);
76         return -1;
77     }
78     return socketFd;
79 }
80 
GetServerSocket(int32_t & sockFd,const char * name)81 static bool GetServerSocket(int32_t& sockFd, const char* name)
82 {
83     sockFd = OHOS_TEMP_FAILURE_RETRY(socket(AF_LOCAL, SOCK_STREAM, 0));
84     if (sockFd < 0) {
85         DFXLOGE("%{public}s :: Failed to create socket, errno(%{public}d)", __func__, errno);
86         return false;
87     }
88 
89     std::string path = std::string(FAULTLOGGERD_SOCK_BASE_PATH) + std::string(name);
90     struct sockaddr_un server{0};
91     server.sun_family = AF_LOCAL;
92     if (strncpy_s(server.sun_path, sizeof(server.sun_path), path.c_str(), sizeof(server.sun_path) - 1) != 0) {
93         DFXLOGE("%{public}s :: strncpy failed.", __func__);
94         return false;
95     }
96 
97     chmod(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IWOTH);
98     unlink(path.c_str());
99 
100     int optval = 1;
101     int ret = OHOS_TEMP_FAILURE_RETRY(setsockopt(sockFd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)));
102     if (ret < 0) {
103         DFXLOGE("%{public}s :: Failed to set socket option, errno(%{public}d)", __func__, errno);
104         return false;
105     }
106 
107     if (bind(sockFd, reinterpret_cast<struct sockaddr *>(&server),
108         offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path)) < 0) {
109         DFXLOGE("%{public}s :: Failed to bind socket, errno(%{public}d)", __func__, errno);
110         return false;
111     }
112 
113     return true;
114 }
115 
StartListen(int32_t & sockFd,const char * name,uint32_t listenCnt)116 bool StartListen(int32_t& sockFd, const char* name, uint32_t listenCnt)
117 {
118     if (name == nullptr) {
119         return false;
120     }
121     sockFd = GetControlSocket(name);
122     if (sockFd < 0) {
123         DFXLOGW("%{public}s :: Failed to get socket fd by cfg", __func__);
124         if (!GetServerSocket(sockFd, name)) {
125             DFXLOGE("%{public}s :: Failed to get socket fd by path", __func__);
126             return false;
127         }
128     }
129 
130     if (listen(sockFd, listenCnt) < 0) {
131         DFXLOGE("%{public}s :: Failed to listen socket, errno(%{public}d)", __func__, errno);
132         close(sockFd);
133         sockFd = -1;
134         return false;
135     }
136 
137     DFXLOGI("%{public}s :: success to listen socket %{public}s", __func__, name);
138     return true;
139 }
140 
RecvMsgFromSocket(int sockFd,void * data,const size_t dataLength)141 static bool RecvMsgFromSocket(int sockFd, void* data, const size_t dataLength)
142 {
143     if (sockFd < 0 || data == nullptr) {
144         return false;
145     }
146 
147     struct msghdr msgh{0};
148     char msgBuffer[SOCKET_BUFFER_SIZE] = { 0 };
149     struct iovec iov = {
150         .iov_base = msgBuffer,
151         .iov_len = sizeof(msgBuffer)
152     };
153     msgh.msg_iov = &iov;
154     msgh.msg_iovlen = 1;
155 
156     char ctlBuffer[SOCKET_BUFFER_SIZE] = { 0 };
157     msgh.msg_control = ctlBuffer;
158     msgh.msg_controllen = sizeof(ctlBuffer);
159 
160     if (OHOS_TEMP_FAILURE_RETRY(recvmsg(sockFd, &msgh, 0)) < 0) {
161         DFXLOGE("%{public}s :: Failed to recv message, errno(%{public}d)", __func__, errno);
162         return false;
163     }
164 
165     struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh);
166     if (cmsg == nullptr) {
167         DFXLOGE("%{public}s :: Invalid message", __func__);
168         return false;
169     }
170     if (dataLength != cmsg->cmsg_len - sizeof(struct cmsghdr)) {
171         DFXLOGE("%{public}s :: msg length is not matched", __func__);
172         return false;
173     }
174     if (memcpy_s(data, dataLength, CMSG_DATA(cmsg), dataLength) != 0) {
175         DFXLOGE("%{public}s :: memcpy error", __func__);
176         return false;
177     }
178     return  true;
179 }
180 
SendMsgCtlToSocket(int sockFd,const void * cmsg,uint32_t cmsgLen)181 static bool SendMsgCtlToSocket(int sockFd, const void *cmsg, uint32_t cmsgLen)
182 {
183     if ((sockFd < 0) || (cmsg == nullptr) || (cmsgLen == 0)) {
184         return false;
185     }
186 
187     struct msghdr msgh{0};
188     char iovBase[] = "";
189     struct iovec iov = {.iov_base = iovBase, .iov_len = 1};
190     msgh.msg_iov = &iov;
191     msgh.msg_iovlen = 1;
192 
193     int controlBufLen = CMSG_SPACE(cmsgLen);
194     char controlBuf[controlBufLen];
195     msgh.msg_control = controlBuf;
196     msgh.msg_controllen = sizeof(controlBuf);
197 
198     struct cmsghdr *cmsgh = CMSG_FIRSTHDR(&msgh);
199     if (cmsgh != nullptr) {
200         cmsgh->cmsg_level = SOL_SOCKET;
201         cmsgh->cmsg_type = SCM_RIGHTS;
202         cmsgh->cmsg_len = CMSG_LEN(cmsgLen);
203         if (memcpy_s(CMSG_DATA(cmsgh), cmsgLen, cmsg, cmsgLen) != 0) {
204             DFXLOGE("%{public}s :: memcpy error", __func__);
205         }
206     }
207 
208     if (OHOS_TEMP_FAILURE_RETRY(sendmsg(sockFd, &msgh, 0)) < 0) {
209         DFXLOGE("%{public}s :: Failed to send message, errno(%{public}d)", __func__, errno);
210         return false;
211     }
212     return true;
213 }
214 
SendFileDescriptorToSocket(int32_t sockFd,const int32_t * fds,uint32_t nFds)215 bool SendFileDescriptorToSocket(int32_t sockFd, const int32_t* fds, uint32_t nFds)
216 {
217     if (nFds == 0 || fds == nullptr) {
218         return false;
219     }
220     return SendMsgCtlToSocket(sockFd, fds, sizeof(int32_t) * nFds);
221 }
222 
ReadFileDescriptorFromSocket(int32_t sockFd,int32_t * fds,uint32_t nFds)223 bool ReadFileDescriptorFromSocket(int32_t sockFd, int32_t* fds, uint32_t nFds)
224 {
225     if (nFds == 0 || fds == nullptr) {
226         return false;
227     }
228     if (!RecvMsgFromSocket(sockFd, fds, sizeof(int32_t) * nFds)) {
229         DFXLOGE("%{public}s :: Failed to recv message", __func__);
230         return false;
231     }
232     return true;
233 }
234 
SendMsgToSocket(int32_t sockFd,const void * data,uint32_t dataLength)235 bool SendMsgToSocket(int32_t sockFd, const void* data, uint32_t dataLength)
236 {
237     if (data == nullptr || sockFd < 0 || dataLength == 0) {
238         DFXLOGE("Failed to write request message to socket, invalid data or socket fd %{public}d.", sockFd);
239         return false;
240     }
241     if (OHOS_TEMP_FAILURE_RETRY(write(sockFd, data, dataLength)) != dataLength) {
242         DFXLOGE("Failed to write request message to socket, errno(%{public}d).", errno);
243         return false;
244     }
245     return true;
246 }
247 
GetMsgFromSocket(int32_t sockFd,void * data,uint32_t dataLength)248 bool GetMsgFromSocket(int32_t sockFd, void* data, uint32_t dataLength)
249 {
250     if (data == nullptr || sockFd < 0 || dataLength == 0) {
251         DFXLOGE("Failed to read message from socket, invalid data or socket fd %{public}d.", sockFd);
252         return false;
253     }
254     ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(sockFd, data, dataLength));
255     if (nread <= 0) {
256         DFXLOGE("Failed to get message from socket, %{public}zd.", nread);
257         return false;
258     }
259     return true;
260 }