• 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 "dfx_socket_request.h"
33 #include "init_socket.h"
34 
35 namespace {
36 constexpr int SOCKET_BUFFER_SIZE = 32;
37 }
38 
39 #define LOGE(isSigalSafe, fmt, ...) \
40     if (!isSigalSafe) \
41         DFXLOGE(fmt, ##__VA_ARGS__)
42 
43 namespace OHOS {
44 namespace HiviewDFX {
45 
GetServerSocket(const char * name)46 static SmartFd GetServerSocket(const char* name)
47 {
48     SmartFd sockFd{static_cast<int>(OHOS_TEMP_FAILURE_RETRY(socket(AF_LOCAL, SOCK_STREAM, 0)))};
49     if (!sockFd) {
50         DFXLOGE("%{public}s :: Failed to create socket, errno(%{public}d)", __func__, errno);
51         return {};
52     }
53 
54     std::string path = std::string(FAULTLOGGERD_SOCK_BASE_PATH) + std::string(name);
55     struct sockaddr_un server{0};
56     server.sun_family = AF_LOCAL;
57     if (strncpy_s(server.sun_path, sizeof(server.sun_path), path.c_str(), sizeof(server.sun_path) - 1) != 0) {
58         DFXLOGE("%{public}s :: strncpy failed.", __func__);
59         return {};
60     }
61 
62     chmod(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IWOTH);
63     unlink(path.c_str());
64 
65     int optval = 1;
66     int ret = OHOS_TEMP_FAILURE_RETRY(setsockopt(sockFd.GetFd(), SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)));
67     if (ret < 0) {
68         DFXLOGE("%{public}s :: Failed to set socket option, errno(%{public}d)", __func__, errno);
69         return {};
70     }
71 
72     if (bind(sockFd.GetFd(), reinterpret_cast<struct sockaddr *>(&server),
73         offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path)) < 0) {
74         DFXLOGE("%{public}s :: Failed to bind socket, errno(%{public}d)", __func__, errno);
75         return {};
76     }
77 
78     return sockFd;
79 }
80 
StartListen(const char * name,uint32_t listenCnt)81 SmartFd StartListen(const char* name, uint32_t listenCnt)
82 {
83     if (name == nullptr) {
84         return {};
85     }
86     SmartFd sockFd{GetControlSocket(name)};
87     if (!sockFd) {
88         DFXLOGW("%{public}s :: Failed to get socket fd by cfg", __func__);
89         sockFd = GetServerSocket(name);
90         if (!sockFd) {
91             DFXLOGE("%{public}s :: Failed to get socket fd by path", __func__);
92             return {};
93         }
94     }
95 
96     if (listen(sockFd.GetFd(), listenCnt) < 0) {
97         DFXLOGE("%{public}s :: Failed to listen socket, errno(%{public}d)", __func__, errno);
98         return {};
99     }
100 
101     DFXLOGI("%{public}s :: success to listen socket %{public}s", __func__, name);
102     return sockFd;
103 }
104 
SendFileDescriptorToSocket(int32_t sockFd,const int32_t * fds,uint32_t nFds)105 bool SendFileDescriptorToSocket(int32_t sockFd, const int32_t* fds, uint32_t nFds)
106 {
107     FaultLoggerdSocket faultLoggerd(sockFd);
108     return faultLoggerd.SendFileDescriptorToSocket(fds, nFds);
109 }
110 
SendMsgToSocket(int32_t sockFd,const void * data,uint32_t dataLength)111 bool SendMsgToSocket(int32_t sockFd, const void* data, uint32_t dataLength)
112 {
113     FaultLoggerdSocket faultLoggerd(sockFd);
114     return faultLoggerd.SendMsgToSocket(data, dataLength);
115 }
116 
GetMsgFromSocket(int32_t sockFd,void * data,uint32_t dataLength)117 bool GetMsgFromSocket(int32_t sockFd, void* data, uint32_t dataLength)
118 {
119     FaultLoggerdSocket faultLoggerd(sockFd);
120     return faultLoggerd.GetMsgFromSocket(data, dataLength);
121 }
122 
CreateSocketFileDescriptor(uint32_t timeout)123 bool FaultLoggerdSocket::CreateSocketFileDescriptor(uint32_t timeout)
124 {
125     if (socketFd_ >= 0) {
126         LOGE(signalSafely_, "%{public}s :: Create the socket repeatedly", __func__);
127         return false;
128     }
129     socketFd_ = socket(AF_LOCAL, SOCK_STREAM, 0);
130     if (socketFd_ < 0) {
131         LOGE(signalSafely_, "%{public}s :: Failed to create socket, errno(%{public}d)", __func__, errno);
132         return false;
133     }
134     if (timeout > 0) {
135         SetSocketTimeOut(timeout, SO_RCVTIMEO);
136         SetSocketTimeOut(timeout, SO_SNDTIMEO);
137     }
138     return true;
139 }
140 
CloseSocketFileDescriptor()141 void FaultLoggerdSocket::CloseSocketFileDescriptor()
142 {
143     if (socketFd_ >= 0) {
144         close(socketFd_);
145         socketFd_ = -1;
146     }
147 }
148 
SetSocketTimeOut(uint32_t timeout,int optName)149 bool FaultLoggerdSocket::SetSocketTimeOut(uint32_t timeout, int optName)
150 {
151     struct timeval timev = { timeout, 0 };
152     if (OHOS_TEMP_FAILURE_RETRY(setsockopt(socketFd_, SOL_SOCKET, optName, &timev, sizeof(timev))) != 0) {
153         LOGE(signalSafely_, "setsockopt(%{public}d) SO_RCVTIMEO error, errno(%{public}d).", socketFd_, errno);
154         return false;
155     }
156     return true;
157 }
158 
ConcatenateSocketName(char * dst,uint32_t dstSize,const char * src,uint32_t srcSize) const159 bool FaultLoggerdSocket::ConcatenateSocketName(char* dst, uint32_t dstSize, const char* src, uint32_t srcSize) const
160 {
161     if (dstSize <= srcSize) {
162         return false;
163     }
164     auto err = strncpy_s(dst, dstSize, src, srcSize);
165     if (err != EOK) {
166         LOGE(signalSafely_, "%{public}s :: strncpy failed, err = %{public}d.", __func__, static_cast<int>(err));
167         return false;
168     }
169     return true;
170 }
171 
StartConnect(const char * socketName)172 bool FaultLoggerdSocket::StartConnect(const char* socketName)
173 {
174     if (UNLIKELY(socketFd_ < 0 || socketName == nullptr)) {
175         return false;
176     }
177     struct sockaddr_un server{0};
178     server.sun_family = AF_LOCAL;
179     auto baseLen = strlen(FAULTLOGGERD_SOCK_BASE_PATH);
180     auto dstSize = sizeof(server.sun_path);
181     if (!ConcatenateSocketName(server.sun_path, dstSize, FAULTLOGGERD_SOCK_BASE_PATH, baseLen)) {
182         return false;
183     }
184     if (!ConcatenateSocketName(server.sun_path + baseLen, dstSize - baseLen, socketName, strlen(socketName))) {
185         return false;
186     }
187     int len = static_cast<int>(offsetof(struct sockaddr_un, sun_path) + strlen(server.sun_path) + 1);
188     int connected = OHOS_TEMP_FAILURE_RETRY(connect(socketFd_, reinterpret_cast<struct sockaddr*>(&server), len));
189     if (connected < 0) {
190         LOGE(signalSafely_, "%{public}s :: connect failed, errno = %{public}d.", __func__, errno);
191         return false;
192     }
193     return true;
194 }
195 
SendFileDescriptorToSocket(const int32_t * fds,uint32_t nFds) const196 bool FaultLoggerdSocket::SendFileDescriptorToSocket(const int32_t* fds, uint32_t nFds) const
197 {
198     if ((socketFd_ < 0) || (fds == nullptr) || (nFds == 0)) {
199         return false;
200     }
201     auto cmsgLen = sizeof(uint32_t) * nFds;
202     struct msghdr msgh{0};
203     char iovBase[] = "";
204     struct iovec iov = {.iov_base = iovBase, .iov_len = 1};
205     msgh.msg_iov = &iov;
206     msgh.msg_iovlen = 1;
207 
208     int controlBufLen = CMSG_SPACE(cmsgLen);
209     char controlBuf[controlBufLen];
210     msgh.msg_control = controlBuf;
211     msgh.msg_controllen = sizeof(controlBuf);
212 
213     struct cmsghdr *cmsgh = CMSG_FIRSTHDR(&msgh);
214     if (cmsgh != nullptr) {
215         cmsgh->cmsg_level = SOL_SOCKET;
216         cmsgh->cmsg_type = SCM_RIGHTS;
217         cmsgh->cmsg_len = CMSG_LEN(cmsgLen);
218         if (memcpy_s(CMSG_DATA(cmsgh), cmsgLen, fds, cmsgLen) != 0) {
219             LOGE(signalSafely_, "%{public}s :: memcpy error", __func__);
220         }
221     }
222     if (OHOS_TEMP_FAILURE_RETRY(sendmsg(socketFd_, &msgh, 0)) < 0) {
223         LOGE(signalSafely_, "%{public}s :: Failed to send message, errno(%{public}d)", __func__, errno);
224         return false;
225     }
226     return true;
227 }
228 
ReadFileDescriptorFromSocket(int32_t * fds,uint32_t nFds) const229 bool FaultLoggerdSocket::ReadFileDescriptorFromSocket(int32_t *fds, uint32_t nFds) const
230 {
231     if (socketFd_ < 0 || fds == nullptr || nFds == 0) {
232         return false;
233     }
234     auto dataLength = sizeof(int32_t) * nFds;
235     struct msghdr msgh{0};
236     char msgBuffer[SOCKET_BUFFER_SIZE] = { 0 };
237     struct iovec iov = {
238         .iov_base = msgBuffer,
239         .iov_len = sizeof(msgBuffer)
240     };
241     msgh.msg_iov = &iov;
242     msgh.msg_iovlen = 1;
243 
244     char ctlBuffer[SOCKET_BUFFER_SIZE] = { 0 };
245     msgh.msg_control = ctlBuffer;
246     msgh.msg_controllen = sizeof(ctlBuffer);
247 
248     if (OHOS_TEMP_FAILURE_RETRY(recvmsg(socketFd_, &msgh, 0)) < 0) {
249         LOGE(signalSafely_, "%{public}s :: Failed to recv message, errno(%{public}d)", __func__, errno);
250         return false;
251     }
252     struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh);
253     if (cmsg == nullptr) {
254         LOGE(signalSafely_, "%{public}s :: Invalid message", __func__);
255         return false;
256     }
257     if (dataLength != cmsg->cmsg_len - sizeof(struct cmsghdr)) {
258         LOGE(signalSafely_, "%{public}s :: msg length is not matched", __func__);
259         return false;
260     }
261     if (memcpy_s(fds, dataLength, CMSG_DATA(cmsg), dataLength) != 0) {
262         LOGE(signalSafely_, "%{public}s :: memcpy error", __func__);
263         return false;
264     }
265     return  true;
266 }
267 
SendMsgToSocket(const void * data,uint32_t dataLength) const268 bool FaultLoggerdSocket::SendMsgToSocket(const void *data, uint32_t dataLength) const
269 {
270     if (socketFd_ < 0 || data == nullptr || dataLength == 0) {
271         return false;
272     }
273     if (OHOS_TEMP_FAILURE_RETRY(write(socketFd_, data, dataLength)) != static_cast<ssize_t>(dataLength)) {
274         LOGE(signalSafely_, "Failed to write request message to socket, errno(%{public}d).", errno);
275         return false;
276     }
277     return true;
278 }
279 
GetMsgFromSocket(void * data,uint32_t dataLength) const280 bool FaultLoggerdSocket::GetMsgFromSocket(void* data, uint32_t dataLength) const
281 {
282     if (socketFd_ < 0 || data == nullptr || dataLength == 0) {
283         return false;
284     }
285     ssize_t nread = OHOS_TEMP_FAILURE_RETRY(read(socketFd_, data, dataLength));
286     if (nread <= 0) {
287         LOGE(signalSafely_, "Failed to get message from socket, %{public}zd, errno(%{public}d). ", nread, errno);
288         return false;
289     }
290     return true;
291 }
292 
RequestServer(const SocketRequestData & socketRequestData) const293 int32_t FaultLoggerdSocket::RequestServer(const SocketRequestData& socketRequestData) const
294 {
295     if (!SendMsgToSocket(socketRequestData.requestData, socketRequestData.requestSize)) {
296         return ResponseCode::SEND_DATA_FAILED;
297     }
298     int32_t retCode{ResponseCode::RECEIVE_DATA_FAILED};
299     GetMsgFromSocket(&retCode, sizeof (retCode));
300     return retCode;
301 }
302 
RequestFdsFromServer(const SocketRequestData & socketRequestData,SocketFdData & socketFdData) const303 int32_t FaultLoggerdSocket::RequestFdsFromServer(const SocketRequestData &socketRequestData,
304     SocketFdData &socketFdData) const
305 {
306     int32_t retCode = RequestServer(socketRequestData);
307     if (retCode != ResponseCode::REQUEST_SUCCESS) {
308         return retCode;
309     }
310     return ReadFileDescriptorFromSocket(socketFdData.fds, socketFdData.nFds) ? ResponseCode::REQUEST_SUCCESS :
311         ResponseCode::RECEIVE_DATA_FAILED;
312 }
313 
314 }
315 }