From: Hannu Nyman Date: Sun, 14 Jun 2026 07:03:41 +0000 (+0300) Subject: collectd: ping - fix use-after-free when re-resolving a host X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=eb219825764e7e51039a3adc6bbaf57b6ea8a625;p=openwrt-packages.git collectd: ping - fix use-after-free when re-resolving a host Add a patch fixing a possible crash, when a non-responding host is tried to be pinged and retry attempts are limited by MaxMissed option. > daemon.err: collectd[14133]: ping plugin: host 192.168.1.99 has not answered 3 PING requests, triggering resolve > daemon.info: procd: Instance collectd::instance1 s in a crash loop 7 crashes, 3 seconds since last crash Fixes: #29649 * upstream bug created: https://github.com/collectd/collectd/issues/4406 * older upstream bug: https://github.com/collectd/collectd/issues/3079 Signed-off-by: Hannu Nyman --- diff --git a/utils/collectd/Makefile b/utils/collectd/Makefile index 6f852b604..77138875d 100644 --- a/utils/collectd/Makefile +++ b/utils/collectd/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=collectd PKG_VERSION:=5.12.0 -PKG_RELEASE:=55 +PKG_RELEASE:=56 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://collectd.org/files/ \ diff --git a/utils/collectd/patches/090-fix-ping-plugin-use-after-free-when-re-resolving-a-h.patch b/utils/collectd/patches/090-fix-ping-plugin-use-after-free-when-re-resolving-a-h.patch new file mode 100644 index 000000000..3d90e4a54 --- /dev/null +++ b/utils/collectd/patches/090-fix-ping-plugin-use-after-free-when-re-resolving-a-h.patch @@ -0,0 +1,45 @@ +From 67e873a4eab151ce4808e84eaba6dbc924e86de4 Mon Sep 17 00:00:00 2001 +From: Nicolas Roche +Date: Fri, 5 Jun 2026 00:55:11 +Subject: [PATCH] ping plugin: fix use-after-free when re-resolving a host +Signed-off-by: Nicolas Roche + +ping_dispatch_all() iterates the pingobj host list and, when a host has +missed ping_max_missed packets, re-resolves it by calling +ping_host_remove() + ping_host_add(). ping_host_remove() frees the +pinghost that the iterator currently points at, but the for-loop's +increment then called ping_iterator_next(iter), dereferencing the freed +node (iter->next) -- a use-after-free. + +It only crashes intermittently: the freed block usually still holds a +valid ->next (or is reused and zeroed by the trailing ping_host_add), +so the loop limps on; it segfaults when ping_host_add's strdup/getaddrinfo +clobbers the freed block's ->next before it is re-read. Reproducible by +monitoring a permanently-unreachable host with MaxMissed enabled. + +Fix: read the next pointer at the top of the loop body, before the +re-resolve can free the current node. Loop body and semantics unchanged. + +Co-Authored-By: Claude Opus 4.8 (1M context) +--- + src/ping.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/src/ping.c ++++ b/src/ping.c +@@ -146,12 +146,13 @@ static int ping_dispatch_all(pingobj_t * + hostlist_t *hl; + int status; + +- for (pingobj_iter_t *iter = ping_iterator_get(pingobj); iter != NULL; +- iter = ping_iterator_next(iter)) { /* {{{ */ ++ for (pingobj_iter_t *iter = ping_iterator_get(pingobj), *next; iter != NULL; ++ iter = next) { /* {{{ */ + char userhost[NI_MAXHOST]; + double latency; + size_t param_size; + ++ next = ping_iterator_next(iter); /* fetch next now: iter may be freed at line 213 (ping_host_remove) */ + param_size = sizeof(userhost); + status = ping_iterator_get_info(iter, + #ifdef PING_INFO_USERNAME