Version in base suite: 2.6.12-1+deb12u2 Base version: haproxy_2.6.12-1+deb12u2 Target version: haproxy_2.6.12-1+deb12u3 Base file: /srv/ftp-master.debian.org/ftp/pool/main/h/haproxy/haproxy_2.6.12-1+deb12u2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/h/haproxy/haproxy_2.6.12-1+deb12u3.dsc changelog | 6 patches/0001-BUG-CRITICAL-mjson-fix-possible-DoS-when-parsing-num.patch | 83 ++++++++++ patches/series | 1 3 files changed, 90 insertions(+) diff -Nru haproxy-2.6.12/debian/changelog haproxy-2.6.12/debian/changelog --- haproxy-2.6.12/debian/changelog 2025-04-29 13:56:20.000000000 +0000 +++ haproxy-2.6.12/debian/changelog 2025-10-03 06:03:00.000000000 +0000 @@ -1,3 +1,9 @@ +haproxy (2.6.12-1+deb12u3) bookworm-security; urgency=high + + * CVE-2025-11230: fix possible DoS when parsing JSON numbers. + + -- Vincent Bernat Fri, 03 Oct 2025 08:03:00 +0200 + haproxy (2.6.12-1+deb12u2) bookworm; urgency=medium * Non-maintainer upload. diff -Nru haproxy-2.6.12/debian/patches/0001-BUG-CRITICAL-mjson-fix-possible-DoS-when-parsing-num.patch haproxy-2.6.12/debian/patches/0001-BUG-CRITICAL-mjson-fix-possible-DoS-when-parsing-num.patch --- haproxy-2.6.12/debian/patches/0001-BUG-CRITICAL-mjson-fix-possible-DoS-when-parsing-num.patch 1970-01-01 00:00:00.000000000 +0000 +++ haproxy-2.6.12/debian/patches/0001-BUG-CRITICAL-mjson-fix-possible-DoS-when-parsing-num.patch 2025-10-03 06:03:00.000000000 +0000 @@ -0,0 +1,83 @@ +From 70087aedf891b9042bd597158e18ae08fab8fd54 Mon Sep 17 00:00:00 2001 +From: Willy Tarreau +Date: Mon, 29 Sep 2025 18:34:11 +0200 +Subject: BUG/CRITICAL: mjson: fix possible DoS when parsing numbers + +Mjson comes with its own strtod() implementation for portability +reasons and probably also because many generic strtod() versions as +provided by operating systems do not focus on resource preservation +and may call malloc(), which is not welcome in a parser. + +The strtod() implementation used here apparently originally comes from +https://gist.github.com/mattn/1890186 and seems to have purposely +omitted a few parts that were considered as not needed in this context +(e.g. skipping white spaces, or setting errno). But when subject to the +relevant test cases of the designated file above, the current function +provides the same results. + +The aforementioned implementation uses pow() to calculate exponents, +but mjson authors visibly preferred not to introduce a libm dependency +and replaced it with an iterative loop in O(exp) time. The problem is +that the exponent is not bounded and that this loop can take a huge +amount of time. There's even an issue already opened on mjson about +this: https://github.com/cesanta/mjson/issues/59. In the case of +haproxy, fortunately, the watchdog will quickly stop a runaway process +but this remains a possible denial of service. + +A first approach would consist in reintroducing pow() like in the +original implementation, but if haproxy is built without Lua nor +51Degrees, -lm is not used so this will not work everywhere. + +Anyway here we're dealing with integer exponents, so an easy alternate +approach consists in simply using shifts and squares, to compute the +exponent in O(log(exp)) time. Not only it doesn't introduce any new +dependency, but it turns out to be even faster than the generic pow() +(85k req/s per core vs 83.5k on the same machine). + +This must be backported as far as 2.4, where mjson was introduced. + +Many thanks to Oula Kivalo for reporting this issue. +--- + src/mjson.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/mjson.c b/src/mjson.c +index 73b7a5797f..2a4106bbd8 100644 +--- a/src/mjson.c ++++ b/src/mjson.c +@@ -767,11 +767,13 @@ static double mystrtod(const char *str, char **end) { + + /* exponential part */ + if ((*p == 'E') || (*p == 'e')) { ++ double exp, f; + int i, e = 0, neg = 0; + p++; + if (*p == '-') p++, neg++; + if (*p == '+') p++; + while (is_digit(*p)) e = e * 10 + *p++ - '0'; ++ i = e; + if (neg) e = -e; + #if 0 + if (d == 2.2250738585072011 && e == -308) { +@@ -785,8 +787,16 @@ static double mystrtod(const char *str, char **end) { + goto done; + } + #endif +- for (i = 0; i < e; i++) d *= 10; +- for (i = 0; i < -e; i++) d /= 10; ++ /* calculate f = 10^i */ ++ exp = 10; ++ f = 1; ++ while (i > 0) { ++ if (i & 1) f *= exp; ++ exp *= exp; ++ i >>= 1; ++ } ++ if (e > 0) d *= f; ++ else if (e < 0) d /= f; + a = p; + } else if (p > str && !is_digit(*(p - 1))) { + a = str; +-- +2.35.3 + diff -Nru haproxy-2.6.12/debian/patches/series haproxy-2.6.12/debian/patches/series --- haproxy-2.6.12/debian/patches/series 2025-04-29 13:56:20.000000000 +0000 +++ haproxy-2.6.12/debian/patches/series 2025-10-03 06:03:00.000000000 +0000 @@ -15,6 +15,7 @@ REGTESTS-http-rules-verify-that-we-block-by-default-.patch DOC-clarify-the-handling-of-URL-fragments-in-request.patch 0001-BUG-MEDIUM-sample-fix-risk-of-overflow-when-replacin.patch +0001-BUG-CRITICAL-mjson-fix-possible-DoS-when-parsing-num.patch # applied during the build process: # debianize-dconv.patch