1 /*
2 * Copyright (c) 2021-2024 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 "event_server.h"
17
18 #include <fstream>
19 #include <memory>
20 #include <string>
21 #include <vector>
22
23 #include <fcntl.h>
24 #include <sys/epoll.h>
25 #include <sys/socket.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/un.h>
29 #include <unistd.h>
30
31 #include <securec.h>
32
33 #include "base/raw_data_base_def.h"
34 #include "decoded/decoded_event.h"
35 #include "device_node.h"
36 #include "init_socket.h"
37 #include "hiview_logger.h"
38 #include "socket_util.h"
39
40 #define SOCKET_FILE_DIR "/dev/unix/socket/hisysevent"
41
42 namespace OHOS {
43 namespace HiviewDFX {
44 DEFINE_LOG_TAG("HiView-EventServer");
45 namespace {
46 constexpr int BUFFER_SIZE = 384 * 1024;
47 #ifndef KERNEL_DEVICE_BUFFER
48 constexpr int EVENT_READ_BUFFER = 2048;
49 #else
50 constexpr int EVENT_READ_BUFFER = KERNEL_DEVICE_BUFFER;
51 #endif
52
53 struct Header {
54 unsigned short len;
55 unsigned short headerSize;
56 char msg[0];
57 };
58
InitSocketBuf(int socketId,int optName)59 void InitSocketBuf(int socketId, int optName)
60 {
61 int bufferSizeOld = 0;
62 socklen_t sizeOfInt = static_cast<socklen_t>(sizeof(int));
63 if (getsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeOld), &sizeOfInt) < 0) {
64 HIVIEW_LOGE("get socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
65 }
66
67 int bufferSizeSet = BUFFER_SIZE;
68 if (setsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeSet), sizeof(int)) < 0) {
69 HIVIEW_LOGE("set socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
70 }
71
72 int bufferSizeNew = 0;
73 sizeOfInt = static_cast<socklen_t>(sizeof(int));
74 if (getsockopt(socketId, SOL_SOCKET, optName, static_cast<void *>(&bufferSizeNew), &sizeOfInt) < 0) {
75 HIVIEW_LOGE("get new socket buffer error=%{public}d, msg=%{public}s", errno, strerror(errno));
76 }
77 HIVIEW_LOGI("reset buffer size old=%{public}d, new=%{public}d", bufferSizeOld, bufferSizeNew);
78 }
79
InitRecvBuffer(int socketId)80 void InitRecvBuffer(int socketId)
81 {
82 InitSocketBuf(socketId, SO_RCVBUF);
83 }
84
ConverRawData(char * source)85 std::shared_ptr<EventRaw::RawData> ConverRawData(char* source)
86 {
87 if (source == nullptr) {
88 HIVIEW_LOGE("invalid source.");
89 return nullptr;
90 }
91 uint32_t sourceLen = *(reinterpret_cast<uint32_t*>(source));
92 uint32_t desLen = sourceLen + sizeof(uint8_t);
93 uint8_t* des = reinterpret_cast<uint8_t*>(malloc(desLen));
94 if (des == nullptr) {
95 HIVIEW_LOGE("malloc failed.");
96 return nullptr;
97 }
98 uint32_t sourceHeaderLen = sizeof(int32_t) + sizeof(EventRaw::HiSysEventHeader) - sizeof(uint8_t);
99 if (memcpy_s(des, desLen, source, sourceHeaderLen) != EOK) {
100 HIVIEW_LOGE("copy failed.");
101 free(des);
102 return nullptr;
103 }
104 *(reinterpret_cast<uint8_t*>(des + sourceHeaderLen)) = 0; // init header.log flag
105 uint32_t desPos = sourceHeaderLen + sizeof(uint8_t);
106 if (memcpy_s(des + desPos, desLen - desPos, source + sourceHeaderLen, sourceLen - sourceHeaderLen) != EOK) {
107 HIVIEW_LOGE("copy failed.");
108 free(des);
109 return nullptr;
110 }
111 *(reinterpret_cast<int32_t*>(des)) = desLen;
112 auto rawData = std::make_shared<EventRaw::RawData>(des, desLen);
113 free(des);
114 return rawData;
115 }
116
InitMsgh(char * buffer,int bufferLen,std::array<char,CMSG_SPACE (sizeof (struct ucred))> & control,struct msghdr & msgh,struct iovec & iov)117 void InitMsgh(char* buffer, int bufferLen, std::array<char, CMSG_SPACE(sizeof(struct ucred))>& control,
118 struct msghdr& msgh, struct iovec& iov)
119 {
120 iov.iov_base = buffer;
121 iov.iov_len = static_cast<uint32_t>(bufferLen);
122 msgh.msg_iov = &iov;
123 msgh.msg_iovlen = 1; // 1 is length of io vector
124
125 msgh.msg_control = control.data();
126 msgh.msg_controllen = control.size();
127
128 msgh.msg_name = nullptr;
129 msgh.msg_namelen = 0;
130 msgh.msg_flags = 0;
131 }
132
ReadPidFromMsgh(struct msghdr & msgh)133 pid_t ReadPidFromMsgh(struct msghdr& msgh)
134 {
135 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msgh);
136 if (cmsg == nullptr) {
137 return UN_INIT_INT_TYPE_VAL;
138 }
139 struct ucred* uCredRecv = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg));
140 if (uCredRecv == nullptr) {
141 return UN_INIT_INT_TYPE_VAL;
142 }
143 return uCredRecv->pid;
144 }
145 }
146
InitSocket(int & socketId)147 void SocketDevice::InitSocket(int &socketId)
148 {
149 struct sockaddr_un serverAddr;
150 serverAddr.sun_family = AF_UNIX;
151 if (strcpy_s(serverAddr.sun_path, sizeof(serverAddr.sun_path), SOCKET_FILE_DIR) != EOK) {
152 socketId = -1;
153 HIVIEW_LOGE("copy hisysevent dev path failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
154 return;
155 }
156 serverAddr.sun_path[sizeof(serverAddr.sun_path) - 1] = '\0';
157 socketId = TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0));
158 if (socketId < 0) {
159 HIVIEW_LOGE("create hisysevent socket failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
160 return;
161 }
162 InitRecvBuffer(socketId_);
163 unlink(serverAddr.sun_path);
164 if (TEMP_FAILURE_RETRY(bind(socketId, reinterpret_cast<sockaddr*>(&serverAddr), sizeof(serverAddr))) < 0) {
165 close(socketId);
166 socketId = -1;
167 HIVIEW_LOGE("bind hisysevent socket failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
168 return;
169 }
170 }
171
Open()172 int SocketDevice::Open()
173 {
174 socketId_ = GetControlSocket("hisysevent");
175 if (socketId_ < 0) {
176 HIVIEW_LOGI("create hisysevent socket");
177 InitSocket(socketId_);
178 } else {
179 InitRecvBuffer(socketId_);
180 HIVIEW_LOGI("use hisysevent exist socket");
181 }
182
183 if (socketId_ < 0) {
184 HIVIEW_LOGE("hisysevent create socket failed");
185 return -1;
186 }
187 return socketId_;
188 }
189
Close()190 int SocketDevice::Close()
191 {
192 if (socketId_ > 0) {
193 close(socketId_);
194 socketId_ = -1;
195 }
196 return 0;
197 }
198
GetEvents()199 uint32_t SocketDevice::GetEvents()
200 {
201 return EPOLLIN | EPOLLET;
202 }
203
GetName()204 std::string SocketDevice::GetName()
205 {
206 return "SysEventSocket";
207 }
208
IsValidMsg(char * msg,int32_t len)209 bool SocketDevice::IsValidMsg(char* msg, int32_t len)
210 {
211 if (len < static_cast<int32_t>(EventRaw::GetValidDataMinimumByteCount())) {
212 HIVIEW_LOGD("the data length=%{public}d is invalid", len);
213 return false;
214 }
215 int32_t dataByteCnt = *(reinterpret_cast<int32_t*>(msg));
216 if (dataByteCnt != len) {
217 HIVIEW_LOGW("the data byte count=%{public}d are not equal to read length %{public}d", dataByteCnt, len);
218 return false;
219 }
220 int32_t pid = *(reinterpret_cast<int32_t*>(msg + sizeof(int32_t) + EventRaw::POS_OF_PID_IN_HEADER));
221 if (uCredPid_ > 0 && pid != uCredPid_) {
222 HIVIEW_LOGW("failed to verify the consistensy of process id: [%{public}" PRId32
223 ", %{public}" PRId32 "]", pid, uCredPid_);
224 return false;
225 }
226 msg[len] = '\0';
227 return true;
228 }
229
SetUCredPid(const pid_t pid)230 void SocketDevice::SetUCredPid(const pid_t pid)
231 {
232 uCredPid_ = pid;
233 }
234
ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> & receivers)235 int SocketDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
236 {
237 char* buffer = new char[BUFFER_SIZE + 1]();
238 std::array<char, CMSG_SPACE(sizeof(struct ucred))> control = {0};
239 struct msghdr msgh = {0};
240 struct iovec iov = {
241 .iov_base = nullptr,
242 .iov_len = 0
243 };
244 InitMsgh(buffer, BUFFER_SIZE, control, msgh, iov);
245 while (true) {
246 int ret = recvmsg(socketId_, &msgh, 0);
247 if (ret <= 0) {
248 HIVIEW_LOGD("failed to recv msg from socket");
249 break;
250 }
251 pid_t uCredPid = ReadPidFromMsgh(msgh);
252 SetUCredPid(uCredPid);
253 if (!IsValidMsg(buffer, ret)) {
254 break;
255 }
256 for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
257 (*receiver)->HandlerEvent(ConverRawData(buffer));
258 }
259 }
260 delete[] buffer;
261 return 0;
262 }
263
Close()264 int BBoxDevice::Close()
265 {
266 if (fd_ > 0) {
267 close(fd_);
268 fd_ = -1;
269 }
270 return 0;
271 }
272
Open()273 int BBoxDevice::Open()
274 {
275 fd_ = open("/dev/sysevent", O_RDONLY | O_NONBLOCK, 0);
276 if (fd_ < 0) {
277 fd_ = open("/dev/bbox", O_RDONLY | O_NONBLOCK, 0);
278 } else {
279 hasBbox_ = true;
280 }
281
282 if (fd_ < 0) {
283 HIVIEW_LOGE("open bbox failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
284 return -1;
285 }
286 return fd_;
287 }
288
GetEvents()289 uint32_t BBoxDevice::GetEvents()
290 {
291 return EPOLLIN;
292 }
293
GetName()294 std::string BBoxDevice::GetName()
295 {
296 return "BBox";
297 }
298
IsValidMsg(char * msg,int32_t len)299 bool BBoxDevice::IsValidMsg(char* msg, int32_t len)
300 {
301 if (len < static_cast<int32_t>(EventRaw::GetValidDataMinimumByteCount())) {
302 HIVIEW_LOGW("the data length=%{public}d is invalid", len);
303 return false;
304 }
305 int32_t dataByteCnt = *(reinterpret_cast<int32_t*>(msg));
306 if ((hasBbox_ && dataByteCnt != len) ||
307 (!hasBbox_ && dataByteCnt != (len - sizeof(struct Header) - 1))) { // extra bytes in kernel write
308 HIVIEW_LOGW("the data lengths=%{public}d are not equal", len);
309 return false;
310 }
311 msg[EVENT_READ_BUFFER - 1] = '\0';
312 return true;
313 }
314
ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> & receivers)315 int BBoxDevice::ReceiveMsg(std::vector<std::shared_ptr<EventReceiver>> &receivers)
316 {
317 char buffer[EVENT_READ_BUFFER];
318 (void)memset_s(buffer, sizeof(buffer), 0, sizeof(buffer));
319 int ret = read(fd_, buffer, EVENT_READ_BUFFER);
320 if (!IsValidMsg(buffer, ret)) {
321 return -1;
322 }
323 for (auto receiver = receivers.begin(); receiver != receivers.end(); receiver++) {
324 (*receiver)->HandlerEvent(ConverRawData(buffer));
325 }
326 return 0;
327 }
328
AddDev(std::shared_ptr<DeviceNode> dev)329 void EventServer::AddDev(std::shared_ptr<DeviceNode> dev)
330 {
331 int fd = dev->Open();
332 if (fd < 0) {
333 HIVIEW_LOGI("open device %{public}s failed", dev->GetName().c_str());
334 return;
335 }
336 devs_[fd] = dev;
337 }
338
OpenDevs()339 int EventServer::OpenDevs()
340 {
341 AddDev(std::make_shared<SocketDevice>());
342 AddDev(std::make_shared<BBoxDevice>());
343 if (devs_.empty()) {
344 HIVIEW_LOGE("can not open any device");
345 return -1;
346 }
347 HIVIEW_LOGI("has open %{public}zu devices", devs_.size());
348 return 0;
349 }
350
AddToMonitor(int pollFd,struct epoll_event pollEvents[])351 int EventServer::AddToMonitor(int pollFd, struct epoll_event pollEvents[])
352 {
353 int index = 0;
354 auto it = devs_.begin();
355 while (it != devs_.end()) {
356 HIVIEW_LOGI("add to poll device %{public}s, fd=%{public}d", it->second->GetName().c_str(), it->first);
357 pollEvents[index].data.fd = it->first;
358 pollEvents[index].events = it->second->GetEvents();
359 int ret = epoll_ctl(pollFd, EPOLL_CTL_ADD, it->first, &pollEvents[index]);
360 if (ret < 0) {
361 HIVIEW_LOGE("add to poll fail device %{public}s error=%{public}d, msg=%{public}s",
362 it->second->GetName().c_str(), errno, strerror(errno));
363 it->second->Close();
364 it = devs_.erase(it);
365 } else {
366 it++;
367 }
368 index++;
369 }
370
371 if (devs_.empty()) {
372 HIVIEW_LOGE("can not monitor any device");
373 return -1;
374 }
375 HIVIEW_LOGI("monitor devices %{public}zu", devs_.size());
376 return 0;
377 }
378
Start()379 void EventServer::Start()
380 {
381 HIVIEW_LOGD("start event server");
382 if (OpenDevs() < 0) {
383 return;
384 }
385
386 int pollFd = epoll_create1(EPOLL_CLOEXEC);
387 if (pollFd < 0) {
388 HIVIEW_LOGE("create poll failed, error=%{public}d, msg=%{public}s", errno, strerror(errno));
389 return;
390 }
391
392 struct epoll_event pollEvents[devs_.size()];
393 if (AddToMonitor(pollFd, pollEvents) < 0) {
394 return;
395 }
396
397 HIVIEW_LOGI("go into event loop");
398 isStart_ = true;
399 while (isStart_) {
400 struct epoll_event chkPollEvents[devs_.size()];
401 int eventCount = epoll_wait(pollFd, chkPollEvents, devs_.size(), -1); // -1: Wait indefinitely
402 if (eventCount <= 0) {
403 HIVIEW_LOGD("read event timeout");
404 continue;
405 }
406 for (int ii = 0; ii < eventCount; ii++) {
407 auto it = devs_.find(chkPollEvents[ii].data.fd);
408 it->second->ReceiveMsg(receivers_);
409 }
410 }
411 CloseDevs();
412 }
413
CloseDevs()414 void EventServer::CloseDevs()
415 {
416 for (auto devItem : devs_) {
417 devItem.second->Close();
418 }
419 }
420
Stop()421 void EventServer::Stop()
422 {
423 isStart_ = false;
424 }
425
AddReceiver(std::shared_ptr<EventReceiver> receiver)426 void EventServer::AddReceiver(std::shared_ptr<EventReceiver> receiver)
427 {
428 receivers_.emplace_back(receiver);
429 }
430 } // namespace HiviewDFX
431 } // namespace OHOS
432