* [OE-core][scarthgap 22/33] libcap: Fix CVE-2026-4878
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Hugo SIMELIERE (Schneider Electric) <hsimeliere.opensource@witekio.com>
Pick patch from [1] as mentioned in Debian report in [2].
[1] https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=286ace1259992bd0c5d9016715833f2e148ac596
[2] https://security-tracker.debian.org/tracker/CVE-2026-4878
Signed-off-by: Hugo SIMELIERE (Schneider Electric) <hsimeliere.opensource@witekio.com>
Reviewed-by: Bruno VERNAY <bruno.vernay@se.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
.../libcap/files/CVE-2026-4878.patch | 164 ++++++++++++++++++
meta/recipes-support/libcap/libcap_2.69.bb | 1 +
2 files changed, 165 insertions(+)
create mode 100644 meta/recipes-support/libcap/files/CVE-2026-4878.patch
diff --git a/meta/recipes-support/libcap/files/CVE-2026-4878.patch b/meta/recipes-support/libcap/files/CVE-2026-4878.patch
new file mode 100644
index 00000000000..dcc63d93a54
--- /dev/null
+++ b/meta/recipes-support/libcap/files/CVE-2026-4878.patch
@@ -0,0 +1,164 @@
+From f17734c6b0f4fd102fe4f7e863cb1165f8ec66e2 Mon Sep 17 00:00:00 2001
+From: "Andrew G. Morgan" <morgan@kernel.org>
+Date: Thu, 12 Mar 2026 07:38:05 -0700
+Subject: [PATCH] Address a potential TOCTOU race condition in cap_set_file().
+
+This issue was researched and reported by Ali Raza (@locus-x64). It
+has been assigned CVE-2026-4878.
+
+The finding is that while cap_set_file() checks if a file is a regular
+file before applying or removing a capability attribute, a small
+window existed after that check when the filepath could be overwritten
+either with new content or a symlink to some other file. To do this
+would imply that the caller of cap_set_file() was directing it to a
+directory over which a local attacker has write access, and performed
+the operation frequently enough that an attacker had a non-negligible
+chance of exploiting the race condition. The code now locks onto the
+intended file, eliminating the race condition.
+
+CVE: CVE-2026-4878
+Upstream-Status: Backport [https://git.kernel.org/pub/scm/libs/libcap/libcap.git/commit/?id=286ace1259992bd0c5d9016715833f2e148ac596]
+
+Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
+(cherry picked from commit 286ace1259992bd0c5d9016715833f2e148ac596)
+Signed-off-by: Hugo SIMELIERE (Schneider Electric) <hsimeliere.opensource@witekio.com>
+---
+ libcap/cap_file.c | 69 +++++++++++++++++++++++++++++++++++++++-------
+ progs/quicktest.sh | 14 +++++++++-
+ 2 files changed, 72 insertions(+), 11 deletions(-)
+
+diff --git a/libcap/cap_file.c b/libcap/cap_file.c
+index 0bc07f7..f02bf9f 100644
+--- a/libcap/cap_file.c
++++ b/libcap/cap_file.c
+@@ -8,8 +8,13 @@
+ #define _DEFAULT_SOURCE
+ #endif
+
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
++
+ #include <sys/types.h>
+ #include <byteswap.h>
++#include <fcntl.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+
+@@ -322,26 +327,70 @@ int cap_set_file(const char *filename, cap_t cap_d)
+ struct vfs_ns_cap_data rawvfscap;
+ int sizeofcaps;
+ struct stat buf;
++ char fdpath[64];
++ int fd, ret;
++
++ _cap_debug("setting filename capabilities");
++ fd = open(filename, O_RDONLY|O_NOFOLLOW);
++ if (fd >= 0) {
++ ret = cap_set_fd(fd, cap_d);
++ close(fd);
++ return ret;
++ }
+
+- if (lstat(filename, &buf) != 0) {
+- _cap_debug("unable to stat file [%s]", filename);
++ /*
++ * Attempting to set a file capability on a file the process can't
++ * read the content of. This is considered a non-standard use case
++ * and the following (slower) code is complicated because it is
++ * trying to avoid a TOCTOU race condition.
++ */
++
++ fd = open(filename, O_PATH|O_NOFOLLOW);
++ if (fd < 0) {
++ _cap_debug("cannot find file at path [%s]", filename);
++ return -1;
++ }
++ if (fstat(fd, &buf) != 0) {
++ _cap_debug("unable to stat file [%s] descriptor %d",
++ filename, fd);
++ close(fd);
+ return -1;
+ }
+ if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
+- _cap_debug("file [%s] is not a regular file", filename);
++ _cap_debug("file [%s] descriptor %d for non-regular file",
++ filename, fd);
++ close(fd);
+ errno = EINVAL;
+ return -1;
+ }
+
+- if (cap_d == NULL) {
+- _cap_debug("removing filename capabilities");
+- return removexattr(filename, XATTR_NAME_CAPS);
++ /*
++ * While the fd remains open, this named file is locked to the
++ * origin regular file. The size of the fdpath variable is
++ * sufficient to support a 160+ bit number.
++ */
++ if (snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", fd)
++ >= sizeof(fdpath)) {
++ _cap_debug("file descriptor too large %d", fd);
++ errno = EINVAL;
++ ret = -1;
++
++ } else if (cap_d == NULL) {
++ _cap_debug("dropping file caps on [%s] via [%s]",
++ filename, fdpath);
++ ret = removexattr(fdpath, XATTR_NAME_CAPS);
++
+ } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
+- return -1;
+- }
++ _cap_debug("problem converting cap_d to vfscap format");
++ ret = -1;
+
+- _cap_debug("setting filename capabilities");
+- return setxattr(filename, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
++ } else {
++ _cap_debug("setting filename capabilities");
++ ret = setxattr(fdpath, XATTR_NAME_CAPS, &rawvfscap,
++ sizeofcaps, 0);
++ }
++ close(fd);
++ return ret;
+ }
+
+ /*
+diff --git a/progs/quicktest.sh b/progs/quicktest.sh
+index 59e16b0..bb49d53 100755
+--- a/progs/quicktest.sh
++++ b/progs/quicktest.sh
+@@ -148,7 +148,19 @@ pass_capsh --caps="cap_setpcap=p" --inh=cap_chown --current
+ pass_capsh --strict --caps="cap_chown=p" --inh=cap_chown --current
+
+ # change the way the capability is obtained (make it inheritable)
++chmod 0000 ./privileged
+ ./setcap cap_setuid,cap_setgid=ei ./privileged
++if [ $? -ne 0 ]; then
++ echo "FAILED to set file capability"
++ exit 1
++fi
++chmod 0755 ./privileged
++ln -s privileged unprivileged
++./setcap -r ./unprivileged
++if [ $? -eq 0 ]; then
++ echo "FAILED by removing a capability from a symlinked file"
++ exit 1
++fi
+
+ # Note, the bounding set (edited with --drop) only limits p
+ # capabilities, not i's.
+@@ -246,7 +258,7 @@ EOF
+ pass_capsh --iab='!%cap_chown,^cap_setpcap,cap_setuid'
+ fail_capsh --mode=PURE1E --iab='!%cap_chown,^cap_setuid'
+ fi
+-/bin/rm -f ./privileged
++/bin/rm -f ./privileged ./unprivileged
+
+ echo "testing namespaced file caps"
+
+--
+2.43.0
+
diff --git a/meta/recipes-support/libcap/libcap_2.69.bb b/meta/recipes-support/libcap/libcap_2.69.bb
index 03975b44a0a..43185f027ea 100644
--- a/meta/recipes-support/libcap/libcap_2.69.bb
+++ b/meta/recipes-support/libcap/libcap_2.69.bb
@@ -16,6 +16,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/libs/security/linux-privs/${BPN}2/${BPN}-${
file://0001-ensure-the-XATTR_NAME_CAPS-is-defined-when-it-is-use.patch \
file://0002-tests-do-not-run-target-executables.patch \
file://CVE-2025-1390.patch \
+ file://CVE-2026-4878.patch \
"
SRC_URI:append:class-nativesdk = " \
file://0001-nativesdk-libcap-Raise-the-size-of-arrays-containing.patch \
^ permalink raw reply related
* [OE-core][scarthgap 12/33] bzip2: fix 'bzip2 --version > /tmp/aaa 2>&1' hang
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Hongxu Jia <hongxu.jia@windriver.com>
According to [1]
As of the current version 1.0.8, bzip2 --version will print version
info but it will also continue compressing stdin:
$ ./bzip2 --version
bzip2, a block-sorting file compressor. Version 1.0.8, 13-Jul-2019.
Copyright (C) 1996-2019 by Julian Seward.
This program is free software; [...]
bzip2: I won't write compressed data to a terminal.
bzip2: For help, type: `bzip2 --help'.
Debian (and its downstreams like Ubuntu) will patch this out [2],
making the < /dev/null unnecessary, port a part of debian patch
to fix the issue
[1] https://stackoverflow.com/questions/59757176/why-using-dev-null-with-a-program-like-bzip2
[2] https://sources.debian.org/src/bzip2/1.0.8-6/debian/patches/20-legacy.patch/
Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit ae4fe4263ba9d372f9b9e80df4ec4697b51c1f9b)
Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
...-fix-bzip2-version-tmp-aaa-will-hang.patch | 62 +++++++++++++++++++
meta/recipes-extended/bzip2/bzip2_1.0.8.bb | 1 +
2 files changed, 63 insertions(+)
create mode 100644 meta/recipes-extended/bzip2/bzip2/0001-fix-bzip2-version-tmp-aaa-will-hang.patch
diff --git a/meta/recipes-extended/bzip2/bzip2/0001-fix-bzip2-version-tmp-aaa-will-hang.patch b/meta/recipes-extended/bzip2/bzip2/0001-fix-bzip2-version-tmp-aaa-will-hang.patch
new file mode 100644
index 00000000000..84206b2a4d0
--- /dev/null
+++ b/meta/recipes-extended/bzip2/bzip2/0001-fix-bzip2-version-tmp-aaa-will-hang.patch
@@ -0,0 +1,62 @@
+From a9dd6acbaca836fc4e943e69a31b2e7acda32045 Mon Sep 17 00:00:00 2001
+From: Hongxu Jia <hongxu.jia@windriver.com>
+Date: Wed, 13 Nov 2024 19:49:23 +0800
+Subject: [PATCH] fix 'bzip2 --version > /tmp/aaa 2>&1' hang
+
+According to [1]
+
+As of the current version 1.0.8, bzip2 --version will print version
+info but it will also continue compressing stdin:
+
+ $ ./bzip2 --version
+ bzip2, a block-sorting file compressor. Version 1.0.8, 13-Jul-2019.
+
+ Copyright (C) 1996-2019 by Julian Seward.
+
+ This program is free software; [...]
+
+ bzip2: I won't write compressed data to a terminal.
+ bzip2: For help, type: `bzip2 --help'.
+
+Debian (and its downstreams like Ubuntu) will patch this out [2],
+making the < /dev/null unnecessary:
+
+[1] https://stackoverflow.com/questions/59757176/why-using-dev-null-with-a-program-like-bzip2
+[2] https://sources.debian.org/src/bzip2/1.0.8-6/debian/patches/20-legacy.patch/
+
+Upstream-Status: Submitted [bzip2-devel@sourceware.org]
+
+Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
+---
+ bzip2.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/bzip2.c b/bzip2.c
+index d95d280..6ec9871 100644
+--- a/bzip2.c
++++ b/bzip2.c
+@@ -1890,7 +1890,9 @@ IntNative main ( IntNative argc, Char *argv[] )
+ case '8': blockSize100k = 8; break;
+ case '9': blockSize100k = 9; break;
+ case 'V':
+- case 'L': license(); break;
++ case 'L': license();
++ exit ( 0 );
++ break;
+ case 'v': verbosity++; break;
+ case 'h': usage ( progName );
+ exit ( 0 );
+@@ -1916,8 +1918,8 @@ IntNative main ( IntNative argc, Char *argv[] )
+ if (ISFLAG("--keep")) keepInputFiles = True; else
+ if (ISFLAG("--small")) smallMode = True; else
+ if (ISFLAG("--quiet")) noisy = False; else
+- if (ISFLAG("--version")) license(); else
+- if (ISFLAG("--license")) license(); else
++ if (ISFLAG("--version")) { license(); exit ( 0 ); } else
++ if (ISFLAG("--license")) { license(); exit ( 0 ); } else
+ if (ISFLAG("--exponential")) workFactor = 1; else
+ if (ISFLAG("--repetitive-best")) redundant(aa->name); else
+ if (ISFLAG("--repetitive-fast")) redundant(aa->name); else
+--
+2.34.1
+
diff --git a/meta/recipes-extended/bzip2/bzip2_1.0.8.bb b/meta/recipes-extended/bzip2/bzip2_1.0.8.bb
index b661bc95465..6c02dc3ed06 100644
--- a/meta/recipes-extended/bzip2/bzip2_1.0.8.bb
+++ b/meta/recipes-extended/bzip2/bzip2_1.0.8.bb
@@ -27,6 +27,7 @@ SRC_URI = "https://sourceware.org/pub/${BPN}/${BPN}-${PV}.tar.gz \
file://Makefile.am;subdir=${BP} \
file://run-ptest \
file://CVE-2026-42250.patch;subdir=${BP} \
+ file://0001-fix-bzip2-version-tmp-aaa-will-hang.patch;subdir=${BP} \
"
SRC_URI[md5sum] = "67e051268d0c475ea773822f7500d0e5"
SRC_URI[sha256sum] = "ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269"
^ permalink raw reply related
* [OE-core][scarthgap 19/33] tzdata/tzcode-native: upgrade 2026b -> 2026c
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Vijay Anusuri <vanusuri@mvista.com>
This release contains the following changes:
Briefly:
Alberta moved to permanent -06 on 2026-06-18.
Morocco moves to permanent +00 on 2026-09-20.
More integer overflow bugs have been fixed in zic.
Changes to future timestamps
Alberta’s 2026-03-08 spring forward was its last foreseeable clock
change, as it moved to permanent -06 thereafter. (Thanks to Roozbeh
Pournader and others.) Model this with its traditional abbreviation
CST. Although the change to permanent -06 legally took place on
2026-06-18, temporarily model the change to occur on 2026-11-01 at
02:00 instead, for the same reason we introduced a similarly
temporary hack for British Columbia in 2026b.
Although another TZDB release will likely be needed soon because
Northwest Territories will likely follow Alberta, the legal
formalities have not yet taken place.
Morocco plans to move back to permanent UTC, without daylight
saving time transitions, on 2026-09-20 at 02:00. This also
affects Western Sahara.
Changes to code
zic no longer overflows integers when processing outlandish input
like ‘Zone Ouch 0 - LMT 9223372036854775807’, ‘Zone Ouch 0
2562047788015215 LMT’, ‘Zone Ouch -2562047788015215:30:08 - LMT’,
and ‘Zone Ouch -2562047788015215:30:08 - %%z’. This avoids
undefined behavior in C. (Problems reported by Naveed Khan.)
On platforms that have EFTYPE, tzalloc now fails with errno set to
EFTYPE, not EINVAL, if it detects that the TZif file has an
invalid format or is not a regular file. Formerly it did this
only on NetBSD, and only when the file was not a regular file.
Unprivileged programs no longer require TZif files to be regular
files or reject relative names containing ".." components. This
reverts to the more-permissive 2025b behavior, as the stricter
behavior did not catch on in FreeBSD.
zic now reports any failure to remove a temporary file when
cleaning up after a previous failure. (Problem reported by Tom
Lane.)
Changes to commentary
Northwest Territories is expected to move to permanent -06 prior to
2026-11-01 02:00, when clocks would otherwise fall back. (Thanks to
Tim Parenti and James Bellaire.) Model this with its traditional
abbreviation CST. Unfortunately the change is not yet official, so
it is currently present only as comments that can be uncommented as
needed.
Changes to build procedure
The undocumented ‘typecheck’ Makefile check rule has been removed.
It stopped working in 2025a and evidently nobody noticed.
The rule was superseded by ‘check_time_t_alternatives’ in 2013d.
Ref: https://lists.iana.org/hyperkitty/list/tz-announce@iana.org/thread/NVHSX2PAQIT44U5FCCEVNJJYXQMMTJSA/
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 33a7e1170b0c8ba83cdb4c7d6d9f83f6c194baed)
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/recipes-extended/timezone/timezone.inc | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/meta/recipes-extended/timezone/timezone.inc b/meta/recipes-extended/timezone/timezone.inc
index a4774370662..4271b306486 100644
--- a/meta/recipes-extended/timezone/timezone.inc
+++ b/meta/recipes-extended/timezone/timezone.inc
@@ -6,7 +6,7 @@ SECTION = "base"
LICENSE = "PD & BSD-3-Clause"
LIC_FILES_CHKSUM = "file://LICENSE;md5=c679c9d6b02bc2757b3eaf8f53c43fba"
-PV = "2026b"
+PV = "2026c"
SRC_URI =" http://www.iana.org/time-zones/repository/releases/tzcode${PV}.tar.gz;name=tzcode;subdir=tz \
http://www.iana.org/time-zones/repository/releases/tzdata${PV}.tar.gz;name=tzdata;subdir=tz \
@@ -16,5 +16,5 @@ S = "${WORKDIR}/tz"
UPSTREAM_CHECK_URI = "http://www.iana.org/time-zones"
-SRC_URI[tzcode.sha256sum] = "37e9ed8427f5d3521c22fc58e293cbfb043d70eedf1003870b33f363f61ca344"
-SRC_URI[tzdata.sha256sum] = "114543d9f19a6bfeb5bca43686aea173d38755a3db1f2eec112647ae92c6f544"
+SRC_URI[tzcode.sha256sum] = "b1cffc3ace4c4c7cd0efba2f7add86ec3d0b79da48bcf03582671fd3c8feace8"
+SRC_URI[tzdata.sha256sum] = "e4a178a4477f3d0ea77cc31828ff72aa38feff8d61aa13e7e99e142e9d902be4"
^ permalink raw reply related
* [OE-core][scarthgap 18/33] util-linux: fix CVE-2026-13595
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Deepak Rathore <deeratho@cisco.com>
This patch applies the upstream stable/v2.41 backport for
CVE-2026-13595. The upstream fix merge or commit is referenced in [1],
and the public CVE advisory is referenced in [2]. The individual
backported commit links are recorded in the embedded patch headers
when the fix expands to multiple commits.
[1] https://github.com/util-linux/util-linux/commit/132d9c8aa15a8efd0a23d8ca7ed8b98f365e84fa
[2] https://access.redhat.com/security/cve/CVE-2026-13595
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/recipes-core/util-linux/util-linux.inc | 1 +
.../util-linux/CVE-2026-13595.patch | 157 ++++++++++++++++++
2 files changed, 158 insertions(+)
create mode 100644 meta/recipes-core/util-linux/util-linux/CVE-2026-13595.patch
diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc
index 83804196345..753d032976d 100644
--- a/meta/recipes-core/util-linux/util-linux.inc
+++ b/meta/recipes-core/util-linux/util-linux.inc
@@ -47,6 +47,7 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin
file://CVE-2025-14104-01.patch \
file://CVE-2025-14104-02.patch \
file://CVE-2026-27456.patch \
+ file://CVE-2026-13595.patch \
"
SRC_URI[sha256sum] = "7b6605e48d1a49f43cc4b4cfc59f313d0dd5402fa40b96810bd572e167dfed0f"
diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2026-13595.patch b/meta/recipes-core/util-linux/util-linux/CVE-2026-13595.patch
new file mode 100644
index 00000000000..36e8658f69b
--- /dev/null
+++ b/meta/recipes-core/util-linux/util-linux/CVE-2026-13595.patch
@@ -0,0 +1,157 @@
+From faf717ca4ed3b603eb213915fe15c6804c4b92d4 Mon Sep 17 00:00:00 2001
+From: Karel Zak <kzak@redhat.com>
+Date: Thu, 7 May 2026 12:50:48 +0200
+Subject: [PATCH] libblkid: fix use-after-free in nested partition probing
+
+The partitions list stores partitions in a contiguous array grown by
+realloc(). When the array is reallocated to a new address, all
+existing blkid_partition pointers (tab->parent, ls->next_parent, local
+parent variables in nested probers) become dangling.
+
+Fix this by changing the storage from an array of structs to an array
+of pointers, where each partition is individually allocated via
+calloc(). This makes all blkid_partition pointers stable across
+reallocations -- only the pointer array itself may move, which is
+harmless since no code caches pointers into the pointer array.
+
+This eliminates the need for callers to re-fetch parent pointers after
+every blkid_partlist_add_partition() call.
+
+CVE: CVE-2026-13595
+Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/132d9c8aa15a8efd0a23d8ca7ed8b98f365e84fa]
+
+Backport Changes:
+- Scarthgap util-linux 2.39.3 still uses realloc() at this allocation site,
+ so this backport keeps realloc() and changes only the element size to
+ sizeof(*ls->parts) instead of adopting upstream's reallocarray() style.
+- The commit text was adjusted from reallocarray() to realloc() to match the
+ target source context.
+
+Reported-by: Thai Duong <thaidn@gmail.com>
+Signed-off-by: Karel Zak <kzak@redhat.com>
+(cherry picked from commit c0186f14fbdb02f64c8e0ba701ce727ea764ff4c)
+(cherry picked from commit 132d9c8aa15a8efd0a23d8ca7ed8b98f365e84fa)
+Signed-off-by: Deepak Rathore <deeratho@cisco.com>
+---
+ libblkid/src/partitions/partitions.c | 36 ++++++++++++++++++----------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+diff --git a/libblkid/src/partitions/partitions.c b/libblkid/src/partitions/partitions.c
+index 8ebf480f5..6089028a8 100644
+--- a/libblkid/src/partitions/partitions.c
++++ b/libblkid/src/partitions/partitions.c
+@@ -197,7 +197,7 @@ struct blkid_struct_partlist {
+
+ int nparts; /* number of partitions */
+ int nparts_max; /* max.number of partitions */
+- blkid_partition parts; /* array of partitions */
++ blkid_partition *parts; /* array of pointers to partitions */
+
+ struct list_head l_tabs; /* list of partition tables */
+ };
+@@ -356,13 +356,16 @@ static void reset_partlist(blkid_partlist ls)
+ free_parttables(ls);
+
+ if (ls->next_partno) {
+- /* already initialized - reset */
+- int tmp_nparts = ls->nparts_max;
+- blkid_partition tmp_parts = ls->parts;
++ /* already initialized - free individually allocated partitions */
++ int i, tmp_nparts_max = ls->nparts_max;
++ blkid_partition *tmp_parts = ls->parts;
++
++ for (i = 0; i < ls->nparts; i++)
++ free(ls->parts[i]);
+
+ memset(ls, 0, sizeof(struct blkid_struct_partlist));
+
+- ls->nparts_max = tmp_nparts;
++ ls->nparts_max = tmp_nparts_max;
+ ls->parts = tmp_parts;
+ }
+
+@@ -397,6 +400,7 @@ static void partitions_free_data(blkid_probe pr __attribute__((__unused__)),
+ void *data)
+ {
+ blkid_partlist ls = (blkid_partlist) data;
++ int i;
+
+ if (!ls)
+ return;
+@@ -404,6 +408,8 @@ static void partitions_free_data(blkid_probe pr __attribute__((__unused__)),
+ free_parttables(ls);
+
+ /* deallocate partitions and partlist */
++ for (i = 0; i < ls->nparts; i++)
++ free(ls->parts[i]);
+ free(ls->parts);
+ free(ls);
+ }
+@@ -436,16 +442,18 @@ static blkid_partition new_partition(blkid_partlist ls, blkid_parttable tab)
+ /* Linux kernel has DISK_MAX_PARTS=256, but it's too much for
+ * generic Linux machine -- let start with 32 partitions.
+ */
+- void *tmp = realloc(ls->parts, (ls->nparts_max + 32) *
+- sizeof(struct blkid_struct_partition));
++ void *tmp = realloc(ls->parts, (ls->nparts_max + 32) *
++ sizeof(*ls->parts));
+ if (!tmp)
+ return NULL;
+ ls->parts = tmp;
+ ls->nparts_max += 32;
+ }
+
+- par = &ls->parts[ls->nparts++];
+- memset(par, 0, sizeof(struct blkid_struct_partition));
++ par = calloc(1, sizeof(struct blkid_struct_partition));
++ if (!par)
++ return NULL;
++ ls->parts[ls->nparts++] = par;
+
+ ref_parttable(tab);
+ par->tab = tab;
+@@ -849,7 +857,7 @@ int blkid_probe_is_covered_by_pt(blkid_probe pr,
+
+ /* check if the partition table fits into the device */
+ for (i = 0; i < nparts; i++) {
+- blkid_partition par = &ls->parts[i];
++ blkid_partition par = ls->parts[i];
+
+ if (par->start + par->size > (pr->size >> 9)) {
+ DBG(LOWPROBE, ul_debug("partition #%d overflows "
+@@ -861,7 +869,7 @@ int blkid_probe_is_covered_by_pt(blkid_probe pr,
+
+ /* check if the requested area is covered by PT */
+ for (i = 0; i < nparts; i++) {
+- blkid_partition par = &ls->parts[i];
++ blkid_partition par = ls->parts[i];
+
+ if (start >= par->start && end <= par->start + par->size) {
+ rc = 1;
+@@ -960,7 +968,7 @@ blkid_partition blkid_partlist_get_partition(blkid_partlist ls, int n)
+ if (n < 0 || n >= ls->nparts)
+ return NULL;
+
+- return &ls->parts[n];
++ return ls->parts[n];
+ }
+
+ blkid_partition blkid_partlist_get_partition_by_start(blkid_partlist ls, uint64_t start)
+@@ -1072,7 +1080,7 @@ blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno
+ * and an entry in partition table.
+ */
+ for (i = 0; i < ls->nparts; i++) {
+- blkid_partition par = &ls->parts[i];
++ blkid_partition par = ls->parts[i];
+
+ if (partno != blkid_partition_get_partno(par))
+ continue;
+@@ -1088,7 +1096,7 @@ blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno
+ DBG(LOWPROBE, ul_debug("searching by offset/size"));
+
+ for (i = 0; i < ls->nparts; i++) {
+- blkid_partition par = &ls->parts[i];
++ blkid_partition par = ls->parts[i];
+
+ if ((uint64_t)blkid_partition_get_start(par) == start &&
+ (uint64_t)blkid_partition_get_size(par) == size)
^ permalink raw reply related
* [OE-core][scarthgap 20/33] expat: patch CVE-2026-41080
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Peter Marko <peter.marko@siemens.com>
Pick github PR [1] mentioned in [2].
* 969af8f4654ce50d837bb9199a73d1d02d2c7e16..4ba09dc471b39a78d77e5179d0243186c0c4ff7a
* dropped code which doesn't exist in 2.6.4 yet (github actions, map
file)
* resolved minor conflicts (formatting)
* picked 2 additional commits to apply the code cleanly
[1] https://github.com/libexpat/libexpat/pull/1183
[2] https://security-tracker.debian.org/tracker/CVE-2026-41080
Signed-off-by: Peter Marko <peter.marko@siemens.com>
[YC: See discussion :
https://lore.kernel.org/openembedded-core/2030b4435c8bc81bb4452637c0517ac33ab94d20.camel@pbarker.dev/T/#m56c5da4033c2f3571027c2745431178064ea1b5d ]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
.../expat/expat/CVE-2026-41080-01.patch | 50 ++
.../expat/expat/CVE-2026-41080-02.patch | 29 ++
.../expat/expat/CVE-2026-41080-03.patch | 467 ++++++++++++++++++
meta/recipes-core/expat/expat_2.6.4.bb | 3 +
4 files changed, 549 insertions(+)
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-41080-01.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-41080-02.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-41080-03.patch
diff --git a/meta/recipes-core/expat/expat/CVE-2026-41080-01.patch b/meta/recipes-core/expat/expat/CVE-2026-41080-01.patch
new file mode 100644
index 00000000000..0c6af75a5de
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-41080-01.patch
@@ -0,0 +1,50 @@
+From fe04a7f0ff8afe57ba33d919f368b1ba23bcda92 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Sun, 30 Mar 2025 19:26:55 +0200
+Subject: [PATCH 1/3] lib/xmlparse.c: Address clang-tidy warning
+ misc-no-recursion
+
+CVE: CVE-2026-41080
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/fe04a7f0ff8afe57ba33d919f368b1ba23bcda92]
+Signed-off-by: Peter Marko <peter.marko@siemens.com>
+---
+ lib/xmlparse.c | 17 ++++++++++-------
+ 1 file changed, 10 insertions(+), 7 deletions(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 9bc67f38..cb25c37b 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -1243,9 +1243,10 @@ generate_hash_secret_salt(XML_Parser parser) {
+
+ static unsigned long
+ get_hash_secret_salt(XML_Parser parser) {
+- if (parser->m_parentParser != NULL)
+- return get_hash_secret_salt(parser->m_parentParser);
+- return parser->m_hash_secret_salt;
++ const XML_Parser rootParser = getRootParserOf(parser, NULL);
++ assert(! rootParser->m_parentParser);
++
++ return rootParser->m_hash_secret_salt;
+ }
+
+ static enum XML_Error
+@@ -2321,12 +2322,14 @@ int XMLCALL
+ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
+ if (parser == NULL)
+ return 0;
+- if (parser->m_parentParser)
+- return XML_SetHashSalt(parser->m_parentParser, hash_salt);
++
++ const XML_Parser rootParser = getRootParserOf(parser, NULL);
++ assert(! rootParser->m_parentParser);
++
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+- if (parserBusy(parser))
++ if (parserBusy(rootParser))
+ return 0;
+- parser->m_hash_secret_salt = hash_salt;
++ rootParser->m_hash_secret_salt = hash_salt;
+ return 1;
+ }
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-41080-02.patch b/meta/recipes-core/expat/expat/CVE-2026-41080-02.patch
new file mode 100644
index 00000000000..953f93c68a9
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-41080-02.patch
@@ -0,0 +1,29 @@
+From 7fb2c7a454edc9e2880073a27f899c31d9b078ce Mon Sep 17 00:00:00 2001
+From: Atrem Borovik <polzovatellllk@gmail.com>
+Date: Sat, 20 Dec 2025 13:22:16 +0300
+Subject: [PATCH 2/3] WASI: remove getpid
+
+CVE: CVE-2026-41080
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/7fb2c7a454edc9e2880073a27f899c31d9b078ce]
+Signed-off-by: Peter Marko <peter.marko@siemens.com>
+---
+ lib/xmlparse.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index cb25c37b..1bafb948 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -1228,8 +1228,11 @@ generate_hash_secret_salt(XML_Parser parser) {
+ # endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
+ /* .. and self-made low quality for backup: */
+
++ entropy = gather_time_entropy();
++# if ! defined(__wasi__)
+ /* Process ID is 0 bits entropy if attacker has local access */
+- entropy = gather_time_entropy() ^ getpid();
++ entropy ^= getpid();
++# endif
+
+ /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
+ if (sizeof(unsigned long) == 4) {
diff --git a/meta/recipes-core/expat/expat/CVE-2026-41080-03.patch b/meta/recipes-core/expat/expat/CVE-2026-41080-03.patch
new file mode 100644
index 00000000000..4d17f1a0b0e
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-41080-03.patch
@@ -0,0 +1,467 @@
+From b77ab600e1893fdcfc3868d0a46efcc87c87943d Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Wed, 8 Apr 2026 15:41:54 +0200
+Subject: [PATCH 3/3] [CVE-2026-41080] Improve protection against hash flooding
+ (fixes #47)
+
+Fixes #47
+
+CVE: CVE-2026-41080
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1183]
+Signed-off-by: Peter Marko <peter.marko@siemens.com>
+---
+ Changes | 16 ++++++
+ doc/reference.html | 51 ++++++++++++++--
+ lib/expat.h | 12 ++++
+ lib/internal.h | 2 +
+ lib/xmlparse.c | 118 ++++++++++++++++++++++++++------------
+ tests/basic_tests.c | 25 ++++++++
+ 6 files changed, 181 insertions(+), 43 deletions(-)
+
+diff --git a/Changes b/Changes
+index 4265d608..1d87d6a0 100644
+--- a/Changes
++++ b/Changes
+@@ -30,6 +30,22 @@
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+ Patches:
++ Security fixes:
++ #47 #1183 CVE-2026-41080 -- The existing hash flooding protection
++ (based on SipHash) only used 4 to 8 bytes of entropy for
++ a salt, when 16 bytes of salt are supported by the
++ implementation of SipHash used by Expat. Now full 16 bytes
++ of entropy are used to improve protection against hash
++ flooding attacks.
++ Existing API function XML_SetHashSalt is now deprecated
++ because of its limitations, and its use should be
++ considered a vulnerability. Please either use the new API
++ function XML_SetHashSalt16Bytes (with known-high-quality
++ entropy input only!) instead, or leave the derivation of
++ a 16-bytes hash salt from high quality entropy to Expat's
++ internal machinery (by *not* calling either of the two
++ XML_SetHashSalt* functions).
++
+ Security fixes:
+ #1018 #1034 CVE-2025-59375 -- Disallow use of disproportional amounts of
+ dynamic memory from within an Expat parser (e.g. previously
+diff --git a/doc/reference.html b/doc/reference.html
+index 8f14b011..7f374f84 100644
+--- a/doc/reference.html
++++ b/doc/reference.html
+@@ -174,7 +174,8 @@ interface.</p>
+ <li><a href="#XML_GetAttributeInfo">XML_GetAttributeInfo</a></li>
+ <li><a href="#XML_SetEncoding">XML_SetEncoding</a></li>
+ <li><a href="#XML_SetParamEntityParsing">XML_SetParamEntityParsing</a></li>
+- <li><a href="#XML_SetHashSalt">XML_SetHashSalt</a></li>
++ <li><a href="#XML_SetHashSalt">XML_SetHashSalt</a> (deprecated)</li>
++ <li><a href="#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></li>
+ <li><a href="#XML_UseForeignDTD">XML_UseForeignDTD</a></li>
+ <li><a href="#XML_SetReturnNSTriplet">XML_SetReturnNSTriplet</a></li>
+ <li><a href="#XML_DefaultCurrent">XML_DefaultCurrent</a></li>
+@@ -2553,10 +2554,10 @@ The choices for <code>code</code> are:
+ no effect and will always return 0.
+ </div>
+
+-<h4 id="XML_SetHashSalt">XML_SetHashSalt</h4>
++<h4 id="XML_SetHashSalt">XML_SetHashSalt (deprecated)</h4>
+ <pre class="fcndec">
+ int XMLCALL
+-XML_SetHashSalt(XML_Parser p,
++XML_SetHashSalt(XML_Parser parser,
+ unsigned long hash_salt);
+ </pre>
+ <div class="fcndef">
+@@ -2564,15 +2565,55 @@ Sets the hash salt to use for internal hash calculations.
+ Helps in preventing DoS attacks based on predicting hash
+ function behavior. In order to have an effect this must be called
+ before parsing has started. Returns 1 if successful, 0 when called
+-after <code>XML_Parse</code> or <code>XML_ParseBuffer</code>.
++after <code>XML_Parse</code> or <code>XML_ParseBuffer</code> or when
++ <code>parser</code> is <code>NULL</code>.
++ <p>
++ <b>Note:</b> Function <code>XML_SetHashSalt</code> is
++ <strong>deprecated</strong>. Please use function <code><a href=
++ "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code> instead for better
++ security. <code>XML_SetHashSalt</code> only provides 4 to 8 bytes of entropy
++ (depending on the size of type <code>unsigned long</code>) while the SipHash
++ implementation used by Expat can leverage up to 16 bytes of entropy — at least
++ twice as much. Function <code><a href=
++ "#XML_SetHashSalt16Bytes">XML_SetHashSalt16Bytes</a></code> of Expat >=2.7.6
++ (and where backported) matches the amount of entropy supported by SipHash.
++ </p>.
+ <p><b>Note:</b> This call is optional, as the parser will auto-generate
+-a new random salt value if no value has been set at the start of parsing.</p>
++a new random salt value internally if no value has been set by the start of parsing.</p>
+ <p><b>Note:</b> One should not call <code>XML_SetHashSalt</code> with a
+ hash salt value of 0, as this value is used as sentinel value to indicate
+ that <code>XML_SetHashSalt</code> has <b>not</b> been called. Consequently
+ such a call will have no effect, even if it returns 1.</p>
+ </div>
+
++ <h4 id="XML_SetHashSalt16Bytes">
++ XML_SetHashSalt16Bytes
++ </h4>
++
++ <pre class="fcndec">
++/* Added in Expat 2.7.6. */
++XML_Bool XMLCALL
++XML_SetHashSalt16Bytes(XML_Parser parser,
++ const uint8_t entropy[16]);
++</pre>
++ <div class="fcndef">
++ Sets the hash salt to use for internal hash calculations. Helps in preventing DoS
++ attacks based on predicting hash function behavior. In order to have an effect
++ this must be called before parsing has started. Returns <code>XML_TRUE</code> if
++ successful, <code>XML_FALSE</code> when called after <code>XML_Parse</code> or
++ <code>XML_ParseBuffer</code> or when <code>parser</code> is <code>NULL</code>.
++ <p>
++ <b>Note:</b> Setting a salt that is <em>not</em> from a source of high quality
++ entropy (like <code>getentropy(3)</code>) will make the parser vulnerable to
++ hash flooding attacks.
++ </p>
++
++ <p>
++ <b>Note:</b> This call is optional, as the parser will auto-generate a new
++ random salt value internally if no value has been set by the start of parsing.
++ </p>
++ </div>
++
+ <h4 id="XML_UseForeignDTD">XML_UseForeignDTD</h4>
+ <pre class="fcndec">
+ enum XML_Error XMLCALL
+diff --git a/lib/expat.h b/lib/expat.h
+index df207e9e..b356e002 100644
+--- a/lib/expat.h
++++ b/lib/expat.h
+@@ -44,6 +44,7 @@
+ #ifndef Expat_INCLUDED
+ #define Expat_INCLUDED 1
+
++# include <stdint.h> // for uint8_t
+ #include <stdlib.h>
+ #include "expat_external.h"
+
+@@ -916,10 +917,21 @@ XML_SetParamEntityParsing(XML_Parser parser,
+ function behavior. This must be called before parsing is started.
+ Returns 1 if successful, 0 when called after parsing has started.
+ Note: If parser == NULL, the function will do nothing and return 0.
++ DEPRECATED since Expat 2.7.6.
+ */
+ XMLPARSEAPI(int)
+ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt);
+
++/* Sets the hash salt to use for internal hash calculations.
++ Helps in preventing DoS attacks based on predicting hash function behavior.
++ This must be called before parsing is started.
++ Returns XML_TRUE if successful, XML_FALSE when called after parsing has
++ started or when parser is NULL.
++ Added in Expat 2.7.6.
++*/
++XMLPARSEAPI(XML_Bool)
++XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]);
++
+ /* If XML_Parse or XML_ParseBuffer have returned XML_STATUS_ERROR, then
+ XML_GetErrorCode returns information about the error.
+ */
+diff --git a/lib/internal.h b/lib/internal.h
+index 32faaa05..617d6454 100644
+--- a/lib/internal.h
++++ b/lib/internal.h
+@@ -113,6 +113,7 @@
+ #if defined(_WIN32) \
+ && (! defined(__USE_MINGW_ANSI_STDIO) \
+ || (1 - __USE_MINGW_ANSI_STDIO - 1 == 0))
++# define EXPAT_FMT_LLX(midpart) "%" midpart "I64x"
+ # define EXPAT_FMT_ULL(midpart) "%" midpart "I64u"
+ # if defined(_WIN64) // Note: modifiers "td" and "zu" do not work for MinGW
+ # define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "I64d"
+@@ -122,6 +123,7 @@
+ # define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
+ # endif
+ #else
++# define EXPAT_FMT_LLX(midpart) "%" midpart "llx"
+ # define EXPAT_FMT_ULL(midpart) "%" midpart "llu"
+ # if ! defined(ULONG_MAX)
+ # error Compiler did not define ULONG_MAX for us
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 1bafb948..75a7e5d0 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -604,7 +604,7 @@ static ELEMENT_TYPE *getElementType(XML_Parser parser, const ENCODING *enc,
+
+ static XML_Char *copyString(const XML_Char *s, XML_Parser parser);
+
+-static unsigned long generate_hash_secret_salt(XML_Parser parser);
++static struct sipkey generate_hash_secret_salt(void);
+ static XML_Bool startParsing(XML_Parser parser);
+
+ static XML_Parser parserCreate(const XML_Char *encodingName,
+@@ -777,7 +777,8 @@ struct XML_ParserStruct {
+ XML_Bool m_useForeignDTD;
+ enum XML_ParamEntityParsing m_paramEntityParsing;
+ #endif
+- unsigned long m_hash_secret_salt;
++ struct sipkey m_hash_secret_salt_128;
++ XML_Bool m_hash_secret_salt_set;
+ #if XML_GE == 1
+ ACCOUNTING m_accounting;
+ MALLOC_TRACKER m_alloc_tracker;
+@@ -1189,69 +1190,65 @@ gather_time_entropy(void) {
+
+ #endif /* ! defined(HAVE_ARC4RANDOM_BUF) && ! defined(HAVE_ARC4RANDOM) */
+
+-static unsigned long
+-ENTROPY_DEBUG(const char *label, unsigned long entropy) {
++static struct sipkey
++ENTROPY_DEBUG(const char *label, struct sipkey entropy_128) {
+ if (getDebugLevel("EXPAT_ENTROPY_DEBUG", 0) >= 1u) {
+- fprintf(stderr, "expat: Entropy: %s --> 0x%0*lx (%lu bytes)\n", label,
+- (int)sizeof(entropy) * 2, entropy, (unsigned long)sizeof(entropy));
++ fprintf(stderr,
++ "expat: Entropy: %s --> [0x" EXPAT_FMT_LLX(
++ "016") ", 0x" EXPAT_FMT_LLX("016") "] (16 bytes)\n",
++ label, (unsigned long long)entropy_128.k[0],
++ (unsigned long long)entropy_128.k[1]);
+ }
+- return entropy;
++ return entropy_128;
+ }
+
+-static unsigned long
+-generate_hash_secret_salt(XML_Parser parser) {
+- unsigned long entropy;
+- (void)parser;
++static struct sipkey
++generate_hash_secret_salt(void) {
++ struct sipkey entropy;
+
+ /* "Failproof" high quality providers: */
+ #if defined(HAVE_ARC4RANDOM_BUF)
+ arc4random_buf(&entropy, sizeof(entropy));
+ return ENTROPY_DEBUG("arc4random_buf", entropy);
+ #elif defined(HAVE_ARC4RANDOM)
+- writeRandomBytes_arc4random((void *)&entropy, sizeof(entropy));
++ writeRandomBytes_arc4random(&entropy, sizeof(entropy));
+ return ENTROPY_DEBUG("arc4random", entropy);
+ #else
+ /* Try high quality providers first .. */
+ # ifdef _WIN32
+- if (writeRandomBytes_rand_s((void *)&entropy, sizeof(entropy))) {
++ if (writeRandomBytes_rand_s(&entropy, sizeof(entropy))) {
+ return ENTROPY_DEBUG("rand_s", entropy);
+ }
+ # elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+- if (writeRandomBytes_getrandom_nonblock((void *)&entropy, sizeof(entropy))) {
++ if (writeRandomBytes_getrandom_nonblock(&entropy, sizeof(entropy))) {
+ return ENTROPY_DEBUG("getrandom", entropy);
+ }
+ # endif
+ # if ! defined(_WIN32) && defined(XML_DEV_URANDOM)
+- if (writeRandomBytes_dev_urandom((void *)&entropy, sizeof(entropy))) {
++ if (writeRandomBytes_dev_urandom(&entropy, sizeof(entropy))) {
+ return ENTROPY_DEBUG("/dev/urandom", entropy);
+ }
+ # endif /* ! defined(_WIN32) && defined(XML_DEV_URANDOM) */
+ /* .. and self-made low quality for backup: */
+
+- entropy = gather_time_entropy();
++ entropy.k[0] = 0;
++ entropy.k[1] = gather_time_entropy();
+ # if ! defined(__wasi__)
+ /* Process ID is 0 bits entropy if attacker has local access */
+- entropy ^= getpid();
++ entropy.k[1] ^= getpid();
+ # endif
+
+ /* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
+ if (sizeof(unsigned long) == 4) {
+- return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
++ entropy.k[1] *= 2147483647;
++ return ENTROPY_DEBUG("fallback(4)", entropy);
+ } else {
+- return ENTROPY_DEBUG("fallback(8)",
+- entropy * (unsigned long)2305843009213693951ULL);
++ entropy.k[1] *= 2305843009213693951ULL;
++ return ENTROPY_DEBUG("fallback(8)", entropy);
+ }
+ #endif
+ }
+
+-static unsigned long
+-get_hash_secret_salt(XML_Parser parser) {
+- const XML_Parser rootParser = getRootParserOf(parser, NULL);
+- assert(! rootParser->m_parentParser);
+-
+- return rootParser->m_hash_secret_salt;
+-}
+-
+ static enum XML_Error
+ callProcessor(XML_Parser parser, const char *start, const char *end,
+ const char **endPtr) {
+@@ -1320,8 +1316,10 @@ callProcessor(XML_Parser parser, const char *start, const char *end,
+ static XML_Bool /* only valid for root parser */
+ startParsing(XML_Parser parser) {
+ /* hash functions must be initialized before setContext() is called */
+- if (parser->m_hash_secret_salt == 0)
+- parser->m_hash_secret_salt = generate_hash_secret_salt(parser);
++ if (parser->m_hash_secret_salt_set != XML_TRUE) {
++ parser->m_hash_secret_salt_128 = generate_hash_secret_salt();
++ parser->m_hash_secret_salt_set = XML_TRUE;
++ }
+ if (parser->m_ns) {
+ /* implicit context only set for root parser, since child
+ parsers (i.e. external entity parsers) will inherit it
+@@ -1609,7 +1607,9 @@ parserInit(XML_Parser parser, const XML_Char *encodingName) {
+ parser->m_useForeignDTD = XML_FALSE;
+ parser->m_paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+ #endif
+- parser->m_hash_secret_salt = 0;
++ parser->m_hash_secret_salt_128.k[0] = 0;
++ parser->m_hash_secret_salt_128.k[1] = 0;
++ parser->m_hash_secret_salt_set = XML_FALSE;
+
+ #if XML_GE == 1
+ memset(&parser->m_accounting, 0, sizeof(ACCOUNTING));
+@@ -1776,7 +1776,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+ from hash tables associated with either parser without us having
+ to worry which hash secrets each table has.
+ */
+- unsigned long oldhash_secret_salt;
++ struct sipkey oldhash_secret_salt_128;
++ XML_Bool oldhash_secret_salt_set;
+ XML_Bool oldReparseDeferralEnabled;
+
+ /* Validate the oldParser parameter before we pull everything out of it */
+@@ -1822,7 +1823,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+ from hash tables associated with either parser without us having
+ to worry which hash secrets each table has.
+ */
+- oldhash_secret_salt = parser->m_hash_secret_salt;
++ oldhash_secret_salt_128 = parser->m_hash_secret_salt_128;
++ oldhash_secret_salt_set = parser->m_hash_secret_salt_set;
+ oldReparseDeferralEnabled = parser->m_reparseDeferralEnabled;
+
+ #ifdef XML_DTD
+@@ -1877,7 +1879,8 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
+ parser->m_externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+ parser->m_defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+ parser->m_ns_triplets = oldns_triplets;
+- parser->m_hash_secret_salt = oldhash_secret_salt;
++ parser->m_hash_secret_salt_128 = oldhash_secret_salt_128;
++ parser->m_hash_secret_salt_set = oldhash_secret_salt_set;
+ parser->m_reparseDeferralEnabled = oldReparseDeferralEnabled;
+ parser->m_parentParser = oldParser;
+ #ifdef XML_DTD
+@@ -2321,6 +2324,7 @@ XML_SetParamEntityParsing(XML_Parser parser,
+ #endif
+ }
+
++// DEPRECATED since Expat 2.7.6.
+ int XMLCALL
+ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
+ if (parser == NULL)
+@@ -2332,10 +2336,46 @@ XML_SetHashSalt(XML_Parser parser, unsigned long hash_salt) {
+ /* block after XML_Parse()/XML_ParseBuffer() has been called */
+ if (parserBusy(rootParser))
+ return 0;
+- rootParser->m_hash_secret_salt = hash_salt;
++
++ rootParser->m_hash_secret_salt_128.k[0] = 0;
++ rootParser->m_hash_secret_salt_128.k[1] = hash_salt;
++
++ if (hash_salt != 0) { // to remain backwards compatible
++ rootParser->m_hash_secret_salt_set = XML_TRUE;
++
++ if (sizeof(unsigned long) == 4)
++ ENTROPY_DEBUG("explicit(4)", rootParser->m_hash_secret_salt_128);
++ else
++ ENTROPY_DEBUG("explicit(8)", rootParser->m_hash_secret_salt_128);
++ }
++
+ return 1;
+ }
+
++XML_Bool XMLCALL
++XML_SetHashSalt16Bytes(XML_Parser parser, const uint8_t entropy[16]) {
++ if (parser == NULL)
++ return XML_FALSE;
++
++ if (entropy == NULL)
++ return XML_FALSE;
++
++ const XML_Parser rootParser = getRootParserOf(parser, NULL);
++ assert(! rootParser->m_parentParser);
++
++ /* block after XML_Parse()/XML_ParseBuffer() has been called */
++ if (parserBusy(rootParser))
++ return XML_FALSE;
++
++ sip_tokey(&(rootParser->m_hash_secret_salt_128), entropy);
++
++ rootParser->m_hash_secret_salt_set = XML_TRUE;
++
++ ENTROPY_DEBUG("explicit(16)", rootParser->m_hash_secret_salt_128);
++
++ return XML_TRUE;
++}
++
+ enum XML_Status XMLCALL
+ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal) {
+ if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
+@@ -7837,8 +7877,10 @@ keylen(KEY s) {
+
+ static void
+ copy_salt_to_sipkey(XML_Parser parser, struct sipkey *key) {
+- key->k[0] = 0;
+- key->k[1] = get_hash_secret_salt(parser);
++ const XML_Parser rootParser = getRootParserOf(parser, NULL);
++ assert(! rootParser->m_parentParser);
++
++ *key = rootParser->m_hash_secret_salt_128;
+ }
+
+ static unsigned long FASTCALL
+diff --git a/tests/basic_tests.c b/tests/basic_tests.c
+index 023d9ce4..380caf19 100644
+--- a/tests/basic_tests.c
++++ b/tests/basic_tests.c
+@@ -204,6 +204,30 @@ START_TEST(test_hash_collision) {
+ END_TEST
+ #undef COLLIDING_HASH_SALT
+
++START_TEST(test_hash_salt_setter) {
++ const uint8_t entropy[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
++ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
++ XML_Parser parser = XML_ParserCreate(NULL);
++
++ // NULL parser should be rejected
++ assert_true(XML_SetHashSalt16Bytes(NULL, entropy) == XML_FALSE);
++
++ // NULL entropy should be rejected
++ assert_true(XML_SetHashSalt16Bytes(parser, NULL) == XML_FALSE);
++
++ // Setting should be allowed more than once
++ assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_TRUE);
++ assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_TRUE);
++
++ // But not after parsing has started
++ assert_true(XML_Parse(parser, "", 0, XML_FALSE /* isFinal */)
++ == XML_STATUS_OK);
++ assert_true(XML_SetHashSalt16Bytes(parser, entropy) == XML_FALSE);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
+ /* Regression test for SF bug #491986. */
+ START_TEST(test_danish_latin1) {
+ const char *text = "<?xml version='1.0' encoding='iso-8859-1'?>\n"
+@@ -6244,6 +6268,7 @@ make_basic_test_case(Suite *s) {
+ tcase_add_test(tc_basic, test_bom_utf16_le);
+ tcase_add_test(tc_basic, test_nobom_utf16_le);
+ tcase_add_test(tc_basic, test_hash_collision);
++ tcase_add_test(tc_basic, test_hash_salt_setter);
+ tcase_add_test(tc_basic, test_illegal_utf8);
+ tcase_add_test(tc_basic, test_utf8_auto_align);
+ tcase_add_test(tc_basic, test_utf16);
diff --git a/meta/recipes-core/expat/expat_2.6.4.bb b/meta/recipes-core/expat/expat_2.6.4.bb
index 151720a9e3c..f5c3e3fdd2f 100644
--- a/meta/recipes-core/expat/expat_2.6.4.bb
+++ b/meta/recipes-core/expat/expat_2.6.4.bb
@@ -51,6 +51,9 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \
file://CVE-2026-32777-02.patch \
file://CVE-2026-32778-01.patch \
file://CVE-2026-32778-02.patch \
+ file://CVE-2026-41080-01.patch \
+ file://CVE-2026-41080-02.patch \
+ file://CVE-2026-41080-03.patch \
"
GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"
^ permalink raw reply related
* [OE-core][scarthgap 21/33] expat: patch CVE-2026-45186
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Theo Gaige <tgaige.opensource@witekio.com>
Backport patches from [1] also mentioned in [2].
[1] https://github.com/libexpat/libexpat/pull/1216
[2] https://security-tracker.debian.org/tracker/CVE-2026-45186
Signed-off-by: Theo Gaige <tgaige.opensource@witekio.com>
Reviewed-by: Bruno Vernay <bruno.vernay@se.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
.../expat/expat/CVE-2026-45186-01.patch | 70 ++++
.../expat/expat/CVE-2026-45186-02.patch | 318 ++++++++++++++++++
.../expat/expat/CVE-2026-45186-03.patch | 46 +++
.../expat/expat/CVE-2026-45186-04.patch | 32 ++
.../expat/expat/CVE-2026-45186-05.patch | 32 ++
.../expat/expat/CVE-2026-45186-06.patch | 87 +++++
.../expat/expat/CVE-2026-45186-07.patch | 52 +++
meta/recipes-core/expat/expat_2.6.4.bb | 7 +
8 files changed, 644 insertions(+)
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-45186-01.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-45186-02.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-45186-03.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-45186-04.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-45186-05.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-45186-06.patch
create mode 100644 meta/recipes-core/expat/expat/CVE-2026-45186-07.patch
diff --git a/meta/recipes-core/expat/expat/CVE-2026-45186-01.patch b/meta/recipes-core/expat/expat/CVE-2026-45186-01.patch
new file mode 100644
index 00000000000..787006c0fdb
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-45186-01.patch
@@ -0,0 +1,70 @@
+From 3020144133b2d860c44f4eeacf72e5f2843235a3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
+Date: Fri, 13 Mar 2026 13:26:45 +0100
+Subject: [PATCH 1/7] Make "counting_start_element_handler" count default attrs
+
+(cherry picked from commit 0802a5892030610144b736dec6e2f63e8600fe85)
+
+CVE: CVE-2026-45186
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1216/commits/0802a5892030610144b736dec6e2f63e8600fe85]
+Signed-off-by: Theo Gaige <tgaige.opensource@witekio.com>
+---
+ tests/basic_tests.c | 8 ++++----
+ tests/handlers.c | 2 +-
+ tests/handlers.h | 1 +
+ 3 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/tests/basic_tests.c b/tests/basic_tests.c
+index 023d9ce..d6edb16 100644
+--- a/tests/basic_tests.c
++++ b/tests/basic_tests.c
+@@ -2439,9 +2439,9 @@ START_TEST(test_attributes) {
+ {XCS("id"), XCS("one")},
+ {NULL, NULL}};
+ AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
+- ElementInfo info[] = {{XCS("doc"), 3, XCS("id"), NULL},
+- {XCS("tag"), 1, NULL, NULL},
+- {NULL, 0, NULL, NULL}};
++ ElementInfo info[] = {{XCS("doc"), 3, 0, XCS("id"), NULL},
++ {XCS("tag"), 1, 0, NULL, NULL},
++ {NULL, 0, 0, NULL, NULL}};
+ info[0].attributes = doc_info;
+ info[1].attributes = tag_info;
+
+@@ -5496,7 +5496,7 @@ START_TEST(test_deep_nested_attribute_entity) {
+ (long unsigned)(N_LINES - 1));
+
+ AttrInfo doc_info[] = {{XCS("name"), XCS("deepText")}, {NULL, NULL}};
+- ElementInfo info[] = {{XCS("foo"), 1, NULL, NULL}, {NULL, 0, NULL, NULL}};
++ ElementInfo info[] = {{XCS("foo"), 1, 0, NULL, NULL}, {NULL, 0, 0, NULL, NULL}};
+ info[0].attributes = doc_info;
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+diff --git a/tests/handlers.c b/tests/handlers.c
+index e658223..9ff7b35 100644
+--- a/tests/handlers.c
++++ b/tests/handlers.c
+@@ -137,7 +137,7 @@ counting_start_element_handler(void *userData, const XML_Char *name,
+ fail("ID does not have the correct name");
+ return;
+ }
+- for (i = 0; i < info->attr_count; i++) {
++ for (i = 0; i < info->attr_count + info->default_attr_count; i++) {
+ attr = info->attributes;
+ while (attr->name != NULL) {
+ if (! xcstrcmp(atts[0], attr->name))
+diff --git a/tests/handlers.h b/tests/handlers.h
+index ac4ca94..11d45eb 100644
+--- a/tests/handlers.h
++++ b/tests/handlers.h
+@@ -88,6 +88,7 @@ typedef struct attrInfo {
+ typedef struct elementInfo {
+ const XML_Char *name;
+ int attr_count;
++ int default_attr_count;
+ const XML_Char *id_name;
+ AttrInfo *attributes;
+ } ElementInfo;
+--
+2.43.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-45186-02.patch b/meta/recipes-core/expat/expat/CVE-2026-45186-02.patch
new file mode 100644
index 00000000000..fef531a4392
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-45186-02.patch
@@ -0,0 +1,318 @@
+From ba12af3b3ffd98b9e31c3a01a20d392c89aa974e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Berkay=20Eren=20=C3=9Cr=C3=BCn?= <berkay.ueruen@siemens.com>
+Date: Fri, 13 Mar 2026 13:27:31 +0100
+Subject: [PATCH 2/7] test(attlist): Cover duplicate attribute names
+
+Co-authored-by: Sebastian Pipping <sebastian@pipping.org>
+(cherry picked from commit e569f47181c43dca5d262089e541ddf9a9c09927)
+
+CVE: CVE-2026-45186
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1216/commits/e569f47181c43dca5d262089e541ddf9a9c09927]
+Signed-off-by: Theo Gaige <tgaige.opensource@witekio.com>
+---
+ tests/basic_tests.c | 282 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 282 insertions(+)
+
+diff --git a/tests/basic_tests.c b/tests/basic_tests.c
+index d6edb16..907a458 100644
+--- a/tests/basic_tests.c
++++ b/tests/basic_tests.c
+@@ -2462,6 +2462,279 @@ START_TEST(test_attributes) {
+ }
+ END_TEST
+
++START_TEST(test_duplicate_cdata_attribute) {
++ /*
++ https://www.w3.org/TR/xml/#attdecls
++
++ Test the following statement from the linked specification:
++ When more than one definition is provided for the same attribute of a given
++ element type, the first declaration is binding and later declarations are
++ ignored.
++ */
++
++ const char *text
++ = "<!DOCTYPE doc [\n"
++ " <!ATTLIST doc attribute CDATA 'expected' attribute CDATA 'ignored'>\n"
++ "]>\n"
++ "<doc/>\n";
++ AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected")}, {NULL, NULL}};
++ ElementInfo info[]
++ = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ assert_true(parser != NULL);
++
++ ParserAndElementInfo parserAndElementInfos = {
++ parser,
++ info,
++ };
++
++ XML_SetStartElementHandler(parser, counting_start_element_handler);
++ XML_SetUserData(parser, &parserAndElementInfos);
++
++ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
++ != XML_STATUS_OK)
++ xml_failure(parser);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
++START_TEST(test_duplicate_id_attribute_1) {
++ /*
++ https://www.w3.org/TR/xml/#attdecls
++
++ Test the following statement from the linked specification:
++ When more than one definition is provided for the same attribute of a given
++ element type, the first declaration is binding and later declarations are
++ ignored.
++ */
++
++ const char *text
++ = "<!DOCTYPE doc [\n"
++ " <!ATTLIST doc identifier CDATA 'expected' identifier ID #REQUIRED>\n"
++ "]>\n"
++ "<doc/>\n";
++ AttrInfo doc_info[] = {{XCS("identifier"), XCS("expected")}, {NULL, NULL}};
++ ElementInfo info[]
++ = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ assert_true(parser != NULL);
++
++ ParserAndElementInfo parserAndElementInfos = {
++ parser,
++ info,
++ };
++
++ XML_SetStartElementHandler(parser, counting_start_element_handler);
++ XML_SetUserData(parser, &parserAndElementInfos);
++
++ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
++ != XML_STATUS_OK)
++ xml_failure(parser);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
++START_TEST(test_duplicate_id_attribute_2) {
++ /*
++ https://www.w3.org/TR/xml/#attdecls
++
++ Test the following statement from the linked specification:
++ When more than one definition is provided for the same attribute of a given
++ element type, the first declaration is binding and later declarations are
++ ignored.
++ */
++
++ const char *text
++ = "<!DOCTYPE doc [\n"
++ " <!ATTLIST doc identifier ID #REQUIRED identifier CDATA 'unexpected'>\n"
++ "]>\n"
++ "<doc/>\n";
++ AttrInfo doc_info[] = {{NULL, NULL}};
++
++ ElementInfo info[]
++ = {{XCS("doc"), 0, 0, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ assert_true(parser != NULL);
++
++ ParserAndElementInfo parserAndElementInfos = {
++ parser,
++ info,
++ };
++
++ XML_SetStartElementHandler(parser, counting_start_element_handler);
++ XML_SetUserData(parser, &parserAndElementInfos);
++
++ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
++ != XML_STATUS_OK)
++ xml_failure(parser);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
++START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl) {
++ /*
++ https://www.w3.org/TR/xml/#attdecls
++
++ Test the following statement from the linked specification:
++ When more than one AttlistDecl is provided for a given element type,
++ the contents of all those provided are merged.
++ */
++ const char *text = "<!DOCTYPE doc [\n"
++ " <!ATTLIST doc attribute CDATA 'expected'>\n"
++ " <!ATTLIST doc attribute CDATA 'ignored'>\n"
++ "]>\n"
++ "<doc/>\n";
++ AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected")}, {NULL, NULL}};
++ ElementInfo info[]
++ = {{XCS("doc"), 0, 1, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ assert_true(parser != NULL);
++
++ ParserAndElementInfo parserAndElementInfos = {
++ parser,
++ info,
++ };
++
++ XML_SetStartElementHandler(parser, counting_start_element_handler);
++ XML_SetUserData(parser, &parserAndElementInfos);
++
++ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
++ != XML_STATUS_OK)
++ xml_failure(parser);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
++START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl_2) {
++ /*
++ https://www.w3.org/TR/xml/#attdecls
++
++ Test the following statement from the linked specification:
++ When more than one AttlistDecl is provided for a given element type,
++ the contents of all those provided are merged.
++ */
++ const char *text = "<!DOCTYPE doc [\n"
++ " <!ATTLIST doc attribute CDATA 'expected_doc'>\n"
++ " <!ATTLIST tag attribute CDATA 'expected_tag'>\n"
++ " <!ATTLIST doc attribute CDATA 'ignored_doc'>\n"
++ "]>\n"
++ "<doc><tag></tag></doc>\n";
++ AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected_doc")}, {NULL, NULL}};
++ AttrInfo tag_info[] = {{XCS("attribute"), XCS("expected_tag")}, {NULL, NULL}};
++ ElementInfo info[] = {{XCS("doc"), 0, 1, NULL, doc_info},
++ {XCS("tag"), 0, 1, NULL, tag_info},
++ {NULL, 0, 0, NULL, NULL}};
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ assert_true(parser != NULL);
++
++ ParserAndElementInfo parserAndElementInfos = {
++ parser,
++ info,
++ };
++
++ XML_SetStartElementHandler(parser, counting_start_element_handler);
++ XML_SetUserData(parser, &parserAndElementInfos);
++
++ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
++ != XML_STATUS_OK)
++ xml_failure(parser);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
++START_TEST(test_duplicate_cdata_attribute_multiple_attlistdecl_3) {
++ /*
++ https://www.w3.org/TR/xml/#attdecls
++
++ Test the following statement from the linked specification:
++ When more than one AttlistDecl is provided for a given element type,
++ the contents of all those provided are merged.
++ */
++ const char *text
++ = "<!DOCTYPE doc [\n"
++ " <!ATTLIST doc attribute CDATA 'expected_doc'>\n"
++ " <!ATTLIST tag attribute CDATA 'expected_tag'>\n"
++ " <!ATTLIST doc second_attribute CDATA 'second_expected_doc' attribute CDATA 'ignored_doc'>\n"
++ "]>\n"
++ "<doc><tag></tag></doc>\n";
++ AttrInfo doc_info[] = {{XCS("attribute"), XCS("expected_doc")},
++ {XCS("second_attribute"), XCS("second_expected_doc")},
++ {NULL, NULL}};
++ AttrInfo tag_info[] = {{XCS("attribute"), XCS("expected_tag")}, {NULL, NULL}};
++ ElementInfo info[] = {{XCS("doc"), 0, 2, NULL, doc_info},
++ {XCS("tag"), 0, 1, NULL, tag_info},
++ {NULL, 0, 0, NULL, NULL}};
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ assert_true(parser != NULL);
++
++ ParserAndElementInfo parserAndElementInfos = {
++ parser,
++ info,
++ };
++
++ XML_SetStartElementHandler(parser, counting_start_element_handler);
++ XML_SetUserData(parser, &parserAndElementInfos);
++
++ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
++ != XML_STATUS_OK)
++ xml_failure(parser);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
++START_TEST(test_duplicate_id_attribute_multiple_attlistdecl) {
++ /*
++ https://www.w3.org/TR/xml/#attdecls
++
++ Test the following statement from the linked specification:
++ When more than one AttlistDecl is provided for a given element type,
++ the contents of all those provided are merged.
++ */
++ const char *text = "<!DOCTYPE doc [\n"
++ " <!ATTLIST doc identifier ID #REQUIRED>\n"
++ " <!ATTLIST tag identifier CDATA 'identifier_tag'>\n"
++ " <!ATTLIST doc identifier CDATA 'ignored'>\n"
++ "]>\n"
++ "<doc identifier='doc_identity'><tag></tag></doc>\n";
++ AttrInfo doc_info[]
++ = {{XCS("identifier"), XCS("doc_identity")}, {NULL, NULL}};
++ AttrInfo tag_info[]
++ = {{XCS("identifier"), XCS("identifier_tag")}, {NULL, NULL}};
++ ElementInfo info[] = {{XCS("doc"), 1, 0, XCS("identifier"), doc_info},
++ {XCS("tag"), 0, 1, NULL, tag_info},
++ {NULL, 0, 0, NULL, NULL}};
++
++ XML_Parser parser = XML_ParserCreate(NULL);
++ assert_true(parser != NULL);
++
++ ParserAndElementInfo parserAndElementInfos = {
++ parser,
++ info,
++ };
++
++ XML_SetStartElementHandler(parser, counting_start_element_handler);
++ XML_SetUserData(parser, &parserAndElementInfos);
++
++ if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
++ != XML_STATUS_OK)
++ xml_failure(parser);
++
++ XML_ParserFree(parser);
++}
++END_TEST
++
+ /* Test reset works correctly in the middle of processing an internal
+ * entity. Exercises some obscure code in XML_ParserReset().
+ */
+@@ -6325,6 +6598,15 @@ make_basic_test_case(Suite *s) {
+ tcase_add_test__ifdef_xml_dtd(tc_basic, test_empty_foreign_dtd);
+ tcase_add_test(tc_basic, test_set_base);
+ tcase_add_test(tc_basic, test_attributes);
++ tcase_add_test(tc_basic, test_duplicate_cdata_attribute);
++ tcase_add_test(tc_basic, test_duplicate_id_attribute_1);
++ tcase_add_test(tc_basic, test_duplicate_id_attribute_2);
++ tcase_add_test(tc_basic, test_duplicate_cdata_attribute_multiple_attlistdecl);
++ tcase_add_test(tc_basic,
++ test_duplicate_cdata_attribute_multiple_attlistdecl_2);
++ tcase_add_test(tc_basic,
++ test_duplicate_cdata_attribute_multiple_attlistdecl_3);
++ tcase_add_test(tc_basic, test_duplicate_id_attribute_multiple_attlistdecl);
+ tcase_add_test__if_xml_ge(tc_basic, test_reset_in_entity);
+ tcase_add_test(tc_basic, test_resume_invalid_parse);
+ tcase_add_test(tc_basic, test_resume_resuspended);
+--
+2.43.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-45186-03.patch b/meta/recipes-core/expat/expat/CVE-2026-45186-03.patch
new file mode 100644
index 00000000000..2afe6dbebc4
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-45186-03.patch
@@ -0,0 +1,46 @@
+From 852ab610685b45c62017556c38096d941c154963 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Mon, 20 Apr 2026 13:44:43 +0200
+Subject: [PATCH 3/7] tests: Define .attributes the first time around
+
+(cherry picked from commit 05307d352a5aa858cdda57ec53a53b597b3a4a82)
+
+CVE: CVE-2026-45186
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1216/commits/05307d352a5aa858cdda57ec53a53b597b3a4a82]
+Signed-off-by: Theo Gaige <tgaige.opensource@witekio.com>
+---
+ tests/basic_tests.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/tests/basic_tests.c b/tests/basic_tests.c
+index 907a458..b0178fc 100644
+--- a/tests/basic_tests.c
++++ b/tests/basic_tests.c
+@@ -2439,11 +2439,9 @@ START_TEST(test_attributes) {
+ {XCS("id"), XCS("one")},
+ {NULL, NULL}};
+ AttrInfo tag_info[] = {{XCS("c"), XCS("3")}, {NULL, NULL}};
+- ElementInfo info[] = {{XCS("doc"), 3, 0, XCS("id"), NULL},
+- {XCS("tag"), 1, 0, NULL, NULL},
++ ElementInfo info[] = {{XCS("doc"), 3, 0, XCS("id"), doc_info},
++ {XCS("tag"), 1, 0, NULL, tag_info},
+ {NULL, 0, 0, NULL, NULL}};
+- info[0].attributes = doc_info;
+- info[1].attributes = tag_info;
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ assert_true(parser != NULL);
+@@ -5769,8 +5767,8 @@ START_TEST(test_deep_nested_attribute_entity) {
+ (long unsigned)(N_LINES - 1));
+
+ AttrInfo doc_info[] = {{XCS("name"), XCS("deepText")}, {NULL, NULL}};
+- ElementInfo info[] = {{XCS("foo"), 1, 0, NULL, NULL}, {NULL, 0, 0, NULL, NULL}};
+- info[0].attributes = doc_info;
++ ElementInfo info[]
++ = {{XCS("foo"), 1, 0, NULL, doc_info}, {NULL, 0, 0, NULL, NULL}};
+
+ XML_Parser parser = XML_ParserCreate(NULL);
+ ParserAndElementInfo parserPlusElemenInfo = {parser, info};
+--
+2.43.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-45186-04.patch b/meta/recipes-core/expat/expat/CVE-2026-45186-04.patch
new file mode 100644
index 00000000000..f4c7733c70d
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-45186-04.patch
@@ -0,0 +1,32 @@
+From 89c6acdcd919b64014b180fadec46b0d25760832 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Mon, 13 Apr 2026 01:34:03 +0200
+Subject: [PATCH 4/7] tests: Make counting_start_element_handler enforce
+ complete attribute lists
+
+(cherry picked from commit 4176aff73840711060913e0ac6aa1168d8ba5c8d)
+
+CVE: CVE-2026-45186
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1216/commits/4176aff73840711060913e0ac6aa1168d8ba5c8d]
+Signed-off-by: Theo Gaige <tgaige.opensource@witekio.com>
+---
+ tests/handlers.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/tests/handlers.c b/tests/handlers.c
+index 9ff7b35..5e72e8b 100644
+--- a/tests/handlers.c
++++ b/tests/handlers.c
+@@ -155,6 +155,9 @@ counting_start_element_handler(void *userData, const XML_Char *name,
+ /* Remember, two entries in atts per attribute (see above) */
+ atts += 2;
+ }
++
++ // Self-test that the test case's list of expected attributes is complete
++ assert_true(atts[0] == NULL);
+ }
+
+ void XMLCALL
+--
+2.43.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-45186-05.patch b/meta/recipes-core/expat/expat/CVE-2026-45186-05.patch
new file mode 100644
index 00000000000..480f941cb6f
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-45186-05.patch
@@ -0,0 +1,32 @@
+From d352c83afaa3945c964aba74cb60a00822af96d3 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Sun, 8 Mar 2026 22:14:41 +0100
+Subject: [PATCH 5/7] lib: Extract a constant for upcoming reuse
+
+(cherry picked from commit fb35f2d2040d114f355bae8a7450942533237530)
+
+CVE: CVE-2026-45186
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1216/commits/fb35f2d2040d114f355bae8a7450942533237530]
+Signed-off-by: Theo Gaige <tgaige.opensource@witekio.com>
+---
+ lib/xmlparse.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 9bc67f3..8d3e8db 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -7708,8 +7708,9 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
+ newE->prefix = (PREFIX *)lookup(oldParser, &(newDtd->prefixes),
+ oldE->prefix->name, 0);
+ for (i = 0; i < newE->nDefaultAtts; i++) {
++ const XML_Char *const attributeName = oldE->defaultAtts[i].id->name;
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(
+- oldParser, &(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
++ oldParser, &(newDtd->attributeIds), attributeName, 0);
+ newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+ if (oldE->defaultAtts[i].value) {
+ newE->defaultAtts[i].value
+--
+2.43.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-45186-06.patch b/meta/recipes-core/expat/expat/CVE-2026-45186-06.patch
new file mode 100644
index 00000000000..d39eb91f2f1
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-45186-06.patch
@@ -0,0 +1,87 @@
+From a2c8ddb3d6f4df7af64e05bed4b3a4edeae33fd0 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Sun, 8 Mar 2026 23:05:49 +0100
+Subject: [PATCH 6/7] lib: Introduce ELEMENT_TYPE.defaultAttsNames
+
+(cherry picked from commit 7f0f1b9e70d937072d2e9e37ae9edf27784cc080)
+
+CVE: CVE-2026-45186
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1216/commits/7f0f1b9e70d937072d2e9e37ae9edf27784cc080]
+Signed-off-by: Theo Gaige <tgaige.opensource@witekio.com>
+---
+ lib/xmlparse.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 8d3e8db..4a29c18 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -388,6 +388,7 @@ typedef struct {
+ int nDefaultAtts;
+ int allocDefaultAtts;
+ DEFAULT_ATTRIBUTE *defaultAtts;
++ HASH_TABLE defaultAttsNames;
+ } ELEMENT_TYPE;
+
+ typedef struct {
+@@ -3844,6 +3845,8 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
+ sizeof(ELEMENT_TYPE));
+ if (! elementType)
+ return XML_ERROR_NO_MEMORY;
++ if (! elementType->defaultAttsNames.parser)
++ hashTableInit(&(elementType->defaultAttsNames), parser);
+ if (parser->m_ns && ! setElementTypePrefix(parser, elementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+@@ -7549,6 +7552,7 @@ dtdReset(DTD *p, XML_Parser parser) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (! e)
+ break;
++ hashTableDestroy(&(e->defaultAttsNames));
+ if (e->allocDefaultAtts != 0)
+ FREE(parser, e->defaultAtts);
+ }
+@@ -7590,6 +7594,7 @@ dtdDestroy(DTD *p, XML_Bool isDocEntity, XML_Parser parser) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (! e)
+ break;
++ hashTableDestroy(&(e->defaultAttsNames));
+ if (e->allocDefaultAtts != 0)
+ FREE(parser, e->defaultAtts);
+ }
+@@ -7683,6 +7688,10 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
+ sizeof(ELEMENT_TYPE));
+ if (! newE)
+ return 0;
++
++ if (! newE->defaultAttsNames.parser)
++ hashTableInit(&(newE->defaultAttsNames), parser);
++
+ if (oldE->nDefaultAtts) {
+ /* Detect and prevent integer overflow.
+ * The preprocessor guard addresses the "always false" warning
+@@ -7719,6 +7728,12 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
+ return 0;
+ } else
+ newE->defaultAtts[i].value = NULL;
++
++ NAMED *const nameAddedOrFound = (NAMED *)lookup(
++ parser, &(newE->defaultAttsNames), attributeName, sizeof(NAMED));
++ if (! nameAddedOrFound) {
++ return 0;
++ }
+ }
+ }
+
+@@ -8458,6 +8473,8 @@ getElementType(XML_Parser parser, const ENCODING *enc, const char *ptr,
+ sizeof(ELEMENT_TYPE));
+ if (! ret)
+ return NULL;
++ if (! ret->defaultAttsNames.parser)
++ hashTableInit(&(ret->defaultAttsNames), getRootParserOf(parser, NULL));
+ if (ret->name != name)
+ poolDiscard(&dtd->pool);
+ else {
+--
+2.43.0
+
diff --git a/meta/recipes-core/expat/expat/CVE-2026-45186-07.patch b/meta/recipes-core/expat/expat/CVE-2026-45186-07.patch
new file mode 100644
index 00000000000..26c829b5220
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2026-45186-07.patch
@@ -0,0 +1,52 @@
+From 0e4829f4be500ce687b37ec82f9650b86c8419c7 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Sun, 8 Mar 2026 23:06:29 +0100
+Subject: [PATCH 7/7] lib: Leverage ELEMENT_TYPE.defaultAttsNames for attribute
+ collision detection
+
+.. to resolve quadratic runtime behavior
+
+(cherry picked from commit 4cd4eb0683e04cd45a2ffc81a08ca2a2663994b5)
+
+CVE: CVE-2026-45186
+Upstream-Status: Backport [https://github.com/libexpat/libexpat/pull/1216/commits/4cd4eb0683e04cd45a2ffc81a08ca2a2663994b5]
+Signed-off-by: Theo Gaige <tgaige.opensource@witekio.com>
+---
+ lib/xmlparse.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/lib/xmlparse.c b/lib/xmlparse.c
+index 4a29c18..b3f0b73 100644
+--- a/lib/xmlparse.c
++++ b/lib/xmlparse.c
+@@ -7177,10 +7177,10 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
+ if (value || isId) {
+ /* The handling of default attributes gets messed up if we have
+ a default which duplicates a non-default. */
+- int i;
+- for (i = 0; i < type->nDefaultAtts; i++)
+- if (attId == type->defaultAtts[i].id)
+- return 1;
++ NAMED *const nameFound
++ = (NAMED *)lookup(parser, &(type->defaultAttsNames), attId->name, 0);
++ if (nameFound)
++ return 1;
+ if (isId && ! type->idAtt && ! attId->xmlns)
+ type->idAtt = attId;
+ }
+@@ -7227,6 +7227,12 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
+ att->isCdata = isCdata;
+ if (! isCdata)
+ attId->maybeTokenized = XML_TRUE;
++
++ NAMED *const nameAddedOrFound = (NAMED *)lookup(
++ parser, &(type->defaultAttsNames), attId->name, sizeof(NAMED));
++ if (! nameAddedOrFound)
++ return 0;
++
+ type->nDefaultAtts += 1;
+ return 1;
+ }
+--
+2.43.0
+
diff --git a/meta/recipes-core/expat/expat_2.6.4.bb b/meta/recipes-core/expat/expat_2.6.4.bb
index f5c3e3fdd2f..3581d94fac4 100644
--- a/meta/recipes-core/expat/expat_2.6.4.bb
+++ b/meta/recipes-core/expat/expat_2.6.4.bb
@@ -54,6 +54,13 @@ SRC_URI = "${GITHUB_BASE_URI}/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \
file://CVE-2026-41080-01.patch \
file://CVE-2026-41080-02.patch \
file://CVE-2026-41080-03.patch \
+ file://CVE-2026-45186-01.patch \
+ file://CVE-2026-45186-02.patch \
+ file://CVE-2026-45186-03.patch \
+ file://CVE-2026-45186-04.patch \
+ file://CVE-2026-45186-05.patch \
+ file://CVE-2026-45186-06.patch \
+ file://CVE-2026-45186-07.patch \
"
GITHUB_BASE_URI = "https://github.com/libexpat/libexpat/releases/"
^ permalink raw reply related
* [OE-core][scarthgap 15/33] vex: remove obsolete semicolon
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Peter Marko <peter.marko@siemens.com>
Usage of semicolon as separator in ROOTFS/IMAGE_*COMMAND was deprecated
long time ago.
Remove it.
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(From OE-Core rev: 311d418d22a609fb54b87bfc909bdd1861892228)
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/classes/vex.bbclass | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meta/classes/vex.bbclass b/meta/classes/vex.bbclass
index 45a15348724..eac68ca6289 100644
--- a/meta/classes/vex.bbclass
+++ b/meta/classes/vex.bbclass
@@ -229,7 +229,7 @@ python vex_write_rootfs_manifest () {
bb.plain("Image VEX JSON report stored in: %s" % manifest_name)
}
-ROOTFS_POSTPROCESS_COMMAND:prepend = "vex_write_rootfs_manifest; "
+ROOTFS_POSTPROCESS_COMMAND:prepend = "vex_write_rootfs_manifest "
do_rootfs[recrdeptask] += "do_generate_vex "
do_populate_sdk[recrdeptask] += "do_generate_vex "
^ permalink raw reply related
* [OE-core][scarthgap 13/33] dropbear: Disable DSS correctly
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Mike Crowe <mac@mcrowe.com>
Take upstream patch that stops sysoptions.h unconditionally turning
DROPBEAR_DSS back on even when it has been disabled (which is the
default).
Signed-off-by: Mike Crowe <mac@mcrowe.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
...PBEAR_DSS-is-only-forced-for-fuzzing.patch | 30 +++++++++++++++++++
.../recipes-core/dropbear/dropbear_2022.83.bb | 1 +
2 files changed, 31 insertions(+)
create mode 100644 meta/recipes-core/dropbear/dropbear/0001-Fix-so-DROPBEAR_DSS-is-only-forced-for-fuzzing.patch
diff --git a/meta/recipes-core/dropbear/dropbear/0001-Fix-so-DROPBEAR_DSS-is-only-forced-for-fuzzing.patch b/meta/recipes-core/dropbear/dropbear/0001-Fix-so-DROPBEAR_DSS-is-only-forced-for-fuzzing.patch
new file mode 100644
index 00000000000..250cbb7a6f0
--- /dev/null
+++ b/meta/recipes-core/dropbear/dropbear/0001-Fix-so-DROPBEAR_DSS-is-only-forced-for-fuzzing.patch
@@ -0,0 +1,30 @@
+From c7dfaebd5f6a4cde4198f4d2a7baabaa1f632274 Mon Sep 17 00:00:00 2001
+From: Matt Johnston <matt@ucc.asn.au>
+Date: Tue, 6 Dec 2022 22:34:11 +0800
+Subject: [PATCH] Fix so DROPBEAR_DSS is only forced for fuzzing
+
+Regression from 787391ea3b5af2acf5e3c83372510f0c79477ad7,
+was missing fuzzing conditional
+
+Upstream-Status: Backport [https://github.com/mkj/dropbear/commit/c043efb47c3173072fa636ca0da0d19875d4511f]
+Signed-off-by: Mike Crowe <mac@mcrowe.com>
+---
+ sysoptions.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sysoptions.h b/sysoptions.h
+index fb6adc7..12db59c 100644
+--- a/sysoptions.h
++++ b/sysoptions.h
+@@ -383,9 +383,11 @@
+ #endif
+
+ /* Fuzzing expects all key types to be enabled */
++#if DROPBEAR_FUZZ
+ #if defined(DROPBEAR_DSS)
+ #undef DROPBEAR_DSS
+ #endif
+ #define DROPBEAR_DSS 1
++#endif
+
+ /* no include guard for this file */
diff --git a/meta/recipes-core/dropbear/dropbear_2022.83.bb b/meta/recipes-core/dropbear/dropbear_2022.83.bb
index 93563aa3b47..d203fee34b3 100644
--- a/meta/recipes-core/dropbear/dropbear_2022.83.bb
+++ b/meta/recipes-core/dropbear/dropbear_2022.83.bb
@@ -28,6 +28,7 @@ SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \
file://0001-Handle-arbitrary-length-paths-and-commands-in-multih.patch \
file://0001-cli-runopts.c-add-missing-DROPBEAR_CLI_PUBKEY_AUTH.patch \
file://0001-Avoid-unused-variable-with-DROPBEAR_CLI_PUBKEY_AUTH-.patch \
+ file://0001-Fix-so-DROPBEAR_DSS-is-only-forced-for-fuzzing.patch \
file://CVE-2025-47203.patch \
file://CVE-2019-6111.patch \
"
^ permalink raw reply related
* [OE-core][scarthgap 16/33] rootfs: move tasks using image_list_installed_packages to postuninstall
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Peter Marko <peter.marko@siemens.com>
Since some packages can be uninstalled, any task querying installed
packages should be run only after both installation and uninstallation
is completed.
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(From OE-Core rev: c3097962ac925538e99b17b771c541950a8b8c26)
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/classes-recipe/license_image.bbclass | 2 +-
meta/classes/vex.bbclass | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/meta/classes-recipe/license_image.bbclass b/meta/classes-recipe/license_image.bbclass
index b18a64d2bc3..e934c74d246 100644
--- a/meta/classes-recipe/license_image.bbclass
+++ b/meta/classes-recipe/license_image.bbclass
@@ -294,7 +294,7 @@ def get_deployed_files(man_file):
dep_files.append(os.path.basename(f))
return dep_files
-ROOTFS_POSTPROCESS_COMMAND:prepend = "write_package_manifest license_create_manifest "
+ROOTFS_POSTUNINSTALL_COMMAND:prepend = "write_package_manifest license_create_manifest "
do_rootfs[recrdeptask] += "do_populate_lic"
python do_populate_lic_deploy() {
diff --git a/meta/classes/vex.bbclass b/meta/classes/vex.bbclass
index eac68ca6289..97213ea3497 100644
--- a/meta/classes/vex.bbclass
+++ b/meta/classes/vex.bbclass
@@ -229,7 +229,7 @@ python vex_write_rootfs_manifest () {
bb.plain("Image VEX JSON report stored in: %s" % manifest_name)
}
-ROOTFS_POSTPROCESS_COMMAND:prepend = "vex_write_rootfs_manifest "
+ROOTFS_POSTUNINSTALL_COMMAND:prepend = "vex_write_rootfs_manifest "
do_rootfs[recrdeptask] += "do_generate_vex "
do_populate_sdk[recrdeptask] += "do_generate_vex "
^ permalink raw reply related
* [OE-core][scarthgap 17/33] gzip: fix CVE-2026-41992
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
Backport upstream fix for a global buffer overflow in the LZH
decompression logic (unlzh.c). The left[] and right[] global arrays
shared across LZW and LZH decompression routines are not reinitialized
between files processed in the same invocation, allowing an
out-of-bounds read in the LZH decoder.
Adapted for gzip 1.13:
- Refreshed NEWS and THANKS hunks to match 1.13 release context.
Reference: https://nvd.nist.gov/vuln/detail/CVE-2026-41992
Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit deaaaacabbf8d21fb9271e3f6f83055893510cff)
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
.../gzip/gzip-1.13/CVE-2026-41992.patch | 64 +++++++++++++++++++
meta/recipes-extended/gzip/gzip_1.13.bb | 1 +
2 files changed, 65 insertions(+)
create mode 100644 meta/recipes-extended/gzip/gzip-1.13/CVE-2026-41992.patch
diff --git a/meta/recipes-extended/gzip/gzip-1.13/CVE-2026-41992.patch b/meta/recipes-extended/gzip/gzip-1.13/CVE-2026-41992.patch
new file mode 100644
index 00000000000..4db9a1c1afd
--- /dev/null
+++ b/meta/recipes-extended/gzip/gzip-1.13/CVE-2026-41992.patch
@@ -0,0 +1,64 @@
+From 63dbf6b3b9e6e781df1a6a64e609b10e23969681 Mon Sep 17 00:00:00 2001
+From: Paul Eggert <eggert@cs.ucla.edu>
+Date: Wed, 15 Apr 2026 12:00:17 -0700
+Subject: =?UTF-8?q?gzip:=20don=E2=80=99t=20mishandle=20.lzh=20after=20.Z?=
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Problem reported by Michał Majchrowicz.
+* unlzh.c (read_c_len): Clear left and right when n == 0.
+
+CVE: CVE-2026-41992
+Upstream-Status: Backport [https://cgit.git.savannah.gnu.org/cgit/gzip.git/commit/?id=63dbf6b3b9e6e781df1a6a64e609b10e23969681]
+Signed-off-by: Jaipaul Cheernam <jaipaul.cheernam@est.tech>
+---
+ NEWS | 4 ++++
+ THANKS | 1 +
+ unlzh.c | 6 ++++++
+ 3 files changed, 11 insertions(+)
+
+diff --git a/NEWS b/NEWS
+index bdb7cc0..af2a08f 100644
+--- a/NEWS
++++ b/NEWS
+@@ -14,6 +14,10 @@ GNU gzip NEWS -*- outline -*-
+
+ ** Bug fixes
+
++ A buffer overflow has been fixed when decompressing an .lzh file
++ after decompressing a .Z file.
++ [bug present since the beginning]
++
+ 'gzip -d' no longer fails to report invalid compressed data
+ that uses a dictionary distance outside the input window.
+ [bug present since the beginning]
+diff --git a/THANKS b/THANKS
+index 4e545d9..a7d25e4 100644
+--- a/THANKS
++++ b/THANKS
+@@ -186,6 +186,7 @@ Jamie Lokier u90jl@ecs.oxford.ac.uk
+ Richard Lloyd R.K.Lloyd@csc.liv.ac.uk
+ David J. MacKenzie djm@eng.umd.edu
+ John R MacMillan john@chance.gts.org
++Michał Majchrowicz mmajchrowicz@afine.com
+ Ron Male male@eso.mc.xerox.com
+ Jakub Martisko jamartis@redhat.com
+ Don R. Maszle maze@bea.lbl.gov
+diff --git a/unlzh.c b/unlzh.c
+index 3320196..a6cf109 100644
+--- a/unlzh.c
++++ b/unlzh.c
+@@ -232,6 +232,12 @@ read_c_len ()
+ c = getbits(CBIT);
+ for (i = 0; i < NC; i++) c_len[i] = 0;
+ for (i = 0; i < 4096; i++) c_table[i] = c;
++
++ /* Needed in case LEFT and RIGHT are reused from a previous
++ LZW decompression. It may be overkill to clear all of both
++ arrays, but nobody has had time to analyze this carefully. */
++ memzero(left, (2 * NC - 1) * sizeof *left);
++ memzero(right, (2 * NC - 1) * sizeof *left);
+ } else {
+ i = 0;
+ while (i < n) {
diff --git a/meta/recipes-extended/gzip/gzip_1.13.bb b/meta/recipes-extended/gzip/gzip_1.13.bb
index fd846b30a55..208220867a6 100644
--- a/meta/recipes-extended/gzip/gzip_1.13.bb
+++ b/meta/recipes-extended/gzip/gzip_1.13.bb
@@ -6,6 +6,7 @@ LICENSE = "GPL-3.0-or-later"
SRC_URI = "${GNU_MIRROR}/gzip/${BP}.tar.gz \
file://run-ptest \
+ file://CVE-2026-41992.patch \
"
SRC_URI:append:class-target = " file://wrong-path-fix.patch"
^ permalink raw reply related
* [OE-core][scarthgap 14/33] socat: patch CVE-2026-56123
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Peter Marko <peter.marko@siemens.com>
Pick the only commit in release 1.8.1.2.
This release has a note for this CVE which was added by this commit.
Drop change in VERSION file (as we're not upgrading).
Resolve minor conflicts in CHANGES and test.sh.
Since we're not running tests, it's not worth to pick next commit from
1.8.1.3 which is fixing test on non-bash shell systems.
Signed-off-by: Peter Marko <peter.marko@siemens.com>
[YC: project git repo seem down. A mirror is here:
https://third-party-mirror.googlesource.com/socat/+/d44cd1cc4fbb70a9ae9e71890024ae8367fcb912%5E%21/ ]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
.../socat/files/CVE-2026-56123.patch | 150 ++++++++++++++++++
.../socat/socat_1.8.0.0.bb | 1 +
2 files changed, 151 insertions(+)
create mode 100644 meta/recipes-connectivity/socat/files/CVE-2026-56123.patch
diff --git a/meta/recipes-connectivity/socat/files/CVE-2026-56123.patch b/meta/recipes-connectivity/socat/files/CVE-2026-56123.patch
new file mode 100644
index 00000000000..e2552a74451
--- /dev/null
+++ b/meta/recipes-connectivity/socat/files/CVE-2026-56123.patch
@@ -0,0 +1,150 @@
+From d44cd1cc4fbb70a9ae9e71890024ae8367fcb912 Mon Sep 17 00:00:00 2001
+From: Gerhard Rieger <gerhard@dest-unreach.org>
+Date: Thu, 25 Jun 2026 14:55:59 +0200
+Subject: [PATCH] Version 1.8.1.2 - fixed SOCKS5 client buffer overflow
+ (CVE-2026-56123)
+
+CVE: CVE-2026-56123
+Upstream-Status: Backport [repo.or.cz/socat.git/commitdiff/d44cd1cc4fbb70a9ae9e71890024ae8367fcb912]
+Signed-off-by: Peter Marko <peter.marko@siemens.com>
+---
+ CHANGES | 13 ++++++++++
+ test.sh | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ xio-socks5.h | 4 +--
+ 3 files changed, 88 insertions(+), 2 deletions(-)
+
+diff --git a/CHANGES b/CHANGES
+index ba82024..3c2f230 100644
+--- a/CHANGES
++++ b/CHANGES
+@@ -1,4 +1,17 @@
+
++Security:
++ Socat security advisory 10
++ CVE-2026-56123
++ There was a possible heap overflow in the socks5 client code. It could
++ be triggered by connecting to a malicious socks5 server that expected
++ this connection and had knowledge about details of the client binary
++ code.
++ Only builds with C signed char (vs.unsigned char) are affected.
++ Thanks to Tristan Madani for finding and reporting this issue, and for
++ conveying the process.
++ Test: SOCKS5_OVERFL
++
++
+ ####################### V 1.8.0.0
+
+ Security:
+diff --git a/test.sh b/test.sh
+index 53bbb2a..467ac57 100755
+--- a/test.sh
++++ b/test.sh
+@@ -601,6 +601,9 @@ rm -rf "$TD" || (echo "cannot rm $TD" >&2; exit 1)
+ mkdir -p "$TD"
+ #trap "rm -r $TD" 0 3
+
++BINDIR=$td/bin
++mkdir -p $BINDIR
++
+ echo "Using temp directory $TD"
+
+ case "$TESTS" in
+@@ -19217,6 +19220,76 @@ fi # NUMCOND
+ esac
+ N=$((N+1))
+
++# Above tests introduced with 1.8.1.0 (none with 1.8.1.1)
++#==============================================================================
++# Below tests introduced with 1.8.1.2
++
++
++# Test socks5 client buffer overflow (CVE-2026-56123)
++NAME=SOCKS5_OVERFL
++case "$TESTS" in
++*%$N%*|*%functions%*|*%bugs%*|*%security%*|*%socks5%*|*%socks%*|*%%*|*%%*|*%socket%*|*%$NAME%*)
++#*%internet%*|*%root%*|*%listen%*|*%fork%*|*%ip4%*|*%tcp4%*|*%bug%*|...
++TEST="$NAME: socks5 client buffer overflow"
++# Start a listener that emulates a malicious socks5 server, using a temporary
++# shell script;
++# connect using Socat with socks5 client;
++# when is terminates with rc=0 the test succeeded (not vulnerable)
++if ! eval $NUMCOND; then :
++# Check if this test can be performed meaningfully
++elif ! cond=$(checkconds \
++ "" \
++ "" \
++ "" \
++ "IP4 TCP LISTEN SHELL GOPEN SOCKS5" \
++ "TCP4-LISTEN SHELL GOPEN SOCKS5" \
++ "socksport" \
++ "tcp4" ); then
++ $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
++ cant
++else
++ mkdir -p "$BINDIR"
++ tf="$td/test$N.stdout"
++ te="$td/test$N.stderr"
++ tdiff="$td/test$N.diff"
++ tsh="$BINDIR/test$N.sh"
++ cat >"$tsh" <<__EOF__
++$ECHO -n "\\x05\\x00"
++relsleep 1
++$ECHO -n "\\x05\\x00\\x00\\x03\\xfdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
++__EOF__
++ chmod a+x "$tsh"
++ newport tcp4 # -> PORT
++ CMD0="$TRACE $SOCAT $opts TCP4-LISTEN:$PORT SHELL:$tsh"
++ CMD1="$TRACE $SOCAT $opts /dev/null SOCKS5:$LOCALHOST4:17.34.51.68:85,socksport=$PORT"
++ printf "test $F_n $TEST... " $N
++ $CMD0 >/dev/null 2>"${te}0" &
++ pid0=$!
++ waittcp4port $PORT 1
++ $CMD1 >"${tf}1" 2>"${te}1"
++ rc1=$?
++ kill $pid0 2>/dev/null; wait
++ if [ "$rc1" -ne 0 ]; then
++ $PRINTF "$FAILED (rc1=$rc1)\n"
++ echo "$CMD0 &"
++ cat "${te}0" >&2
++ echo "$CMD1"
++ cat "${te}1" >&2
++ failed
++ else
++ $PRINTF "$OK\n"
++ if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
++ if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
++ if [ "$VERBOSE" ]; then echo "$CMD1"; fi
++ if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
++ ok
++ fi
++fi # NUMCOND
++ ;;
++esac
++N=$((N+1))
++
++
+ # end of common tests
+
+ ##################################################################################
+diff --git a/xio-socks5.h b/xio-socks5.h
+index 4dab76b..d4712d2 100644
+--- a/xio-socks5.h
++++ b/xio-socks5.h
+@@ -23,7 +23,7 @@ struct socks5_request {
+ uint8_t command;
+ uint8_t reserved;
+ uint8_t address_type;
+- char dstdata[];
++ unsigned char dstdata[];
+ };
+
+ struct socks5_reply {
+@@ -31,7 +31,7 @@ struct socks5_reply {
+ uint8_t reply;
+ uint8_t reserved;
+ uint8_t address_type;
+- char dstdata[];
++ unsigned char dstdata[];
+ };
+
+ extern const struct addrdesc xioaddr_socks5_connect;
diff --git a/meta/recipes-connectivity/socat/socat_1.8.0.0.bb b/meta/recipes-connectivity/socat/socat_1.8.0.0.bb
index bb39730005a..156fd590aee 100644
--- a/meta/recipes-connectivity/socat/socat_1.8.0.0.bb
+++ b/meta/recipes-connectivity/socat/socat_1.8.0.0.bb
@@ -12,6 +12,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
SRC_URI = "http://www.dest-unreach.org/socat/download/socat-${PV}.tar.bz2 \
file://0001-fix-compile-procan.c-failed.patch \
file://CVE-2024-54661.patch \
+ file://CVE-2026-56123.patch \
"
SRC_URI[sha256sum] = "e1de683dd22ee0e3a6c6bbff269abe18ab0c9d7eb650204f125155b9005faca7"
^ permalink raw reply related
* [OE-core][scarthgap 24/33] wic: Fix updating fstab for nvme devices
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Aleksandar Nikolic <aleksandar.nikolic@zeiss.com>
In case wks file references nvme, update_fstab() function will not add
prefix 'p' before the partition number, as the if condition only takes
mmcblk into consideration.
In case of nvme0n1 this leads that following entries are added to fstab:
/dev/nvme0n11
/dev/nvme0n13
instead of:
/dev/nvme0n1p1
/dev/nvme0n1p3
The patch fixes this as it extends the if condition and adds prefix 'p' for
both mmcblk and nvme.
Upstream-Status: Backport [https://git.yoctoproject.org/wic/commit/?id=f20cda73b495b75ef399c331f59b0e2401a3e76a]
Signed-off-by: Aleksandar Nikolic <aleksandar.nikolic@zeiss.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
scripts/lib/wic/plugins/imager/direct.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py
index a1d152659b6..b06e6a8f236 100644
--- a/scripts/lib/wic/plugins/imager/direct.py
+++ b/scripts/lib/wic/plugins/imager/direct.py
@@ -133,8 +133,8 @@ class DirectPlugin(ImagerPlugin):
elif part.use_label:
device_name = "LABEL=%s" % part.label
else:
- # mmc device partitions are named mmcblk0p1, mmcblk0p2..
- prefix = 'p' if part.disk.startswith('mmcblk') else ''
+ # mmc and nvme device partitions start with prefix 'p'
+ prefix = 'p' if part.disk.startswith(('mmcblk', 'nvme')) else ''
device_name = "/dev/%s%s%d" % (part.disk, prefix, part.realnum)
opts = part.fsopts if part.fsopts else "defaults"
@@ -266,7 +266,7 @@ class DirectPlugin(ImagerPlugin):
elif part.label and self.ptable_format != 'msdos':
return "PARTLABEL=%s" % part.label
else:
- suffix = 'p' if part.disk.startswith('mmcblk') else ''
+ suffix = 'p' if part.disk.startswith(('mmcblk', 'nvme')) else ''
return "/dev/%s%s%-d" % (part.disk, suffix, part.realnum)
def cleanup(self):
^ permalink raw reply related
* [OE-core][scarthgap 23/33] python3-urllib3: fix CVE-2026-44431
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Sudhir Dumbhare <sudumbha@cisco.com>
Applies the upstream fix [1] referenced in [2] and addresses the
sensitive-header redirect handling issue in proxied low-level urllib3 requests.
[1] https://github.com/urllib3/urllib3/commit/5ec0de499b9166ca71c65ab04f2a7e4eb0d66fcc
[2] https://ubuntu.com/security/CVE-2026-44431
References:
https://nvd.nist.gov/vuln/detail/CVE-2026-44431
Signed-off-by: Sudhir Dumbhare <sudumbha@cisco.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
.../python3-urllib3/CVE-2026-44431.patch | 163 ++++++++++++++++++
.../python/python3-urllib3_2.2.2.bb | 1 +
2 files changed, 164 insertions(+)
create mode 100644 meta/recipes-devtools/python/python3-urllib3/CVE-2026-44431.patch
diff --git a/meta/recipes-devtools/python/python3-urllib3/CVE-2026-44431.patch b/meta/recipes-devtools/python/python3-urllib3/CVE-2026-44431.patch
new file mode 100644
index 00000000000..042b46f47a2
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-urllib3/CVE-2026-44431.patch
@@ -0,0 +1,163 @@
+From d5517b0ab50030a8f389757b3ba648633c504cbc Mon Sep 17 00:00:00 2001
+From: Illia Volochii <illia.volochii@gmail.com>
+Date: Thu, 7 May 2026 18:40:31 +0300
+Subject: [PATCH] Merge commit from fork
+
+* Remove sensitive headers in proxy pools too
+
+* Add a changelog entry
+
+* Check retries history in tests
+
+CVE: CVE-2026-44431
+Upstream-Status: Backport [https://github.com/urllib3/urllib3/commit/5ec0de499b9166ca71c65ab04f2a7e4eb0d66fcc]
+
+Co-authored-by: Copilot <copilot@github.com>
+
+---------
+
+Co-authored-by: Copilot <copilot@github.com>
+(cherry picked from commit 5ec0de499b9166ca71c65ab04f2a7e4eb0d66fcc)
+Signed-off-by: Sudhir Dumbhare <sudumbha@cisco.com>
+---
+ changelog/GHSA-qccp-gfcp-xxvc.bugfix.rst | 3 +
+ dummyserver/asgi_proxy.py | 1 +
+ src/urllib3/connectionpool.py | 12 ++++
+ .../test_proxy_poolmanager.py | 72 +++++++++++++++++++
+ 4 files changed, 88 insertions(+)
+ create mode 100644 changelog/GHSA-qccp-gfcp-xxvc.bugfix.rst
+
+diff --git a/changelog/GHSA-qccp-gfcp-xxvc.bugfix.rst b/changelog/GHSA-qccp-gfcp-xxvc.bugfix.rst
+new file mode 100644
+index 00000000..bac765ea
+--- /dev/null
++++ b/changelog/GHSA-qccp-gfcp-xxvc.bugfix.rst
+@@ -0,0 +1,3 @@
++Fixed HTTP pools created using ``ProxyManager.connection_from_url`` to strip
++sensitive headers specified in ``Retry.remove_headers_on_redirect`` when
++redirecting to a different host.
+diff --git a/dummyserver/asgi_proxy.py b/dummyserver/asgi_proxy.py
+index 107c5e0a..094807cd 100755
+--- a/dummyserver/asgi_proxy.py
++++ b/dummyserver/asgi_proxy.py
+@@ -52,6 +52,7 @@ class ProxyApp:
+ client_response = await client.request(
+ method=scope["method"],
+ url=scope["path"],
++ params=scope["query_string"].decode(),
+ headers=list(scope["headers"]),
+ content=await _read_body(receive),
+ )
+diff --git a/src/urllib3/connectionpool.py b/src/urllib3/connectionpool.py
+index a2c3cf60..f64ee2f8 100644
+--- a/src/urllib3/connectionpool.py
++++ b/src/urllib3/connectionpool.py
+@@ -898,6 +898,18 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
+ body = None
+ headers = HTTPHeaderDict(headers)._prepare_for_method_change()
+
++ # Strip headers marked as unsafe to forward to the redirected location.
++ # Check remove_headers_on_redirect to avoid a potential network call within
++ # self.is_same_host() which may use socket.gethostbyname() in the future.
++ if retries.remove_headers_on_redirect and not self.is_same_host(
++ redirect_location
++ ):
++ new_headers = headers.copy() # type: ignore[union-attr]
++ for header in headers:
++ if header.lower() in retries.remove_headers_on_redirect:
++ new_headers.pop(header, None)
++ headers = new_headers
++
+ try:
+ retries = retries.increment(method, url, response=response, _pool=self)
+ except MaxRetryError:
+diff --git a/test/with_dummyserver/test_proxy_poolmanager.py b/test/with_dummyserver/test_proxy_poolmanager.py
+index 397181a9..a0b11726 100644
+--- a/test/with_dummyserver/test_proxy_poolmanager.py
++++ b/test/with_dummyserver/test_proxy_poolmanager.py
+@@ -37,6 +37,7 @@ from urllib3.exceptions import (
+ SSLError,
+ )
+ from urllib3.poolmanager import ProxyManager, proxy_from_url
++from urllib3.util.retry import RequestHistory
+ from urllib3.util.ssl_ import create_urllib3_context
+ from urllib3.util.timeout import Timeout
+
+@@ -299,6 +300,77 @@ class TestHTTPProxyManager(HypercornDummyProxyTestCase):
+ assert r._pool is not None
+ assert r._pool.host != self.http_host_alt
+
++ _sensitive_headers = {
++ "Authorization": "foo",
++ "Proxy-Authorization": "bar",
++ "Cookie": "foo=bar",
++ }
++
++ @pytest.mark.parametrize(
++ "sensitive_headers",
++ (_sensitive_headers, {k.lower(): v for k, v in _sensitive_headers.items()}),
++ ids=("capitalized", "lowercase"),
++ )
++ def test_cross_host_redirect_remove_headers_via_proxy_manager(
++ self, sensitive_headers: dict[str, str]
++ ) -> None:
++ headers_url = f"{self.http_url_alt}/headers"
++ initial_url = f"{self.http_url}/redirect?target={headers_url}"
++ with proxy_from_url(self.proxy_url) as proxy_mgr:
++ r = proxy_mgr.request(
++ "GET", initial_url, headers=sensitive_headers, retries=1
++ )
++ assert r.status == 200
++ assert r.retries is not None
++ assert r.retries.history == (
++ RequestHistory(
++ method="GET",
++ url=initial_url,
++ error=None,
++ status=303,
++ redirect_location=headers_url,
++ ),
++ )
++ data = r.json()
++ for header in sensitive_headers:
++ assert header not in data
++
++ @pytest.mark.parametrize(
++ "sensitive_headers",
++ (_sensitive_headers, {k.lower(): v for k, v in _sensitive_headers.items()}),
++ ids=("capitalized", "lowercase"),
++ )
++ def test_cross_host_redirect_remove_headers_via_pool(
++ self, sensitive_headers: dict[str, str]
++ ) -> None:
++ headers_url = f"{self.http_url_alt}/headers"
++ initial_url = f"{self.http_url}/redirect?target={headers_url}"
++ with proxy_from_url(self.proxy_url) as proxy_mgr:
++ pool = proxy_mgr.connection_from_url(self.http_url)
++ r = pool.urlopen(
++ "GET",
++ initial_url,
++ headers=sensitive_headers,
++ retries=1,
++ redirect=True,
++ assert_same_host=False,
++ preload_content=True,
++ )
++ assert r.status == 200
++ assert r.retries is not None
++ assert r.retries.history == (
++ RequestHistory(
++ method="GET",
++ url=initial_url,
++ error=None,
++ status=303,
++ redirect_location=headers_url,
++ ),
++ )
++ data = r.json()
++ for header in sensitive_headers:
++ assert header not in data
++
+ def test_cross_protocol_redirect(self) -> None:
+ with proxy_from_url(self.proxy_url, ca_certs=DEFAULT_CA) as http:
+ cross_protocol_location = f"{self.https_url}/echo?a=b"
diff --git a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb
index f6ac8f89cad..b77dd5297d3 100644
--- a/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb
+++ b/meta/recipes-devtools/python/python3-urllib3_2.2.2.bb
@@ -12,6 +12,7 @@ SRC_URI += " \
file://CVE-2025-66418.patch \
file://CVE-2025-66471.patch \
file://CVE-2026-21441.patch \
+ file://CVE-2026-44431.patch \
"
RDEPENDS:${PN} += "\
^ permalink raw reply related
* [OE-core][scarthgap 32/33] binutils: Add CVE-2025-69646 to "CVE:" tag
From: Yoann Congal @ 2026-07-20 17:23 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Harish Sadineni <Harish.Sadineni@windriver.com>
Bugzilla bug 33641 (assigned CVE-2025-69648) has been resolved as a
duplicate of bug 33638 (assigned CVE-2025-69646):
https://sourceware.org/bugzilla/show_bug.cgi?id=33641
The existing patch already fixes the issue associated with both CVEs.
Update the "CVE:" tag to reference both identifiers.
Signed-off-by: Harish Sadineni <Harish.Sadineni@windriver.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/recipes-devtools/binutils/binutils/CVE-2025-69648.patch | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2025-69648.patch b/meta/recipes-devtools/binutils/binutils/CVE-2025-69648.patch
index e04d7ed6c21..e123273338c 100644
--- a/meta/recipes-devtools/binutils/binutils/CVE-2025-69648.patch
+++ b/meta/recipes-devtools/binutils/binutils/CVE-2025-69648.patch
@@ -19,7 +19,7 @@ length field.
(display_debug_ranges): Check display_debug_rnglists_unit_header
return status. Stop output on error.
-CVE: CVE-2025-69648
+CVE: CVE-2025-69648 CVE-2025-69646
Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=598704a00cbac5e85c2bedd363357b5bf6fcee33]
(cherry picked from commit 598704a00cbac5e85c2bedd363357b5bf6fcee33)
^ permalink raw reply related
* [OE-core][scarthgap 33/33] glibc-testsuite: Do not generate SPDX
From: Yoann Congal @ 2026-07-20 17:23 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Joshua Watt <JPEWhacker@gmail.com>
glibc-testsuite does not run on target or factor into the build supply
chain, since its purpose is run tests in Qemu at build time
Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 32801348ca231978498612f3ebee121ca27459c1)
[YC: See https://lore.kernel.org/all/20260708115052.71740-1-jaipaul.cheernam@est.tech/ ]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/recipes-core/glibc/glibc-testsuite_2.39.bb | 1 +
1 file changed, 1 insertion(+)
diff --git a/meta/recipes-core/glibc/glibc-testsuite_2.39.bb b/meta/recipes-core/glibc/glibc-testsuite_2.39.bb
index 2e076f4b0f4..e0e3e8ba847 100644
--- a/meta/recipes-core/glibc/glibc-testsuite_2.39.bb
+++ b/meta/recipes-core/glibc/glibc-testsuite_2.39.bb
@@ -31,6 +31,7 @@ do_check:append () {
}
inherit nopackages
+inherit nospdx
deltask do_stash_locale
deltask do_install
deltask do_populate_sysroot
^ permalink raw reply related
* [OE-core][scarthgap 29/33] wireless-regdb: upgrade 2026.02.04 -> 2026.03.18
From: Yoann Congal @ 2026-07-20 17:23 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Ankur Tyagi <ankur.tyagi85@gmail.com>
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 97a940bfdeaa3f9f4442a6fbb0fabe1ce5eaff69)
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
[YC: Changelog:
https://git.kernel.org/pub/scm/linux/kernel/git/wens/wireless-regdb.git/log/?qt=range&q=master-2026-02-04..master-2026-03-18
"wireless-regdb: Replace M2Crypto with cryptography package" only
impacts signing code that maintainers run.
]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
...ireless-regdb_2026.02.04.bb => wireless-regdb_2026.03.18.bb} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename meta/recipes-kernel/wireless-regdb/{wireless-regdb_2026.02.04.bb => wireless-regdb_2026.03.18.bb} (94%)
diff --git a/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.02.04.bb b/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.03.18.bb
similarity index 94%
rename from meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.02.04.bb
rename to meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.03.18.bb
index 2f7c8160434..a70e9dd0dae 100644
--- a/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.02.04.bb
+++ b/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.03.18.bb
@@ -5,7 +5,7 @@ LICENSE = "ISC"
LIC_FILES_CHKSUM = "file://LICENSE;md5=07c4f6dea3845b02a18dc00c8c87699c"
SRC_URI = "https://www.kernel.org/pub/software/network/${BPN}/${BP}.tar.xz"
-SRC_URI[sha256sum] = "0ff48a5cd9e9cfe8e815a24e023734919e9a3b7ad2f039243ad121cf5aabf6c6"
+SRC_URI[sha256sum] = "5fc0000475d8c5368ccc5222827c16aef98b1eb6a69c9b5a3e7b7e98528945ac"
inherit bin_package allarch
^ permalink raw reply related
* [OE-core][scarthgap 25/33] openssh: set status for CVE-2026-3497
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Sudhir Dumbhare <sudumbha@cisco.com>
Analysis:
- CVE-2026-3497 affects downstream OpenSSH GSSAPI Key Exchange patches.
- The vulnerable code uses sshpkt_disconnect() in the GSSAPI KEX server path.
- Upstream OpenSSH/OE-Core does not carry the vulnerable GSSAPI key-exchange delta.
- Hence ignoring the CVE for this version.
Reference:
https://nvd.nist.gov/vuln/detail/CVE-2026-3497
https://github.com/advisories/ghsa-wcpp-3x59-h8vp
https://ubuntu.com/security/CVE-2026-3497
https://security-tracker.debian.org/tracker/CVE-2026-3497
https://www.openwall.com/lists/oss-security/2026/03/12/3
Signed-off-by: Sudhir Dumbhare <sudumbha@cisco.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit c2bd43b373d65d717e606cab3793b8a64facd946)
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/recipes-connectivity/openssh/openssh_9.6p1.bb | 1 +
1 file changed, 1 insertion(+)
diff --git a/meta/recipes-connectivity/openssh/openssh_9.6p1.bb b/meta/recipes-connectivity/openssh/openssh_9.6p1.bb
index 4193bc8a5b4..4ab3174924c 100644
--- a/meta/recipes-connectivity/openssh/openssh_9.6p1.bb
+++ b/meta/recipes-connectivity/openssh/openssh_9.6p1.bb
@@ -49,6 +49,7 @@ Red Hat Enterprise Linux 7 and when running in a Kerberos environment"
CVE_STATUS[CVE-2008-3844] = "not-applicable-platform: Only applies to some distributed RHEL binaries."
CVE_STATUS[CVE-2023-51767] = "upstream-wontfix: It was demonstrated on modified sshd and does not exist in upstream openssh https://bugzilla.mindrot.org/show_bug.cgi?id=3656#c1."
+CVE_STATUS[CVE-2026-3497] = "not-applicable-platform: Only affects GSSAPI Key Exchange patches used by some Linux distributions and does not exist in upstream openssh."
PAM_SRC_URI = "file://sshd"
^ permalink raw reply related
* [OE-core][scarthgap 28/33] xmlto: update SRC_URI
From: Yoann Congal @ 2026-07-20 17:23 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Ross Burton <ross.burton@arm.com>
xmlto was previously hosted on Fedora's pagure.io server, but this is
being decomissioned. As xmlto isn't Fedora-specific the repository has
migrated to codeberg.org.
>From discussion with Michal Schorm <mschorm@redhat.com>:
I became the new maintainer of the project upstream and after a
discussion with Kevin Fenzi, migrated it to a new home on the
codeberg.org: https://codeberg.org/xmlto/xmlto
Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 0046c780bf612aa7946023f8993c45f0c0b65c08)
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
meta/recipes-devtools/xmlto/xmlto_0.0.28.bb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/meta/recipes-devtools/xmlto/xmlto_0.0.28.bb b/meta/recipes-devtools/xmlto/xmlto_0.0.28.bb
index d5a0e69849e..b7bfdb69bf0 100644
--- a/meta/recipes-devtools/xmlto/xmlto_0.0.28.bb
+++ b/meta/recipes-devtools/xmlto/xmlto_0.0.28.bb
@@ -8,7 +8,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=59530bdf33659b29e73d4adb9f9f6552"
SRCREV = "6fa6a0e07644f20abf2596f78a60112713e11cbe"
UPSTREAM_CHECK_COMMITS = "1"
-SRC_URI = "git://pagure.io/xmlto.git;protocol=https;branch=master"
+SRC_URI = "git://codeberg.org/xmlto/xmlto.git;protocol=https;branch=master"
S = "${WORKDIR}/git"
PV .= "+0.0.29+git"
^ permalink raw reply related
* [OE-core][scarthgap 30/33] wireless-regdb: upgrade 2026.03.18 -> 2026.05.30
From: Yoann Congal @ 2026-07-20 17:23 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Ankur Tyagi <ankur.tyagi85@gmail.com>
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 86e35bc1ab5fb2132b06b666fe73fc9bd6446ab6)
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
[YC: Changelog:
https://git.kernel.org/pub/scm/linux/kernel/git/wens/wireless-regdb.git/log/?qt=range&q=master-2026-03-18..master-2026-05-30
]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
...ireless-regdb_2026.03.18.bb => wireless-regdb_2026.05.30.bb} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename meta/recipes-kernel/wireless-regdb/{wireless-regdb_2026.03.18.bb => wireless-regdb_2026.05.30.bb} (94%)
diff --git a/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.03.18.bb b/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.05.30.bb
similarity index 94%
rename from meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.03.18.bb
rename to meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.05.30.bb
index a70e9dd0dae..e544b729656 100644
--- a/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.03.18.bb
+++ b/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.05.30.bb
@@ -5,7 +5,7 @@ LICENSE = "ISC"
LIC_FILES_CHKSUM = "file://LICENSE;md5=07c4f6dea3845b02a18dc00c8c87699c"
SRC_URI = "https://www.kernel.org/pub/software/network/${BPN}/${BP}.tar.xz"
-SRC_URI[sha256sum] = "5fc0000475d8c5368ccc5222827c16aef98b1eb6a69c9b5a3e7b7e98528945ac"
+SRC_URI[sha256sum] = "8a27bfc081bafed8c24dd70fab0d96f098e5a0bfcd08d3da672595f225ab8993"
inherit bin_package allarch
^ permalink raw reply related
* [OE-core][scarthgap 31/33] ca-certificates: upgrade 20260223 -> 20260601
From: Yoann Congal @ 2026-07-20 17:23 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Ankur Tyagi <ankur.tyagi85@gmail.com>
License-Update: ca-certificates-local example removed[1]
[1] https://salsa.debian.org/debian/ca-certificates/-/commit/0ba2e089daf128206b0a13423ceede612bb60270
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit 366cfc1103661f98020d7b7c8d249f2b7f9432af)
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
[YC: Changelog:
https://metadata.ftp-master.debian.org/changelogs/main/c/ca-certificates/ca-certificates_20260601_changelog
]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
...a-certificates_20260223.bb => ca-certificates_20260601.bb} | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
rename meta/recipes-support/ca-certificates/{ca-certificates_20260223.bb => ca-certificates_20260601.bb} (94%)
diff --git a/meta/recipes-support/ca-certificates/ca-certificates_20260223.bb b/meta/recipes-support/ca-certificates/ca-certificates_20260601.bb
similarity index 94%
rename from meta/recipes-support/ca-certificates/ca-certificates_20260223.bb
rename to meta/recipes-support/ca-certificates/ca-certificates_20260601.bb
index 9cf6d5afc7d..b23f20a7828 100644
--- a/meta/recipes-support/ca-certificates/ca-certificates_20260223.bb
+++ b/meta/recipes-support/ca-certificates/ca-certificates_20260601.bb
@@ -5,7 +5,7 @@ This derived from Debian's CA Certificates."
HOMEPAGE = "http://packages.debian.org/sid/ca-certificates"
SECTION = "misc"
LICENSE = "GPL-2.0-or-later & MPL-2.0"
-LIC_FILES_CHKSUM = "file://debian/copyright;md5=ae5b36b514e3f12ce1aa8e2ee67f3d7e"
+LIC_FILES_CHKSUM = "file://debian/copyright;md5=dab7c7cea776d1a1648deb0052c72647"
# This is needed to ensure we can run the postinst at image creation time
DEPENDS = ""
@@ -14,7 +14,7 @@ DEPENDS:class-nativesdk = "openssl-native"
# Need rehash from openssl and run-parts from debianutils
PACKAGE_WRITE_DEPS += "openssl-native debianutils-native"
-SRC_URI[sha256sum] = "2fa2b00d4360f0d14ec51640ae8aea9e563956b95ea786e3c3c01c4eead42b56"
+SRC_URI[sha256sum] = "7ab6301f7f34eef90a4d278647c260bc0762e0e14561f4649854cf4b0d4bea21"
SRC_URI = "${DEBIAN_MIRROR}/main/c/ca-certificates/${BPN}_${PV}.tar.xz \
file://0001-update-ca-certificates-don-t-use-Debianisms-in-run-p.patch \
file://0003-update-ca-certificates-use-relative-symlinks-from-ET.patch \
^ permalink raw reply related
* [OE-core][scarthgap 27/33] glib-2.0: fix CVE-2026-58016
From: Yoann Congal @ 2026-07-20 17:23 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
A flaw was found in GLib. A state confusion issue exists in
g_dbus_node_info_new_for_xml() in the gio/gdbusintrospection.c file when
processing malformed D-Bus introspection XML, specifically with a <node>
element nested within other elements like <method>, <signal>, <property>
or <arg>. This issue can cause an unsigned integer overflow and lead to an
out-of-bounds read, resulting in a denial of service.
The CVE NVD entry is wrong, it indicates that the CVE is fixed in 2.88.1
but the fix was realized in 2.89.0, see [1]. The fix is not present in 2.88.2.
[1] https://gitlab.gnome.org/GNOME/glib/-/commit/c9da977c178fbfc0e4caf99f9fdf5dc433d6fcc2
Signed-off-by: Benjamin Robin (Schneider Electric) <benjamin.robin@bootlin.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
(cherry picked from commit d52f4d582cc71ada3c8ebe54be1a5b70278ea1ca)
[YC: re-added the removed Signed-off-bys from the patches]
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
.../glib-2.0/glib-2.0/CVE-2026-58016-1.patch | 94 ++++++++++++++++++
.../glib-2.0/glib-2.0/CVE-2026-58016-2.patch | 98 +++++++++++++++++++
meta/recipes-core/glib-2.0/glib-2.0_2.78.6.bb | 2 +
3 files changed, 194 insertions(+)
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58016-1.patch
create mode 100644 meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58016-2.patch
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58016-1.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58016-1.patch
new file mode 100644
index 00000000000..2c4b248b97b
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58016-1.patch
@@ -0,0 +1,94 @@
+From 38eee3870fbcf6bdf8e6b1281bc7a98d32b68521 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Thu, 16 Apr 2026 15:27:37 +0100
+Subject: [PATCH 1/2] gdbusintrospection: Fix XML parser state handling for
+ <node> element nesting
+
+The check for whether a `<node>` element in D-Bus introspection XML was
+nested correctly was broken. `<node>` elements can only be at the top
+level, or nested immediately within another `<node>` element.
+
+Fix the check and add some unit tests for it.
+
+Spotted by linhlhq as #YWH-PGM9867-204. The fix is mine, and the unit test
+uses example XML strings adapted from their report.
+
+Signed-off-by: Philip Withnall <pwithnall@gnome.org>
+
+Fixes: #3932
+
+CVE: CVE-2026-58016
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/c9da977c178fbfc0e4caf99f9fdf5dc433d6fcc2]
+
+Signed-off-by: Benjamin Robin <benjamin.robin@bootlin.com>
+---
+ gio/gdbusintrospection.c | 2 +-
+ gio/tests/gdbus-introspection.c | 33 +++++++++++++++++++++++++++++++++
+ 2 files changed, 34 insertions(+), 1 deletion(-)
+
+diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c
+index c7be334ce2f7..6f722ee6153d 100644
+--- a/gio/gdbusintrospection.c
++++ b/gio/gdbusintrospection.c
+@@ -1272,7 +1272,7 @@ parser_start_element (GMarkupParseContext *context,
+ /* ---------------------------------------------------------------------------------------------------- */
+ if (strcmp (element_name, "node") == 0)
+ {
+- if (!(g_slist_length (stack) >= 1 || strcmp (stack->next->data, "node") != 0))
++ if (stack->next != NULL && strcmp (stack->next->data, "node") != 0)
+ {
+ g_set_error_literal (error,
+ G_MARKUP_ERROR,
+diff --git a/gio/tests/gdbus-introspection.c b/gio/tests/gdbus-introspection.c
+index 44cb7a96af45..daca313f77e7 100644
+--- a/gio/tests/gdbus-introspection.c
++++ b/gio/tests/gdbus-introspection.c
+@@ -299,6 +299,38 @@ test_extra_data (void)
+ g_dbus_node_info_unref (info);
+ }
+
++static void
++test_invalid (void)
++{
++ const struct
++ {
++ const char *xml;
++ GMarkupError expected_error_code;
++ }
++ vectors[] =
++ {
++ { "", G_MARKUP_ERROR_EMPTY },
++ { "<node><interface name=\"I\"><method name=\"M\"><node><interface name=\"I2\"></interface></node></method>", G_MARKUP_ERROR_INVALID_CONTENT },
++ { "<node><interface name=\"I\"><signal name=\"S\"><node><interface name=\"I2\"><signal name=\"S2\"></signal></interface></node></signal>", G_MARKUP_ERROR_INVALID_CONTENT },
++ { "<node><interface name=\"I\"><property name=\"P\" type=\"s\" access=\"read\"><node><interface name=\"I2\"></interface></node></property>", G_MARKUP_ERROR_INVALID_CONTENT },
++ { "<node><interface name=\"I\"><method name=\"M\"><arg type=\"\"><node><interface name=\"I2\"><method name=\"M2\"></method></interface></node></arg>", G_MARKUP_ERROR_INVALID_CONTENT },
++ };
++
++ for (size_t i = 0; i < G_N_ELEMENTS (vectors); i++)
++ {
++ GDBusNodeInfo *node;
++ GError *local_error = NULL;
++
++ g_test_message ("Testing parsing of %s gives an error", vectors[i].xml);
++
++ node = g_dbus_node_info_new_for_xml (vectors[i].xml, &local_error);
++ g_assert_error (local_error, G_MARKUP_ERROR, (int) vectors[i].expected_error_code);
++ g_assert_null (node);
++
++ g_clear_error (&local_error);
++ }
++}
++
+ /* ---------------------------------------------------------------------------------------------------- */
+
+ int
+@@ -316,6 +348,7 @@ main (int argc,
+ g_test_add_func ("/gdbus/introspection-generate", test_generate);
+ g_test_add_func ("/gdbus/introspection-default-direction", test_default_direction);
+ g_test_add_func ("/gdbus/introspection-extra-data", test_extra_data);
++ g_test_add_func ("/gdbus/introspection/invalid", test_invalid);
+
+ ret = session_bus_run ();
+
+--
+2.54.0
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58016-2.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58016-2.patch
new file mode 100644
index 00000000000..a61e35ad8a7
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-58016-2.patch
@@ -0,0 +1,98 @@
+From a75052ceeebea434f271b670766acd5416bc83b9 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Thu, 16 Apr 2026 15:08:10 +0100
+Subject: [PATCH 2/2] gdbusintrospection: Add some assertions before array
+ dereferences
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The state handling inside the D-Bus introspection XML parser is
+complicated, and it’s possible that these dereferences of the
+`len - 1`th element might get reached when the array is empty.
+
+Make failures like that more debuggable by adding an assertion on the
+length beforehand.
+
+Signed-off-by: Philip Withnall <pwithnall@gnome.org>
+
+Helps: #3932
+
+CVE: CVE-2026-58016
+Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/656ad4582cb1d7a7fa8bafe3ce8aec6aa3c17da0]
+
+Signed-off-by: Benjamin Robin <benjamin.robin@bootlin.com>
+---
+ gio/gdbusintrospection.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c
+index 6f722ee6153d..ed0d291f99f0 100644
+--- a/gio/gdbusintrospection.c
++++ b/gio/gdbusintrospection.c
+@@ -1110,6 +1110,7 @@ parse_data_get_annotation (ParseData *data,
+ {
+ if (create_new)
+ g_ptr_array_add (data->annotations, g_new0 (GDBusAnnotationInfo, 1));
++ g_assert (data->annotations->len > 0);
+ return data->annotations->pdata[data->annotations->len - 1];
+ }
+
+@@ -1119,6 +1120,7 @@ parse_data_get_arg (ParseData *data,
+ {
+ if (create_new)
+ g_ptr_array_add (data->args, g_new0 (GDBusArgInfo, 1));
++ g_assert (data->args->len > 0);
+ return data->args->pdata[data->args->len - 1];
+ }
+
+@@ -1128,6 +1130,7 @@ parse_data_get_out_arg (ParseData *data,
+ {
+ if (create_new)
+ g_ptr_array_add (data->out_args, g_new0 (GDBusArgInfo, 1));
++ g_assert (data->out_args->len > 0);
+ return data->out_args->pdata[data->out_args->len - 1];
+ }
+
+@@ -1137,6 +1140,7 @@ parse_data_get_method (ParseData *data,
+ {
+ if (create_new)
+ g_ptr_array_add (data->methods, g_new0 (GDBusMethodInfo, 1));
++ g_assert (data->methods->len > 0);
+ return data->methods->pdata[data->methods->len - 1];
+ }
+
+@@ -1146,6 +1150,7 @@ parse_data_get_signal (ParseData *data,
+ {
+ if (create_new)
+ g_ptr_array_add (data->signals, g_new0 (GDBusSignalInfo, 1));
++ g_assert (data->signals->len > 0);
+ return data->signals->pdata[data->signals->len - 1];
+ }
+
+@@ -1155,6 +1160,7 @@ parse_data_get_property (ParseData *data,
+ {
+ if (create_new)
+ g_ptr_array_add (data->properties, g_new0 (GDBusPropertyInfo, 1));
++ g_assert (data->properties->len > 0);
+ return data->properties->pdata[data->properties->len - 1];
+ }
+
+@@ -1164,6 +1170,7 @@ parse_data_get_interface (ParseData *data,
+ {
+ if (create_new)
+ g_ptr_array_add (data->interfaces, g_new0 (GDBusInterfaceInfo, 1));
++ g_assert (data->interfaces->len > 0);
+ return data->interfaces->pdata[data->interfaces->len - 1];
+ }
+
+@@ -1173,6 +1180,7 @@ parse_data_get_node (ParseData *data,
+ {
+ if (create_new)
+ g_ptr_array_add (data->nodes, g_new0 (GDBusNodeInfo, 1));
++ g_assert (data->nodes->len > 0);
+ return data->nodes->pdata[data->nodes->len - 1];
+ }
+
+--
+2.54.0
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.78.6.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.78.6.bb
index b8212c9d12b..549584f3d8f 100644
--- a/meta/recipes-core/glib-2.0/glib-2.0_2.78.6.bb
+++ b/meta/recipes-core/glib-2.0/glib-2.0_2.78.6.bb
@@ -47,6 +47,8 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \
file://CVE-2026-1489-02.patch \
file://CVE-2026-1489-03.patch \
file://CVE-2026-1489-04.patch \
+ file://CVE-2026-58016-1.patch \
+ file://CVE-2026-58016-2.patch \
"
SRC_URI:append:class-native = " file://relocate-modules.patch \
file://0001-meson.build-do-not-enable-pidfd-features-on-native-g.patch \
^ permalink raw reply related
* [OE-core][scarthgap 26/33] vim: Fix for CVE-2026-52858,CVE-2026-52859,CVE-2026-52860
From: Yoann Congal @ 2026-07-20 17:22 UTC (permalink / raw)
To: openembedded-core
In-Reply-To: <cover.1784567958.git.yoann.congal@smile.fr>
From: Hitendra Prajapati <hprajapati@mvista.com>
Pick patch from [1], [2] & [3] also mentioned at NVD report in [4,5 & 6]
[1] https://github.com/vim/vim/commit/4b850457e12e1a678dd209f2868154f7553cbf8d
[2] https://github.com/vim/vim/commit/63680c6d3d52477817b49cd1a66e7aabe8a7aa19
[3] https://github.com/vim/vim/commit/c8c63673bc4253212820626aeeb75999d9a539d2
[4] https://nvd.nist.gov/vuln/detail/CVE-2026-52858
[5] https://nvd.nist.gov/vuln/detail/CVE-2026-52859
[6] https://nvd.nist.gov/vuln/detail/CVE-2026-52860
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
Signed-off-by: Yoann Congal <yoann.congal@smile.fr>
---
.../vim/files/CVE-2026-52858.patch | 167 +++++++
.../vim/files/CVE-2026-52859.patch | 274 +++++++++++
.../vim/files/CVE-2026-52860.patch | 446 ++++++++++++++++++
meta/recipes-support/vim/vim.inc | 3 +
4 files changed, 890 insertions(+)
create mode 100644 meta/recipes-support/vim/files/CVE-2026-52858.patch
create mode 100644 meta/recipes-support/vim/files/CVE-2026-52859.patch
create mode 100644 meta/recipes-support/vim/files/CVE-2026-52860.patch
diff --git a/meta/recipes-support/vim/files/CVE-2026-52858.patch b/meta/recipes-support/vim/files/CVE-2026-52858.patch
new file mode 100644
index 00000000000..7e036e45ea8
--- /dev/null
+++ b/meta/recipes-support/vim/files/CVE-2026-52858.patch
@@ -0,0 +1,167 @@
+From 4b850457e12e1a678dd209f2868154f7553cbf8d Mon Sep 17 00:00:00 2001
+From: Christian Brabandt <cb@256bit.org>
+Date: Fri, 29 May 2026 19:05:53 +0000
+Subject: [PATCH] patch 9.2.0561: [security]: possible code execution with
+ python3complete
+
+Problem: [security]: possible code execution with python3complete
+Solution: Disable execution of import/from statements
+
+Github Security Advisory:
+https://github.com/vim/vim/security/advisories/GHSA-52mc-rq6p-rc7c
+
+Signed-off-by: Christian Brabandt <cb@256bit.org>
+
+Upstream-Status: Backport [https://github.com/vim/vim/commit/4b850457e12e1a678dd209f2868154f7553cbf8d]
+CVE: CVE-2026-52858
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ runtime/autoload/README.txt | 1 +
+ runtime/autoload/python3complete.vim | 17 ++++++++++++++---
+ runtime/autoload/pythoncomplete.vim | 17 ++++++++++++++---
+ runtime/doc/filetype.txt | 15 ++++++++++++++-
+ 4 files changed, 43 insertions(+), 7 deletions(-)
+
+diff --git a/runtime/autoload/README.txt b/runtime/autoload/README.txt
+index 3b18d3d..b225819 100644
+--- a/runtime/autoload/README.txt
++++ b/runtime/autoload/README.txt
+@@ -17,6 +17,7 @@ htmlcomplete.vim HTML
+ javascriptcomplete.vim Javascript
+ phpcomplete.vim PHP
+ pythoncomplete.vim Python
++python3complete.vim Python
+ rubycomplete.vim Ruby
+ syntaxcomplete.vim from syntax highlighting
+ xmlcomplete.vim XML (uses files in the xml directory)
+diff --git a/runtime/autoload/python3complete.vim b/runtime/autoload/python3complete.vim
+index ea0a331..aba3412 100644
+--- a/runtime/autoload/python3complete.vim
++++ b/runtime/autoload/python3complete.vim
+@@ -14,6 +14,10 @@
+ " i.e. "import url<c-x,c-o>"
+ " Continue parsing on invalid line??
+ "
++" v 0.10 by Vim project
++" * disables importing local modules, unless the global Vim variable
++" g:pythoncomplete_allow_import is set to non-zero
++"
+ " v 0.9
+ " * Fixed docstring parsing for classes and functions
+ " * Fixed parsing of *args and **kwargs type arguments
+@@ -132,11 +136,20 @@ class Completer(object):
+
+ def evalsource(self,text,line=0):
+ sc = self.parser.parse(text,line)
++ try: allow_imports = int(
++ vim.eval("get(g:, 'pythoncomplete_allow_import', 0)"))
++ except Exception:
++ allow_imports = 0
+ src = sc.get_code()
+ dbg("source: %s" % src)
+ try: exec(src,self.compldict)
+ except: dbg("parser: %s, %s" % (sys.exc_info()[0],sys.exc_info()[1]))
+ for l in sc.locals:
++ # Executing import/from statements harvested from the buffer runs
++ # arbitrary package code; only do so when the user opted in.
++ if not allow_imports and (l.startswith('import')
++ or l.startswith('from ')):
++ continue
+ try: exec(l,self.compldict)
+ except: dbg("locals: %s, %s [%s]" % (sys.exc_info()[0],sys.exc_info()[1],l))
+
+@@ -300,13 +313,11 @@ class Scope(object):
+ def get_code(self):
+ str = ""
+ if len(self.docstr) > 0: str += '"""'+self.docstr+'"""\n'
+- for l in self.locals:
+- if l.startswith('import'): str += l+'\n'
+ str += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n'
+ for sub in self.subscopes:
+ str += sub.get_code()
+ for l in self.locals:
+- if not l.startswith('import'): str += l+'\n'
++ if not l.startswith('import') and not l.startswith('from '): str += l+'\n'
+
+ return str
+
+diff --git a/runtime/autoload/pythoncomplete.vim b/runtime/autoload/pythoncomplete.vim
+index aa28bb7..1014776 100644
+--- a/runtime/autoload/pythoncomplete.vim
++++ b/runtime/autoload/pythoncomplete.vim
+@@ -12,6 +12,10 @@
+ " i.e. "import url<c-x,c-o>"
+ " Continue parsing on invalid line??
+ "
++" v 0.10 by Vim project
++" * disables importing local modules, unless the global Vim variable
++" g:pythoncomplete_allow_import is set to non-zero
++"
+ " v 0.9
+ " * Fixed docstring parsing for classes and functions
+ " * Fixed parsing of *args and **kwargs type arguments
+@@ -146,11 +150,20 @@ class Completer(object):
+
+ def evalsource(self,text,line=0):
+ sc = self.parser.parse(text,line)
++ try: allow_imports = int(
++ vim.eval("get(g:, 'pythoncomplete_allow_import', 0)"))
++ except Exception:
++ allow_imports = 0
+ src = sc.get_code()
+ dbg("source: %s" % src)
+ try: exec(src) in self.compldict
+ except: dbg("parser: %s, %s" % (sys.exc_info()[0],sys.exc_info()[1]))
+ for l in sc.locals:
++ # Executing import/from statements harvested from the buffer runs
++ # arbitrary package code; only do so when the user opted in.
++ if not allow_imports and (l.startswith('import')
++ or l.startswith('from ')):
++ continue
+ try: exec(l) in self.compldict
+ except: dbg("locals: %s, %s [%s]" % (sys.exc_info()[0],sys.exc_info()[1],l))
+
+@@ -315,13 +328,11 @@ class Scope(object):
+ def get_code(self):
+ str = ""
+ if len(self.docstr) > 0: str += '"""'+self.docstr+'"""\n'
+- for l in self.locals:
+- if l.startswith('import'): str += l+'\n'
+ str += 'class _PyCmplNoType:\n def __getattr__(self,name):\n return None\n'
+ for sub in self.subscopes:
+ str += sub.get_code()
+ for l in self.locals:
+- if not l.startswith('import'): str += l+'\n'
++ if not l.startswith('import') and not l.startswith('from '): str += l+'\n'
+
+ return str
+
+diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
+index 597141d..c8572fe 100644
+--- a/runtime/doc/filetype.txt
++++ b/runtime/doc/filetype.txt
+@@ -739,7 +739,20 @@ By default the following options are set, in accordance with PEP8: >
+ To disable this behavior, set the following variable in your vimrc: >
+
+ let g:python_recommended_style = 0
+-
++<
++Python omni-completion |compl-omni| is provided by python3complete.vim (or
++pythoncomplete.vim) for Vim builds with the |+python|/|+python3| interpreter.
++By default it does not inspect the import / from statements found in the
++buffer. This means completion of names defined in the buffer itself (classes,
++functions, variables) works, but completion of members of imported modules is
++not offered.
++
++To enable completion of imported module members, set: >
++ let g:pythoncomplete_allow_import = 1
++<
++WARNING: enabling this causes omni-completion to execute the import statements
++found in the buffer through Python's import machinery, which runs the imported
++modules' top-level code. Only enable this for code you trust.
+
+ QF QUICKFIX *qf.vim* *ft-qf-plugin*
+
+--
+2.34.1
+
diff --git a/meta/recipes-support/vim/files/CVE-2026-52859.patch b/meta/recipes-support/vim/files/CVE-2026-52859.patch
new file mode 100644
index 00000000000..472d7c06401
--- /dev/null
+++ b/meta/recipes-support/vim/files/CVE-2026-52859.patch
@@ -0,0 +1,274 @@
+From 63680c6d3d52477817b49cd1a66e7aabe8a7aa19 Mon Sep 17 00:00:00 2001
+From: Christian Brabandt <cb@256bit.org>
+Date: Sat, 30 May 2026 16:34:40 +0000
+Subject: [PATCH] patch 9.2.0565: [security]: out-of-bounds read in
+ update_snapshot()
+
+Problem: Out-of-bounds read in update_snapshot() when a terminal cell
+ fills all VTERM_MAX_CHARS_PER_CELL slots (a base character
+ plus five combining marks): the loop over cell.chars[] has no
+ upper bound and libvterm leaves the array unterminated when full, so
+ it reads past the array and appends out-of-bounds values to a
+ buffer sized for only VTERM_MAX_CHARS_PER_CELL characters.
+Solution: Bound the loop with i < VTERM_MAX_CHARS_PER_CELL, mirroring
+ the loop in handle_pushline() (Christian Brabandt).
+
+Signed-off-by: Christian Brabandt <cb@256bit.org>
+
+Upstream-Status: Backport [https://github.com/vim/vim/commit/63680c6d3d52477817b49cd1a66e7aabe8a7aa19]
+CVE: CVE-2026-52859
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ src/terminal.c | 3 +-
+ src/testdir/samples/combining_chars.txt | 200 ++++++++++++++++++++++++
+ src/testdir/test_terminal3.vim | 15 ++
+ 3 files changed, 217 insertions(+), 1 deletion(-)
+ create mode 100644 src/testdir/samples/combining_chars.txt
+
+diff --git a/src/terminal.c b/src/terminal.c
+index 78990ac..527f1b9 100644
+--- a/src/terminal.c
++++ b/src/terminal.c
+@@ -2080,7 +2080,8 @@ update_snapshot(term_T *term)
+ int i;
+ int c;
+
+- for (i = 0; (c = cell.chars[i]) > 0 || i == 0; ++i)
++ for (i = 0; i < VTERM_MAX_CHARS_PER_CELL &&
++ ((c = cell.chars[i]) > 0 || i == 0); ++i)
+ ga.ga_len += utf_char2bytes(c == NUL ? ' ' : c,
+ (char_u *)ga.ga_data + ga.ga_len);
+ }
+diff --git a/src/testdir/samples/combining_chars.txt b/src/testdir/samples/combining_chars.txt
+new file mode 100644
+index 0000000..d9a3c17
+--- /dev/null
++++ b/src/testdir/samples/combining_chars.txt
+@@ -0,0 +1,200 @@
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́
++á́́́́ጁ
++á́́́́ጁ
++á́́́́ጁ
++á́́́́ጁ
++á́́́́ጁ
++á́́́́ጁ
++á́́́́ጁ
++á́́́́ጁ
++á́́́́ጁ
++á́́́́ጁ
+diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim
+index cb1946f..c02801e 100644
+--- a/src/testdir/test_terminal3.vim
++++ b/src/testdir/test_terminal3.vim
+@@ -1051,4 +1051,19 @@ func Test_terminal_max_combining_chars()
+ exe buf . "bwipe!"
+ endfunc
+
++func Test_terminal_output_combining_chars()
++ CheckUnix
++ new
++ let cmd = "cat samples/combining_chars.txt"
++ let buf = term_start(cmd, {'curwin': 1, 'term_finish': 'open', 'term_rows': 10, 'term_cols': 30})
++ call WaitForAssert({-> assert_match('finished', term_getstatus(buf))})
++ call TermWait(buf)
++ let lines = getbufline(buf, 1, '$')
++ " get byte lengths to confirm combining chars present
++ let lens = map(copy(lines), 'len(v:val)')
++ let expected = repeat([11], 190) + repeat([14], 10)
++ call assert_equal(expected, lens)
++ bw!
++endfunc
++
+ " vim: shiftwidth=2 sts=2 expandtab
+--
+2.34.1
+
diff --git a/meta/recipes-support/vim/files/CVE-2026-52860.patch b/meta/recipes-support/vim/files/CVE-2026-52860.patch
new file mode 100644
index 00000000000..52a18415ce1
--- /dev/null
+++ b/meta/recipes-support/vim/files/CVE-2026-52860.patch
@@ -0,0 +1,446 @@
+From c8c63673bc4253212820626aeeb75999d9a539d2 Mon Sep 17 00:00:00 2001
+From: Christian Brabandt <cb@256bit.org>
+Date: Thu, 4 Jun 2026 21:06:09 +0000
+Subject: [PATCH] patch 9.2.0597: [security]: possible code execution with
+ python complete
+
+Problem: [security]: another possible code execution with python complete
+ (David Carliez)
+Solution: Strip default expressions and annotations from generated
+ source for pythoncomplete and python3complete.
+
+Github Security Advisory:
+https://github.com/vim/vim/security/advisories/GHSA-65p9-mwwx-7468
+
+Signed-off-by: Christian Brabandt <cb@256bit.org>
+
+Upstream-Status: Backport [https://github.com/vim/vim/commit/c8c63673bc4253212820626aeeb75999d9a539d2]
+CVE: CVE-2026-52860
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ runtime/autoload/python3complete.vim | 43 +++-
+ runtime/autoload/pythoncomplete.vim | 43 +++-
+ src/testdir/Make_all.mak | 2 +
+ src/testdir/test_plugin_python3complete.vim | 224 ++++++++++++++++++++
+ 4 files changed, 304 insertions(+), 8 deletions(-)
+ create mode 100644 src/testdir/test_plugin_python3complete.vim
+
+diff --git a/runtime/autoload/python3complete.vim b/runtime/autoload/python3complete.vim
+index aba3412..a031424 100644
+--- a/runtime/autoload/python3complete.vim
++++ b/runtime/autoload/python3complete.vim
+@@ -1,8 +1,8 @@
+ "python3complete.vim - Omni Completion for python
+ " Maintainer: <vacancy>
+ " Previous Maintainer: Aaron Griffin <aaronmgriffin@gmail.com>
+-" Version: 0.9
+-" Last Updated: 2022 Mar 30
++" Version: 0.10
++" Last Updated: 2026 Jun 04
+ "
+ " Roland Puntaier: this file contains adaptations for python3 and is parallel to pythoncomplete.vim
+ "
+@@ -17,6 +17,11 @@
+ " v 0.10 by Vim project
+ " * disables importing local modules, unless the global Vim variable
+ " g:pythoncomplete_allow_import is set to non-zero
++" * strip default values and annotations from function parameter lists
++" before exec(), and whitelist class base lists to dotted names: the
++" previous code passed buffer-supplied expressions to exec() which
++" Python evaluates at definition time, allowing arbitrary code
++" execution via crafted def/class headers
+ "
+ " v 0.9
+ " * Fixed docstring parsing for classes and functions
+@@ -100,6 +105,24 @@ warnings.simplefilter(action='ignore', category=FutureWarning)
+
+ import sys, tokenize, io, types
+ from token import NAME, DEDENT, NEWLINE, STRING
++import re
++
++# Used by Class.get_code(): a base class expression is only included in the
++# code passed to exec() if it is a pure dotted name (e.g. "Base", "mod.Base",
++# "pkg.sub.Cls"). Anything containing calls, subscripts, "=", ":" or other
++# operators is dropped, since exec()-ing it would evaluate buffer-supplied
++# expressions. See the security note in the file header.
++_DOTTED_NAME_RE = re.compile(r'^[A-Za-z_]\w*(\s*\.\s*[A-Za-z_]\w*)*$')
++
++def _strip_param(p):
++ # Return the bare parameter name from a parameter spec harvested by
++ # _parenparse(), discarding any default value or annotation. Default
++ # values and annotations would otherwise be evaluated by exec() at
++ # function-definition time. Star prefixes ("*args", "**kw") and bare
++ # "*" / "/" are preserved as written.
++ p = p.split('=', 1)[0]
++ p = p.split(':', 1)[0]
++ return p.strip()
+
+ debugstmts=[]
+ def dbg(s): debugstmts.append(s)
+@@ -347,7 +370,13 @@ class Class(Scope):
+ return c
+ def get_code(self):
+ str = '%sclass %s' % (self.currentindent(),self.name)
+- if len(self.supers) > 0: str += '(%s)' % ','.join(self.supers)
++ # Only include base class expressions that are pure dotted names.
++ # Anything else (calls, subscripts, conditionals, ...) is dropped
++ # because exec() would evaluate it at class-definition time. See
++ # the security note in the file header.
++ safe_supers = [s.strip() for s in self.supers
++ if _DOTTED_NAME_RE.match(s.strip())]
++ if len(safe_supers) > 0: str += '(%s)' % ','.join(safe_supers)
+ str += ':\n'
+ if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n'
+ if len(self.subscopes) > 0:
+@@ -364,8 +393,14 @@ class Function(Scope):
+ def copy_decl(self,indent=0):
+ return Function(self.name,self.params,indent, self.docstr)
+ def get_code(self):
++ # Strip default values and annotations from each parameter before
++ # joining: exec() evaluates these at definition time and a hostile
++ # buffer could otherwise execute arbitrary code via crafted def
++ # headers. See file header for details.
++ safe_params = [_strip_param(p) for p in self.params]
++ safe_params = [p for p in safe_params if p]
+ str = "%sdef %s(%s):\n" % \
+- (self.currentindent(),self.name,','.join(self.params))
++ (self.currentindent(),self.name,','.join(safe_params))
+ if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n'
+ str += "%spass\n" % self.childindent()
+ return str
+diff --git a/runtime/autoload/pythoncomplete.vim b/runtime/autoload/pythoncomplete.vim
+index 1014776..39b1efd 100644
+--- a/runtime/autoload/pythoncomplete.vim
++++ b/runtime/autoload/pythoncomplete.vim
+@@ -1,8 +1,8 @@
+ "pythoncomplete.vim - Omni Completion for python
+ " Maintainer: <vacancy>
+ " Previous Maintainer: Aaron Griffin <aaronmgriffin@gmail.com>
+-" Version: 0.9
+-" Last Updated: 2020 Oct 9
++" Version: 0.10
++" Last Updated: 2026 Jun 04
+ "
+ " Changes
+ " TODO:
+@@ -15,6 +15,11 @@
+ " v 0.10 by Vim project
+ " * disables importing local modules, unless the global Vim variable
+ " g:pythoncomplete_allow_import is set to non-zero
++" * strip default values and annotations from function parameter lists
++" before exec(), and whitelist class base lists to dotted names: the
++" previous code passed buffer-supplied expressions to exec() which
++" Python evaluates at definition time, allowing arbitrary code
++" execution via crafted def/class headers
+ "
+ " v 0.9
+ " * Fixed docstring parsing for classes and functions
+@@ -95,6 +100,24 @@ function! s:DefPython()
+ python << PYTHONEOF
+ import sys, tokenize, cStringIO, types
+ from token import NAME, DEDENT, NEWLINE, STRING
++import re
++
++# Used by Class.get_code(): a base class expression is only included in the
++# code passed to exec() if it is a pure dotted name (e.g. "Base", "mod.Base",
++# "pkg.sub.Cls"). Anything containing calls, subscripts, "=", ":" or other
++# operators is dropped, since exec()-ing it would evaluate buffer-supplied
++# expressions. See the security note in the file header.
++_DOTTED_NAME_RE = re.compile(r'^[A-Za-z_]\w*(\s*\.\s*[A-Za-z_]\w*)*$')
++
++def _strip_param(p):
++ # Return the bare parameter name from a parameter spec harvested by
++ # _parenparse(), discarding any default value or annotation. Default
++ # values and annotations would otherwise be evaluated by exec() at
++ # function-definition time. Star prefixes ("*args", "**kw") and bare
++ # "*" / "/" are preserved as written.
++ p = p.split('=', 1)[0]
++ p = p.split(':', 1)[0]
++ return p.strip()
+
+ debugstmts=[]
+ def dbg(s): debugstmts.append(s)
+@@ -362,7 +385,13 @@ class Class(Scope):
+ return c
+ def get_code(self):
+ str = '%sclass %s' % (self.currentindent(),self.name)
+- if len(self.supers) > 0: str += '(%s)' % ','.join(self.supers)
++ # Only include base class expressions that are pure dotted names.
++ # Anything else (calls, subscripts, conditionals, ...) is dropped
++ # because exec() would evaluate it at class-definition time. See
++ # the security note in the file header.
++ safe_supers = [s.strip() for s in self.supers
++ if _DOTTED_NAME_RE.match(s.strip())]
++ if len(safe_supers) > 0: str += '(%s)' % ','.join(safe_supers)
+ str += ':\n'
+ if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n'
+ if len(self.subscopes) > 0:
+@@ -379,8 +408,14 @@ class Function(Scope):
+ def copy_decl(self,indent=0):
+ return Function(self.name,self.params,indent, self.docstr)
+ def get_code(self):
++ # Strip default values and annotations from each parameter before
++ # joining: exec() evaluates these at definition time and a hostile
++ # buffer could otherwise execute arbitrary code via crafted def
++ # headers. See file header for details.
++ safe_params = [_strip_param(p) for p in self.params]
++ safe_params = [p for p in safe_params if p]
+ str = "%sdef %s(%s):\n" % \
+- (self.currentindent(),self.name,','.join(self.params))
++ (self.currentindent(),self.name,','.join(safe_params))
+ if len(self.docstr) > 0: str += self.childindent()+'"""'+self.docstr+'"""\n'
+ str += "%spass\n" % self.childindent()
+ return str
+diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
+index 0d4aeb0..87545b7 100644
+--- a/src/testdir/Make_all.mak
++++ b/src/testdir/Make_all.mak
+@@ -247,6 +247,7 @@ NEW_TESTS = \
+ test_plugin_helptoc \
+ test_plugin_man \
+ test_plugin_matchparen \
++ test_plugin_python3complete \
+ test_plugin_tar \
+ test_plugin_termdebug \
+ test_plugin_tohtml \
+@@ -520,6 +521,7 @@ NEW_TESTS_RES = \
+ test_plugin_helptoc.res \
+ test_plugin_man.res \
+ test_plugin_matchparen.res \
++ test_plugin_python3complete.res \
+ test_plugin_tar.res \
+ test_plugin_termdebug.res \
+ test_plugin_tohtml.res \
+diff --git a/src/testdir/test_plugin_python3complete.vim b/src/testdir/test_plugin_python3complete.vim
+new file mode 100644
+index 0000000..e2b0c66
+--- /dev/null
++++ b/src/testdir/test_plugin_python3complete.vim
+@@ -0,0 +1,224 @@
++" Tests for the Python omni-completion plugin (runtime/autoload/python3complete.vim).
++"
++CheckFeature python3
++
++" Run omni-completion against the given buffer contents and assert that the
++" marker file was not created. Pre-patch behaviour exec()s reconstructed
++" def/class headers, which evaluates the buffer-supplied expression and
++" creates the marker file. Post-patch, the expressions are stripped.
++func s:CompleteAndExpectNoMarker(buffer_lines, marker_path, msg)
++ call delete(a:marker_path)
++ defer delete(a:marker_path)
++ let g:pythoncomplete_allow_import = 0
++ new
++ setfiletype python
++ call setline(1, a:buffer_lines)
++ call cursor(line('$'), col([line('$'), '$']))
++
++ " The PoC trigger -- direct invocation of the omnifunc with an empty base.
++ " This is the same path Vim takes for CTRL-X CTRL-O.
++ silent! call python3complete#Complete(0, '')
++
++ call assert_false(filereadable(a:marker_path),
++ \ a:msg . ' (marker ' . a:marker_path . ' was created)')
++
++ bwipe!
++ unlet! g:pythoncomplete_allow_import
++endfunc
++
++func Test_python3complete_no_exec_via_function_default()
++ let marker = tempname()
++ call s:CompleteAndExpectNoMarker([
++ \ 'def f(x=open(' . string(marker) . ', "w").close()):',
++ \ ' pass',
++ \ 'f.',
++ \ ], marker,
++ \ 'function default expression was evaluated during omni-completion')
++endfunc
++
++func Test_python3complete_no_exec_via_function_annotation()
++ let marker = tempname()
++ call s:CompleteAndExpectNoMarker([
++ \ 'def f(x: open(' . string(marker) . ', "w").close()):',
++ \ ' pass',
++ \ 'f.',
++ \ ], marker,
++ \ 'function annotation expression was evaluated during omni-completion')
++endfunc
++
++func Test_python3complete_no_exec_via_class_base()
++ let marker = tempname()
++ " "or object" gives the class a valid base after the side-effecting
++ " open().close() expression returns None. Without "or object" the
++ " exec would raise TypeError, but the file would still be created
++ " before the exception -- the assertion would still hold. Using
++ " "or object" keeps the buffer parseable as valid Python.
++ call s:CompleteAndExpectNoMarker([
++ \ 'class Foo(open(' . string(marker) . ', "w").close() or object):',
++ \ ' pass',
++ \ 'Foo.',
++ \ ], marker,
++ \ 'class base expression was evaluated during omni-completion')
++endfunc
++
++func Test_python3complete_no_exec_with_multiple_params()
++ " The strip must apply to every parameter, not just the first.
++ let marker = tempname()
++ call s:CompleteAndExpectNoMarker([
++ \ 'def f(a, b=1, c=open(' . string(marker) . ', "w").close(), d=2):',
++ \ ' pass',
++ \ 'f.',
++ \ ], marker,
++ \ 'non-first parameter default was evaluated during omni-completion')
++endfunc
++
++func Test_python3complete_no_exec_via_starargs_default()
++ " "*args" and "**kw" must still be preserved after stripping; ensure a
++ " default following them is also stripped.
++ let marker = tempname()
++ call s:CompleteAndExpectNoMarker([
++ \ 'def f(*args, key=open(' . string(marker) . ', "w").close(), **kw):',
++ \ ' pass',
++ \ 'f.',
++ \ ], marker,
++ \ 'keyword-only default after *args was evaluated during omni-completion')
++endfunc
++
++func Test_python3complete_normal_completion_still_works()
++ " Positive control: completion against a buffer with a legitimate class
++ " must still produce completion items. The stripping logic should not
++ " break the normal completion path.
++ let g:pythoncomplete_allow_import = 0
++
++ new
++ setfiletype python
++ call setline(1, [
++ \ 'class MyHelper:',
++ \ ' def alpha(self): pass',
++ \ ' def beta(self): pass',
++ \ 'h = MyHelper()',
++ \ 'h.',
++ \ ])
++ call cursor(5, 3)
++
++ " First call returns the column to start completion at; second returns
++ " the list of completion items.
++ let start = python3complete#Complete(1, '')
++ call assert_true(start >= 0,
++ \ 'python3complete#Complete(1, "") returned ' . start)
++
++ let items = python3complete#Complete(0, '')
++ " Items should be a list (possibly empty if the parser can't resolve "h",
++ " but should not be a parse error from our stripping changes).
++ call assert_equal(type([]), type(items),
++ \ 'python3complete#Complete(0, "") did not return a list')
++
++ bwipe!
++ unlet! g:pythoncomplete_allow_import
++endfunc
++
++func Test_python3complete_inherited_completion_via_dotted_base()
++ " Positive control for the class-base whitelist: a dotted-name base class
++ " (the common, safe case) must still be carried into the reconstructed
++ " source so that completion on a subclass can resolve inherited members.
++ let g:pythoncomplete_allow_import = 0
++
++ new
++ setfiletype python
++ call setline(1, [
++ \ 'class Base:',
++ \ ' def shared(self): pass',
++ \ 'class Derived(Base):',
++ \ ' def own(self): pass',
++ \ 'd = Derived()',
++ \ 'd.',
++ \ ])
++ call cursor(6, 3)
++
++ let items = python3complete#Complete(0, '')
++ call assert_equal(type([]), type(items),
++ \ 'completion against a subclass with a dotted base did not return a list')
++
++ bwipe!
++ unlet! g:pythoncomplete_allow_import
++endfunc
++
++" Build a tiny Python module that creates a marker file as a side effect of
++" being imported, add its directory to sys.path, run omni-completion against
++" a buffer containing `import vimtest_marker_mod`, and report whether the
++" marker file was created. Used by the two allow_import tests below.
++func s:RunImportCompletion(allow_import_value)
++ let g:pythoncomplete_allow_import = a:allow_import_value
++ let marker = tempname()
++ let module_dir = tempname()
++ call mkdir(module_dir, 'R')
++
++ call writefile([
++ \ 'open(' . string(marker) . ', "w").close()',
++ \ ], module_dir . '/vimtest_marker_mod.py')
++
++ defer delete(marker)
++
++ " Pass module_dir to Python via a g: variable so vim.eval() can read it.
++ let g:pythoncomplete_test_module_dir = module_dir
++ py3 << EOF
++import sys, vim
++_p = vim.eval('g:pythoncomplete_test_module_dir')
++if _p not in sys.path:
++ sys.path.insert(0, _p)
++# Drop any cached copy so the module body re-runs and the marker side
++# effect fires on import.
++sys.modules.pop('vimtest_marker_mod', None)
++EOF
++
++ new
++ setfiletype python
++ call setline(1, [
++ \ 'import vimtest_marker_mod',
++ \ 'vimtest_marker_mod.',
++ \ ])
++ call cursor(2, 2)
++
++ silent! call python3complete#Complete(0, '')
++
++ let ran = filereadable(marker)
++
++ bwipe!
++ unlet g:pythoncomplete_allow_import
++
++ " Teardown: restore sys.path, drop the cached module so a subsequent
++ " test run starts clean, clean up the temp module dir.
++ py3 << EOF
++import sys, vim
++_p = vim.eval('g:pythoncomplete_test_module_dir')
++if _p in sys.path:
++ sys.path.remove(_p)
++sys.modules.pop('vimtest_marker_mod', None)
++EOF
++ unlet g:pythoncomplete_test_module_dir
++ call delete(module_dir, 'rf')
++ call delete(marker)
++ unlet! g:pythoncomplete_allow_import
++
++ return ran
++endfunc
++
++func Test_python3complete_allow_import_off_blocks_imports()
++ " GHSA-52mc-rq6p-rc7c mitigation: with the default flag value (0), an
++ " `import` line harvested from the buffer must NOT be exec()'d. The
++ " marker module's side effect (creating a file when its body runs) is
++ " the observable proof that the exec did or did not happen.
++ call assert_false(s:RunImportCompletion(0),
++ \ 'g:pythoncomplete_allow_import=0 did not block the buffer import')
++endfunc
++
++func Test_python3complete_allow_import_on_runs_imports()
++ " Symmetric positive control: with the flag set to non-zero, the harvested
++ " import IS exec()'d and the module loads. Without this control the
++ " negative test above could pass for unrelated reasons (e.g. completion
++ " failing to parse the buffer at all).
++ call assert_true(s:RunImportCompletion(1),
++ \ 'g:pythoncomplete_allow_import=1 did not run the buffer import')
++endfunc
++
++" vim: shiftwidth=2 sts=2 expandtab
+--
+2.34.1
+
diff --git a/meta/recipes-support/vim/vim.inc b/meta/recipes-support/vim/vim.inc
index 9a4b21f5305..d69a337b4e8 100644
--- a/meta/recipes-support/vim/vim.inc
+++ b/meta/recipes-support/vim/vim.inc
@@ -33,6 +33,9 @@ SRC_URI = "git://github.com/vim/vim.git;branch=master;protocol=https \
file://CVE-2026-45130.patch \
file://CVE-2026-46483.patch \
file://CVE-2026-28420.patch \
+ file://CVE-2026-52858.patch \
+ file://CVE-2026-52859.patch \
+ file://CVE-2026-52860.patch \
"
PV .= ".1683"
^ permalink raw reply related
* [OE-core][wrynose][PATCH 3/8] openssh: Fix CVE-2026-59998
From: Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco) @ 2026-07-20 17:55 UTC (permalink / raw)
To: openembedded-core; +Cc: xe-linux-external, Devansh Patel
In-Reply-To: <20260720175518.3546447-1-devanshp@cisco.com>
From: Devansh Patel <devanshp@cisco.com>
This patch applies the upstream OpenSSH 10.4p1 backport for
CVE-2026-59998. The upstream fix commit is referenced in [1],
and the public CVE advisory is referenced in [2].
[1] https://github.com/openssh/openssh-portable/commit/8058c5bdb507591b79ec926221fbe6fcc296d432
[2] https://www.cve.org/CVERecord?id=CVE-2026-59998
Signed-off-by: Devansh Patel <devanshp@cisco.com>
---
.../openssh/openssh/CVE-2026-59998.patch | 36 +++++++++++++++++++
.../openssh/openssh_10.3p1.bb | 1 +
2 files changed, 37 insertions(+)
create mode 100644 meta/recipes-connectivity/openssh/openssh/CVE-2026-59998.patch
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2026-59998.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2026-59998.patch
new file mode 100644
index 0000000000..3e15fe19fa
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2026-59998.patch
@@ -0,0 +1,36 @@
+From 94a089cd331eeea77ffd6fd715e61d281c3b97c3 Mon Sep 17 00:00:00 2001
+From: "djm@openbsd.org" <djm@openbsd.org>
+Date: Wed, 24 Jun 2026 06:55:12 +0000
+Subject: [PATCH] upstream: mention a caveat regarding
+ GSSAPIStrictAcceptorCheck in
+
+some environments
+
+OpenBSD-Commit-ID: aa7158d8f22cb34063c1c2d3cbcf30a9489847c2
+
+CVE: CVE-2026-59998
+Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/8058c5bdb507591b79ec926221fbe6fcc296d432]
+
+Backport Changes:
+- Omitted the upstream OpenBSD revision and Mdocdate-only hunks in
+ sshd_config.5 and retained the Wrynose OpenSSH 10.3p1 values because
+ this stable backport carries only the security-relevant documentation.
+
+(cherry picked from commit 8058c5bdb507591b79ec926221fbe6fcc296d432)
+Signed-off-by: Devansh Patel <devanshp@cisco.com>
+---
+ sshd_config.5 | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sshd_config.5 b/sshd_config.5
+index 3f5e29812..22b9039d2 100644
+--- a/sshd_config.5
++++ b/sshd_config.5
+@@ -769,6 +769,7 @@ machine's default store.
+ This facility is provided to assist with operation on multi homed machines.
+ The default is
+ .Cm yes .
++This option may not be effective in Windows Active Directory environments.
+ .It Cm HostbasedAcceptedAlgorithms
+ Specifies the signature algorithms that will be accepted for hostbased
+ authentication as a list of comma-separated patterns.
diff --git a/meta/recipes-connectivity/openssh/openssh_10.3p1.bb b/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
index 87bd417b2d..b9f2a37c57 100644
--- a/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
+++ b/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
@@ -26,6 +26,7 @@ SRC_URI = "https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.ta
file://0001-regress-banner.sh-log-input-and-output-files-on-erro.patch \
file://CVE-2026-59999.patch \
file://CVE-2026-59997.patch \
+ file://CVE-2026-59998.patch \
"
SRC_URI[sha256sum] = "56682a36bb92dcf4b4f016fd8ec8e74059b79a8de25c15d670d731e7d18e45f4"
--
2.35.6
^ permalink raw reply related
* [OE-core][wrynose][PATCH 7/8] openssh: Fix CVE-2026-60002
From: Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco) @ 2026-07-20 17:55 UTC (permalink / raw)
To: openembedded-core; +Cc: xe-linux-external, Devansh Patel
In-Reply-To: <20260720175518.3546447-1-devanshp@cisco.com>
From: Devansh Patel <devanshp@cisco.com>
This patch applies the upstream OpenSSH 10.4p1 backport for
CVE-2026-60002. The upstream fix commit is referenced in [1],
and the public CVE advisory is referenced in [2].
[1] https://github.com/openssh/openssh-portable/commit/e8bdfb151a356d0171fea4194dd205fbb252be23
[2] https://www.cve.org/CVERecord?id=CVE-2026-60002
Signed-off-by: Devansh Patel <devanshp@cisco.com>
---
.../openssh/openssh/CVE-2026-60002.patch | 225 ++++++++++++++++++
.../openssh/openssh_10.3p1.bb | 1 +
2 files changed, 226 insertions(+)
create mode 100644 meta/recipes-connectivity/openssh/openssh/CVE-2026-60002.patch
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2026-60002.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2026-60002.patch
new file mode 100644
index 0000000000..85937279a2
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2026-60002.patch
@@ -0,0 +1,225 @@
+From b571549bc93e95f0d3d563094f825544228501de Mon Sep 17 00:00:00 2001
+From: "djm@openbsd.org" <djm@openbsd.org>
+Date: Mon, 6 Jul 2026 07:49:58 +0000
+Subject: [PATCH] upstream: fix ownership and lifetime of several bits of
+ client
+
+state that need to persist for the life of the connection, especially the
+cached hostkey that was being incorrectly freed early on some paths, possibly
+allowing its use after free.
+
+Reported by Zhenpeng (Leo) Lin from depthfirst.com
+
+OpenBSD-Commit-ID: faaa6ad72e7d69d41fa8b197b606265b7d9bc73f
+
+CVE: CVE-2026-60002
+Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/e8bdfb151a356d0171fea4194dd205fbb252be23]
+
+Backport Changes:
+- Omitted the upstream OpenBSD revision-only hunks in ssh.c,
+ sshconnect.c, sshconnect.h, and sshconnect2.c and retained the Wrynose
+ OpenSSH 10.3p1 revisions because this stable backport carries only the
+ functional security changes.
+
+(cherry picked from commit e8bdfb151a356d0171fea4194dd205fbb252be23)
+Signed-off-by: Devansh Patel <devanshp@cisco.com>
+---
+ ssh.c | 24 ++----------------------
+ sshconnect.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
+ sshconnect.h | 7 +++++--
+ sshconnect2.c | 20 +++++++++++---------
+ 4 files changed, 63 insertions(+), 35 deletions(-)
+
+diff --git a/ssh.c b/ssh.c
+index 531f28eb2..efb8930f4 100644
+--- a/ssh.c
++++ b/ssh.c
+@@ -612,26 +612,6 @@ set_addrinfo_port(struct addrinfo *addrs, int port)
+ }
+ }
+
+-static void
+-ssh_conn_info_free(struct ssh_conn_info *cinfo)
+-{
+- if (cinfo == NULL)
+- return;
+- free(cinfo->conn_hash_hex);
+- free(cinfo->shorthost);
+- free(cinfo->uidstr);
+- free(cinfo->keyalias);
+- free(cinfo->thishost);
+- free(cinfo->host_arg);
+- free(cinfo->portstr);
+- free(cinfo->remhost);
+- free(cinfo->remuser);
+- free(cinfo->homedir);
+- free(cinfo->locuser);
+- free(cinfo->jmphost);
+- free(cinfo);
+-}
+-
+ /*
+ * Main program for the ssh client.
+ */
+@@ -1799,8 +1779,8 @@ main(int ac, char **av)
+ ssh_signal(SIGCHLD, main_sigchld_handler);
+
+ /* Log into the remote system. Never returns if the login fails. */
+- ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr,
+- options.port, pw, timeout_ms, cinfo);
++ ssh_login(ssh, &sensitive_data, host, &hostaddr, options.port,
++ pw, timeout_ms, cinfo);
+
+ /* We no longer need the private host keys. Clear them now. */
+ if (sensitive_data.nkeys != 0) {
+diff --git a/sshconnect.c b/sshconnect.c
+index 4384277a6..3d338ff23 100644
+--- a/sshconnect.c
++++ b/sshconnect.c
+@@ -70,6 +70,49 @@ extern char *__progname;
+ static int show_other_keys(struct hostkeys *, struct sshkey *);
+ static void warn_changed_key(struct sshkey *);
+
++void
++ssh_conn_info_free(struct ssh_conn_info *cinfo)
++{
++ if (cinfo == NULL)
++ return;
++ free(cinfo->conn_hash_hex);
++ free(cinfo->shorthost);
++ free(cinfo->uidstr);
++ free(cinfo->keyalias);
++ free(cinfo->thishost);
++ free(cinfo->host_arg);
++ free(cinfo->portstr);
++ free(cinfo->remhost);
++ free(cinfo->remuser);
++ free(cinfo->homedir);
++ free(cinfo->locuser);
++ free(cinfo->jmphost);
++ freezero(cinfo, sizeof(*cinfo));
++}
++
++struct ssh_conn_info *
++ssh_conn_info_dup(const struct ssh_conn_info *cinfo)
++{
++ struct ssh_conn_info *ret;
++
++ if (cinfo == NULL)
++ return NULL;
++ ret = xcalloc(1, sizeof(*ret));
++ ret->conn_hash_hex = xstrdup(cinfo->conn_hash_hex);
++ ret->shorthost = xstrdup(cinfo->shorthost);
++ ret->uidstr = xstrdup(cinfo->uidstr);
++ ret->keyalias = xstrdup(cinfo->keyalias);
++ ret->thishost = xstrdup(cinfo->thishost);
++ ret->host_arg = xstrdup(cinfo->host_arg);
++ ret->portstr = xstrdup(cinfo->portstr);
++ ret->remhost = xstrdup(cinfo->remhost);
++ ret->remuser = xstrdup(cinfo->remuser);
++ ret->homedir = xstrdup(cinfo->homedir);
++ ret->locuser = xstrdup(cinfo->locuser);
++ ret->jmphost = xstrdup(cinfo->jmphost);
++ return ret;
++}
++
+ /* Expand a proxy command */
+ static char *
+ expand_proxy_command(const char *proxy_command, const char *user,
+@@ -1585,8 +1628,8 @@ warn_nonpq_kex(void)
+ */
+ void
+ ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
+- struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms,
+- const struct ssh_conn_info *cinfo)
++ struct sockaddr_storage *hostaddr, u_short port, struct passwd *pw,
++ int timeout_ms, const struct ssh_conn_info *cinfo)
+ {
+ char *host;
+ char *server_user, *local_user;
+diff --git a/sshconnect.h b/sshconnect.h
+index 4c19490da..8da0e04b9 100644
+--- a/sshconnect.h
++++ b/sshconnect.h
+@@ -76,7 +76,7 @@ int ssh_connect(struct ssh *, const char *, const char *,
+ void ssh_kill_proxy_command(void);
+
+ void ssh_login(struct ssh *, Sensitive *, const char *,
+- struct sockaddr *, u_short, struct passwd *, int,
++ struct sockaddr_storage *, u_short, struct passwd *, int,
+ const struct ssh_conn_info *);
+
+ int verify_host_key(char *, struct sockaddr *, struct sshkey *,
+@@ -85,7 +85,7 @@ int verify_host_key(char *, struct sockaddr *, struct sshkey *,
+ void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short,
+ char **, char **);
+
+-void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short,
++void ssh_kex2(struct ssh *ssh, char *, struct sockaddr_storage *, u_short,
+ const struct ssh_conn_info *);
+
+ void ssh_userauth2(struct ssh *ssh, const char *, const char *,
+@@ -101,3 +101,6 @@ void load_hostkeys_command(struct hostkeys *, const char *,
+ const struct sshkey *, const char *);
+
+ int hostkey_accepted_by_hostkeyalgs(const struct sshkey *);
++
++void ssh_conn_info_free(struct ssh_conn_info *);
++struct ssh_conn_info *ssh_conn_info_dup(const struct ssh_conn_info *);
+diff --git a/sshconnect2.c b/sshconnect2.c
+index 478a9a52f..50ac6b89d 100644
+--- a/sshconnect2.c
++++ b/sshconnect2.c
+@@ -83,7 +83,7 @@ extern Options options;
+ */
+
+ static char *xxx_host;
+-static struct sockaddr *xxx_hostaddr;
++static struct sockaddr_storage xxx_hostaddr;
+ static const struct ssh_conn_info *xxx_conn_info;
+ static int key_type_allowed(struct sshkey *, const char *);
+
+@@ -99,7 +99,7 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
+ fatal("Server host key %s not in HostKeyAlgorithms",
+ sshkey_ssh_name(hostkey));
+ }
+- if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
++ if (verify_host_key(xxx_host, (struct sockaddr *)&xxx_hostaddr, hostkey,
+ xxx_conn_info) != 0)
+ fatal("Host key verification failed.");
+ return 0;
+@@ -216,16 +216,16 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port,
+ }
+
+ void
+-ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
+- const struct ssh_conn_info *cinfo)
++ssh_kex2(struct ssh *ssh, char *host, struct sockaddr_storage *hostaddr,
++ u_short port, const struct ssh_conn_info *cinfo)
+ {
+ char *myproposal[PROPOSAL_MAX];
+ char *all_key, *hkalgs = NULL;
+ int r, use_known_hosts_order = 0;
+
+- xxx_host = host;
+- xxx_hostaddr = hostaddr;
+- xxx_conn_info = cinfo;
++ xxx_host = xstrdup(host);
++ xxx_hostaddr = *hostaddr;
++ xxx_conn_info = ssh_conn_info_dup(cinfo);
+
+ if (options.rekey_limit || options.rekey_interval)
+ ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
+@@ -248,8 +248,10 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
+ fatal_fr(r, "kex_assemble_namelist");
+ free(all_key);
+
+- if (use_known_hosts_order)
+- hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo);
++ if (use_known_hosts_order) {
++ hkalgs = order_hostkeyalgs(host, (struct sockaddr *)hostaddr,
++ port, cinfo);
++ }
+
+ kex_proposal_populate_entries(ssh, myproposal,
+ options.kex_algorithms, options.ciphers, options.macs,
diff --git a/meta/recipes-connectivity/openssh/openssh_10.3p1.bb b/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
index dba0dcaa8a..d3d00b994d 100644
--- a/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
+++ b/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
@@ -30,6 +30,7 @@ SRC_URI = "https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.ta
file://CVE-2026-59996.patch \
file://CVE-2026-59995.patch \
file://CVE-2026-60001.patch \
+ file://CVE-2026-60002.patch \
"
SRC_URI[sha256sum] = "56682a36bb92dcf4b4f016fd8ec8e74059b79a8de25c15d670d731e7d18e45f4"
--
2.35.6
^ permalink raw reply related
* [OE-core][wrynose][PATCH 5/8] openssh: Fix CVE-2026-59995
From: Devansh Patel -X (devanshp - E INFOCHIPS PRIVATE LIMITED at Cisco) @ 2026-07-20 17:55 UTC (permalink / raw)
To: openembedded-core; +Cc: xe-linux-external, Devansh Patel
In-Reply-To: <20260720175518.3546447-1-devanshp@cisco.com>
From: Devansh Patel <devanshp@cisco.com>
This patch applies the upstream OpenSSH 10.4p1 backport for
CVE-2026-59995. The upstream fix commit is referenced in [1],
and the public CVE advisory is referenced in [2].
[1] https://github.com/openssh/openssh-portable/commit/1b39f39657d2e58f8ec57341581a39bbf0be645b
[2] https://www.cve.org/CVERecord?id=CVE-2026-59995
Signed-off-by: Devansh Patel <devanshp@cisco.com>
---
.../openssh/openssh/CVE-2026-59995.patch | 44 +++++++++++++++++++
.../openssh/openssh_10.3p1.bb | 1 +
2 files changed, 45 insertions(+)
create mode 100644 meta/recipes-connectivity/openssh/openssh/CVE-2026-59995.patch
diff --git a/meta/recipes-connectivity/openssh/openssh/CVE-2026-59995.patch b/meta/recipes-connectivity/openssh/openssh/CVE-2026-59995.patch
new file mode 100644
index 0000000000..ac1712eec2
--- /dev/null
+++ b/meta/recipes-connectivity/openssh/openssh/CVE-2026-59995.patch
@@ -0,0 +1,44 @@
+From 02e4b3cfd0bef64381921cdb9d6a21b1f50fdb74 Mon Sep 17 00:00:00 2001
+From: "djm@openbsd.org" <djm@openbsd.org>
+Date: Mon, 29 Jun 2026 01:47:21 +0000
+Subject: [PATCH] upstream: avoid download to server-controlled path when
+ performing
+
+download on the commandline. From Swival scanner
+
+OpenBSD-Commit-ID: d1b2c44305fdfe6d51eed9ecc727e59478bf311f
+
+CVE: CVE-2026-59995
+Upstream-Status: Backport [https://github.com/openssh/openssh-portable/commit/1b39f39657d2e58f8ec57341581a39bbf0be645b]
+
+Backport Changes:
+- Omitted the upstream OpenBSD revision-only hunk in sftp.c and retained
+ the Wrynose OpenSSH 10.3p1 revision because this stable backport carries
+ only the functional security change.
+
+(cherry picked from commit 1b39f39657d2e58f8ec57341581a39bbf0be645b)
+Signed-off-by: Devansh Patel <devanshp@cisco.com>
+---
+ sftp.c | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/sftp.c b/sftp.c
+index eebb166e8..33c8364e3 100644
+--- a/sftp.c
++++ b/sftp.c
+@@ -2287,13 +2287,8 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
+ return (-1);
+ }
+ } else {
+- /* XXX this is wrong wrt quoting */
+- snprintf(cmd, sizeof cmd, "get%s %s%s%s",
+- global_aflag ? " -a" : "", dir,
+- file2 == NULL ? "" : " ",
+- file2 == NULL ? "" : file2);
+- err = parse_dispatch_command(conn, cmd,
+- &remote_path, startdir, 1, 0);
++ err = process_get(conn, dir, file2, remote_path, 0, 0,
++ global_aflag, 0);
+ free(dir);
+ free(startdir);
+ free(remote_path);
diff --git a/meta/recipes-connectivity/openssh/openssh_10.3p1.bb b/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
index 807e718ffb..4aa81214e0 100644
--- a/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
+++ b/meta/recipes-connectivity/openssh/openssh_10.3p1.bb
@@ -28,6 +28,7 @@ SRC_URI = "https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${PV}.ta
file://CVE-2026-59997.patch \
file://CVE-2026-59998.patch \
file://CVE-2026-59996.patch \
+ file://CVE-2026-59995.patch \
"
SRC_URI[sha256sum] = "56682a36bb92dcf4b4f016fd8ec8e74059b79a8de25c15d670d731e7d18e45f4"
--
2.35.6
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox