From 0cfcfac12d991f96150c66a797fa03d448771e1b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 5 Aug 2024 15:51:46 -0700 Subject: [PATCH] libhealthloop: Handle netlink receive buffer overflows The Linux kernel netlink implementation sets EPOLLERR if delivery of a netlink message fails because of a buffer overrun (see also the Linux kernel netlink_overrun() and sock_def_error_report() functions). Handle buffer overruns by calling ScheduleBatteryUpdate() unconditionally. Bug: 203462310 Change-Id: I54f7d239e6b4caad0db4d1b15de7c0385f796ebd Signed-off-by: Bart Van Assche --- health/utils/libhealthloop/HealthLoop.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/health/utils/libhealthloop/HealthLoop.cpp b/health/utils/libhealthloop/HealthLoop.cpp index ba7e75aa3d..f8c3490cbe 100644 --- a/health/utils/libhealthloop/HealthLoop.cpp +++ b/health/utils/libhealthloop/HealthLoop.cpp @@ -57,14 +57,13 @@ int HealthLoop::RegisterEvent(int fd, BoundFunction func, EventWakeup wakeup) { EventHandler{this, fd, std::move(func)})) .get(); - struct epoll_event ev; - - ev.events = EPOLLIN; + struct epoll_event ev = { + .events = EPOLLIN | EPOLLERR, + .data.ptr = reinterpret_cast(event_handler), + }; if (wakeup == EVENT_WAKEUP_FD) ev.events |= EPOLLWAKEUP; - ev.data.ptr = reinterpret_cast(event_handler); - if (epoll_ctl(epollfd_, EPOLL_CTL_ADD, fd, &ev) == -1) { KLOG_ERROR(LOG_TAG, "epoll_ctl failed; errno=%d\n", errno); return -1; @@ -119,9 +118,15 @@ void HealthLoop::PeriodicChores() { // TODO(b/140330870): Use BPF instead. #define UEVENT_MSG_LEN 2048 -void HealthLoop::UeventEvent(uint32_t /*epevents*/) { +void HealthLoop::UeventEvent(uint32_t epevents) { // No need to lock because uevent_fd_ is guaranteed to be initialized. + if (epevents & EPOLLERR) { + // The netlink receive buffer overflowed. + ScheduleBatteryUpdate(); + return; + } + char msg[UEVENT_MSG_LEN + 2]; char* cp; int n;