已开启
fix(cve): 修复 CVE-2026-114605 在 python-dns 中的漏洞 #70
fix(cve): 修复 CVE-2026-114605 在 python-dns 中的漏洞 #70
已开启
infra_team创建于 12 天前
共 2 个文件变更+111-1
@@ -0,0 +1,102 @@
1+From 154620137dfda9ae05a19c23b7cd2589ee841a7f Mon Sep 17 00:00:00 2001
E
Eeaglegai10 天前

@infra_team commit id建议跟社区保持一致

likedislike
2+From: Bob Halley <halley@dnspython.org>
3+Date: Sat, 26 Sep 2026 13:38:07 -0700
4+Subject: [PATCH] Limit decompression to a chain length of at most 16 pointers.
5+ 
6+A maliciously crafted DNS message may cause dns.name.from_wire_parser()
7+to use excessive CPU for DNS name decompression. Applications which
8+process untrusted DNS wire form messages with dnspython may be degraded
9+or DoS'd by the extra CPU use required.
10+ 
11+Backport to dnspython 2.4.2: adapted for the 2.4.2 signature of
12+from_wire_parser() ("dns.wire.Parser"); the doc/whatsnew.rst hunk is
13+dropped as 2.4.2 has no 2.9.0 section.
14+ 
15+fix: CVE-2026-114605
16+ 
17+Upstream-commit: https://github.com/rthalley/dnspython/commit/b485e460c266540a1a09ca6d8d1d7b685b1d3023
18+Signed-off-by: infra_team <zhaiwenjie1@huawei.com>
19+---
20+ dns/name.py | 11 +++++++++++
21+ tests/test_name.py | 22 ++++++++++++++++++++++
22+ 2 files changed, 33 insertions(+)
23+ 
24+diff --git a/dns/name.py b/dns/name.py
25+index f452bfe..ada3a51 100644
26+--- a/dns/name.py
27++++ b/dns/name.py
28+@@ -84,6 +84,10 @@ class BadPointer(dns.exception.FormError):
29+ """A DNS compression pointer points forward instead of backward."""
30+
31+
32++class PointerChainTooLong(dns.exception.FormError):
33++ """A DNS compression pointer chain was too long."""
34++
35++
36+ class BadLabelType(dns.exception.FormError):
37+ """The label type in DNS name wire format is unknown."""
38+
39+@@ -1025,6 +1029,9 @@ def from_text(
40+ # we need 'dns.wire.Parser' quoted as dns.name and dns.wire depend on each other.
41+
42+
43++MAX_COMPRESSION_POINTER_CHAIN = 16
44++
45++
46+ def from_wire_parser(parser: "dns.wire.Parser") -> Name:
47+ """Convert possibly compressed wire format into a Name.
48+
49+@@ -1040,6 +1047,7 @@ def from_wire_parser(parser: "dns.wire.Parser") -> Name:
50+
51+ labels = []
52+ biggest_pointer = parser.current
53++ hops = 0
54+ with parser.restore_furthest():
55+ count = parser.get_uint8()
56+ while count != 0:
57+@@ -1050,6 +1058,9 @@ def from_wire_parser(parser: "dns.wire.Parser") -> Name:
58+ if current >= biggest_pointer:
59+ raise BadPointer
60+ biggest_pointer = current
61++ hops += 1
62++ if hops > MAX_COMPRESSION_POINTER_CHAIN:
63++ raise PointerChainTooLong
64+ parser.seek(current)
65+ else:
66+ raise BadLabelType
67+diff --git a/tests/test_name.py b/tests/test_name.py
68+index 1d18ce3..e9303ae 100644
69+--- a/tests/test_name.py
70++++ b/tests/test_name.py
71+@@ -693,6 +693,28 @@ class NameTestCase(unittest.TestCase):
72+
73+ self.assertRaises(dns.name.BadLabelType, bad)
74+
75++ def testCompressionChainLength(self):
76++ # We're going to decode some wire starting two bytes from the end. At this
77++ # position is a pointer which points to four bytes from the end, and it points
78++ # to one 6 bytes from the end, etc., until finally the 16th pointer points at
79++ # offset zero, which is the root label followed by a byte of padding. After
80++ # all of this useless pointer hopping, we should get the root name.
81++ w = b"\x00\x00\xc0\x00\xc0\x02\xc0\x04\xc0\x06\xc0\x08\xc0\x0a\xc0\x0c\xc0\x0e\xc0\x10\xc0\x12\xc0\x14\xc0\x16\xc0\x18\xc0\x1a\xc0\x1c\xc0\x1e"
82++ self.assertEqual(len(w), 34)
83++ starts = [c for c in w if c == 0xC0]
84++ self.assertEqual(len(starts), dns.name.MAX_COMPRESSION_POINTER_CHAIN)
85++
86++ def bad():
87++ # Now we make the wire one pointer longer, which is too long!
88++ w1 = w + b"\xc0\x20"
89++ self.assertEqual(len(w1), 36)
90++ starts = [c for c in w1 if c == 0xC0]
91++ self.assertEqual(len(starts), dns.name.MAX_COMPRESSION_POINTER_CHAIN + 1)
92++ dns.name.from_wire(w1, 34)
93++
94++ self.assertEqual(dns.name.from_wire(w, 32)[0], dns.name.from_text("."))
95++ self.assertRaises(dns.name.PointerChainTooLong, bad)
96++
97+ def testParent1(self):
98+ n = dns.name.from_text("foo.bar.")
99+ self.assertEqual(n.parent(), dns.name.from_text("bar."))
100+--
101+2.39.5
102+ 
@@ -14,7 +14,7 @@ messages, names, and records.
14Name: python-dns14Name: python-dns
15Summary: %{sum}15Summary: %{sum}
16Version: 2.4.216Version: 2.4.2
17-Release: 417+Release: 5
18License: ISC and MIT18License: ISC and MIT
19URL: http://www.dnspython.org/19URL: http://www.dnspython.org/
20Source0: https://github.com/rthalley/dnspython/archive/v%{version}/dnspython-%{version}.tar.gz20Source0: https://github.com/rthalley/dnspython/archive/v%{version}/dnspython-%{version}.tar.gz
@@ -31,6 +31,9 @@ Patch0007: backport-Retry-on-test-timeout.patch
31Patch0008: backport-add-more-wrapping-accidentally-omitted-from-the-PR.patch31Patch0008: backport-add-more-wrapping-accidentally-omitted-from-the-PR.patch
32Patch0009: fix-to-skip-unsupport-testcases.patch32Patch0009: fix-to-skip-unsupport-testcases.patch
33 33 
34+# fix CVE-2026-114605
35+Patch0010: backport-CVE-2026-114605-limit-compression-pointer-chain-length.patch
36+ 
34BuildArch: noarch37BuildArch: noarch
35 38 
36BuildRequires: python3-devel python3-setuptools python3-cryptography39BuildRequires: python3-devel python3-setuptools python3-cryptography
@@ -83,6 +86,11 @@ fi
83%doc examples86%doc examples
84 87 
85%changelog88%changelog
89+* Sat Oct 24 2026 infra_team <zhaiwenjie1@huawei.com> - 2.4.2-5
90+- fix CVE-2026-114605
91+- limit DNS name decompression to a chain length of at most 16 pointers
92+ to prevent excessive CPU use in dns.name.from_wire_parser()
93+ 
86* Wed Oct 29 2025 gaihuiying <eaglegai@163.com> - 2.4.2-494* Wed Oct 29 2025 gaihuiying <eaglegai@163.com> - 2.4.2-4
87- sync to skip testResolveTCP on loongarch6495- sync to skip testResolveTCP on loongarch64
88 96