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 }