mirror of
https://git.yoctoproject.org/poky
synced 2026-05-07 16:59:22 +00:00
python3-pyasn1: fix CVE-2026-23490
pyasn1 is a generic ASN.1 library for Python. Prior to 0.6.2, a Denial-of-Service issue has been found that leads to memory exhaustion from malformed RELATIVE-OID with excessive continuation octets. This vulnerability is fixed in 0.6.2. References: https://nvd.nist.gov/vuln/detail/CVE-2026-23490 (From OE-Core rev: 205d360b49c7bbaa8709cb5a0b2e57457c32ad22) Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com> Signed-off-by: Jinfeng Wang <jinfeng.wang.cn@windriver.com> Signed-off-by: Yoann Congal <yoann.congal@smile.fr> Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
committed by
Paul Barker
parent
62a327e3bc
commit
60345ecc4b
@@ -18,7 +18,8 @@ inherit ptest
|
||||
|
||||
SRC_URI += " \
|
||||
file://run-ptest \
|
||||
"
|
||||
file://CVE-2026-23490.patch \
|
||||
"
|
||||
|
||||
RDEPENDS:${PN}-ptest += " \
|
||||
python3-pytest \
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
From d98d7bc91864e1e368d4849c26568e33c0dd0e27 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Pichugin <simon.pichugin@gmail.com>
|
||||
Date: Wed, 28 Jan 2026 16:31:29 +0800
|
||||
Subject: [PATCH] Merge commit from fork
|
||||
|
||||
Add limit of 20 continuation octets per OID arc to prevent a potential
|
||||
memory exhaustion from excessive continuation bytes input.
|
||||
|
||||
CVE: CVE-2026-23490
|
||||
|
||||
Upstream-Status: Backport [https://github.com/pyasn1/pyasn1/commit/3908f14422]
|
||||
|
||||
Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
|
||||
---
|
||||
pyasn1/codec/ber/decoder.py | 13 ++++++-
|
||||
tests/codec/ber/test_decoder.py | 65 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 77 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py
|
||||
index 7cc863d..be8ba65 100644
|
||||
--- a/pyasn1/codec/ber/decoder.py
|
||||
+++ b/pyasn1/codec/ber/decoder.py
|
||||
@@ -35,6 +35,10 @@ noValue = base.noValue
|
||||
|
||||
SubstrateUnderrunError = error.SubstrateUnderrunError
|
||||
|
||||
+# Maximum number of continuation octets (high-bit set) allowed per OID arc.
|
||||
+# 20 octets allows up to 140-bit integers, supporting UUID-based OIDs
|
||||
+MAX_OID_ARC_CONTINUATION_OCTETS = 20
|
||||
+
|
||||
|
||||
class AbstractPayloadDecoder(object):
|
||||
protoComponent = None
|
||||
@@ -431,7 +435,14 @@ class ObjectIdentifierPayloadDecoder(AbstractSimplePayloadDecoder):
|
||||
# Construct subid from a number of octets
|
||||
nextSubId = subId
|
||||
subId = 0
|
||||
+ continuationOctetCount = 0
|
||||
while nextSubId >= 128:
|
||||
+ continuationOctetCount += 1
|
||||
+ if continuationOctetCount > MAX_OID_ARC_CONTINUATION_OCTETS:
|
||||
+ raise error.PyAsn1Error(
|
||||
+ 'OID arc exceeds maximum continuation octets limit (%d) '
|
||||
+ 'at position %d' % (MAX_OID_ARC_CONTINUATION_OCTETS, index)
|
||||
+ )
|
||||
subId = (subId << 7) + (nextSubId & 0x7F)
|
||||
if index >= substrateLen:
|
||||
raise error.SubstrateUnderrunError(
|
||||
@@ -1872,7 +1883,7 @@ class StreamingDecoder(object):
|
||||
:py:class:`~pyasn1.error.SubstrateUnderrunError` object indicating
|
||||
insufficient BER/CER/DER serialization on input to fully recover ASN.1
|
||||
objects from it.
|
||||
-
|
||||
+
|
||||
In the latter case the caller is advised to ensure some more data in
|
||||
the input stream, then call the iterator again. The decoder will resume
|
||||
the decoding process using the newly arrived data.
|
||||
diff --git a/tests/codec/ber/test_decoder.py b/tests/codec/ber/test_decoder.py
|
||||
index 3b97ce4..f033dfd 100644
|
||||
--- a/tests/codec/ber/test_decoder.py
|
||||
+++ b/tests/codec/ber/test_decoder.py
|
||||
@@ -450,6 +450,71 @@ class ObjectIdentifierDecoderTestCase(BaseTestCase):
|
||||
ints2octs((0x06, 0x13, 0x88, 0x37, 0x83, 0xC6, 0xDF, 0xD4, 0xCC, 0xB3, 0xFF, 0xFF, 0xFE, 0xF0, 0xB8, 0xD6, 0xB8, 0xCB, 0xE2, 0xB6, 0x47))
|
||||
) == ((2, 999, 18446744073709551535184467440737095), null)
|
||||
|
||||
+ def testExcessiveContinuationOctets(self):
|
||||
+ """Test that OID arcs with excessive continuation octets are rejected."""
|
||||
+ # Create a payload with 25 continuation octets (exceeds 20 limit)
|
||||
+ # 0x81 bytes are continuation octets, 0x01 terminates
|
||||
+ malicious_payload = bytes([0x06, 26]) + bytes([0x81] * 25) + bytes([0x01])
|
||||
+ try:
|
||||
+ decoder.decode(malicious_payload)
|
||||
+ except error.PyAsn1Error:
|
||||
+ pass
|
||||
+ else:
|
||||
+ assert 0, 'Excessive continuation octets tolerated'
|
||||
+
|
||||
+ def testMaxAllowedContinuationOctets(self):
|
||||
+ """Test that OID arcs at the maximum continuation octets limit work."""
|
||||
+ # Create a payload with exactly 20 continuation octets (at limit)
|
||||
+ # This should succeed
|
||||
+ payload = bytes([0x06, 21]) + bytes([0x81] * 20) + bytes([0x01])
|
||||
+ try:
|
||||
+ decoder.decode(payload)
|
||||
+ except error.PyAsn1Error:
|
||||
+ assert 0, 'Valid OID with 20 continuation octets rejected'
|
||||
+
|
||||
+ def testOneOverContinuationLimit(self):
|
||||
+ """Test boundary: 21 continuation octets (one over limit) is rejected."""
|
||||
+ payload = bytes([0x06, 22]) + bytes([0x81] * 21) + bytes([0x01])
|
||||
+ try:
|
||||
+ decoder.decode(payload)
|
||||
+ except error.PyAsn1Error:
|
||||
+ pass
|
||||
+ else:
|
||||
+ assert 0, '21 continuation octets tolerated (should be rejected)'
|
||||
+
|
||||
+ def testExcessiveContinuationInSecondArc(self):
|
||||
+ """Test that limit applies to subsequent arcs, not just the first."""
|
||||
+ # First arc: valid simple byte (0x55 = 85, decodes to arc 2.5)
|
||||
+ # Second arc: excessive continuation octets
|
||||
+ payload = bytes([0x06, 27]) + bytes([0x55]) + bytes([0x81] * 25) + bytes([0x01])
|
||||
+ try:
|
||||
+ decoder.decode(payload)
|
||||
+ except error.PyAsn1Error:
|
||||
+ pass
|
||||
+ else:
|
||||
+ assert 0, 'Excessive continuation in second arc tolerated'
|
||||
+
|
||||
+ def testMultipleArcsAtLimit(self):
|
||||
+ """Test multiple arcs each at the continuation limit work correctly."""
|
||||
+ # Two arcs, each with 20 continuation octets (both at limit)
|
||||
+ arc1 = bytes([0x81] * 20) + bytes([0x01]) # 21 bytes
|
||||
+ arc2 = bytes([0x81] * 20) + bytes([0x01]) # 21 bytes
|
||||
+ payload = bytes([0x06, 42]) + arc1 + arc2
|
||||
+ try:
|
||||
+ decoder.decode(payload)
|
||||
+ except error.PyAsn1Error:
|
||||
+ assert 0, 'Multiple valid arcs at limit rejected'
|
||||
+
|
||||
+ def testExcessiveContinuationWithMaxBytes(self):
|
||||
+ """Test with 0xFF continuation bytes (maximum value, not just 0x81)."""
|
||||
+ # 0xFF bytes are also continuation octets (high bit set)
|
||||
+ malicious_payload = bytes([0x06, 26]) + bytes([0xFF] * 25) + bytes([0x01])
|
||||
+ try:
|
||||
+ decoder.decode(malicious_payload)
|
||||
+ except error.PyAsn1Error:
|
||||
+ pass
|
||||
+ else:
|
||||
+ assert 0, 'Excessive 0xFF continuation octets tolerated'
|
||||
|
||||
class RealDecoderTestCase(BaseTestCase):
|
||||
def testChar(self):
|
||||
--
|
||||
2.34.1
|
||||
|
||||
Reference in New Issue
Block a user