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