* [scarthgap][PATCH 0/3] python3: fix CVE-2026-11940, CVE-2026-11972 and CVE-2026-9669
@ 2026-07-06 11:01 Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 1/3] python3: fix CVE-2026-11940 Benjamin Robin (Schneider Electric)
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Benjamin Robin (Schneider Electric) @ 2026-07-06 11:01 UTC (permalink / raw)
To: openembedded-core
Cc: olivier.benjamin, mathieu.dubois-briand, pascal.eberhard,
wahid.essid, Benjamin Robin (Schneider Electric)
This series fix the following CVEs:
- CVE-2026-11940
- CVE-2026-11972
- CVE-2026-9669
On master and wrynose the CVE-2026-9669 patch is not necessary since it is
already included in 3.14.6
Signed-off-by: Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
---
Benjamin Robin (Schneider Electric) (3):
python3: fix CVE-2026-11940
python3: fix CVE-2026-11972
python3: fix CVE-2026-9669
.../python/python3/CVE-2026-11940.patch | 66 +++++++++++++++
.../python/python3/CVE-2026-11972.patch | 58 +++++++++++++
.../python/python3/CVE-2026-9669.patch | 97 ++++++++++++++++++++++
meta/recipes-devtools/python/python3_3.12.13.bb | 3 +
4 files changed, 224 insertions(+)
---
base-commit: 2814f0962f56c8d1afa4de76d2895ba9b5cb767d
change-id: 20260706-fix-cves-python-scarthgap-76eb4e1f3d78
Best regards,
--
Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [scarthgap][PATCH 1/3] python3: fix CVE-2026-11940
2026-07-06 11:01 [scarthgap][PATCH 0/3] python3: fix CVE-2026-11940, CVE-2026-11972 and CVE-2026-9669 Benjamin Robin (Schneider Electric)
@ 2026-07-06 11:01 ` Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 2/3] python3: fix CVE-2026-11972 Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 3/3] python3: fix CVE-2026-9669 Benjamin Robin (Schneider Electric)
2 siblings, 0 replies; 4+ messages in thread
From: Benjamin Robin (Schneider Electric) @ 2026-07-06 11:01 UTC (permalink / raw)
To: openembedded-core
Cc: olivier.benjamin, mathieu.dubois-briand, pascal.eberhard,
wahid.essid, Benjamin Robin (Schneider Electric)
tarfile.extractall() with the 'data' or 'tar' filter could be bypassed
by a crafted archive where a hardlink references a symlink stored at a
deeper name than the hardlink itself.
Signed-off-by: Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
---
.../python/python3/CVE-2026-11940.patch | 66 ++++++++++++++++++++++
meta/recipes-devtools/python/python3_3.12.13.bb | 1 +
2 files changed, 67 insertions(+)
diff --git a/meta/recipes-devtools/python/python3/CVE-2026-11940.patch b/meta/recipes-devtools/python/python3/CVE-2026-11940.patch
new file mode 100644
index 000000000000..0851138ae892
--- /dev/null
+++ b/meta/recipes-devtools/python/python3/CVE-2026-11940.patch
@@ -0,0 +1,66 @@
+From 91a9bd79cdbab8f8518c4a5e669b3f19680a2f31 Mon Sep 17 00:00:00 2001
+From: Stan Ulbrych <stan@python.org>
+Date: Tue, 23 Jun 2026 14:31:38 +0100
+Subject: [PATCH] gh-151558: Fix symlink escape via `tarfile`
+ hardlink-extraction fallback (GH-151559)
+
+CVE: CVE-2026-11940
+Upstream-Status: Backport [https://github.com/python/cpython/commit/27dd970bf6b17ebca7c8ed486a40ab043ed7af8f]
+
+Signed-off-by: Benjamin Robin <benjamin.robin@bootlin.com>
+---
+ Lib/tarfile.py | 3 +++
+ Lib/test/test_tarfile.py | 24 ++++++++++++++++++++++++
+ 2 files changed, 27 insertions(+)
+
+diff --git a/Lib/tarfile.py b/Lib/tarfile.py
+index 59d3f6e5cce1..83226e907e4b 100755
+--- a/Lib/tarfile.py
++++ b/Lib/tarfile.py
+@@ -2650,6 +2650,9 @@ def makelink_with_filter(self, tarinfo, targetpath,
+ "makelink_with_filter: if filter_function is not None, "
+ + "extraction_root must also not be None")
+ try:
++ filter_function(
++ unfiltered.replace(name=tarinfo.name, deep=False),
++ extraction_root)
+ filtered = filter_function(unfiltered, extraction_root)
+ except _FILTER_ERRORS as cause:
+ raise LinkFallbackError(tarinfo, unfiltered.name) from cause
+diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
+index 759fa03ead70..29719d95b6c1 100644
+--- a/Lib/test/test_tarfile.py
++++ b/Lib/test/test_tarfile.py
+@@ -4080,6 +4080,30 @@ def test_sneaky_hardlink_fallback(self):
+ self.expect_file("boom", symlink_to='../../link_here')
+ self.expect_file("c", symlink_to='b')
+
++ @symlink_test
++ def test_sneaky_hardlink_fallback_deep(self):
++ # (CVE-2026-11940)
++ with ArchiveMaker() as arc:
++ arc.add("a/b/s", symlink_to=os.path.join("..", "escape"))
++ arc.add("s", hardlink_to=os.path.join("a", "b", "s"))
++
++ with self.check_context(arc.open(), 'data'):
++ e = self.expect_exception(
++ tarfile.LinkFallbackError,
++ "link 's' would be extracted as a copy of "
++ + "'a/b/s', which was rejected")
++ self.assertIsInstance(e.__cause__,
++ tarfile.LinkOutsideDestinationError)
++
++ for filter in 'tar', 'fully_trusted':
++ with self.subTest(filter), self.check_context(arc.open(), filter):
++ if not os_helper.can_symlink():
++ self.expect_file("a/")
++ self.expect_file("a/b/")
++ else:
++ self.expect_file("a/b/s", symlink_to=os.path.join('..', 'escape'))
++ self.expect_file("s", symlink_to=os.path.join('..', 'escape'))
++
+ @symlink_test
+ def test_exfiltration_via_symlink(self):
+ # (CVE-2025-4138)
+--
+2.54.0
diff --git a/meta/recipes-devtools/python/python3_3.12.13.bb b/meta/recipes-devtools/python/python3_3.12.13.bb
index 06dbc8e892d9..f41588055f32 100644
--- a/meta/recipes-devtools/python/python3_3.12.13.bb
+++ b/meta/recipes-devtools/python/python3_3.12.13.bb
@@ -44,6 +44,7 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \
file://CVE-2026-6019_p2.patch \
file://CVE-2025-13462.patch \
file://CVE-2026-4224.patch \
+ file://CVE-2026-11940.patch \
"
SRC_URI:append:class-native = " \
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [scarthgap][PATCH 2/3] python3: fix CVE-2026-11972
2026-07-06 11:01 [scarthgap][PATCH 0/3] python3: fix CVE-2026-11940, CVE-2026-11972 and CVE-2026-9669 Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 1/3] python3: fix CVE-2026-11940 Benjamin Robin (Schneider Electric)
@ 2026-07-06 11:01 ` Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 3/3] python3: fix CVE-2026-9669 Benjamin Robin (Schneider Electric)
2 siblings, 0 replies; 4+ messages in thread
From: Benjamin Robin (Schneider Electric) @ 2026-07-06 11:01 UTC (permalink / raw)
To: openembedded-core
Cc: olivier.benjamin, mathieu.dubois-briand, pascal.eberhard,
wahid.essid, Benjamin Robin (Schneider Electric)
When using the "tarfile" module with a file opened in "streaming mode"
(mode="r|") the tarfile module did not properly handle EOF, making archive
parsing take exponentially longer.
Signed-off-by: Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
---
.../python/python3/CVE-2026-11972.patch | 58 ++++++++++++++++++++++
meta/recipes-devtools/python/python3_3.12.13.bb | 1 +
2 files changed, 59 insertions(+)
diff --git a/meta/recipes-devtools/python/python3/CVE-2026-11972.patch b/meta/recipes-devtools/python/python3/CVE-2026-11972.patch
new file mode 100644
index 000000000000..0752ba372dcc
--- /dev/null
+++ b/meta/recipes-devtools/python/python3/CVE-2026-11972.patch
@@ -0,0 +1,58 @@
+From a83ebdb495a9cbd28a03675acdeda235fade90b3 Mon Sep 17 00:00:00 2001
+From: Petr Viktorin <encukou@gmail.com>
+Date: Tue, 23 Jun 2026 15:13:30 +0200
+Subject: [PATCH] gh-151981: Make tarfile._Stream.seek break at EOF (GH-151982)
+
+CVE: CVE-2026-11972
+Upstream-Status: Backport [https://github.com/python/cpython/commit/f50bf13566189c8d0ce5a814f33eff3d89951896]
+
+Signed-off-by: Benjamin Robin <benjamin.robin@bootlin.com>
+---
+ Lib/tarfile.py | 4 +++-
+ Lib/test/test_tarfile.py | 16 ++++++++++++++++
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/Lib/tarfile.py b/Lib/tarfile.py
+index 83226e907e4b..c0007a78f700 100755
+--- a/Lib/tarfile.py
++++ b/Lib/tarfile.py
+@@ -516,7 +516,9 @@ def seek(self, pos=0):
+ if pos - self.pos >= 0:
+ blocks, remainder = divmod(pos - self.pos, self.bufsize)
+ for i in range(blocks):
+- self.read(self.bufsize)
++ data = self.read(self.bufsize)
++ if not data:
++ break
+ self.read(remainder)
+ else:
+ raise StreamError("seeking backwards is not allowed")
+diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
+index 29719d95b6c1..8aeb2e1b1b9a 100644
+--- a/Lib/test/test_tarfile.py
++++ b/Lib/test/test_tarfile.py
+@@ -4480,6 +4480,22 @@ def valueerror_filter(tarinfo, path):
+ with self.check_context(arc.open(errorlevel='boo!'), filtererror_filter):
+ self.expect_exception(TypeError) # errorlevel is not int
+
++ @support.subTests('format', [tarfile.GNU_FORMAT, tarfile.PAX_FORMAT])
++ def test_getmembers_big_size(self, format):
++ # gh-151981: A loop in seek() for streaming files tried to read the
++ # declared number of blocks even at EOF
++ tinfo = tarfile.TarInfo("huge-file")
++ tinfo.size = 1 << 64
++ bio = io.BytesIO()
++ # Write header without data
++ bio.write(tinfo.tobuf(format))
++
++ # Reset & try to get contents
++ bio.seek(0)
++ with tarfile.open(fileobj=bio, mode="r|") as tar:
++ with self.assertRaises(tarfile.ReadError):
++ tar.getmembers()
++
+
+ class OverwriteTests(archiver_tests.OverwriteTests, unittest.TestCase):
+ testdir = os.path.join(TEMPDIR, "testoverwrite")
+--
+2.54.0
diff --git a/meta/recipes-devtools/python/python3_3.12.13.bb b/meta/recipes-devtools/python/python3_3.12.13.bb
index f41588055f32..24ceeb30a416 100644
--- a/meta/recipes-devtools/python/python3_3.12.13.bb
+++ b/meta/recipes-devtools/python/python3_3.12.13.bb
@@ -45,6 +45,7 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \
file://CVE-2025-13462.patch \
file://CVE-2026-4224.patch \
file://CVE-2026-11940.patch \
+ file://CVE-2026-11972.patch \
"
SRC_URI:append:class-native = " \
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [scarthgap][PATCH 3/3] python3: fix CVE-2026-9669
2026-07-06 11:01 [scarthgap][PATCH 0/3] python3: fix CVE-2026-11940, CVE-2026-11972 and CVE-2026-9669 Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 1/3] python3: fix CVE-2026-11940 Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 2/3] python3: fix CVE-2026-11972 Benjamin Robin (Schneider Electric)
@ 2026-07-06 11:01 ` Benjamin Robin (Schneider Electric)
2 siblings, 0 replies; 4+ messages in thread
From: Benjamin Robin (Schneider Electric) @ 2026-07-06 11:01 UTC (permalink / raw)
To: openembedded-core
Cc: olivier.benjamin, mathieu.dubois-briand, pascal.eberhard,
wahid.essid, Benjamin Robin (Schneider Electric)
bz2.BZ2Decompressor objects could be reused after a decompression error.
If an application caught the resulting OSError and retried with the same
decompressor, crafted input could cause the decompressor to resume from an
invalid internal state and perform out-of-bounds writes to a stack buffer.
This could crash the process when processing untrusted data.
Signed-off-by: Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
---
.../python/python3/CVE-2026-9669.patch | 97 ++++++++++++++++++++++
meta/recipes-devtools/python/python3_3.12.13.bb | 1 +
2 files changed, 98 insertions(+)
diff --git a/meta/recipes-devtools/python/python3/CVE-2026-9669.patch b/meta/recipes-devtools/python/python3/CVE-2026-9669.patch
new file mode 100644
index 000000000000..933d6f410ee1
--- /dev/null
+++ b/meta/recipes-devtools/python/python3/CVE-2026-9669.patch
@@ -0,0 +1,97 @@
+From 5b412e1f7bdb3e0667b2bc8b216ad216d59d8373 Mon Sep 17 00:00:00 2001
+From: "Miss Islington (bot)"
+ <31488909+miss-islington@users.noreply.github.com>
+Date: Mon, 8 Jun 2026 11:55:32 +0200
+Subject: [PATCH] gh-150599: Prevent bz2 decompressor reuse after errors
+ (GH-150600)
+
+CVE: CVE-2026-9669
+Upstream-Status: Backport [https://github.com/python/cpython/commit/5755d0f083949ff3c5bf3a37e673e24e306b036e]
+
+Signed-off-by: Benjamin Robin <benjamin.robin@bootlin.com>
+---
+ Lib/test/test_bz2.py | 15 +++++++++++++++
+ Modules/_bz2module.c | 18 +++++++++++++++---
+ 2 files changed, 30 insertions(+), 3 deletions(-)
+
+diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py
+index cb730a1a46e2..dcbf6a298264 100644
+--- a/Lib/test/test_bz2.py
++++ b/Lib/test/test_bz2.py
+@@ -958,6 +958,21 @@ def test_failure(self):
+ # Previously, a second call could crash due to internal inconsistency
+ self.assertRaises(Exception, bzd.decompress, self.BAD_DATA * 30)
+
++ def test_decompress_after_data_error(self):
++ data = bytes.fromhex(
++ "425a6839314159265359000000000000007fffff000000000000000000000000"
++ "00000000000000000000000000000000000000e0370000000000000000000000"
++ "000000000000000000000000000000000000000000000000000083f3"
++ )
++ bzd = BZ2Decompressor()
++ with self.assertRaisesRegex(OSError, "Invalid data stream"):
++ bzd.decompress(data)
++ # Previously, a second call could crash due to internal inconsistency
++ self.assertFalse(bzd.needs_input)
++ self.assertFalse(bzd.eof)
++ with self.assertRaisesRegex(ValueError, "previous error"):
++ bzd.decompress(b'\x00' * 18)
++
+ @support.refcount_test
+ def test_refleaks_in___init__(self):
+ gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount')
+diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c
+index 97bd44b4ac96..0b0916142f57 100644
+--- a/Modules/_bz2module.c
++++ b/Modules/_bz2module.c
+@@ -114,6 +114,7 @@ typedef struct {
+ typedef struct {
+ PyObject_HEAD
+ bz_stream bzs;
++ int bzerror;
+ char eof; /* T_BOOL expects a char */
+ PyObject *unused_data;
+ char needs_input;
+@@ -453,8 +454,11 @@ decompress_buf(BZ2Decompressor *d, Py_ssize_t max_length)
+
+ d->bzs_avail_in_real += bzs->avail_in;
+
+- if (catch_bz2_error(bzret))
++ if (catch_bz2_error(bzret)) {
++ d->bzerror = bzret;
++ d->needs_input = 0;
+ goto error;
++ }
+ if (bzret == BZ_STREAM_END) {
+ d->eof = 1;
+ break;
+@@ -621,10 +625,17 @@ _bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data,
+ PyObject *result = NULL;
+
+ ACQUIRE_LOCK(self);
+- if (self->eof)
++ if (self->eof) {
+ PyErr_SetString(PyExc_EOFError, "End of stream already reached");
+- else
++ }
++ else if (self->bzerror) {
++ // Re-entering BZ2_bzDecompress() after an error can write out of bounds.
++ PyErr_SetString(PyExc_ValueError,
++ "Decompressor is unusable after a previous error");
++ }
++ else {
+ result = decompress(self, data->buf, data->len, max_length);
++ }
+ RELEASE_LOCK(self);
+ return result;
+ }
+@@ -658,6 +669,7 @@ _bz2_BZ2Decompressor_impl(PyTypeObject *type)
+ return NULL;
+ }
+
++ self->bzerror = 0;
+ self->needs_input = 1;
+ self->bzs_avail_in_real = 0;
+ self->input_buffer = NULL;
+--
+2.54.0
diff --git a/meta/recipes-devtools/python/python3_3.12.13.bb b/meta/recipes-devtools/python/python3_3.12.13.bb
index 24ceeb30a416..fc9764b9f641 100644
--- a/meta/recipes-devtools/python/python3_3.12.13.bb
+++ b/meta/recipes-devtools/python/python3_3.12.13.bb
@@ -46,6 +46,7 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \
file://CVE-2026-4224.patch \
file://CVE-2026-11940.patch \
file://CVE-2026-11972.patch \
+ file://CVE-2026-9669.patch \
"
SRC_URI:append:class-native = " \
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-06 11:01 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 11:01 [scarthgap][PATCH 0/3] python3: fix CVE-2026-11940, CVE-2026-11972 and CVE-2026-9669 Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 1/3] python3: fix CVE-2026-11940 Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 2/3] python3: fix CVE-2026-11972 Benjamin Robin (Schneider Electric)
2026-07-06 11:01 ` [scarthgap][PATCH 3/3] python3: fix CVE-2026-9669 Benjamin Robin (Schneider Electric)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox