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 42namespace OHOS { 43namespace HiviewDFX { 44DEFINE_LOG_TAG("HiView-EventServer"); 45namespace { 46constexpr int BUFFER_SIZE = 384 * 1024; 47#ifndef KERNEL_DEVICE_BUFFER 48constexpr int EVENT_READ_BUFFER = 2048; 49#else 50constexpr int EVENT_READ_BUFFER = KERNEL_DEVICE_BUFFER; 51#endif 52 53struct Header { 54 unsigned short len; 55 unsigned short headerSize; 56 char msg[0]; 57}; 58 59void 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 80void InitRecvBuffer(int socketId) 81{ 82 InitSocketBuf(socketId, SO_RCVBUF); 83} 84 85std::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 117void 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 133pid_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 147void 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 172int 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 190int SocketDevice::Close() 191{ 192 if (socketId_ > 0) { 193 close(socketId_); 194 socketId_ = -1; 195 } 196 return 0; 197} 198 199uint32_t SocketDevice::GetEvents() 200{ 201 return EPOLLIN | EPOLLET; 202} 203 204std::string SocketDevice::GetName() 205{ 206 return "SysEventSocket"; 207} 208 209bool 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 230void SocketDevice::SetUCredPid(const pid_t pid) 231{ 232 uCredPid_ = pid; 233} 234 235int 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 264int BBoxDevice::Close() 265{ 266 if (fd_ > 0) { 267 close(fd_); 268 fd_ = -1; 269 } 270 return 0; 271} 272 273int 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 289uint32_t BBoxDevice::GetEvents() 290{ 291 return EPOLLIN; 292} 293 294std::string BBoxDevice::GetName() 295{ 296 return "BBox"; 297} 298 299bool 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 315int 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 329void 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 339int 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 351int 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 379void 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 414void EventServer::CloseDevs() 415{ 416 for (auto devItem : devs_) { 417 devItem.second->Close(); 418 } 419} 420 421void EventServer::Stop() 422{ 423 isStart_ = false; 424} 425 426void EventServer::AddReceiver(std::shared_ptr<EventReceiver> receiver) 427{ 428 receivers_.emplace_back(receiver); 429} 430} // namespace HiviewDFX 431} // namespace OHOS 432