Hi,
Two notes on this bug, for the CVEs I could settle.
CVE-2026-100890, opendmarc_spf_ipv6_explode()
Upstream fixed this in commit a1fea0b ("libopendmarc: fix NULL-pointer
deref in opendmarc_spf_ipv6_explode()", May 2025). It is on the develop
branch but not on master or in any release tag, so 1.4.2 lacks it. The
commit is attached as a format-patch and applies without changes on top of
the patch series of 1.4.2-5.1, 1.4.2-5 and 1.4.2-2.
I did not reproduce the crash. I compiled the function before and after
with ASan and UBSan in a small harness and ran 5 well-formed IPv6 addresses
through it on those three versions. The eight chunks were identical and the
sanitizers reported nothing. One visible change: nstrs becomes 8 instead of
9 for those addresses, because the loop now breaks before the final
decrement. nstrs bounds the loop in opendmarc_spf_ipv6_cidr_populate() over
strs[8], so 8 looks like the correct value, but I did not trace that
function further. I did not build the full package or run its tests.
CVE-2026-101014, opendmarc_util_cleanup()
The CVE's off-by-one is already fixed in Debian by cleanup-buflen.patch,
which the changelog adds in 1.4.1.1-2. The patched check (strlen >= buflen)
is in the applied sources of 1.4.2-2, 1.4.2-5 and 1.4.2-5.1. Upstream made
the same change much later, in 2c4c094. Tracker suggestion:
CVE-2026-101014
- opendmarc 1.4.1.1-2 (bug #1149876)
Bullseye's 1.4.0~beta1+dfsg-6+deb11u1 has no such patch in debian/patches,
so it probably remains open there; I did not read that version's code.
I have not assessed the other CVEs in this bug.
Regards,
Sumit Verma
From a1fea0b405f7c69fbe13a0f1cec38413f678a0b3 Mon Sep 17 00:00:00 2001
From: Mikel Olasagasti Uranga <[email protected]>
Date: Fri, 2 May 2025 23:07:50 +0200
Subject: [PATCH] =?UTF-8?q?libopendmarc:=20fix=20NULL=E2=80=93pointer=20de?=
=?UTF-8?q?ref=20in=20opendmarc=5Fspf=5Fipv6=5Fexplode()?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When parsing IPv6 literals the loop in opendmarc_spf_ipv6_explode()
advances the working pointer with
cp = ep + 1;
unconditionally. For the last 16-bit chunk of the address
âstrchr(cp, ':')â returns NULL, so the assignment produces the invalid
pointer (NULL + 1). On the following iteration strchr() immediately
reads from that address and the milter crashes with SIGSEGV.
The bug is exposed whenever OpenDMARC evaluates an âip6:â SPF mechanism
whose prefix lacks a trailing colon, e.g.
ip6:2001:db8::/32
Typical trigger path:
* Postfix submission (SASL) from ::1
* OpenDMARC runs SPF check against the domainâs own record
* ::1 is matched against the record above
* opendmarc_spf_ipv6_explode() crashes
Guard the assignment by bailing out of the loop when no further â:â
is present, thereby preserving the valid value of âcpâ.
Closes: #274
Signed-off-by: Mikel Olasagasti Uranga <[email protected]>
---
libopendmarc/opendmarc_spf.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/libopendmarc/opendmarc_spf.c b/libopendmarc/opendmarc_spf.c
index e015183..c02ba6f 100644
--- a/libopendmarc/opendmarc_spf.c
+++ b/libopendmarc/opendmarc_spf.c
@@ -745,7 +745,15 @@ opendmarc_spf_ipv6_explode(char *str, TXT_ARY_T *ap)
}
i+= 1;
}
- cp = ep+1;
+ /*
+ * If strchr() did not find another ':' we have reached the
+ * last chunk of the IPv6 literal. Advancing the pointer
+ * when ep is NULL would yield (NULL + 1) and lead to a
+ * segmentation fault on the next iteration.
+ */
+ if (ep == NULL)
+ break;
+ cp = ep + 1;
}
ap->nstrs = 8 - i;
return 0;
--
2.53.0