From 66b59faded0e123780d49043b95102c582458a84 Mon Sep 17 00:00:00 2001 From: Oyvind Albrigtsen Date: Thu, 6 Nov 2025 14:10:02 +0100 Subject: [PATCH] - Fix denial of service vulnerability in mjson library (CVE-2025-11230) Resolves: RHEL-126665 --- ...rvice-vulnerability-in-mjson-library.patch | 86 +++++++++++++++++++ haproxy.spec | 8 +- 2 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 RHEL-126665-CVE-2025-11230-fix-denial-of-service-vulnerability-in-mjson-library.patch diff --git a/RHEL-126665-CVE-2025-11230-fix-denial-of-service-vulnerability-in-mjson-library.patch b/RHEL-126665-CVE-2025-11230-fix-denial-of-service-vulnerability-in-mjson-library.patch new file mode 100644 index 0000000..f7eceeb --- /dev/null +++ b/RHEL-126665-CVE-2025-11230-fix-denial-of-service-vulnerability-in-mjson-library.patch @@ -0,0 +1,86 @@ +From: Willy Tarreau +Date: Mon, 29 Sep 2025 16:34:11 +0000 (+0200) +Subject: BUG/CRITICAL: mjson: fix possible DoS when parsing numbers +X-Git-Tag: v2.4.30~6 +X-Git-Url: http://git.haproxy.org/?p=haproxy-2.4.git;a=commitdiff_plain;h=2b278798cbdf4a8596149b5769ca98b325acc535;hp=d258af5a33893e52504431a46b5ab50a807280b5 + +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. + +CVE-2025-11230 was assigned to this issue. + +(cherry picked from commit 06675db4bf234ed17e14305f1d59259d2fe78b06) +Signed-off-by: Christopher Faulet +--- + +diff --git a/src/mjson.c b/src/mjson.c +index 73b7a57..2a4106b 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; diff --git a/haproxy.spec b/haproxy.spec index 7bdde3c..3b52825 100644 --- a/haproxy.spec +++ b/haproxy.spec @@ -8,7 +8,7 @@ Name: haproxy Version: 2.8.14 -Release: 2%{?dist} +Release: 3%{?dist} Summary: HAProxy reverse proxy for high availability environments License: GPLv2+ @@ -21,6 +21,7 @@ Source3: %{name}.logrotate Source4: %{name}.sysconfig Source5: %{name}.sysusers Source6: halog.1 +Patch0: RHEL-126665-CVE-2025-11230-fix-denial-of-service-vulnerability-in-mjson-library.patch BuildRequires: gcc BuildRequires: lua-devel @@ -50,6 +51,7 @@ availability environments. Indeed, it can: %prep %setup -q +%autopatch -p1 %build make %{?_smp_mflags} CPU="generic" TARGET="linux-glibc" USE_OPENSSL=1 USE_PCRE2=1 USE_SLZ=1 USE_LUA=1 USE_CRYPT_H=1 USE_SYSTEMD=1 USE_LINUX_TPROXY=1 USE_GETADDRINFO=1 USE_PROMEX=1 ADDINC="%{build_cflags}" ADDLIB="%{build_ldflags}" @@ -131,6 +133,10 @@ echo "d /var/lib/haproxy 0755 root root - -" > %{buildroot}%{_tmpfilesdir}/%{nam %{_tmpfilesdir}/%{name}.conf %changelog +* Thu Nov 6 2025 Oyvind Albrigtsen - 2.8.14-3 +- Fix denial of service vulnerability in mjson library (CVE-2025-11230) + Resolves: RHEL-126665 + * Tue Oct 21 2025 Oyvind Albrigtsen - 2.8.14-2 - Add tmpfiles.d file to make systemd-tmpfiles create/set correct ownership/permissions of /var/lib/haproxy