c-ares: patch CVE-2026-69186

Pick patch per [1].

[1] https://security-tracker.debian.org/tracker/CVE-2026-69184

Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
Peter Marko authored and Anuj Mittal committed 2026-10-26 10:10:40 +05:30
1 parent aaeb87a013
commit 9c30658af2
2 files changed
+162 -1

No files matched your search

@@ -0,0 +1,159 @@
From e47c203f91cd8b749c8736bc18d75a31ffdec8f4 Mon Sep 17 00:00:00 2001
From: jmestwa-coder <jmestwa@gmail.com>
Date: Sun, 12 Apr 2026 23:50:54 +0530
Subject: [PATCH] validate RR counts before preallocation to reject malformed
packets early (#1134)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Summary
Validate DNS RR counts before preallocation to reject malformed packets
early.
## What’s the issue?
The parser currently trusts RR counts from the DNS header (`ANCOUNT`,
`NSCOUNT`, `ARCOUNT`) without verifying that the packet contains enough
data.
A malformed packet can claim a large number of records without providing
sufficient payload, causing the parser to proceed with unnecessary work
and incorrect handling.
## What changed?
- Added validation to ensure RR counts are feasible based on the
remaining buffer size
- Moved RR preallocation from `ares_dns_parse_header` to
`ares_dns_parse_buf`
- Perform validation after question parsing and before preallocation
- Return `ARES_EBADRESP` early for malformed packets
## Why this approach?
This keeps the parser aligned with its natural flow:
parse header → parse question → validate → preallocate → parse records
It avoids trusting unverified input and ensures malformed packets are
rejected early and consistently.
## Test
Added a regression test (`ParseMalformedRRCount`) that reproduces the
issue using a malformed packet with inconsistent RR count.
Signed-off-by: @jmestwa-coder
CVE: CVE-2026-69186
Upstream-Status: Backport [https://github.com/c-ares/c-ares/commit/e47c203f91cd8b749c8736bc18d75a31ffdec8f4]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
src/lib/ares_dns_parse.c | 55 ++++++++++++++++++++++------------------
test/ares-test-parse.cc | 11 ++++++++
2 files changed, 42 insertions(+), 24 deletions(-)
diff --git a/src/lib/ares_dns_parse.c b/src/lib/ares_dns_parse.c
index 2d2a7bb2..01f3f43c 100644
--- a/src/lib/ares_dns_parse.c
+++ b/src/lib/ares_dns_parse.c
@@ -848,30 +848,6 @@ static ares_status_t ares_dns_parse_header(ares__buf_t *buf, unsigned int flags,
(*dnsrec)->raw_rcode = rcode;
- if (*ancount > 0) {
- status =
- ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ANSWER, *ancount);
- if (status != ARES_SUCCESS) {
- goto fail;
- }
- }
-
- if (*nscount > 0) {
- status =
- ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_AUTHORITY, *nscount);
- if (status != ARES_SUCCESS) {
- goto fail;
- }
- }
-
- if (*arcount > 0) {
- status =
- ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ADDITIONAL, *arcount);
- if (status != ARES_SUCCESS) {
- goto fail;
- }
- }
-
return ARES_SUCCESS;
fail:
@@ -1134,6 +1110,8 @@ static ares_status_t ares_dns_parse_buf(ares__buf_t *buf, unsigned int flags,
ares_dns_record_t **dnsrec)
{
ares_status_t status;
+ size_t total_rr_count;
+ const size_t min_rr_wire_len = 11;
unsigned short qdcount;
unsigned short ancount;
unsigned short nscount;
@@ -1194,6 +1172,35 @@ static ares_status_t ares_dns_parse_buf(ares__buf_t *buf, unsigned int flags,
}
}
+ total_rr_count = (size_t)ancount + (size_t)nscount + (size_t)arcount;
+ if (total_rr_count > ares__buf_len(buf) / min_rr_wire_len) {
+ status = ARES_EBADRESP;
+ goto fail;
+ }
+
+ if (ancount > 0) {
+ status = ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ANSWER, ancount);
+ if (status != ARES_SUCCESS) {
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
+ }
+
+ if (nscount > 0) {
+ status =
+ ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_AUTHORITY, nscount);
+ if (status != ARES_SUCCESS) {
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
+ }
+
+ if (arcount > 0) {
+ status =
+ ares_dns_record_rr_prealloc(*dnsrec, ARES_SECTION_ADDITIONAL, arcount);
+ if (status != ARES_SUCCESS) {
+ goto fail; /* LCOV_EXCL_LINE: OutOfMemory */
+ }
+ }
+
/* Parse Answers */
for (i = 0; i < ancount; i++) {
status = ares_dns_parse_rr(buf, flags, ARES_SECTION_ANSWER, *dnsrec);
diff --git a/test/ares-test-parse.cc b/test/ares-test-parse.cc
index ff1fe14d..81fd7deb 100644
--- a/test/ares-test-parse.cc
+++ b/test/ares-test-parse.cc
@@ -207,6 +207,17 @@ TEST_F(LibraryTest, ParseFullyCompressedName) {
ares_free_hostent(host);
}
+TEST_F(LibraryTest, ParseMalformedRRCount) {
+ ares_dns_record_t *dnsrec = NULL;
+ const unsigned char data[] = {
+ 0x12, 0x34, 0x81, 0x80, 0x00, 0x01, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 'a', 0x00, 0x00,
+ 0x01, 0x00, 0x01,
+ };
+
+ EXPECT_EQ(ARES_EBADRESP, ares_dns_parse(data, sizeof(data), 0, &dnsrec));
+ EXPECT_EQ(nullptr, dnsrec);
+}
} // namespace test
} // namespace ares
@@ -6,7 +6,9 @@ LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://LICENSE.md;md5=fdbc58a6da11a9f68aa73c453818decc"
SRC_URI = "https://github.com/c-ares/c-ares/releases/download/cares-1_27_0/${BPN}-${PV}.tar.gz \
file://run-ptest"
file://run-ptest \
file://CVE-2026-69186.patch \
"
SRC_URI[sha256sum] = "0a72be66959955c43e2af2fbd03418e82a2bd5464604ec9a62147e37aceb420b"
PACKAGECONFIG ?= "${@bb.utils.contains('PTEST_ENABLED', '1', 'tests', '', d)}"