• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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