已开启
fix(cve): 修复 CVE-2026-114605 在 python-dns 中的漏洞 #71
fix(cve): 修复 CVE-2026-114605 在 python-dns 中的漏洞 #71
已开启
infra_team创建于 12 天前
共 2 个文件变更+107-1
@@ -0,0 +1,99 @@
1+From 3c1991fea116bb0e905c93efa98782399611ef3a 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() to use excessive CPU for DNS name decompression. Applications which process untrusted DNS wire form messages with dnspython may be degraded or DoS'd by the extra CPU use required.
7+ 
8+Credit:
9+ 
10+Evgenios Gkritsis, Department of Informatics, University of Piraeus & Athena Research Center, Greece
11+Constantinos Patsakis, Department of Informatics, University of Piraeus & Athena Research Center, Greece
12+George Stergiopoulos, Department of Informatics, Athens University of Economics and Business, Greece
13+ 
14+Upstream-commit: https://github.com/rthalley/dnspython/commit/b485e460c266540a1a09ca6d8d1d7b685b1d3023
15+Signed-off-by: infra_team <zhaiwenjie1@huawei.com>
16+---
17+ dns/name.py | 11 +++++++++++
18+ tests/test_name.py | 22 ++++++++++++++++++++++
19+ 2 files changed, 33 insertions(+)
20+ 
21+diff --git a/dns/name.py b/dns/name.py
22+index f452bfe..8d701ab 100644
23+--- a/dns/name.py
24++++ b/dns/name.py
25+@@ -84,6 +84,10 @@ class BadPointer(dns.exception.FormError):
26+ """A DNS compression pointer points forward instead of backward."""
27+
28+
29++class PointerChainTooLong(dns.exception.FormError):
30++ """A DNS compression pointer chain was too long."""
31++
32++
33+ class BadLabelType(dns.exception.FormError):
34+ """The label type in DNS name wire format is unknown."""
35+
36+@@ -1022,6 +1026,9 @@ def from_text(
37+ return Name(labels)
38+
39+
40++MAX_COMPRESSION_POINTER_CHAIN = 16
41++
42++
43+ # we need 'dns.wire.Parser' quoted as dns.name and dns.wire depend on each other.
44+
45+
46+@@ -1040,6 +1047,7 @@ def from_wire_parser(parser: "dns.wire.Parser") -> Name:
47+
48+ labels = []
49+ biggest_pointer = parser.current
50++ hops = 0
51+ with parser.restore_furthest():
52+ count = parser.get_uint8()
53+ while count != 0:
54+@@ -1050,6 +1058,9 @@ def from_wire_parser(parser: "dns.wire.Parser") -> Name:
55+ if current >= biggest_pointer:
56+ raise BadPointer
57+ biggest_pointer = current
58++ hops += 1
59++ if hops > MAX_COMPRESSION_POINTER_CHAIN:
60++ raise PointerChainTooLong
61+ parser.seek(current)
62+ else:
63+ raise BadLabelType
64+diff --git a/tests/test_name.py b/tests/test_name.py
65+index 1d18ce3..e9303ae 100644
66+--- a/tests/test_name.py
67++++ b/tests/test_name.py
68+@@ -693,6 +693,28 @@ class NameTestCase(unittest.TestCase):
69+
70+ self.assertRaises(dns.name.BadLabelType, bad)
71+
72++ def testCompressionChainLength(self):
73++ # We're going to decode some wire starting two bytes from the end. At this
74++ # position is a pointer which points to four bytes from the end, and it points
75++ # to one 6 bytes from the end, etc., until finally the 16th pointer points at
76++ # offset zero, which is the root label followed by a byte of padding. After
77++ # all of this useless pointer hopping, we should get the root name.
78++ 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"
79++ self.assertEqual(len(w), 34)
80++ starts = [c for c in w if c == 0xC0]
81++ self.assertEqual(len(starts), dns.name.MAX_COMPRESSION_POINTER_CHAIN)
82++
83++ def bad():
84++ # Now we make the wire one pointer longer, which is too long!
85++ w1 = w + b"\xc0\x20"
86++ self.assertEqual(len(w1), 36)
87++ starts = [c for c in w1 if c == 0xC0]
88++ self.assertEqual(len(starts), dns.name.MAX_COMPRESSION_POINTER_CHAIN + 1)
89++ dns.name.from_wire(w1, 34)
90++
91++ self.assertEqual(dns.name.from_wire(w, 32)[0], dns.name.from_text("."))
92++ self.assertRaises(dns.name.PointerChainTooLong, bad)
93++
94+ def testParent1(self):
95+ n = dns.name.from_text("foo.bar.")
96+ self.assertEqual(n.parent(), dns.name.from_text("bar."))
97+--
98+2.39.5
99+ 
@@ -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: 0010-Limit-decompression-to-a-chain-length-of-at-most-16-.patch
36+ 
34BuildArch: noarch37BuildArch: noarch
35 38 
36BuildRequires: python3-devel python3-setuptools python3-cryptography39BuildRequires: python3-devel python3-setuptools python3-cryptography
@@ -83,6 +86,10 @@ 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+ 
86* Wed Oct 29 2025 gaihuiying <eaglegai@163.com> - 2.4.2-493* Wed Oct 29 2025 gaihuiying <eaglegai@163.com> - 2.4.2-4
87- sync to skip testResolveTCP on loongarch6494- sync to skip testResolveTCP on loongarch64
88 95