From 645a14f7b4afcdbd3043e66d3032ffad5b0856e2 Mon Sep 17 00:00:00 2001 From: Cyril Hrubis Date: Fri, 16 May 2025 17:57:10 +0200 Subject: [PATCH] ping: Fix moving average rtt calculation The rts->rtt counts an exponential weight moving average in a fixed point, that means that even if we limit the triptime to fit into a 32bit number the average will overflow because because fixed point needs eight more bits. We also have to limit the triptime to 32bit number because otherwise the moving average may stil overflow if we manage to produce a large enough triptime. Fixes: CVE-2025-48964 Fixes: https://bugzilla.suse.com/show_bug.cgi?id=1243772 Closes: https://github.com/iputils/iputils-ghsa-25fr-jw29-74f9/pull/1 Reported-by: Mohamed Maatallah Reviewed-by: Petr Vorel Tested-by: Petr Vorel Reviewed-by: Michal Kubecek Reviewed-by: Mohamed Maatallah Signed-off-by: Cyril Hrubis (cherry picked from commit afa36390394a6e0cceba03b52b59b6d41710608c) --- iputils_common.h | 2 +- ping/ping.h | 2 +- ping/ping_common.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/iputils_common.h b/iputils_common.h index 829a749..1296905 100644 --- a/iputils_common.h +++ b/iputils_common.h @@ -11,7 +11,7 @@ __typeof__(&arr[0]))])) * 0) /* 1000001 = 1000000 tv_sec + 1 tv_usec */ -#define TV_SEC_MAX_VAL (LONG_MAX/1000001) +#define TV_SEC_MAX_VAL (INT32_MAX/1000001) #ifdef __GNUC__ # define iputils_attribute_format(t, n, m) __attribute__((__format__ (t, n, m))) diff --git a/ping/ping.h b/ping/ping.h index 48e35b7..cd5b786 100644 --- a/ping/ping.h +++ b/ping/ping.h @@ -194,7 +194,7 @@ struct ping_rts { long tmax; /* maximum round trip time */ double tsum; /* sum of all times, for doing average */ double tsum2; - int rtt; + uint64_t rtt; /* Exponential weight moving average calculated in fixed point */ int rtt_addend; uint16_t acked; int pipesize; diff --git a/ping/ping_common.c b/ping/ping_common.c index 13e29f5..1c1b54b 100644 --- a/ping/ping_common.c +++ b/ping/ping_common.c @@ -281,7 +281,7 @@ int __schedule_exit(int next) static inline void update_interval(struct ping_rts *rts) { - int est = rts->rtt ? rts->rtt / 8 : rts->interval * 1000; + int est = rts->rtt ? (int)(rts->rtt / 8) : rts->interval * 1000; rts->interval = (est + rts->rtt_addend + 500) / 1000; if (rts->uid && rts->interval < MIN_USER_INTERVAL_MS) @@ -788,7 +788,7 @@ restamp: if (triptime > rts->tmax) rts->tmax = triptime; if (!rts->rtt) - rts->rtt = triptime * 8; + rts->rtt = ((uint64_t)triptime) * 8; else rts->rtt += triptime - rts->rtt / 8; if (rts->opt_adaptive) @@ -960,7 +960,7 @@ int finish(struct ping_rts *rts) int ipg = (1000000 * (long long)tv.tv_sec + tv.tv_nsec / 1000) / (rts->ntransmitted - 1); printf(_("%sipg/ewma %d.%03d/%d.%03d ms"), - comma, ipg / 1000, ipg % 1000, rts->rtt / 8000, (rts->rtt / 8) % 1000); + comma, ipg / 1000, ipg % 1000, (int)(rts->rtt / 8000), (int)((rts->rtt / 8) % 1000)); } putchar('\n'); return (!rts->nreceived || (rts->deadline && rts->nreceived < rts->npackets)); @@ -985,7 +985,7 @@ void status(struct ping_rts *rts) fprintf(stderr, _(", min/avg/ewma/max = %ld.%03ld/%lu.%03ld/%d.%03d/%ld.%03ld ms"), (long)rts->tmin / 1000, (long)rts->tmin % 1000, tavg / 1000, tavg % 1000, - rts->rtt / 8000, (rts->rtt / 8) % 1000, (long)rts->tmax / 1000, (long)rts->tmax % 1000); + (int)(rts->rtt / 8000), (int)((rts->rtt / 8) % 1000), (long)rts->tmax / 1000, (long)rts->tmax % 1000); } fprintf(stderr, "\n"); } -- 2.51.0