mirror of
https://github.com/openwrt/packages.git
synced 2026-10-13 05:47:27 +04:00
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 <hannu.nyman@iki.fi>
(cherry picked from commit eb21982576)
This commit is contained in:
1 parent
ae5f45f46f
commit
3ff8177aaa
2 files changed
+46
-1
No files matched your search
@@ -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/ \
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
From 67e873a4eab151ce4808e84eaba6dbc924e86de4 Mon Sep 17 00:00:00 2001
|
||||
From: Nicolas Roche <nicolasroche898@gmail.com>
|
||||
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 <nicolasroche898@gmail.com>
|
||||
|
||||
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) <noreply@anthropic.com>
|
||||
---
|
||||
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
|
||||
Reference in new issue
Block a user