summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
Diffstat (limited to 'meta')
-rw-r--r--meta/classes/cross.bbclass36
-rw-r--r--meta/lib/oeqa/runtime/cases/buildcpio.py2
-rw-r--r--meta/lib/oeqa/sdk/cases/buildcpio.py4
-rw-r--r--meta/lib/oeqa/selftest/cases/meta_ide.py2
-rw-r--r--meta/recipes-bsp/grub/files/CVE-2025-61661.patch40
-rw-r--r--meta/recipes-bsp/grub/files/CVE-2025-61662.patch72
-rw-r--r--meta/recipes-bsp/grub/files/CVE-2025-61663_61664.patch64
-rw-r--r--meta/recipes-bsp/grub/grub2.inc3
-rw-r--r--meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11961-01.patch38
-rw-r--r--meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11961-02.patch433
-rw-r--r--meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11964.patch33
-rw-r--r--meta/recipes-connectivity/libpcap/libpcap_1.10.1.bb3
-rw-r--r--meta/recipes-core/dropbear/dropbear.inc1
-rw-r--r--meta/recipes-core/dropbear/dropbear/CVE-2019-6111.patch157
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-13601-01.patch125
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-13601-02.patch128
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-01.patch69
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-02.patch240
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-03.patch150
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14512.patch70
-rw-r--r--meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb6
-rw-r--r--meta/recipes-core/images/build-appliance-image_15.0.0.bb2
-rw-r--r--meta/recipes-core/util-linux/util-linux.inc2
-rw-r--r--meta/recipes-core/util-linux/util-linux/CVE-2025-14104-01.patch33
-rw-r--r--meta/recipes-core/util-linux/util-linux/CVE-2025-14104-02.patch28
-rw-r--r--meta/recipes-devtools/binutils/binutils-2.38.inc5
-rw-r--r--meta/recipes-devtools/binutils/binutils/0048-CVE-2025-11494.patch43
-rw-r--r--meta/recipes-devtools/binutils/binutils/0049-CVE-2025-11839.patch32
-rw-r--r--meta/recipes-devtools/binutils/binutils/0050-CVE-2025-11840.patch37
-rw-r--r--meta/recipes-devtools/binutils/binutils/CVE-2025-1181-pre.patch149
-rw-r--r--meta/recipes-devtools/binutils/binutils/CVE-2025-1181.patch342
-rw-r--r--meta/recipes-devtools/go/go-1.17.13.inc6
-rw-r--r--meta/recipes-devtools/go/go-1.18/CVE-2025-58187-1.patch (renamed from meta/recipes-devtools/go/go-1.18/CVE-2025-58187.patch)0
-rw-r--r--meta/recipes-devtools/go/go-1.18/CVE-2025-58187-2.patch516
-rw-r--r--meta/recipes-devtools/go/go-1.18/CVE-2025-61727.patch229
-rw-r--r--meta/recipes-devtools/go/go-1.18/CVE-2025-61729.patch172
-rw-r--r--meta/recipes-devtools/go/go-1.21/CVE-2023-39323.patch55
-rw-r--r--meta/recipes-devtools/pseudo/files/0001-configure-Prune-PIE-flags.patch44
-rw-r--r--meta/recipes-devtools/pseudo/files/glibc238.patch65
-rw-r--r--meta/recipes-devtools/pseudo/files/older-glibc-symbols.patch4
-rw-r--r--meta/recipes-devtools/pseudo/pseudo.inc7
-rw-r--r--meta/recipes-devtools/pseudo/pseudo_git.bb6
-rw-r--r--meta/recipes-devtools/python/python3-urllib3/CVE-2025-66418.patch74
-rw-r--r--meta/recipes-devtools/python/python3-urllib3_1.26.20.bb1
-rw-r--r--meta/recipes-devtools/python/python3/CVE-2025-13836.patch163
-rw-r--r--meta/recipes-devtools/python/python3_3.10.19.bb1
-rw-r--r--meta/recipes-devtools/qemu/qemu.inc4
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2025-12464.patch70
-rw-r--r--meta/recipes-devtools/rsync/files/CVE-2025-10158.patch36
-rw-r--r--meta/recipes-devtools/rsync/rsync_3.2.7.bb1
-rw-r--r--meta/recipes-extended/cups/cups.inc3
-rw-r--r--meta/recipes-extended/cups/cups/0001-conf.c-Fix-stopping-scheduler-on-unknown-directive.patch43
-rw-r--r--meta/recipes-extended/cups/cups/CVE-2025-58436.patch630
-rw-r--r--meta/recipes-extended/cups/cups/CVE-2025-61915.patch487
-rw-r--r--meta/recipes-extended/libarchive/libarchive/CVE-2025-60753-01.patch (renamed from meta/recipes-extended/libarchive/libarchive/CVE-2025-60753.patch)0
-rw-r--r--meta/recipes-extended/libarchive/libarchive/CVE-2025-60753-02.patch46
-rw-r--r--meta/recipes-extended/libarchive/libarchive_3.6.2.bb3
-rw-r--r--meta/recipes-support/curl/curl/CVE-2025-14017.patch115
-rw-r--r--meta/recipes-support/curl/curl/CVE-2025-15079.patch32
-rw-r--r--meta/recipes-support/curl/curl/CVE-2025-15224.patch31
-rw-r--r--meta/recipes-support/curl/curl_7.82.0.bb3
-rw-r--r--meta/recipes-support/gnupg/gnupg/CVE-2025-68973.patch108
-rw-r--r--meta/recipes-support/gnupg/gnupg_2.3.7.bb1
-rw-r--r--meta/recipes-support/libsoup/libsoup/CVE-2025-12105.patch34
-rw-r--r--meta/recipes-support/libsoup/libsoup_3.0.7.bb1
-rw-r--r--meta/recipes-support/libxslt/libxslt/CVE-2025-11731.patch42
-rw-r--r--meta/recipes-support/libxslt/libxslt_1.1.35.bb1
67 files changed, 5261 insertions, 122 deletions
diff --git a/meta/classes/cross.bbclass b/meta/classes/cross.bbclass
index 9d951076a7..a292a98335 100644
--- a/meta/classes/cross.bbclass
+++ b/meta/classes/cross.bbclass
@@ -95,3 +95,39 @@ addtask addto_recipe_sysroot after do_populate_sysroot
95do_addto_recipe_sysroot[deptask] = "do_populate_sysroot" 95do_addto_recipe_sysroot[deptask] = "do_populate_sysroot"
96 96
97PATH:prepend = "${COREBASE}/scripts/cross-intercept:" 97PATH:prepend = "${COREBASE}/scripts/cross-intercept:"
98
99#
100# Cross task outputs can call native dependencies and even when cross
101# recipe output doesn't change it might produce different results when
102# the called native dependency is changed, e.g. clang-cross-${TARGET_ARCH}
103# contains symlink to clang binary from clang-native, but when clang-native
104# outhash is changed, clang-cross-${TARGET_ARCH} will still be considered
105# equivalent and target recipes aren't rebuilt with new clang binary, see
106# work around in https://github.com/kraj/meta-clang/pull/1140 to make target
107# recipes to depend directly not only on clang-cross-${TARGET_ARCH} but
108# clang-native as well.
109#
110# This can cause poor interactions with hash equivalence, since this recipes
111# output-changing dependency is "hidden" and downstream task only see that this
112# recipe has the same outhash and therefore is equivalent. This can result in
113# different output in different cases.
114#
115# To resolve this, unhide the output-changing dependency by adding its unihash
116# to this tasks outhash calculation. Unfortunately, don't know specifically
117# know which dependencies are output-changing, so we have to add all of them.
118#
119python cross_add_do_populate_sysroot_deps () {
120 current_task = "do_" + d.getVar("BB_CURRENTTASK")
121 if current_task != "do_populate_sysroot":
122 return
123
124 taskdepdata = d.getVar("BB_TASKDEPDATA", False)
125 pn = d.getVar("PN")
126 deps = {
127 dep[0]:dep[6] for dep in taskdepdata.values() if
128 dep[1] == current_task and dep[0] != pn
129 }
130
131 d.setVar("HASHEQUIV_EXTRA_SIGDATA", "\n".join("%s: %s" % (k, deps[k]) for k in sorted(deps.keys())))
132}
133SSTATECREATEFUNCS += "cross_add_do_populate_sysroot_deps"
diff --git a/meta/lib/oeqa/runtime/cases/buildcpio.py b/meta/lib/oeqa/runtime/cases/buildcpio.py
index e29bf16ccb..90abd98c40 100644
--- a/meta/lib/oeqa/runtime/cases/buildcpio.py
+++ b/meta/lib/oeqa/runtime/cases/buildcpio.py
@@ -12,7 +12,7 @@ class BuildCpioTest(OERuntimeTestCase):
12 12
13 @classmethod 13 @classmethod
14 def setUpClass(cls): 14 def setUpClass(cls):
15 uri = 'https://downloads.yoctoproject.org/mirror/sources/cpio-2.13.tar.gz' 15 uri = 'https://downloads.yoctoproject.org/mirror/sources/cpio-2.14.tar.gz'
16 cls.project = TargetBuildProject(cls.tc.target, 16 cls.project = TargetBuildProject(cls.tc.target,
17 uri, 17 uri,
18 dl_dir = cls.tc.td['DL_DIR']) 18 dl_dir = cls.tc.td['DL_DIR'])
diff --git a/meta/lib/oeqa/sdk/cases/buildcpio.py b/meta/lib/oeqa/sdk/cases/buildcpio.py
index 00088d0ea0..2e9d4f5f18 100644
--- a/meta/lib/oeqa/sdk/cases/buildcpio.py
+++ b/meta/lib/oeqa/sdk/cases/buildcpio.py
@@ -17,10 +17,10 @@ class BuildCpioTest(OESDKTestCase):
17 """ 17 """
18 def test_cpio(self): 18 def test_cpio(self):
19 with tempfile.TemporaryDirectory(prefix="cpio-", dir=self.tc.sdk_dir) as testdir: 19 with tempfile.TemporaryDirectory(prefix="cpio-", dir=self.tc.sdk_dir) as testdir:
20 tarball = self.fetch(testdir, self.td["DL_DIR"], "https://ftpmirror.gnu.org/gnu/cpio/cpio-2.13.tar.gz") 20 tarball = self.fetch(testdir, self.td["DL_DIR"], "https://ftpmirror.gnu.org/gnu/cpio/cpio-2.14.tar.gz")
21 21
22 dirs = {} 22 dirs = {}
23 dirs["source"] = os.path.join(testdir, "cpio-2.13") 23 dirs["source"] = os.path.join(testdir, "cpio-2.14")
24 dirs["build"] = os.path.join(testdir, "build") 24 dirs["build"] = os.path.join(testdir, "build")
25 dirs["install"] = os.path.join(testdir, "install") 25 dirs["install"] = os.path.join(testdir, "install")
26 26
diff --git a/meta/lib/oeqa/selftest/cases/meta_ide.py b/meta/lib/oeqa/selftest/cases/meta_ide.py
index 3dc81b20a7..1432736b7e 100644
--- a/meta/lib/oeqa/selftest/cases/meta_ide.py
+++ b/meta/lib/oeqa/selftest/cases/meta_ide.py
@@ -40,7 +40,7 @@ class MetaIDE(OESelftestTestCase):
40 def test_meta_ide_can_build_cpio_project(self): 40 def test_meta_ide_can_build_cpio_project(self):
41 dl_dir = self.td.get('DL_DIR', None) 41 dl_dir = self.td.get('DL_DIR', None)
42 self.project = SDKBuildProject(self.tmpdir_metaideQA + "/cpio/", self.environment_script_path, 42 self.project = SDKBuildProject(self.tmpdir_metaideQA + "/cpio/", self.environment_script_path,
43 "https://ftpmirror.gnu.org/gnu/cpio/cpio-2.13.tar.gz", 43 "https://ftpmirror.gnu.org/gnu/cpio/cpio-2.14.tar.gz",
44 self.tmpdir_metaideQA, self.td['DATETIME'], dl_dir=dl_dir) 44 self.tmpdir_metaideQA, self.td['DATETIME'], dl_dir=dl_dir)
45 self.project.download_archive() 45 self.project.download_archive()
46 self.assertEqual(self.project.run_configure('$CONFIGURE_FLAGS --disable-maintainer-mode','sed -i -e "/char \*program_name/d" src/global.c;'), 0, 46 self.assertEqual(self.project.run_configure('$CONFIGURE_FLAGS --disable-maintainer-mode','sed -i -e "/char \*program_name/d" src/global.c;'), 0,
diff --git a/meta/recipes-bsp/grub/files/CVE-2025-61661.patch b/meta/recipes-bsp/grub/files/CVE-2025-61661.patch
new file mode 100644
index 0000000000..9ae4f3b307
--- /dev/null
+++ b/meta/recipes-bsp/grub/files/CVE-2025-61661.patch
@@ -0,0 +1,40 @@
1From 9c2ae73b549a653f5f1bd5d4edebc50a764bad06 Mon Sep 17 00:00:00 2001
2From: Jamie <volticks@gmail.com>
3Date: Mon, 14 Jul 2025 09:52:59 +0100
4Subject: [PATCH 1/3] commands/usbtest: Use correct string length field
5
6An incorrect length field is used for buffer allocation. This leads to
7grub_utf16_to_utf8() receiving an incorrect/different length and possibly
8causing OOB write. This makes sure to use the correct length.
9
10Fixes: CVE-2025-61661
11
12CVE: CVE-2025-61661
13
14Upstream-Status: Backport
15[https://gitweb.git.savannah.gnu.org/gitweb/?p=grub.git;a=commit;h=549a9cc372fd0b96a4ccdfad0e12140476cc62a3]
16
17Reported-by: Jamie <volticks@gmail.com>
18Signed-off-by: Jamie <volticks@gmail.com>
19Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
20Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
21---
22 grub-core/commands/usbtest.c | 2 +-
23 1 file changed, 1 insertion(+), 1 deletion(-)
24
25diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c
26index 2c6d93fe6..8ef187a9a 100644
27--- a/grub-core/commands/usbtest.c
28+++ b/grub-core/commands/usbtest.c
29@@ -99,7 +99,7 @@ grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid,
30 return GRUB_USB_ERR_NONE;
31 }
32
33- *string = grub_malloc (descstr.length * 2 + 1);
34+ *string = grub_malloc (descstrp->length * 2 + 1);
35 if (! *string)
36 {
37 grub_free (descstrp);
38--
392.34.1
40
diff --git a/meta/recipes-bsp/grub/files/CVE-2025-61662.patch b/meta/recipes-bsp/grub/files/CVE-2025-61662.patch
new file mode 100644
index 0000000000..1614b00d53
--- /dev/null
+++ b/meta/recipes-bsp/grub/files/CVE-2025-61662.patch
@@ -0,0 +1,72 @@
1From c47760a907c91283bac9a8400d6975574b1d3986 Mon Sep 17 00:00:00 2001
2From: Alec Brown <alec.r.brown@oracle.com>
3Date: Thu, 21 Aug 2025 21:14:06 +0000
4Subject: [PATCH 2/3] gettext/gettext: Unregister gettext command on module
5 unload
6
7When the gettext module is loaded, the gettext command is registered but
8isn't unregistered when the module is unloaded. We need to add a call to
9grub_unregister_command() when unloading the module.
10
11Fixes: CVE-2025-61662
12
13CVE: CVE-2025-61662
14
15Upstream-Status: Backport
16[https://gitweb.git.savannah.gnu.org/gitweb/?p=grub.git;a=commit;h=8ed78fd9f0852ab218cc1f991c38e5a229e43807]
17
18Reported-by: Alec Brown <alec.r.brown@oracle.com>
19Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
20Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
21Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
22---
23 grub-core/gettext/gettext.c | 19 ++++++++++++-------
24 1 file changed, 12 insertions(+), 7 deletions(-)
25
26diff --git a/grub-core/gettext/gettext.c b/grub-core/gettext/gettext.c
27index 7a25c9d67..ef1258ee0 100644
28--- a/grub-core/gettext/gettext.c
29+++ b/grub-core/gettext/gettext.c
30@@ -502,6 +502,8 @@ grub_cmd_translate (grub_command_t cmd __attribute__ ((unused)),
31 return 0;
32 }
33
34+static grub_command_t cmd;
35+
36 GRUB_MOD_INIT (gettext)
37 {
38 const char *lang;
39@@ -521,13 +523,14 @@ GRUB_MOD_INIT (gettext)
40 grub_register_variable_hook ("locale_dir", NULL, read_main);
41 grub_register_variable_hook ("secondary_locale_dir", NULL, read_secondary);
42
43- grub_register_command_p1 ("gettext", grub_cmd_translate,
44- N_("STRING"),
45- /* TRANSLATORS: It refers to passing the string through gettext.
46- So it's "translate" in the same meaning as in what you're
47- doing now.
48- */
49- N_("Translates the string with the current settings."));
50+ cmd = grub_register_command_p1 ("gettext", grub_cmd_translate,
51+ N_("STRING"),
52+ /*
53+ * TRANSLATORS: It refers to passing the string through gettext.
54+ * So it's "translate" in the same meaning as in what you're
55+ * doing now.
56+ */
57+ N_("Translates the string with the current settings."));
58
59 /* Reload .mo file information if lang changes. */
60 grub_register_variable_hook ("lang", NULL, grub_gettext_env_write_lang);
61@@ -544,6 +547,8 @@ GRUB_MOD_FINI (gettext)
62 grub_register_variable_hook ("secondary_locale_dir", NULL, NULL);
63 grub_register_variable_hook ("lang", NULL, NULL);
64
65+ grub_unregister_command (cmd);
66+
67 grub_gettext_delete_list (&main_context);
68 grub_gettext_delete_list (&secondary_context);
69
70--
712.34.1
72
diff --git a/meta/recipes-bsp/grub/files/CVE-2025-61663_61664.patch b/meta/recipes-bsp/grub/files/CVE-2025-61663_61664.patch
new file mode 100644
index 0000000000..cdf1e4ca36
--- /dev/null
+++ b/meta/recipes-bsp/grub/files/CVE-2025-61663_61664.patch
@@ -0,0 +1,64 @@
1From a182bd873e4aa93205ecbb7845ef7f0eda99dcf5 Mon Sep 17 00:00:00 2001
2From: Alec Brown <alec.r.brown@oracle.com>
3Date: Thu, 21 Aug 2025 21:14:07 +0000
4Subject: [PATCH 3/3] normal/main: Unregister commands on module unload
5
6When the normal module is loaded, the normal and normal_exit commands
7are registered but aren't unregistered when the module is unloaded. We
8need to add calls to grub_unregister_command() when unloading the module
9for these commands.
10
11Fixes: CVE-2025-61663
12Fixes: CVE-2025-61664
13
14CVE: CVE-2025-61663 CVE-2025-61664
15
16Upstream-Status: Backport
17[https://gitweb.git.savannah.gnu.org/gitweb/?p=grub.git;a=commit;h=05d3698b8b03eccc49e53491bbd75dba15f40917]
18
19Reported-by: Alec Brown <alec.r.brown@oracle.com>
20Signed-off-by: Alec Brown <alec.r.brown@oracle.com>
21Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
22Signed-off-by: Jiaying Song <jiaying.song.cn@windriver.com>
23---
24 grub-core/normal/main.c | 12 +++++++-----
25 1 file changed, 7 insertions(+), 5 deletions(-)
26
27diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
28index a95c25e5f..9d576de7a 100644
29--- a/grub-core/normal/main.c
30+++ b/grub-core/normal/main.c
31@@ -499,7 +499,7 @@ grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
32 return 0;
33 }
34
35-static grub_command_t cmd_clear;
36+static grub_command_t cmd_clear, cmd_normal, cmd_normal_exit;
37
38 static void (*grub_xputs_saved) (const char *str);
39 static const char *features[] = {
40@@ -541,10 +541,10 @@ GRUB_MOD_INIT(normal)
41 grub_env_export ("pager");
42
43 /* Register a command "normal" for the rescue mode. */
44- grub_register_command ("normal", grub_cmd_normal,
45- 0, N_("Enter normal mode."));
46- grub_register_command ("normal_exit", grub_cmd_normal_exit,
47- 0, N_("Exit from normal mode."));
48+ cmd_normal = grub_register_command ("normal", grub_cmd_normal,
49+ 0, N_("Enter normal mode."));
50+ cmd_normal_exit = grub_register_command ("normal_exit", grub_cmd_normal_exit,
51+ 0, N_("Exit from normal mode."));
52
53 /* Reload terminal colors when these variables are written to. */
54 grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
55@@ -586,4 +586,6 @@ GRUB_MOD_FINI(normal)
56 grub_register_variable_hook ("color_highlight", NULL, NULL);
57 grub_fs_autoload_hook = 0;
58 grub_unregister_command (cmd_clear);
59+ grub_unregister_command (cmd_normal);
60+ grub_unregister_command (cmd_normal_exit);
61 }
62--
632.34.1
64
diff --git a/meta/recipes-bsp/grub/grub2.inc b/meta/recipes-bsp/grub/grub2.inc
index 94eeadfb99..4744e26693 100644
--- a/meta/recipes-bsp/grub/grub2.inc
+++ b/meta/recipes-bsp/grub/grub2.inc
@@ -60,6 +60,9 @@ SRC_URI = "${GNU_MIRROR}/grub/grub-${PV}.tar.gz \
60 file://CVE-2025-0690.patch \ 60 file://CVE-2025-0690.patch \
61 file://CVE-2025-1118.patch \ 61 file://CVE-2025-1118.patch \
62 file://CVE-2024-56738.patch \ 62 file://CVE-2024-56738.patch \
63 file://CVE-2025-61661.patch \
64 file://CVE-2025-61662.patch \
65 file://CVE-2025-61663_61664.patch \
63" 66"
64 67
65SRC_URI[sha256sum] = "23b64b4c741569f9426ed2e3d0e6780796fca081bee4c99f62aa3f53ae803f5f" 68SRC_URI[sha256sum] = "23b64b4c741569f9426ed2e3d0e6780796fca081bee4c99f62aa3f53ae803f5f"
diff --git a/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11961-01.patch b/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11961-01.patch
new file mode 100644
index 0000000000..73c3ab3f5c
--- /dev/null
+++ b/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11961-01.patch
@@ -0,0 +1,38 @@
1From 7224be0fe2f4beb916b7b69141f478facd0f0634 Mon Sep 17 00:00:00 2001
2From: Denis Ovsienko <denis@ovsienko.info>
3Date: Sat, 27 Dec 2025 21:36:11 +0000
4Subject: [PATCH] Rename one of the xdtoi() copies to simplify backporting.
5
6CVE: CVE-2025-11961
7Upstream-Status: Backport [https://github.com/the-tcpdump-group/libpcap/commit/7224be0fe2f4beb916b7b69141f478facd0f0634]
8Signed-off-by: Peter Marko <peter.marko@siemens.com>
9---
10 nametoaddr.c | 6 +++---
11 1 file changed, 3 insertions(+), 3 deletions(-)
12
13diff --git a/nametoaddr.c b/nametoaddr.c
14index dc75495c..bdaacbf1 100644
15--- a/nametoaddr.c
16+++ b/nametoaddr.c
17@@ -646,7 +646,7 @@ pcap_nametollc(const char *s)
18
19 /* Hex digit to 8-bit unsigned integer. */
20 static inline u_char
21-xdtoi(u_char c)
22+pcapint_xdtoi(u_char c)
23 {
24 if (c >= '0' && c <= '9')
25 return (u_char)(c - '0');
26@@ -728,10 +728,10 @@ pcap_ether_aton(const char *s)
27 while (*s) {
28 if (*s == ':' || *s == '.' || *s == '-')
29 s += 1;
30- d = xdtoi(*s++);
31+ d = pcapint_xdtoi(*s++);
32 if (PCAP_ISXDIGIT(*s)) {
33 d <<= 4;
34- d |= xdtoi(*s++);
35+ d |= pcapint_xdtoi(*s++);
36 }
37 *ep++ = d;
38 }
diff --git a/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11961-02.patch b/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11961-02.patch
new file mode 100644
index 0000000000..0b0dc5ac40
--- /dev/null
+++ b/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11961-02.patch
@@ -0,0 +1,433 @@
1From b2d2f9a9a0581c40780bde509f7cc715920f1c02 Mon Sep 17 00:00:00 2001
2From: Denis Ovsienko <denis@ovsienko.info>
3Date: Fri, 19 Dec 2025 17:31:13 +0000
4Subject: [PATCH] CVE-2025-11961: Fix OOBR and OOBW in pcap_ether_aton().
5
6pcap_ether_aton() has for a long time required its string argument to be
7a well-formed MAC-48 address, which is always the case when the argument
8comes from other libpcap code, so the function has never validated the
9input and used a simple loop to parse any of the three common MAC-48
10address formats. However, the function has also been a part of the
11public API, so calling it directly with a malformed address can cause
12the loop to read beyond the end of the input string and/or to write
13beyond the end of the allocated output buffer.
14
15To handle invalid input more appropriately, replace the simple loop with
16new functions and require the input to match a supported address format.
17
18This problem was reported by Jin Wei, Kunwei Qian and Ping Chen.
19
20(backported from commit dd08e53e9380e217ae7c7768da9cc3d7bf37bf83)
21
22CVE: CVE-2025-11961
23Upstream-Status: Backport [https://github.com/the-tcpdump-group/libpcap/commit/b2d2f9a9a0581c40780bde509f7cc715920f1c02]
24Signed-off-by: Peter Marko <peter.marko@siemens.com>
25---
26 gencode.c | 5 +
27 nametoaddr.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++----
28 2 files changed, 349 insertions(+), 23 deletions(-)
29
30diff --git a/gencode.c b/gencode.c
31index 3ddd15f8..76fb2d82 100644
32--- a/gencode.c
33+++ b/gencode.c
34@@ -7206,6 +7206,11 @@ gen_ecode(compiler_state_t *cstate, const char *s, struct qual q)
35 return (NULL);
36
37 if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
38+ /*
39+ * Because the lexer guards the input string format, in this
40+ * context the function returns NULL iff the implicit malloc()
41+ * has failed.
42+ */
43 cstate->e = pcap_ether_aton(s);
44 if (cstate->e == NULL)
45 bpf_error(cstate, "malloc");
46diff --git a/nametoaddr.c b/nametoaddr.c
47index f9fcd288..f50d0da5 100644
48--- a/nametoaddr.c
49+++ b/nametoaddr.c
50@@ -703,39 +703,360 @@ __pcap_atodn(const char *s, bpf_u_int32 *addr)
51 return(32);
52 }
53
54+// Man page: "xxxxxxxxxxxx", regexp: "^[0-9a-fA-F]{12}$".
55+static u_char
56+pcapint_atomac48_xxxxxxxxxxxx(const char *s, uint8_t *addr)
57+{
58+ if (strlen(s) == 12 &&
59+ PCAP_ISXDIGIT(s[0]) &&
60+ PCAP_ISXDIGIT(s[1]) &&
61+ PCAP_ISXDIGIT(s[2]) &&
62+ PCAP_ISXDIGIT(s[3]) &&
63+ PCAP_ISXDIGIT(s[4]) &&
64+ PCAP_ISXDIGIT(s[5]) &&
65+ PCAP_ISXDIGIT(s[6]) &&
66+ PCAP_ISXDIGIT(s[7]) &&
67+ PCAP_ISXDIGIT(s[8]) &&
68+ PCAP_ISXDIGIT(s[9]) &&
69+ PCAP_ISXDIGIT(s[10]) &&
70+ PCAP_ISXDIGIT(s[11])) {
71+ addr[0] = pcapint_xdtoi(s[0]) << 4 | pcapint_xdtoi(s[1]);
72+ addr[1] = pcapint_xdtoi(s[2]) << 4 | pcapint_xdtoi(s[3]);
73+ addr[2] = pcapint_xdtoi(s[4]) << 4 | pcapint_xdtoi(s[5]);
74+ addr[3] = pcapint_xdtoi(s[6]) << 4 | pcapint_xdtoi(s[7]);
75+ addr[4] = pcapint_xdtoi(s[8]) << 4 | pcapint_xdtoi(s[9]);
76+ addr[5] = pcapint_xdtoi(s[10]) << 4 | pcapint_xdtoi(s[11]);
77+ return 1;
78+ }
79+ return 0;
80+}
81+
82+// Man page: "xxxx.xxxx.xxxx", regexp: "^[0-9a-fA-F]{4}(\.[0-9a-fA-F]{4}){2}$".
83+static u_char
84+pcapint_atomac48_xxxx_3_times(const char *s, uint8_t *addr)
85+{
86+ const char sep = '.';
87+ if (strlen(s) == 14 &&
88+ PCAP_ISXDIGIT(s[0]) &&
89+ PCAP_ISXDIGIT(s[1]) &&
90+ PCAP_ISXDIGIT(s[2]) &&
91+ PCAP_ISXDIGIT(s[3]) &&
92+ s[4] == sep &&
93+ PCAP_ISXDIGIT(s[5]) &&
94+ PCAP_ISXDIGIT(s[6]) &&
95+ PCAP_ISXDIGIT(s[7]) &&
96+ PCAP_ISXDIGIT(s[8]) &&
97+ s[9] == sep &&
98+ PCAP_ISXDIGIT(s[10]) &&
99+ PCAP_ISXDIGIT(s[11]) &&
100+ PCAP_ISXDIGIT(s[12]) &&
101+ PCAP_ISXDIGIT(s[13])) {
102+ addr[0] = pcapint_xdtoi(s[0]) << 4 | pcapint_xdtoi(s[1]);
103+ addr[1] = pcapint_xdtoi(s[2]) << 4 | pcapint_xdtoi(s[3]);
104+ addr[2] = pcapint_xdtoi(s[5]) << 4 | pcapint_xdtoi(s[6]);
105+ addr[3] = pcapint_xdtoi(s[7]) << 4 | pcapint_xdtoi(s[8]);
106+ addr[4] = pcapint_xdtoi(s[10]) << 4 | pcapint_xdtoi(s[11]);
107+ addr[5] = pcapint_xdtoi(s[12]) << 4 | pcapint_xdtoi(s[13]);
108+ return 1;
109+ }
110+ return 0;
111+}
112+
113 /*
114- * Convert 's', which can have the one of the forms:
115+ * Man page: "xx:xx:xx:xx:xx:xx", regexp: "^[0-9a-fA-F]{1,2}(:[0-9a-fA-F]{1,2}){5}$".
116+ * Man page: "xx-xx-xx-xx-xx-xx", regexp: "^[0-9a-fA-F]{1,2}(-[0-9a-fA-F]{1,2}){5}$".
117+ * Man page: "xx.xx.xx.xx.xx.xx", regexp: "^[0-9a-fA-F]{1,2}(\.[0-9a-fA-F]{1,2}){5}$".
118+ * (Any "xx" above can be "x", which is equivalent to "0x".)
119 *
120- * "xx:xx:xx:xx:xx:xx"
121- * "xx.xx.xx.xx.xx.xx"
122- * "xx-xx-xx-xx-xx-xx"
123- * "xxxx.xxxx.xxxx"
124- * "xxxxxxxxxxxx"
125+ * An equivalent (and parametrisable for EUI-64) FSM could be implemented using
126+ * a smaller graph, but that graph would be neither acyclic nor planar nor
127+ * trivial to verify.
128 *
129- * (or various mixes of ':', '.', and '-') into a new
130- * ethernet address. Assumes 's' is well formed.
131+ * |
132+ * [.] v
133+ * +<---------- START
134+ * | |
135+ * | | [0-9a-fA-F]
136+ * | [.] v
137+ * +<--------- BYTE0_X ----------+
138+ * | | |
139+ * | | [0-9a-fA-F] |
140+ * | [.] v |
141+ * +<--------- BYTE0_XX | [:\.-]
142+ * | | |
143+ * | | [:\.-] |
144+ * | [.] v |
145+ * +<----- BYTE0_SEP_BYTE1 <-----+
146+ * | |
147+ * | | [0-9a-fA-F]
148+ * | [.] v
149+ * +<--------- BYTE1_X ----------+
150+ * | | |
151+ * | | [0-9a-fA-F] |
152+ * | [.] v |
153+ * +<--------- BYTE1_XX | <sep>
154+ * | | |
155+ * | | <sep> |
156+ * | [.] v |
157+ * +<----- BYTE1_SEP_BYTE2 <-----+
158+ * | |
159+ * | | [0-9a-fA-F]
160+ * | [.] v
161+ * +<--------- BYTE2_X ----------+
162+ * | | |
163+ * | | [0-9a-fA-F] |
164+ * | [.] v |
165+ * +<--------- BYTE2_XX | <sep>
166+ * | | |
167+ * | | <sep> |
168+ * | [.] v |
169+ * +<----- BYTE2_SEP_BYTE3 <-----+
170+ * | |
171+ * | | [0-9a-fA-F]
172+ * | [.] v
173+ * +<--------- BYTE3_X ----------+
174+ * | | |
175+ * | | [0-9a-fA-F] |
176+ * | [.] v |
177+ * +<--------- BYTE3_XX | <sep>
178+ * | | |
179+ * | | <sep> |
180+ * | [.] v |
181+ * +<----- BYTE3_SEP_BYTE4 <-----+
182+ * | |
183+ * | | [0-9a-fA-F]
184+ * | [.] v
185+ * +<--------- BYTE4_X ----------+
186+ * | | |
187+ * | | [0-9a-fA-F] |
188+ * | [.] v |
189+ * +<--------- BYTE4_XX | <sep>
190+ * | | |
191+ * | | <sep> |
192+ * | [.] v |
193+ * +<----- BYTE4_SEP_BYTE5 <-----+
194+ * | |
195+ * | | [0-9a-fA-F]
196+ * | [.] v
197+ * +<--------- BYTE5_X ----------+
198+ * | | |
199+ * | | [0-9a-fA-F] |
200+ * | [.] v |
201+ * +<--------- BYTE5_XX | \0
202+ * | | |
203+ * | | \0 |
204+ * | | v
205+ * +--> (reject) +---------> (accept)
206+ *
207+ */
208+static u_char
209+pcapint_atomac48_x_xx_6_times(const char *s, uint8_t *addr)
210+{
211+ enum {
212+ START,
213+ BYTE0_X,
214+ BYTE0_XX,
215+ BYTE0_SEP_BYTE1,
216+ BYTE1_X,
217+ BYTE1_XX,
218+ BYTE1_SEP_BYTE2,
219+ BYTE2_X,
220+ BYTE2_XX,
221+ BYTE2_SEP_BYTE3,
222+ BYTE3_X,
223+ BYTE3_XX,
224+ BYTE3_SEP_BYTE4,
225+ BYTE4_X,
226+ BYTE4_XX,
227+ BYTE4_SEP_BYTE5,
228+ BYTE5_X,
229+ BYTE5_XX,
230+ } fsm_state = START;
231+ uint8_t buf[6];
232+ const char *seplist = ":.-";
233+ char sep;
234+
235+ while (*s) {
236+ switch (fsm_state) {
237+ case START:
238+ if (PCAP_ISXDIGIT(*s)) {
239+ buf[0] = pcapint_xdtoi(*s);
240+ fsm_state = BYTE0_X;
241+ break;
242+ }
243+ goto reject;
244+ case BYTE0_X:
245+ if (strchr(seplist, *s)) {
246+ sep = *s;
247+ fsm_state = BYTE0_SEP_BYTE1;
248+ break;
249+ }
250+ if (PCAP_ISXDIGIT(*s)) {
251+ buf[0] = buf[0] << 4 | pcapint_xdtoi(*s);
252+ fsm_state = BYTE0_XX;
253+ break;
254+ }
255+ goto reject;
256+ case BYTE0_XX:
257+ if (strchr(seplist, *s)) {
258+ sep = *s;
259+ fsm_state = BYTE0_SEP_BYTE1;
260+ break;
261+ }
262+ goto reject;
263+ case BYTE0_SEP_BYTE1:
264+ if (PCAP_ISXDIGIT(*s)) {
265+ buf[1] = pcapint_xdtoi(*s);
266+ fsm_state = BYTE1_X;
267+ break;
268+ }
269+ goto reject;
270+ case BYTE1_X:
271+ if (*s == sep) {
272+ fsm_state = BYTE1_SEP_BYTE2;
273+ break;
274+ }
275+ if (PCAP_ISXDIGIT(*s)) {
276+ buf[1] = buf[1] << 4 | pcapint_xdtoi(*s);
277+ fsm_state = BYTE1_XX;
278+ break;
279+ }
280+ goto reject;
281+ case BYTE1_XX:
282+ if (*s == sep) {
283+ fsm_state = BYTE1_SEP_BYTE2;
284+ break;
285+ }
286+ goto reject;
287+ case BYTE1_SEP_BYTE2:
288+ if (PCAP_ISXDIGIT(*s)) {
289+ buf[2] = pcapint_xdtoi(*s);
290+ fsm_state = BYTE2_X;
291+ break;
292+ }
293+ goto reject;
294+ case BYTE2_X:
295+ if (*s == sep) {
296+ fsm_state = BYTE2_SEP_BYTE3;
297+ break;
298+ }
299+ if (PCAP_ISXDIGIT(*s)) {
300+ buf[2] = buf[2] << 4 | pcapint_xdtoi(*s);
301+ fsm_state = BYTE2_XX;
302+ break;
303+ }
304+ goto reject;
305+ case BYTE2_XX:
306+ if (*s == sep) {
307+ fsm_state = BYTE2_SEP_BYTE3;
308+ break;
309+ }
310+ goto reject;
311+ case BYTE2_SEP_BYTE3:
312+ if (PCAP_ISXDIGIT(*s)) {
313+ buf[3] = pcapint_xdtoi(*s);
314+ fsm_state = BYTE3_X;
315+ break;
316+ }
317+ goto reject;
318+ case BYTE3_X:
319+ if (*s == sep) {
320+ fsm_state = BYTE3_SEP_BYTE4;
321+ break;
322+ }
323+ if (PCAP_ISXDIGIT(*s)) {
324+ buf[3] = buf[3] << 4 | pcapint_xdtoi(*s);
325+ fsm_state = BYTE3_XX;
326+ break;
327+ }
328+ goto reject;
329+ case BYTE3_XX:
330+ if (*s == sep) {
331+ fsm_state = BYTE3_SEP_BYTE4;
332+ break;
333+ }
334+ goto reject;
335+ case BYTE3_SEP_BYTE4:
336+ if (PCAP_ISXDIGIT(*s)) {
337+ buf[4] = pcapint_xdtoi(*s);
338+ fsm_state = BYTE4_X;
339+ break;
340+ }
341+ goto reject;
342+ case BYTE4_X:
343+ if (*s == sep) {
344+ fsm_state = BYTE4_SEP_BYTE5;
345+ break;
346+ }
347+ if (PCAP_ISXDIGIT(*s)) {
348+ buf[4] = buf[4] << 4 | pcapint_xdtoi(*s);
349+ fsm_state = BYTE4_XX;
350+ break;
351+ }
352+ goto reject;
353+ case BYTE4_XX:
354+ if (*s == sep) {
355+ fsm_state = BYTE4_SEP_BYTE5;
356+ break;
357+ }
358+ goto reject;
359+ case BYTE4_SEP_BYTE5:
360+ if (PCAP_ISXDIGIT(*s)) {
361+ buf[5] = pcapint_xdtoi(*s);
362+ fsm_state = BYTE5_X;
363+ break;
364+ }
365+ goto reject;
366+ case BYTE5_X:
367+ if (PCAP_ISXDIGIT(*s)) {
368+ buf[5] = buf[5] << 4 | pcapint_xdtoi(*s);
369+ fsm_state = BYTE5_XX;
370+ break;
371+ }
372+ goto reject;
373+ case BYTE5_XX:
374+ goto reject;
375+ } // switch
376+ s++;
377+ } // while
378+
379+ if (fsm_state == BYTE5_X || fsm_state == BYTE5_XX) {
380+ // accept
381+ memcpy(addr, buf, sizeof(buf));
382+ return 1;
383+ }
384+
385+reject:
386+ return 0;
387+}
388+
389+// The 'addr' argument must point to an array of at least 6 elements.
390+static int
391+pcapint_atomac48(const char *s, uint8_t *addr)
392+{
393+ return s && (
394+ pcapint_atomac48_xxxxxxxxxxxx(s, addr) ||
395+ pcapint_atomac48_xxxx_3_times(s, addr) ||
396+ pcapint_atomac48_x_xx_6_times(s, addr)
397+ );
398+}
399+
400+/*
401+ * If 's' is a MAC-48 address in one of the forms documented in pcap-filter(7)
402+ * for "ether host", return a pointer to an allocated buffer with the binary
403+ * value of the address. Return NULL on any error.
404 */
405 u_char *
406 pcap_ether_aton(const char *s)
407 {
408- register u_char *ep, *e;
409- register u_char d;
410+ uint8_t tmp[6];
411+ if (! pcapint_atomac48(s, tmp))
412+ return (NULL);
413
414- e = ep = (u_char *)malloc(6);
415+ u_char *e = malloc(6);
416 if (e == NULL)
417 return (NULL);
418-
419- while (*s) {
420- if (*s == ':' || *s == '.' || *s == '-')
421- s += 1;
422- d = pcapint_xdtoi(*s++);
423- if (PCAP_ISXDIGIT(*s)) {
424- d <<= 4;
425- d |= pcapint_xdtoi(*s++);
426- }
427- *ep++ = d;
428- }
429-
430+ memcpy(e, tmp, sizeof(tmp));
431 return (e);
432 }
433
diff --git a/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11964.patch b/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11964.patch
new file mode 100644
index 0000000000..003d21fb1f
--- /dev/null
+++ b/meta/recipes-connectivity/libpcap/libpcap/CVE-2025-11964.patch
@@ -0,0 +1,33 @@
1From 7fabf607f2319a36a0bd78444247180acb838e69 Mon Sep 17 00:00:00 2001
2From: Guy Harris <gharris@sonic.net>
3Date: Sun, 7 Sep 2025 12:51:56 -0700
4Subject: [PATCH] Fix a copy-and-pasteo in utf_16le_to_utf_8_truncated().
5
6For the four octets of UTF-8 case, it was decrementing the remaining
7buffer length by 3, not 4.
8
9Thanks to a team of developers from the Univesity of Waterloo for
10reporting this.
11
12(cherry picked from commit aebfca1aea2fc8c177760a26e8f4de27b51d1b3b)
13
14CVE: CVE-2025-11964
15Upstream-Status: Backport [https://github.com/the-tcpdump-group/libpcap/commit/7fabf607f2319a36a0bd78444247180acb838e69]
16Signed-off-by: Peter Marko <peter.marko@siemens.com>
17---
18 fmtutils.c | 2 +-
19 1 file changed, 1 insertion(+), 1 deletion(-)
20
21diff --git a/fmtutils.c b/fmtutils.c
22index a5a4fe62..78a0f8b7 100644
23--- a/fmtutils.c
24+++ b/fmtutils.c
25@@ -235,7 +235,7 @@ utf_16le_to_utf_8_truncated(const wchar_t *utf_16, char *utf_8,
26 *utf_8++ = ((uc >> 12) & 0x3F) | 0x80;
27 *utf_8++ = ((uc >> 6) & 0x3F) | 0x80;
28 *utf_8++ = ((uc >> 0) & 0x3F) | 0x80;
29- utf_8_len -= 3;
30+ utf_8_len -= 4;
31 }
32 }
33
diff --git a/meta/recipes-connectivity/libpcap/libpcap_1.10.1.bb b/meta/recipes-connectivity/libpcap/libpcap_1.10.1.bb
index 584e98c76d..5e136e3b1a 100644
--- a/meta/recipes-connectivity/libpcap/libpcap_1.10.1.bb
+++ b/meta/recipes-connectivity/libpcap/libpcap_1.10.1.bb
@@ -17,6 +17,9 @@ SRC_URI = "https://www.tcpdump.org/release/${BP}.tar.gz \
17 file://CVE-2023-7256-pre4.patch \ 17 file://CVE-2023-7256-pre4.patch \
18 file://CVE-2023-7256.patch \ 18 file://CVE-2023-7256.patch \
19 file://CVE-2024-8006.patch \ 19 file://CVE-2024-8006.patch \
20 file://CVE-2025-11961-01.patch \
21 file://CVE-2025-11961-02.patch \
22 file://CVE-2025-11964.patch \
20 " 23 "
21 24
22SRC_URI[sha256sum] = "ed285f4accaf05344f90975757b3dbfe772ba41d1c401c2648b7fa45b711bdd4" 25SRC_URI[sha256sum] = "ed285f4accaf05344f90975757b3dbfe772ba41d1c401c2648b7fa45b711bdd4"
diff --git a/meta/recipes-core/dropbear/dropbear.inc b/meta/recipes-core/dropbear/dropbear.inc
index 94059df258..cebb1e49c9 100644
--- a/meta/recipes-core/dropbear/dropbear.inc
+++ b/meta/recipes-core/dropbear/dropbear.inc
@@ -34,6 +34,7 @@ SRC_URI = "http://matt.ucc.asn.au/dropbear/releases/dropbear-${PV}.tar.bz2 \
34 file://0001-Add-m_snprintf-that-won-t-return-negative.patch \ 34 file://0001-Add-m_snprintf-that-won-t-return-negative.patch \
35 file://0001-Handle-arbitrary-length-paths-and-commands-in-multih.patch \ 35 file://0001-Handle-arbitrary-length-paths-and-commands-in-multih.patch \
36 file://CVE-2025-47203.patch \ 36 file://CVE-2025-47203.patch \
37 file://CVE-2019-6111.patch \
37 " 38 "
38 39
39PAM_SRC_URI = "file://0005-dropbear-enable-pam.patch \ 40PAM_SRC_URI = "file://0005-dropbear-enable-pam.patch \
diff --git a/meta/recipes-core/dropbear/dropbear/CVE-2019-6111.patch b/meta/recipes-core/dropbear/dropbear/CVE-2019-6111.patch
new file mode 100644
index 0000000000..84224a5f57
--- /dev/null
+++ b/meta/recipes-core/dropbear/dropbear/CVE-2019-6111.patch
@@ -0,0 +1,157 @@
1From 48a17cff6aa104b8e806ddb2191f83f1024060f1 Mon Sep 17 00:00:00 2001
2From: Matt Johnston <matt@ucc.asn.au>
3Date: Tue, 9 Dec 2025 22:59:19 +0900
4Subject: [PATCH] scp CVE-2019-6111 fix
5
6Cherry-pick from OpenSSH portable
7
8391ffc4b9d31 ("upstream: check in scp client that filenames sent during")
9
10upstream: check in scp client that filenames sent during
11
12remote->local directory copies satisfy the wildcard specified by the user.
13
14This checking provides some protection against a malicious server
15sending unexpected filenames, but it comes at a risk of rejecting wanted
16files due to differences between client and server wildcard expansion rules.
17
18For this reason, this also adds a new -T flag to disable the check.
19
20reported by Harry Sintonen
21fix approach suggested by markus@;
22has been in snaps for ~1wk courtesy deraadt@
23
24CVE: CVE-2019-6111
25Upstream-Status: Backport [https://github.com/mkj/dropbear/commit/48a17cff6aa104b8e806ddb2191f83f1024060f1]
26Signed-off-by: Peter Marko <peter.marko@siemens.com>
27---
28 scp.c | 38 +++++++++++++++++++++++++++++---------
29 1 file changed, 29 insertions(+), 9 deletions(-)
30
31diff --git a/scp.c b/scp.c
32index 384f2cb..bf98986 100644
33--- a/scp.c
34+++ b/scp.c
35@@ -76,6 +76,8 @@
36 #include "includes.h"
37 /*RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");*/
38
39+#include <fnmatch.h>
40+
41 #include "atomicio.h"
42 #include "compat.h"
43 #include "scpmisc.h"
44@@ -291,14 +293,14 @@ void verifydir(char *);
45
46 uid_t userid;
47 int errs, remin, remout;
48-int pflag, iamremote, iamrecursive, targetshouldbedirectory;
49+int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
50
51 #define CMDNEEDS 64
52 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
53
54 int response(void);
55 void rsource(char *, struct stat *);
56-void sink(int, char *[]);
57+void sink(int, char *[], const char *);
58 void source(int, char *[]);
59 void tolocal(int, char *[]);
60 void toremote(char *, int, char *[]);
61@@ -325,8 +327,8 @@ main(int argc, char **argv)
62 args.list = NULL;
63 addargs(&args, "%s", ssh_program);
64
65- fflag = tflag = 0;
66- while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
67+ fflag = Tflag = tflag = 0;
68+ while ((ch = getopt(argc, argv, "dfl:prtTvBCc:i:P:q1246S:o:F:")) != -1)
69 switch (ch) {
70 /* User-visible flags. */
71 case '1':
72@@ -389,9 +391,12 @@ main(int argc, char **argv)
73 setmode(0, O_BINARY);
74 #endif
75 break;
76+ case 'T':
77+ Tflag = 1;
78+ break;
79 default:
80 usage();
81- }
82+ }
83 argc -= optind;
84 argv += optind;
85
86@@ -409,7 +414,7 @@ main(int argc, char **argv)
87 }
88 if (tflag) {
89 /* Receive data. */
90- sink(argc, argv);
91+ sink(argc, argv, NULL);
92 exit(errs != 0);
93 }
94 if (argc < 2)
95@@ -590,7 +595,7 @@ tolocal(int argc, char **argv)
96 continue;
97 }
98 xfree(bp);
99- sink(1, argv + argc - 1);
100+ sink(1, argv + argc - 1, src);
101 (void) close(remin);
102 remin = remout = -1;
103 }
104@@ -823,7 +828,7 @@ bwlimit(int amount)
105 }
106
107 void
108-sink(int argc, char **argv)
109+sink(int argc, char **argv, const char *src)
110 {
111 static BUF buffer;
112 struct stat stb;
113@@ -837,6 +842,7 @@ sink(int argc, char **argv)
114 off_t size, statbytes;
115 int setimes, targisdir, wrerrno = 0;
116 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
117+ char *src_copy = NULL, *restrict_pattern = NULL;
118 struct timeval tv[2];
119
120 #define atime tv[0]
121@@ -858,6 +864,17 @@ sink(int argc, char **argv)
122 (void) atomicio(vwrite, remout, "", 1);
123 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
124 targisdir = 1;
125+ if (src != NULL && !iamrecursive && !Tflag) {
126+ /*
127+ * Prepare to try to restrict incoming filenames to match
128+ * the requested destination file glob.
129+ */
130+ if ((src_copy = strdup(src)) == NULL)
131+ fatal("strdup failed");
132+ if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
133+ *restrict_pattern++ = '\0';
134+ }
135+ }
136 for (first = 1;; first = 0) {
137 cp = buf;
138 if (atomicio(read, remin, cp, 1) != 1)
139@@ -940,6 +957,9 @@ sink(int argc, char **argv)
140 run_err("error: unexpected filename: %s", cp);
141 exit(1);
142 }
143+ if (restrict_pattern != NULL &&
144+ fnmatch(restrict_pattern, cp, 0) != 0)
145+ SCREWUP("filename does not match request");
146 if (targisdir) {
147 static char *namebuf = NULL;
148 static size_t cursize = 0;
149@@ -978,7 +998,7 @@ sink(int argc, char **argv)
150 goto bad;
151 }
152 vect[0] = xstrdup(np);
153- sink(1, vect);
154+ sink(1, vect, src);
155 if (setimes) {
156 setimes = 0;
157 if (utimes(vect[0], tv) < 0)
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-13601-01.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-13601-01.patch
new file mode 100644
index 0000000000..7046d2405e
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-13601-01.patch
@@ -0,0 +1,125 @@
1From f28340ee62c655487972ad3c632d231ee098fb7f Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@gnome.org>
3Date: Thu, 13 Nov 2025 18:27:22 +0000
4Subject: [PATCH] gconvert: Error out if g_escape_uri_string() would overflow
5
6If the string to escape contains a very large number of unacceptable
7characters (which would need escaping), the calculation of the length of
8the escaped string could overflow, leading to a potential write off the
9end of the newly allocated string.
10
11In addition to that, the number of unacceptable characters was counted
12in a signed integer, which would overflow to become negative, making it
13easier for an attacker to craft an input string which would cause an
14out-of-bounds write.
15
16Fix that by validating the allocation length, and using an unsigned
17integer to count the number of unacceptable characters.
18
19Spotted by treeplus. Thanks to the Sovereign Tech Resilience programme
20from the Sovereign Tech Agency. ID: #YWH-PGM9867-134
21
22Signed-off-by: Philip Withnall <pwithnall@gnome.org>
23
24Fixes: #3827
25
26CVE: CVE-2025-13601
27Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/f28340ee62c655487972ad3c632d231ee098fb7f]
28Signed-off-by: Peter Marko <peter.marko@siemens.com>
29---
30 glib/gconvert.c | 36 +++++++++++++++++++++++++-----------
31 1 file changed, 25 insertions(+), 11 deletions(-)
32
33diff --git a/glib/gconvert.c b/glib/gconvert.c
34index b066dd5a8..a02d2ea73 100644
35--- a/glib/gconvert.c
36+++ b/glib/gconvert.c
37@@ -1425,8 +1425,9 @@ static const gchar hex[] = "0123456789ABCDEF";
38 /* Note: This escape function works on file: URIs, but if you want to
39 * escape something else, please read RFC-2396 */
40 static gchar *
41-g_escape_uri_string (const gchar *string,
42- UnsafeCharacterSet mask)
43+g_escape_uri_string (const gchar *string,
44+ UnsafeCharacterSet mask,
45+ GError **error)
46 {
47 #define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
48
49@@ -1434,7 +1435,7 @@ g_escape_uri_string (const gchar *string,
50 gchar *q;
51 gchar *result;
52 int c;
53- gint unacceptable;
54+ size_t unacceptable;
55 UnsafeCharacterSet use_mask;
56
57 g_return_val_if_fail (mask == UNSAFE_ALL
58@@ -1451,7 +1452,14 @@ g_escape_uri_string (const gchar *string,
59 if (!ACCEPTABLE (c))
60 unacceptable++;
61 }
62-
63+
64+ if (unacceptable >= (G_MAXSIZE - (p - string)) / 2)
65+ {
66+ g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
67+ _("The URI is too long"));
68+ return NULL;
69+ }
70+
71 result = g_malloc (p - string + unacceptable * 2 + 1);
72
73 use_mask = mask;
74@@ -1476,12 +1484,13 @@ g_escape_uri_string (const gchar *string,
75
76
77 static gchar *
78-g_escape_file_uri (const gchar *hostname,
79- const gchar *pathname)
80+g_escape_file_uri (const gchar *hostname,
81+ const gchar *pathname,
82+ GError **error)
83 {
84 char *escaped_hostname = NULL;
85- char *escaped_path;
86- char *res;
87+ char *escaped_path = NULL;
88+ char *res = NULL;
89
90 #ifdef G_OS_WIN32
91 char *p, *backslash;
92@@ -1502,10 +1511,14 @@ g_escape_file_uri (const gchar *hostname,
93
94 if (hostname && *hostname != '\0')
95 {
96- escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST);
97+ escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST, error);
98+ if (escaped_hostname == NULL)
99+ goto out;
100 }
101
102- escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH);
103+ escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH, error);
104+ if (escaped_path == NULL)
105+ goto out;
106
107 res = g_strconcat ("file://",
108 (escaped_hostname) ? escaped_hostname : "",
109@@ -1513,6 +1526,7 @@ g_escape_file_uri (const gchar *hostname,
110 escaped_path,
111 NULL);
112
113+out:
114 #ifdef G_OS_WIN32
115 g_free ((char *) pathname);
116 #endif
117@@ -1832,7 +1846,7 @@ g_filename_to_uri (const gchar *filename,
118 hostname = NULL;
119 #endif
120
121- escaped_uri = g_escape_file_uri (hostname, filename);
122+ escaped_uri = g_escape_file_uri (hostname, filename, error);
123
124 return escaped_uri;
125 }
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-13601-02.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-13601-02.patch
new file mode 100644
index 0000000000..4be8d0d947
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-13601-02.patch
@@ -0,0 +1,128 @@
1From 7bd3fc372040cdf8eada7f65c32c30da52a7461d Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@gnome.org>
3Date: Thu, 13 Nov 2025 18:31:43 +0000
4Subject: [PATCH] fuzzing: Add fuzz tests for g_filename_{to,from}_uri()
5
6These functions could be called on untrusted input data, and since they
7do URI escaping/unescaping, they have non-trivial string handling code.
8
9Signed-off-by: Philip Withnall <pwithnall@gnome.org>
10
11See: #3827
12
13CVE: CVE-2025-13601
14Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/7bd3fc372040cdf8eada7f65c32c30da52a7461d]
15Signed-off-by: Peter Marko <peter.marko@siemens.com>
16---
17 fuzzing/fuzz_filename_from_uri.c | 40 ++++++++++++++++++++++++++++++++
18 fuzzing/fuzz_filename_to_uri.c | 40 ++++++++++++++++++++++++++++++++
19 fuzzing/meson.build | 2 ++
20 3 files changed, 82 insertions(+)
21 create mode 100644 fuzzing/fuzz_filename_from_uri.c
22 create mode 100644 fuzzing/fuzz_filename_to_uri.c
23
24diff --git a/fuzzing/fuzz_filename_from_uri.c b/fuzzing/fuzz_filename_from_uri.c
25new file mode 100644
26index 000000000..9b7a715f0
27--- /dev/null
28+++ b/fuzzing/fuzz_filename_from_uri.c
29@@ -0,0 +1,40 @@
30+/*
31+ * Copyright 2025 GNOME Foundation, Inc.
32+ *
33+ * SPDX-License-Identifier: LGPL-2.1-or-later
34+ *
35+ * This library is free software; you can redistribute it and/or
36+ * modify it under the terms of the GNU Lesser General Public
37+ * License as published by the Free Software Foundation; either
38+ * version 2.1 of the License, or (at your option) any later version.
39+ *
40+ * This library is distributed in the hope that it will be useful,
41+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
42+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43+ * Lesser General Public License for more details.
44+ *
45+ * You should have received a copy of the GNU Lesser General Public
46+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
47+ */
48+
49+#include "fuzz.h"
50+
51+int
52+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
53+{
54+ unsigned char *nul_terminated_data = NULL;
55+ char *filename = NULL;
56+ GError *local_error = NULL;
57+
58+ fuzz_set_logging_func ();
59+
60+ /* ignore @size (g_filename_from_uri() doesn’t support it); ensure @data is nul-terminated */
61+ nul_terminated_data = (unsigned char *) g_strndup ((const char *) data, size);
62+ filename = g_filename_from_uri ((const char *) nul_terminated_data, NULL, &local_error);
63+ g_free (nul_terminated_data);
64+
65+ g_free (filename);
66+ g_clear_error (&local_error);
67+
68+ return 0;
69+}
70diff --git a/fuzzing/fuzz_filename_to_uri.c b/fuzzing/fuzz_filename_to_uri.c
71new file mode 100644
72index 000000000..acb319203
73--- /dev/null
74+++ b/fuzzing/fuzz_filename_to_uri.c
75@@ -0,0 +1,40 @@
76+/*
77+ * Copyright 2025 GNOME Foundation, Inc.
78+ *
79+ * SPDX-License-Identifier: LGPL-2.1-or-later
80+ *
81+ * This library is free software; you can redistribute it and/or
82+ * modify it under the terms of the GNU Lesser General Public
83+ * License as published by the Free Software Foundation; either
84+ * version 2.1 of the License, or (at your option) any later version.
85+ *
86+ * This library is distributed in the hope that it will be useful,
87+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
88+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
89+ * Lesser General Public License for more details.
90+ *
91+ * You should have received a copy of the GNU Lesser General Public
92+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
93+ */
94+
95+#include "fuzz.h"
96+
97+int
98+LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
99+{
100+ unsigned char *nul_terminated_data = NULL;
101+ char *uri = NULL;
102+ GError *local_error = NULL;
103+
104+ fuzz_set_logging_func ();
105+
106+ /* ignore @size (g_filename_to_uri() doesn’t support it); ensure @data is nul-terminated */
107+ nul_terminated_data = (unsigned char *) g_strndup ((const char *) data, size);
108+ uri = g_filename_to_uri ((const char *) nul_terminated_data, NULL, &local_error);
109+ g_free (nul_terminated_data);
110+
111+ g_free (uri);
112+ g_clear_error (&local_error);
113+
114+ return 0;
115+}
116diff --git a/fuzzing/meson.build b/fuzzing/meson.build
117index addbe9071..05f936eeb 100644
118--- a/fuzzing/meson.build
119+++ b/fuzzing/meson.build
120@@ -4,6 +4,8 @@ fuzz_targets = [
121 'fuzz_date_parse',
122 'fuzz_date_time_new_from_iso8601',
123 'fuzz_dbus_message',
124+ 'fuzz_filename_from_uri',
125+ 'fuzz_filename_to_uri',
126 'fuzz_inet_address_mask_new_from_string',
127 'fuzz_inet_address_new_from_string',
128 'fuzz_inet_socket_address_new_from_string',
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-01.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-01.patch
new file mode 100644
index 0000000000..ec7b1fecaa
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-01.patch
@@ -0,0 +1,69 @@
1From 31f82e22e21bae520b7228f7f57d357fb20df8a4 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@gnome.org>
3Date: Tue, 25 Nov 2025 19:02:56 +0000
4Subject: [PATCH] gvariant-parser: Fix potential integer overflow parsing
5 (byte)strings
6
7The termination condition for parsing string and bytestring literals in
8GVariant text format input was subject to an integer overflow for input
9string (or bytestring) literals longer than `INT_MAX`.
10
11Fix that by counting as a `size_t` rather than as an `int`. The counter
12can never correctly be negative.
13
14Spotted by treeplus. Thanks to the Sovereign Tech Resilience programme
15from the Sovereign Tech Agency. ID: #YWH-PGM9867-145
16
17Signed-off-by: Philip Withnall <pwithnall@gnome.org>
18Fixes: #3834
19
20CVE: CVE-2025-14087
21Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/31f82e22e21bae520b7228f7f57d357fb20df8a4]
22Signed-off-by: Peter Marko <peter.marko@siemens.com>
23---
24 glib/gvariant-parser.c | 10 +++++-----
25 1 file changed, 5 insertions(+), 5 deletions(-)
26
27diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
28index 2f1d3db9f..2d6e9856f 100644
29--- a/glib/gvariant-parser.c
30+++ b/glib/gvariant-parser.c
31@@ -594,7 +594,7 @@ ast_resolve (AST *ast,
32 {
33 GVariant *value;
34 gchar *pattern;
35- gint i, j = 0;
36+ size_t i, j = 0;
37
38 pattern = ast_get_pattern (ast, error);
39
40@@ -1555,9 +1555,9 @@ string_free (AST *ast)
41 * No leading/trailing space allowed. */
42 static gboolean
43 unicode_unescape (const gchar *src,
44- gint *src_ofs,
45+ size_t *src_ofs,
46 gchar *dest,
47- gint *dest_ofs,
48+ size_t *dest_ofs,
49 gsize length,
50 SourceRef *ref,
51 GError **error)
52@@ -1618,7 +1618,7 @@ string_parse (TokenStream *stream,
53 gsize length;
54 gchar quote;
55 gchar *str;
56- gint i, j;
57+ size_t i, j;
58
59 token_stream_start_ref (stream, &ref);
60 token = token_stream_get (stream);
61@@ -1748,7 +1748,7 @@ bytestring_parse (TokenStream *stream,
62 gsize length;
63 gchar quote;
64 gchar *str;
65- gint i, j;
66+ size_t i, j;
67
68 token_stream_start_ref (stream, &ref);
69 token = token_stream_get (stream);
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-02.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-02.patch
new file mode 100644
index 0000000000..595f9c1b93
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-02.patch
@@ -0,0 +1,240 @@
1From ac9de0871281cf734f6e269988f90a2521582a08 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@gnome.org>
3Date: Tue, 25 Nov 2025 19:19:16 +0000
4Subject: [PATCH] gvariant-parser: Use size_t to count numbers of child
5 elements
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10Rather than using `gint`, which could overflow for arrays (or dicts, or
11tuples) longer than `INT_MAX`. There may be other limits which prevent
12parsed containers becoming that long, but we might as well make the type
13system reflect the programmer’s intention as best it can anyway.
14
15For arrays and tuples this is straightforward. For dictionaries, it’s
16slightly complicated by the fact that the code used
17`dict->n_children == -1` to indicate that the `Dictionary` struct in
18question actually represented a single freestanding dict entry. In
19GVariant text format, that would be `{1, "one"}`.
20
21The implementation previously didn’t define the semantics of
22`dict->n_children < -1`.
23
24Now, instead, change `Dictionary.n_children` to `size_t`, and define a
25magic value `DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY` to indicate that
26the `Dictionary` represents a single freestanding dict entry.
27
28This magic value is `SIZE_MAX`, and given that a dictionary entry takes
29more than one byte to represent in GVariant text format, that means it’s
30not possible to have that many entries in a parsed dictionary, so this
31magic value won’t be hit by a normal dictionary. An assertion checks
32this anyway.
33
34Spotted while working on #3834.
35
36Signed-off-by: Philip Withnall <pwithnall@gnome.org>
37
38CVE: CVE-2025-14087
39Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/ac9de0871281cf734f6e269988f90a2521582a08]
40Signed-off-by: Peter Marko <peter.marko@siemens.com>
41---
42 glib/gvariant-parser.c | 58 ++++++++++++++++++++++++------------------
43 1 file changed, 33 insertions(+), 25 deletions(-)
44
45diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
46index 2d6e9856f..519baa3f3 100644
47--- a/glib/gvariant-parser.c
48+++ b/glib/gvariant-parser.c
49@@ -647,9 +647,9 @@ static AST *parse (TokenStream *stream,
50 GError **error);
51
52 static void
53-ast_array_append (AST ***array,
54- gint *n_items,
55- AST *ast)
56+ast_array_append (AST ***array,
57+ size_t *n_items,
58+ AST *ast)
59 {
60 if ((*n_items & (*n_items - 1)) == 0)
61 *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
62@@ -658,10 +658,10 @@ ast_array_append (AST ***array,
63 }
64
65 static void
66-ast_array_free (AST **array,
67- gint n_items)
68+ast_array_free (AST **array,
69+ size_t n_items)
70 {
71- gint i;
72+ size_t i;
73
74 for (i = 0; i < n_items; i++)
75 ast_free (array[i]);
76@@ -670,11 +670,11 @@ ast_array_free (AST **array,
77
78 static gchar *
79 ast_array_get_pattern (AST **array,
80- gint n_items,
81+ size_t n_items,
82 GError **error)
83 {
84 gchar *pattern;
85- gint i;
86+ size_t i;
87
88 /* Find the pattern which applies to all children in the array, by l-folding a
89 * coalesce operation.
90@@ -706,7 +706,7 @@ ast_array_get_pattern (AST **array,
91 * pair of values.
92 */
93 {
94- int j = 0;
95+ size_t j = 0;
96
97 while (TRUE)
98 {
99@@ -891,7 +891,7 @@ typedef struct
100 AST ast;
101
102 AST **children;
103- gint n_children;
104+ size_t n_children;
105 } Array;
106
107 static gchar *
108@@ -924,7 +924,7 @@ array_get_value (AST *ast,
109 Array *array = (Array *) ast;
110 const GVariantType *childtype;
111 GVariantBuilder builder;
112- gint i;
113+ size_t i;
114
115 if (!g_variant_type_is_array (type))
116 return ast_type_error (ast, type, error);
117@@ -1010,7 +1010,7 @@ typedef struct
118 AST ast;
119
120 AST **children;
121- gint n_children;
122+ size_t n_children;
123 } Tuple;
124
125 static gchar *
126@@ -1020,7 +1020,7 @@ tuple_get_pattern (AST *ast,
127 Tuple *tuple = (Tuple *) ast;
128 gchar *result = NULL;
129 gchar **parts;
130- gint i;
131+ size_t i;
132
133 parts = g_new (gchar *, tuple->n_children + 4);
134 parts[tuple->n_children + 1] = (gchar *) ")";
135@@ -1050,7 +1050,7 @@ tuple_get_value (AST *ast,
136 Tuple *tuple = (Tuple *) ast;
137 const GVariantType *childtype;
138 GVariantBuilder builder;
139- gint i;
140+ size_t i;
141
142 if (!g_variant_type_is_tuple (type))
143 return ast_type_error (ast, type, error);
144@@ -1242,9 +1242,16 @@ typedef struct
145
146 AST **keys;
147 AST **values;
148- gint n_children;
149+
150+ /* Iff this is DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY then this struct
151+ * represents a single freestanding dict entry (`{1, "one"}`) rather than a
152+ * full dict. In the freestanding case, @keys and @values have exactly one
153+ * member each. */
154+ size_t n_children;
155 } Dictionary;
156
157+#define DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY ((size_t) -1)
158+
159 static gchar *
160 dictionary_get_pattern (AST *ast,
161 GError **error)
162@@ -1259,7 +1266,7 @@ dictionary_get_pattern (AST *ast,
163 return g_strdup ("Ma{**}");
164
165 key_pattern = ast_array_get_pattern (dict->keys,
166- abs (dict->n_children),
167+ (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) ? 1 : dict->n_children,
168 error);
169
170 if (key_pattern == NULL)
171@@ -1290,7 +1297,7 @@ dictionary_get_pattern (AST *ast,
172 return NULL;
173
174 result = g_strdup_printf ("M%s{%c%s}",
175- dict->n_children > 0 ? "a" : "",
176+ (dict->n_children > 0 && dict->n_children != DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) ? "a" : "",
177 key_char, value_pattern);
178 g_free (value_pattern);
179
180@@ -1304,7 +1311,7 @@ dictionary_get_value (AST *ast,
181 {
182 Dictionary *dict = (Dictionary *) ast;
183
184- if (dict->n_children == -1)
185+ if (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY)
186 {
187 const GVariantType *subtype;
188 GVariantBuilder builder;
189@@ -1337,7 +1344,7 @@ dictionary_get_value (AST *ast,
190 {
191 const GVariantType *entry, *key, *val;
192 GVariantBuilder builder;
193- gint i;
194+ size_t i;
195
196 if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
197 return ast_type_error (ast, type, error);
198@@ -1378,12 +1385,12 @@ static void
199 dictionary_free (AST *ast)
200 {
201 Dictionary *dict = (Dictionary *) ast;
202- gint n_children;
203+ size_t n_children;
204
205- if (dict->n_children > -1)
206- n_children = dict->n_children;
207- else
208+ if (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY)
209 n_children = 1;
210+ else
211+ n_children = dict->n_children;
212
213 ast_array_free (dict->keys, n_children);
214 ast_array_free (dict->values, n_children);
215@@ -1401,7 +1408,7 @@ dictionary_parse (TokenStream *stream,
216 maybe_wrapper, dictionary_get_value,
217 dictionary_free
218 };
219- gint n_keys, n_values;
220+ size_t n_keys, n_values;
221 gboolean only_one;
222 Dictionary *dict;
223 AST *first;
224@@ -1444,7 +1451,7 @@ dictionary_parse (TokenStream *stream,
225 goto error;
226
227 g_assert (n_keys == 1 && n_values == 1);
228- dict->n_children = -1;
229+ dict->n_children = DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY;
230
231 return (AST *) dict;
232 }
233@@ -1477,6 +1484,7 @@ dictionary_parse (TokenStream *stream,
234 }
235
236 g_assert (n_keys == n_values);
237+ g_assert (n_keys != DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY);
238 dict->n_children = n_keys;
239
240 return (AST *) dict;
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-03.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-03.patch
new file mode 100644
index 0000000000..4a474f39fc
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14087-03.patch
@@ -0,0 +1,150 @@
1From acaabfedff42e974334dd5368e6103d2845aaba6 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@gnome.org>
3Date: Tue, 25 Nov 2025 19:25:58 +0000
4Subject: [PATCH] gvariant-parser: Convert error handling code to use size_t
5
6The error handling code allows for printing out the range of input bytes
7related to a parsing error. This was previously done using `gint`, but
8the input could be longer than `INT_MAX`, so it should really be done
9using `size_t`.
10
11Spotted while working on #3834.
12
13Signed-off-by: Philip Withnall <pwithnall@gnome.org>
14
15CVE: CVE-2025-14087
16Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/acaabfedff42e974334dd5368e6103d2845aaba6]
17Signed-off-by: Peter Marko <peter.marko@siemens.com>
18---
19 glib/gvariant-parser.c | 36 +++++++++++++++++++++++-------------
20 1 file changed, 23 insertions(+), 13 deletions(-)
21
22diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
23index 519baa3f3..1b1ddd654 100644
24--- a/glib/gvariant-parser.c
25+++ b/glib/gvariant-parser.c
26@@ -88,7 +88,9 @@ g_variant_parser_get_error_quark (void)
27
28 typedef struct
29 {
30- gint start, end;
31+ /* Offsets from the start of the input, in bytes. Can be equal when referring
32+ * to a point rather than a range. The invariant `end >= start` always holds. */
33+ size_t start, end;
34 } SourceRef;
35
36 G_GNUC_PRINTF(5, 0)
37@@ -103,14 +105,16 @@ parser_set_error_va (GError **error,
38 GString *msg = g_string_new (NULL);
39
40 if (location->start == location->end)
41- g_string_append_printf (msg, "%d", location->start);
42+ g_string_append_printf (msg, "%" G_GSIZE_FORMAT, location->start);
43 else
44- g_string_append_printf (msg, "%d-%d", location->start, location->end);
45+ g_string_append_printf (msg, "%" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
46+ location->start, location->end);
47
48 if (other != NULL)
49 {
50 g_assert (other->start != other->end);
51- g_string_append_printf (msg, ",%d-%d", other->start, other->end);
52+ g_string_append_printf (msg, ",%" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
53+ other->start, other->end);
54 }
55 g_string_append_c (msg, ':');
56
57@@ -137,11 +141,15 @@ parser_set_error (GError **error,
58
59 typedef struct
60 {
61+ /* We should always have the following ordering constraint:
62+ * start <= this <= stream <= end
63+ * Additionally, unless in an error or EOF state, `this < stream`.
64+ */
65 const gchar *start;
66 const gchar *stream;
67 const gchar *end;
68
69- const gchar *this;
70+ const gchar *this; /* (nullable) */
71 } TokenStream;
72
73
74@@ -172,7 +180,7 @@ token_stream_set_error (TokenStream *stream,
75 static gboolean
76 token_stream_prepare (TokenStream *stream)
77 {
78- gint brackets = 0;
79+ gssize brackets = 0;
80 const gchar *end;
81
82 if (stream->this != NULL)
83@@ -402,7 +410,7 @@ static void
84 pattern_copy (gchar **out,
85 const gchar **in)
86 {
87- gint brackets = 0;
88+ gssize brackets = 0;
89
90 while (**in == 'a' || **in == 'm' || **in == 'M')
91 *(*out)++ = *(*in)++;
92@@ -2666,7 +2674,7 @@ g_variant_builder_add_parsed (GVariantBuilder *builder,
93 static gboolean
94 parse_num (const gchar *num,
95 const gchar *limit,
96- guint *result)
97+ size_t *result)
98 {
99 gchar *endptr;
100 gint64 bignum;
101@@ -2676,10 +2684,12 @@ parse_num (const gchar *num,
102 if (endptr != limit)
103 return FALSE;
104
105+ /* The upper bound here is more restrictive than it technically needs to be,
106+ * but should be enough for any practical situation: */
107 if (bignum < 0 || bignum > G_MAXINT)
108 return FALSE;
109
110- *result = (guint) bignum;
111+ *result = (size_t) bignum;
112
113 return TRUE;
114 }
115@@ -2690,7 +2700,7 @@ add_last_line (GString *err,
116 {
117 const gchar *last_nl;
118 gchar *chomped;
119- gint i;
120+ size_t i;
121
122 /* This is an error at the end of input. If we have a file
123 * with newlines, that's probably the empty string after the
124@@ -2835,7 +2845,7 @@ g_variant_parse_error_print_context (GError *error,
125
126 if (dash == NULL || colon < dash)
127 {
128- guint point;
129+ size_t point;
130
131 /* we have a single point */
132 if (!parse_num (error->message, colon, &point))
133@@ -2853,7 +2863,7 @@ g_variant_parse_error_print_context (GError *error,
134 /* We have one or two ranges... */
135 if (comma && comma < colon)
136 {
137- guint start1, end1, start2, end2;
138+ size_t start1, end1, start2, end2;
139 const gchar *dash2;
140
141 /* Two ranges */
142@@ -2869,7 +2879,7 @@ g_variant_parse_error_print_context (GError *error,
143 }
144 else
145 {
146- guint start, end;
147+ size_t start, end;
148
149 /* One range */
150 if (!parse_num (error->message, dash, &start) || !parse_num (dash + 1, colon, &end))
diff --git a/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14512.patch b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14512.patch
new file mode 100644
index 0000000000..fd3ba765b1
--- /dev/null
+++ b/meta/recipes-core/glib-2.0/glib-2.0/CVE-2025-14512.patch
@@ -0,0 +1,70 @@
1From 1909d8ea9297287f1ff6862968608dcf06e60523 Mon Sep 17 00:00:00 2001
2From: Philip Withnall <pwithnall@gnome.org>
3Date: Thu, 4 Dec 2025 16:37:19 +0000
4Subject: [PATCH] gfileattribute: Fix integer overflow calculating escaping for
5 byte strings
6
7The number of invalid characters in the byte string (characters which
8would have to be percent-encoded) was only stored in an `int`, which
9gave the possibility of a long string largely full of invalid
10characters overflowing this and allowing an attacker-controlled buffer
11size to be allocated.
12
13This could be triggered by an attacker controlled file attribute (of
14type `G_FILE_ATTRIBUTE_TYPE_BYTE_STRING`), such as
15`G_FILE_ATTRIBUTE_THUMBNAIL_PATH` or `G_FILE_ATTRIBUTE_STANDARD_NAME`,
16being read by user code.
17
18Spotted by Codean Labs.
19
20Signed-off-by: Philip Withnall <pwithnall@gnome.org>
21
22Fixes: #3845
23
24CVE: CVE-2025-14512
25Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/1909d8ea9297287f1ff6862968608dcf06e60523]
26Signed-off-by: Peter Marko <peter.marko@siemens.com>
27---
28 gio/gfileattribute.c | 11 +++++++++--
29 1 file changed, 9 insertions(+), 2 deletions(-)
30
31diff --git a/gio/gfileattribute.c b/gio/gfileattribute.c
32index c6fde60fa..d3083e5bd 100644
33--- a/gio/gfileattribute.c
34+++ b/gio/gfileattribute.c
35@@ -20,6 +20,7 @@
36
37 #include "config.h"
38
39+#include <stdint.h>
40 #include <string.h>
41
42 #include "gfileattribute.h"
43@@ -271,11 +272,12 @@ valid_char (char c)
44 return c >= 32 && c <= 126 && c != '\\';
45 }
46
47+/* Returns NULL on error */
48 static char *
49 escape_byte_string (const char *str)
50 {
51 size_t i, len;
52- int num_invalid;
53+ size_t num_invalid;
54 char *escaped_val, *p;
55 unsigned char c;
56 const char hex_digits[] = "0123456789abcdef";
57@@ -293,7 +295,12 @@ escape_byte_string (const char *str)
58 return g_strdup (str);
59 else
60 {
61- escaped_val = g_malloc (len + num_invalid*3 + 1);
62+ /* Check for overflow. We want to check the inequality:
63+ * !(len + num_invalid * 3 + 1 > SIZE_MAX) */
64+ if (num_invalid >= (SIZE_MAX - len) / 3)
65+ return NULL;
66+
67+ escaped_val = g_malloc (len + num_invalid * 3 + 1);
68
69 p = escaped_val;
70 for (i = 0; i < len; i++)
diff --git a/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb b/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb
index 7ba52b5c79..50701be3d0 100644
--- a/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb
+++ b/meta/recipes-core/glib-2.0/glib-2.0_2.72.3.bb
@@ -64,6 +64,12 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \
64 file://CVE-2025-4373-02.patch \ 64 file://CVE-2025-4373-02.patch \
65 file://CVE-2025-7039-01.patch \ 65 file://CVE-2025-7039-01.patch \
66 file://CVE-2025-7039-02.patch \ 66 file://CVE-2025-7039-02.patch \
67 file://CVE-2025-13601-01.patch \
68 file://CVE-2025-13601-02.patch \
69 file://CVE-2025-14087-01.patch \
70 file://CVE-2025-14087-02.patch \
71 file://CVE-2025-14087-03.patch \
72 file://CVE-2025-14512.patch \
67 " 73 "
68SRC_URI:append:class-native = " file://relocate-modules.patch" 74SRC_URI:append:class-native = " file://relocate-modules.patch"
69 75
diff --git a/meta/recipes-core/images/build-appliance-image_15.0.0.bb b/meta/recipes-core/images/build-appliance-image_15.0.0.bb
index 37328be02a..5b74c10a9a 100644
--- a/meta/recipes-core/images/build-appliance-image_15.0.0.bb
+++ b/meta/recipes-core/images/build-appliance-image_15.0.0.bb
@@ -24,7 +24,7 @@ IMAGE_FSTYPES = "wic.vmdk wic.vhd wic.vhdx"
24 24
25inherit core-image setuptools3 25inherit core-image setuptools3
26 26
27SRCREV ?= "8d5cd4a310e1807e841b25aaa46261dc24cea1eb" 27SRCREV ?= "ff118ede826a9ae45eb35025a5f7f612880fba01"
28SRC_URI = "git://git.yoctoproject.org/poky;branch=kirkstone \ 28SRC_URI = "git://git.yoctoproject.org/poky;branch=kirkstone \
29 file://Yocto_Build_Appliance.vmx \ 29 file://Yocto_Build_Appliance.vmx \
30 file://Yocto_Build_Appliance.vmxf \ 30 file://Yocto_Build_Appliance.vmxf \
diff --git a/meta/recipes-core/util-linux/util-linux.inc b/meta/recipes-core/util-linux/util-linux.inc
index c62c6d70c3..a8b505a122 100644
--- a/meta/recipes-core/util-linux/util-linux.inc
+++ b/meta/recipes-core/util-linux/util-linux.inc
@@ -42,6 +42,8 @@ SRC_URI = "${KERNELORG_MIRROR}/linux/utils/util-linux/v${MAJOR_VERSION}/util-lin
42 file://CVE-2024-28085-0004.patch \ 42 file://CVE-2024-28085-0004.patch \
43 file://CVE-2024-28085-0005.patch \ 43 file://CVE-2024-28085-0005.patch \
44 file://fstab-isolation.patch \ 44 file://fstab-isolation.patch \
45 file://CVE-2025-14104-01.patch \
46 file://CVE-2025-14104-02.patch \
45 " 47 "
46 48
47SRC_URI[sha256sum] = "634e6916ad913366c3536b6468e7844769549b99a7b2bf80314de78ab5655b83" 49SRC_URI[sha256sum] = "634e6916ad913366c3536b6468e7844769549b99a7b2bf80314de78ab5655b83"
diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2025-14104-01.patch b/meta/recipes-core/util-linux/util-linux/CVE-2025-14104-01.patch
new file mode 100644
index 0000000000..23677345c9
--- /dev/null
+++ b/meta/recipes-core/util-linux/util-linux/CVE-2025-14104-01.patch
@@ -0,0 +1,33 @@
1From aaa9e718c88d6916b003da7ebcfe38a3c88df8e6 Mon Sep 17 00:00:00 2001
2From: Mohamed Maatallah <hotelsmaatallahrecemail@gmail.com>
3Date: Sat, 24 May 2025 03:16:09 +0100
4Subject: [PATCH] Update setpwnam.c
5
6CVE: CVE-2025-14104
7Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/aaa9e718c88d6916b003da7ebcfe38a3c88df8e6]
8Signed-off-by: Peter Marko <peter.marko@siemens.com>
9---
10 login-utils/setpwnam.c | 10 ++++++----
11 1 file changed, 6 insertions(+), 4 deletions(-)
12
13diff --git a/login-utils/setpwnam.c b/login-utils/setpwnam.c
14index 3e3c1abde..95e470b5a 100644
15--- a/login-utils/setpwnam.c
16+++ b/login-utils/setpwnam.c
17@@ -126,10 +126,12 @@ int setpwnam(struct passwd *pwd, const char *prefix)
18 }
19
20 /* Is this the username we were sent to change? */
21- if (!found && linebuf[namelen] == ':' &&
22- !strncmp(linebuf, pwd->pw_name, namelen)) {
23- /* Yes! So go forth in the name of the Lord and
24- * change it! */
25+ if (!found &&
26+ strncmp(linebuf, pwd->pw_name, namelen) == 0 &&
27+ strlen(linebuf) > namelen &&
28+ linebuf[namelen] == ':') {
29+ /* Yes! But this time let’s not walk past the end of the buffer
30+ * in the name of the Lord, SUID, or anything else. */
31 if (putpwent(pwd, fp) < 0)
32 goto fail;
33 found = 1;
diff --git a/meta/recipes-core/util-linux/util-linux/CVE-2025-14104-02.patch b/meta/recipes-core/util-linux/util-linux/CVE-2025-14104-02.patch
new file mode 100644
index 0000000000..9d21db2743
--- /dev/null
+++ b/meta/recipes-core/util-linux/util-linux/CVE-2025-14104-02.patch
@@ -0,0 +1,28 @@
1From 9a36d77012c4c771f8d51eba46b6e62c29bf572a Mon Sep 17 00:00:00 2001
2From: Mohamed Maatallah <hotelsmaatallahrecemail@gmail.com>
3Date: Mon, 26 May 2025 10:06:02 +0100
4Subject: [PATCH] Update bufflen
5
6Update buflen
7
8CVE: CVE-2025-14104
9Upstream-Status: Backport [https://github.com/util-linux/util-linux/commit/9a36d77012c4c771f8d51eba46b6e62c29bf572a]
10Signed-off-by: Peter Marko <peter.marko@siemens.com>
11---
12 login-utils/setpwnam.c | 3 ++-
13 1 file changed, 2 insertions(+), 1 deletion(-)
14
15diff --git a/login-utils/setpwnam.c b/login-utils/setpwnam.c
16index 95e470b5a..7778e98f7 100644
17--- a/login-utils/setpwnam.c
18+++ b/login-utils/setpwnam.c
19@@ -99,7 +99,8 @@ int setpwnam(struct passwd *pwd, const char *prefix)
20 goto fail;
21
22 namelen = strlen(pwd->pw_name);
23-
24+ if (namelen > buflen)
25+ buflen += namelen;
26 linebuf = malloc(buflen);
27 if (!linebuf)
28 goto fail;
diff --git a/meta/recipes-devtools/binutils/binutils-2.38.inc b/meta/recipes-devtools/binutils/binutils-2.38.inc
index d5ad3c0ecb..36f9c7ce27 100644
--- a/meta/recipes-devtools/binutils/binutils-2.38.inc
+++ b/meta/recipes-devtools/binutils/binutils-2.38.inc
@@ -86,5 +86,10 @@ SRC_URI = "\
86 file://0047-CVE-2025-8225.patch \ 86 file://0047-CVE-2025-8225.patch \
87 file://CVE-2025-11412.patch \ 87 file://CVE-2025-11412.patch \
88 file://CVE-2025-11413.patch \ 88 file://CVE-2025-11413.patch \
89 file://0048-CVE-2025-11494.patch \
90 file://0049-CVE-2025-11839.patch \
91 file://0050-CVE-2025-11840.patch \
92 file://CVE-2025-1181-pre.patch \
93 file://CVE-2025-1181.patch \
89" 94"
90S = "${WORKDIR}/git" 95S = "${WORKDIR}/git"
diff --git a/meta/recipes-devtools/binutils/binutils/0048-CVE-2025-11494.patch b/meta/recipes-devtools/binutils/binutils/0048-CVE-2025-11494.patch
new file mode 100644
index 0000000000..dc4b413658
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/0048-CVE-2025-11494.patch
@@ -0,0 +1,43 @@
1From: "H.J. Lu" <hjl.tools@gmail.com>
2Date: Tue, 30 Sep 2025 08:13:56 +0800
3
4Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=b6ac5a8a5b82f0ae6a4642c8d7149b325f4cc60a]
5CVE: CVE-2025-11494
6
7Since x86 .eh_frame section may reference _GLOBAL_OFFSET_TABLE_, keep
8_GLOBAL_OFFSET_TABLE_ if there is dynamic section and the output
9.eh_frame section is non-empty.
10
11 PR ld/33499
12 * elfxx-x86.c (_bfd_x86_elf_late_size_sections): Keep
13 _GLOBAL_OFFSET_TABLE_ if there is dynamic section and the
14 output .eh_frame section is non-empty.
15
16Signed-off-by: Deepesh Varatharajan <Deepesh.Varatharajan@windriver.com>
17
18diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c
19index c054f7cd..ddc15945 100644
20--- a/bfd/elfxx-x86.c
21+++ b/bfd/elfxx-x86.c
22@@ -2447,6 +2447,8 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
23
24 if (htab->elf.sgotplt)
25 {
26+ asection *eh_frame;
27+
28 /* Don't allocate .got.plt section if there are no GOT nor PLT
29 entries and there is no reference to _GLOBAL_OFFSET_TABLE_. */
30 if ((htab->elf.hgot == NULL
31@@ -2459,7 +2461,11 @@ _bfd_x86_elf_late_size_sections (bfd *output_bfd,
32 && (htab->elf.iplt == NULL
33 || htab->elf.iplt->size == 0)
34 && (htab->elf.igotplt == NULL
35- || htab->elf.igotplt->size == 0))
36+ || htab->elf.igotplt->size == 0)
37+ && (!htab->elf.dynamic_sections_created
38+ || (eh_frame = bfd_get_section_by_name (output_bfd,
39+ ".eh_frame")) == NULL
40+ || eh_frame->rawsize == 0))
41 {
42 htab->elf.sgotplt->size = 0;
43 /* Solaris requires to keep _GLOBAL_OFFSET_TABLE_ even if it
diff --git a/meta/recipes-devtools/binutils/binutils/0049-CVE-2025-11839.patch b/meta/recipes-devtools/binutils/binutils/0049-CVE-2025-11839.patch
new file mode 100644
index 0000000000..7f2f6d553d
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/0049-CVE-2025-11839.patch
@@ -0,0 +1,32 @@
1From 12ef7d5b7b02d0023db645d86eb9d0797bc747fe Mon Sep 17 00:00:00 2001
2From: Nick Clifton <nickc@redhat.com>
3Date: Mon, 3 Nov 2025 11:49:02 +0000
4Subject: [PATCH] Remove call to abort in the DGB debug format printing code,
5 thus allowing the display of a fuzzed input file to complete without
6 triggering an abort.
7
8PR 33448
9---
10 binutils/prdbg.c | 1 -
11 1 file changed, 1 deletion(-)
12
13Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=12ef7d5b7b02d0023db645d86eb9d0797bc747fe]
14CVE: CVE-2025-11839
15
16Signed-off-by: Yash Shinde <Yash.Shinde@windriver.com>
17
18diff --git a/binutils/prdbg.c b/binutils/prdbg.c
19index c239aeb1a79..5d405c48e3d 100644
20--- a/binutils/prdbg.c
21+++ b/binutils/prdbg.c
22@@ -2449,7 +2449,6 @@ tg_tag_type (void *p, const char *name, unsigned int id,
23 t = "union class ";
24 break;
25 default:
26- abort ();
27 return false;
28 }
29
30--
312.43.7
32
diff --git a/meta/recipes-devtools/binutils/binutils/0050-CVE-2025-11840.patch b/meta/recipes-devtools/binutils/binutils/0050-CVE-2025-11840.patch
new file mode 100644
index 0000000000..3fb4db880e
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/0050-CVE-2025-11840.patch
@@ -0,0 +1,37 @@
1From f6b0f53a36820da91eadfa9f466c22f92e4256e0 Mon Sep 17 00:00:00 2001
2From: Alan Modra <amodra@gmail.com>
3Date: Mon, 3 Nov 2025 09:03:37 +1030
4Subject: [PATCH] PR 33455 SEGV in vfinfo at ldmisc.c:527
5
6A reloc howto set up with EMPTY_HOWTO has a NULL name. More than one
7place emitting diagnostics assumes a reloc howto won't have a NULL
8name.
9
10 PR 33455
11 * coffcode.h (coff_slurp_reloc_table): Don't allow a howto with
12 a NULL name.
13---
14 bfd/coffcode.h | 2 +-
15 1 file changed, 1 insertion(+), 1 deletion(-)
16
17Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=f6b0f53a36820da91eadfa9f466c22f92e4256e0]
18CVE: CVE-2025-11840
19
20Signed-off-by: Yash Shinde <Yash.Shinde@windriver.com>
21
22diff --git a/bfd/coffcode.h b/bfd/coffcode.h
23index 1e5acc0032c..ce1e39131b4 100644
24--- a/bfd/coffcode.h
25+++ b/bfd/coffcode.h
26@@ -5345,7 +5345,7 @@ coff_slurp_reloc_table (bfd * abfd, sec_ptr asect, asymbol ** symbols)
27 RTYPE2HOWTO (cache_ptr, &dst);
28 #endif /* RELOC_PROCESSING */
29
30- if (cache_ptr->howto == NULL)
31+ if (cache_ptr->howto == NULL || cache_ptr->howto->name == NULL)
32 {
33 _bfd_error_handler
34 /* xgettext:c-format */
35--
362.43.7
37
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2025-1181-pre.patch b/meta/recipes-devtools/binutils/binutils/CVE-2025-1181-pre.patch
new file mode 100644
index 0000000000..ffad871657
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/CVE-2025-1181-pre.patch
@@ -0,0 +1,149 @@
1Backported of:
2
3From 18cc11a2771d9e40180485da9a4fb660c03efac3 Mon Sep 17 00:00:00 2001
4From: Nick Clifton <nickc@redhat.com>
5Date: Wed, 5 Feb 2025 14:31:10 +0000
6Subject: [PATCH] Prevent illegal memory access when checking relocs in a
7 corrupt ELF binary.
8
9PR 32641
10
11Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/binutils/tree/debian/patches/CVE-2025-1181-pre.patch?h=ubuntu/jammy-security
12Upstream commit https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=18cc11a2771d9e40180485da9a4fb660c03efac3]
13CVE: CVE-2025-1181
14Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
15---
16 bfd/elf-bfd.h | 3 +++
17 bfd/elf64-x86-64.c | 10 +++++-----
18 bfd/elflink.c | 24 ++++++++++++++++++++++++
19 bfd/elfxx-x86.c | 20 +++++++-------------
20 4 files changed, 39 insertions(+), 18 deletions(-)
21Index: binutils-2.38/bfd/elf-bfd.h
22===================================================================
23--- binutils-2.38.orig/bfd/elf-bfd.h
24+++ binutils-2.38/bfd/elf-bfd.h
25@@ -3007,6 +3007,9 @@ extern bool _bfd_elf_maybe_set_textrel
26 extern bool _bfd_elf_add_dynamic_tags
27 (bfd *, struct bfd_link_info *, bool);
28
29+extern struct elf_link_hash_entry * _bfd_elf_get_link_hash_entry
30+ (struct elf_link_hash_entry **, unsigned int, Elf_Internal_Shdr *);
31+
32 /* Large common section. */
33 extern asection _bfd_elf_large_com_section;
34
35Index: binutils-2.38/bfd/elf64-x86-64.c
36===================================================================
37--- binutils-2.38.orig/bfd/elf64-x86-64.c
38+++ binutils-2.38/bfd/elf64-x86-64.c
39@@ -1484,7 +1484,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd
40 bool to_reloc_pc32;
41 bool abs_symbol;
42 bool local_ref;
43- asection *tsec;
44+ asection *tsec = NULL;
45 bfd_signed_vma raddend;
46 unsigned int opcode;
47 unsigned int modrm;
48@@ -1639,6 +1639,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd
49 return true;
50 }
51
52+ if (tsec == NULL)
53+ return false;
54+
55 /* Don't convert GOTPCREL relocation against large section. */
56 if (elf_section_data (tsec) != NULL
57 && (elf_section_flags (tsec) & SHF_X86_64_LARGE) != 0)
58@@ -1915,10 +1918,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struc
59 else
60 {
61 isym = NULL;
62- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
63- while (h->root.type == bfd_link_hash_indirect
64- || h->root.type == bfd_link_hash_warning)
65- h = (struct elf_link_hash_entry *) h->root.u.i.link;
66+ h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
67 }
68
69 /* Check invalid x32 relocations. */
70Index: binutils-2.38/bfd/elflink.c
71===================================================================
72--- binutils-2.38.orig/bfd/elflink.c
73+++ binutils-2.38/bfd/elflink.c
74@@ -62,6 +62,27 @@ struct elf_find_verdep_info
75 static bool _bfd_elf_fix_symbol_flags
76 (struct elf_link_hash_entry *, struct elf_info_failed *);
77
78+struct elf_link_hash_entry *
79+_bfd_elf_get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes,
80+ unsigned int symndx,
81+ Elf_Internal_Shdr * symtab_hdr)
82+{
83+ if (symndx < symtab_hdr->sh_info)
84+ return NULL;
85+
86+ struct elf_link_hash_entry *h = sym_hashes[symndx - symtab_hdr->sh_info];
87+
88+ /* The hash might be empty. See PR 32641 for an example of this. */
89+ if (h == NULL)
90+ return NULL;
91+
92+ while (h->root.type == bfd_link_hash_indirect
93+ || h->root.type == bfd_link_hash_warning)
94+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
95+
96+ return h;
97+}
98+
99 static struct elf_link_hash_entry *
100 get_ext_sym_hash (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
101 {
102@@ -75,6 +96,9 @@ get_ext_sym_hash (struct elf_reloc_cooki
103
104 h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
105
106+ if (h == NULL)
107+ return NULL;
108+
109 while (h->root.type == bfd_link_hash_indirect
110 || h->root.type == bfd_link_hash_warning)
111 h = (struct elf_link_hash_entry *) h->root.u.i.link;
112Index: binutils-2.38/bfd/elfxx-x86.c
113===================================================================
114--- binutils-2.38.orig/bfd/elfxx-x86.c
115+++ binutils-2.38/bfd/elfxx-x86.c
116@@ -973,15 +973,7 @@ _bfd_x86_elf_check_relocs (bfd *abfd,
117 goto error_return;
118 }
119
120- if (r_symndx < symtab_hdr->sh_info)
121- h = NULL;
122- else
123- {
124- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
125- while (h->root.type == bfd_link_hash_indirect
126- || h->root.type == bfd_link_hash_warning)
127- h = (struct elf_link_hash_entry *) h->root.u.i.link;
128- }
129+ h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
130
131 if (X86_NEED_DYNAMIC_RELOC_TYPE_P (is_x86_64, r_type)
132 && NEED_DYNAMIC_RELOCATION_P (is_x86_64, info, true, h, sec,
133@@ -1200,10 +1192,12 @@ _bfd_x86_elf_link_relax_section (bfd *ab
134 else
135 {
136 /* Get H and SEC for GENERATE_DYNAMIC_RELOCATION_P below. */
137- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
138- while (h->root.type == bfd_link_hash_indirect
139- || h->root.type == bfd_link_hash_warning)
140- h = (struct elf_link_hash_entry *) h->root.u.i.link;
141+ h = _bfd_elf_get_link_hash_entry (sym_hashes, r_symndx, symtab_hdr);
142+ if (h == NULL)
143+ {
144+ /* FIXMEL: Issue an error message ? */
145+ continue;
146+ }
147
148 if (h->root.type == bfd_link_hash_defined
149 || h->root.type == bfd_link_hash_defweak)
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2025-1181.patch b/meta/recipes-devtools/binutils/binutils/CVE-2025-1181.patch
new file mode 100644
index 0000000000..2bcd55795d
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/CVE-2025-1181.patch
@@ -0,0 +1,342 @@
1Backported of:
2
3From 931494c9a89558acb36a03a340c01726545eef24 Mon Sep 17 00:00:00 2001
4From: Nick Clifton <nickc@redhat.com>
5Date: Wed, 5 Feb 2025 15:43:04 +0000
6Subject: [PATCH] Add even more checks for corrupt input when processing
7 relocations for ELF files.
8
9PR 32643
10
11Upstream-Status: Backport [import from ubuntu https://git.launchpad.net/ubuntu/+source/binutils/tree/debian/patches/CVE-2025-1181.patch?h=ubuntu/jammy-security
12Upstream commit https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=931494c9a89558acb36a03a340c01726545eef24]
13CVE: CVE-2025-1181
14Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
15
16Index: binutils-2.38/bfd/elflink.c
17===================================================================
18--- binutils-2.38.orig/bfd/elflink.c
19+++ binutils-2.38/bfd/elflink.c
20@@ -62,15 +62,17 @@ struct elf_find_verdep_info
21 static bool _bfd_elf_fix_symbol_flags
22 (struct elf_link_hash_entry *, struct elf_info_failed *);
23
24-struct elf_link_hash_entry *
25-_bfd_elf_get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes,
26- unsigned int symndx,
27- Elf_Internal_Shdr * symtab_hdr)
28+static struct elf_link_hash_entry *
29+get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes,
30+ unsigned int symndx,
31+ unsigned int ext_sym_start)
32 {
33- if (symndx < symtab_hdr->sh_info)
34+ if (sym_hashes == NULL
35+ /* Guard against corrupt input. See PR 32636 for an example. */
36+ || symndx < ext_sym_start)
37 return NULL;
38
39- struct elf_link_hash_entry *h = sym_hashes[symndx - symtab_hdr->sh_info];
40+ struct elf_link_hash_entry *h = sym_hashes[symndx - ext_sym_start];
41
42 /* The hash might be empty. See PR 32641 for an example of this. */
43 if (h == NULL)
44@@ -83,29 +85,28 @@ _bfd_elf_get_link_hash_entry (struct elf
45 return h;
46 }
47
48-static struct elf_link_hash_entry *
49-get_ext_sym_hash (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
50+struct elf_link_hash_entry *
51+_bfd_elf_get_link_hash_entry (struct elf_link_hash_entry ** sym_hashes,
52+ unsigned int symndx,
53+ Elf_Internal_Shdr * symtab_hdr)
54 {
55- struct elf_link_hash_entry *h = NULL;
56-
57- if ((r_symndx >= cookie->locsymcount
58- || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
59- /* Guard against corrupt input. See PR 32636 for an example. */
60- && r_symndx >= cookie->extsymoff)
61- {
62-
63- h = cookie->sym_hashes[r_symndx - cookie->extsymoff];
64-
65- if (h == NULL)
66- return NULL;
67+ if (symtab_hdr == NULL)
68+ return NULL;
69
70- while (h->root.type == bfd_link_hash_indirect
71- || h->root.type == bfd_link_hash_warning)
72- h = (struct elf_link_hash_entry *) h->root.u.i.link;
73+ return get_link_hash_entry (sym_hashes, symndx, symtab_hdr->sh_info);
74+}
75
76- }
77+static struct elf_link_hash_entry *
78+get_ext_sym_hash_from_cookie (struct elf_reloc_cookie *cookie, unsigned long r_symndx)
79+{
80+ if (cookie == NULL || cookie->sym_hashes == NULL)
81+ return NULL;
82+
83+ if (r_symndx >= cookie->locsymcount
84+ || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
85+ return get_link_hash_entry (cookie->sym_hashes, r_symndx, cookie->extsymoff);
86
87- return h;
88+ return NULL;
89 }
90
91 asection *
92@@ -115,7 +116,7 @@ _bfd_elf_section_for_symbol (struct elf_
93 {
94 struct elf_link_hash_entry *h;
95
96- h = get_ext_sym_hash (cookie, r_symndx);
97+ h = get_ext_sym_hash_from_cookie (cookie, r_symndx);
98
99 if (h != NULL)
100 {
101@@ -8783,7 +8784,6 @@ set_symbol_value (bfd *bfd_with_globals,
102 size_t symidx,
103 bfd_vma val)
104 {
105- struct elf_link_hash_entry **sym_hashes;
106 struct elf_link_hash_entry *h;
107 size_t extsymoff = locsymcount;
108
109@@ -8806,12 +8806,12 @@ set_symbol_value (bfd *bfd_with_globals,
110
111 /* It is a global symbol: set its link type
112 to "defined" and give it a value. */
113-
114- sym_hashes = elf_sym_hashes (bfd_with_globals);
115- h = sym_hashes [symidx - extsymoff];
116- while (h->root.type == bfd_link_hash_indirect
117- || h->root.type == bfd_link_hash_warning)
118- h = (struct elf_link_hash_entry *) h->root.u.i.link;
119+ h = get_link_hash_entry (elf_sym_hashes (bfd_with_globals), symidx, extsymoff);
120+ if (h == NULL)
121+ {
122+ /* FIXMEL What should we do ? */
123+ return;
124+ }
125 h->root.type = bfd_link_hash_defined;
126 h->root.u.def.value = val;
127 h->root.u.def.section = bfd_abs_section_ptr;
128@@ -11281,10 +11281,19 @@ elf_link_input_bfd (struct elf_final_lin
129 || (elf_bad_symtab (input_bfd)
130 && flinfo->sections[symndx] == NULL))
131 {
132- struct elf_link_hash_entry *h = sym_hashes[symndx - extsymoff];
133- while (h->root.type == bfd_link_hash_indirect
134- || h->root.type == bfd_link_hash_warning)
135- h = (struct elf_link_hash_entry *) h->root.u.i.link;
136+ struct elf_link_hash_entry *h;
137+
138+ h = get_link_hash_entry (sym_hashes, symndx, extsymoff);
139+ if (h == NULL)
140+ {
141+ _bfd_error_handler
142+ /* xgettext:c-format */
143+ (_("error: %pB: unable to create group section symbol"),
144+ input_bfd);
145+ bfd_set_error (bfd_error_bad_value);
146+ return false;
147+ }
148+
149 /* Arrange for symbol to be output. */
150 h->indx = -2;
151 elf_section_data (osec)->this_hdr.sh_info = -2;
152@@ -11411,7 +11420,7 @@ elf_link_input_bfd (struct elf_final_lin
153 || (elf_bad_symtab (input_bfd)
154 && flinfo->sections[r_symndx] == NULL))
155 {
156- h = sym_hashes[r_symndx - extsymoff];
157+ h = get_link_hash_entry (sym_hashes, r_symndx, extsymoff);
158
159 /* Badly formatted input files can contain relocs that
160 reference non-existant symbols. Check here so that
161@@ -11420,17 +11429,13 @@ elf_link_input_bfd (struct elf_final_lin
162 {
163 _bfd_error_handler
164 /* xgettext:c-format */
165- (_("error: %pB contains a reloc (%#" PRIx64 ") for section %pA "
166+ (_("error: %pB contains a reloc (%#" PRIx64 ") for section '%pA' "
167 "that references a non-existent global symbol"),
168 input_bfd, (uint64_t) rel->r_info, o);
169 bfd_set_error (bfd_error_bad_value);
170 return false;
171 }
172
173- while (h->root.type == bfd_link_hash_indirect
174- || h->root.type == bfd_link_hash_warning)
175- h = (struct elf_link_hash_entry *) h->root.u.i.link;
176-
177 s_type = h->type;
178
179 /* If a plugin symbol is referenced from a non-IR file,
180@@ -11646,7 +11651,6 @@ elf_link_input_bfd (struct elf_final_lin
181 && flinfo->sections[r_symndx] == NULL))
182 {
183 struct elf_link_hash_entry *rh;
184- unsigned long indx;
185
186 /* This is a reloc against a global symbol. We
187 have not yet output all the local symbols, so
188@@ -11655,15 +11659,16 @@ elf_link_input_bfd (struct elf_final_lin
189 reloc to point to the global hash table entry
190 for this symbol. The symbol index is then
191 set at the end of bfd_elf_final_link. */
192- indx = r_symndx - extsymoff;
193- rh = elf_sym_hashes (input_bfd)[indx];
194- while (rh->root.type == bfd_link_hash_indirect
195- || rh->root.type == bfd_link_hash_warning)
196- rh = (struct elf_link_hash_entry *) rh->root.u.i.link;
197-
198- /* Setting the index to -2 tells
199- elf_link_output_extsym that this symbol is
200- used by a reloc. */
201+ rh = get_link_hash_entry (elf_sym_hashes (input_bfd),
202+ r_symndx, extsymoff);
203+ if (rh == NULL)
204+ {
205+ /* FIXME: Generate an error ? */
206+ continue;
207+ }
208+
209+ /* Setting the index to -2 tells elf_link_output_extsym
210+ that this symbol is used by a reloc. */
211 BFD_ASSERT (rh->indx < 0);
212 rh->indx = -2;
213 *rel_hash = rh;
214@@ -13615,25 +13620,21 @@ _bfd_elf_gc_mark_hook (asection *sec,
215 struct elf_link_hash_entry *h,
216 Elf_Internal_Sym *sym)
217 {
218- if (h != NULL)
219+ if (h == NULL)
220+ return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
221+
222+ switch (h->root.type)
223 {
224- switch (h->root.type)
225- {
226- case bfd_link_hash_defined:
227- case bfd_link_hash_defweak:
228- return h->root.u.def.section;
229+ case bfd_link_hash_defined:
230+ case bfd_link_hash_defweak:
231+ return h->root.u.def.section;
232
233- case bfd_link_hash_common:
234- return h->root.u.c.p->section;
235+ case bfd_link_hash_common:
236+ return h->root.u.c.p->section;
237
238- default:
239- break;
240- }
241+ default:
242+ return NULL;
243 }
244- else
245- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
246-
247- return NULL;
248 }
249
250 /* Return the debug definition section. */
251@@ -13682,46 +13683,49 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_i
252 if (r_symndx == STN_UNDEF)
253 return NULL;
254
255- h = get_ext_sym_hash (cookie, r_symndx);
256-
257- if (h != NULL)
258+ h = get_ext_sym_hash_from_cookie (cookie, r_symndx);
259+ if (h == NULL)
260 {
261- bool was_marked;
262+ /* A corrup tinput file can lead to a situation where the index
263+ does not reference either a local or an external symbol. */
264+ if (r_symndx >= cookie->locsymcount)
265+ return NULL;
266
267- was_marked = h->mark;
268- h->mark = 1;
269- /* Keep all aliases of the symbol too. If an object symbol
270- needs to be copied into .dynbss then all of its aliases
271- should be present as dynamic symbols, not just the one used
272- on the copy relocation. */
273- hw = h;
274- while (hw->is_weakalias)
275- {
276- hw = hw->u.alias;
277- hw->mark = 1;
278- }
279+ return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
280+ &cookie->locsyms[r_symndx]);
281+ }
282
283- if (!was_marked && h->start_stop && !h->root.ldscript_def)
284- {
285- if (info->start_stop_gc)
286- return NULL;
287+ bool was_marked = h->mark;
288
289- /* To work around a glibc bug, mark XXX input sections
290- when there is a reference to __start_XXX or __stop_XXX
291- symbols. */
292- else if (start_stop != NULL)
293- {
294- asection *s = h->u2.start_stop_section;
295- *start_stop = true;
296- return s;
297- }
298- }
299+ h->mark = 1;
300+ /* Keep all aliases of the symbol too. If an object symbol
301+ needs to be copied into .dynbss then all of its aliases
302+ should be present as dynamic symbols, not just the one used
303+ on the copy relocation. */
304+ hw = h;
305+ while (hw->is_weakalias)
306+ {
307+ hw = hw->u.alias;
308+ hw->mark = 1;
309+ }
310
311- return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
312+ if (!was_marked && h->start_stop && !h->root.ldscript_def)
313+ {
314+ if (info->start_stop_gc)
315+ return NULL;
316+
317+ /* To work around a glibc bug, mark XXX input sections
318+ when there is a reference to __start_XXX or __stop_XXX
319+ symbols. */
320+ else if (start_stop != NULL)
321+ {
322+ asection *s = h->u2.start_stop_section;
323+ *start_stop = true;
324+ return s;
325+ }
326 }
327
328- return (*gc_mark_hook) (sec, info, cookie->rel, NULL,
329- &cookie->locsyms[r_symndx]);
330+ return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
331 }
332
333 /* COOKIE->rel describes a relocation against section SEC, which is
334@@ -14735,7 +14739,7 @@ bfd_elf_reloc_symbol_deleted_p (bfd_vma
335
336 struct elf_link_hash_entry *h;
337
338- h = get_ext_sym_hash (rcookie, r_symndx);
339+ h = get_ext_sym_hash_from_cookie (rcookie, r_symndx);
340
341 if (h != NULL)
342 {
diff --git a/meta/recipes-devtools/go/go-1.17.13.inc b/meta/recipes-devtools/go/go-1.17.13.inc
index bb5e839950..e95003db96 100644
--- a/meta/recipes-devtools/go/go-1.17.13.inc
+++ b/meta/recipes-devtools/go/go-1.17.13.inc
@@ -69,10 +69,14 @@ SRC_URI = "https://golang.org/dl/go${PV}.src.tar.gz;name=main \
69 file://CVE-2025-47907.patch \ 69 file://CVE-2025-47907.patch \
70 file://CVE-2025-47906.patch \ 70 file://CVE-2025-47906.patch \
71 file://CVE-2024-24783.patch \ 71 file://CVE-2024-24783.patch \
72 file://CVE-2025-58187.patch \ 72 file://CVE-2025-58187-1.patch \
73 file://CVE-2025-58187-2.patch \
73 file://CVE-2025-58189.patch \ 74 file://CVE-2025-58189.patch \
74 file://CVE-2025-61723.patch \ 75 file://CVE-2025-61723.patch \
75 file://CVE-2025-61724.patch \ 76 file://CVE-2025-61724.patch \
77 file://CVE-2023-39323.patch \
78 file://CVE-2025-61727.patch \
79 file://CVE-2025-61729.patch \
76 " 80 "
77SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd" 81SRC_URI[main.sha256sum] = "a1a48b23afb206f95e7bbaa9b898d965f90826f6f1d1fc0c1d784ada0cd300fd"
78 82
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2025-58187.patch b/meta/recipes-devtools/go/go-1.18/CVE-2025-58187-1.patch
index 810487674c..810487674c 100644
--- a/meta/recipes-devtools/go/go-1.18/CVE-2025-58187.patch
+++ b/meta/recipes-devtools/go/go-1.18/CVE-2025-58187-1.patch
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2025-58187-2.patch b/meta/recipes-devtools/go/go-1.18/CVE-2025-58187-2.patch
new file mode 100644
index 0000000000..65f176f027
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.18/CVE-2025-58187-2.patch
@@ -0,0 +1,516 @@
1From ca6a5545ba18844a97c88a90a385eb6335bb7526 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <roland@golang.org>
3Date: Thu, 9 Oct 2025 13:35:24 -0700
4Subject: [PATCH] [release-branch.go1.24] crypto/x509: rework fix for
5 CVE-2025-58187
6
7In CL 709854 we enabled strict validation for a number of properties of
8domain names (and their constraints). This caused significant breakage,
9since we didn't previously disallow the creation of certificates which
10contained these malformed domains.
11
12Rollback a number of the properties we enforced, making domainNameValid
13only enforce the same properties that domainToReverseLabels does. Since
14this also undoes some of the DoS protections our initial fix enabled,
15this change also adds caching of constraints in isValid (which perhaps
16is the fix we should've initially chosen).
17
18Updates #75835
19Updates #75828
20Fixes #75860
21
22Change-Id: Ie6ca6b4f30e9b8a143692b64757f7bbf4671ed0e
23Reviewed-on: https://go-review.googlesource.com/c/go/+/710735
24LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
25Reviewed-by: Damien Neil <dneil@google.com>
26(cherry picked from commit 1cd71689f2ed8f07031a0cc58fc3586ca501839f)
27Reviewed-on: https://go-review.googlesource.com/c/go/+/710879
28Reviewed-by: Michael Pratt <mpratt@google.com>
29Auto-Submit: Michael Pratt <mpratt@google.com>
30
31Upstream-Status: Backport [https://github.com/golang/go/commit/ca6a5545ba18844a97c88a90a385eb6335bb7526]
32CVE: CVE-2025-58187
33Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
34---
35 src/crypto/x509/name_constraints_test.go | 66 +++++++++++++++++--
36 src/crypto/x509/parser.go | 57 +++++++++++-----
37 src/crypto/x509/parser_test.go | 84 +++++++++++++++++++++---
38 src/crypto/x509/verify.go | 53 ++++++++++-----
39 src/crypto/x509/verify_test.go | 2 +-
40 5 files changed, 213 insertions(+), 49 deletions(-)
41
42diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go
43index d4f7d41..c59a7dc 100644
44--- a/src/crypto/x509/name_constraints_test.go
45+++ b/src/crypto/x509/name_constraints_test.go
46@@ -1452,7 +1452,63 @@ var nameConstraintsTests = []nameConstraintsTest{
47 requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
48 },
49
50- // #77: if several EKUs are requested, satisfying any of them is sufficient.
51+ // An invalid DNS SAN should be detected only at validation time so
52+ // that we can process CA certificates in the wild that have invalid SANs.
53+ // See https://github.com/golang/go/issues/23995
54+
55+ // #77: an invalid DNS or mail SAN will not be detected if name constraint
56+ // checking is not triggered.
57+ {
58+ roots: make([]constraintsSpec, 1),
59+ intermediates: [][]constraintsSpec{
60+ {
61+ {},
62+ },
63+ },
64+ leaf: leafSpec{
65+ sans: []string{"dns:this is invalid", "email:this @ is invalid"},
66+ },
67+ },
68+
69+ // #78: an invalid DNS SAN will be detected if any name constraint checking
70+ // is triggered.
71+ {
72+ roots: []constraintsSpec{
73+ {
74+ bad: []string{"uri:"},
75+ },
76+ },
77+ intermediates: [][]constraintsSpec{
78+ {
79+ {},
80+ },
81+ },
82+ leaf: leafSpec{
83+ sans: []string{"dns:this is invalid"},
84+ },
85+ expectedError: "cannot parse dnsName",
86+ },
87+
88+ // #79: an invalid email SAN will be detected if any name constraint
89+ // checking is triggered.
90+ {
91+ roots: []constraintsSpec{
92+ {
93+ bad: []string{"uri:"},
94+ },
95+ },
96+ intermediates: [][]constraintsSpec{
97+ {
98+ {},
99+ },
100+ },
101+ leaf: leafSpec{
102+ sans: []string{"email:this @ is invalid"},
103+ },
104+ expectedError: "cannot parse rfc822Name",
105+ },
106+
107+ // #80: if several EKUs are requested, satisfying any of them is sufficient.
108 {
109 roots: make([]constraintsSpec, 1),
110 intermediates: [][]constraintsSpec{
111@@ -1467,7 +1523,7 @@ var nameConstraintsTests = []nameConstraintsTest{
112 requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection},
113 },
114
115- // #78: EKUs that are not asserted in VerifyOpts are not required to be
116+ // #81: EKUs that are not asserted in VerifyOpts are not required to be
117 // nested.
118 {
119 roots: make([]constraintsSpec, 1),
120@@ -1486,7 +1542,7 @@ var nameConstraintsTests = []nameConstraintsTest{
121 },
122 },
123
124- // #79: a certificate without SANs and CN is accepted in a constrained chain.
125+ // #82: a certificate without SANs and CN is accepted in a constrained chain.
126 {
127 roots: []constraintsSpec{
128 {
129@@ -1503,7 +1559,7 @@ var nameConstraintsTests = []nameConstraintsTest{
130 },
131 },
132
133- // #80: a certificate without SANs and with a CN that does not parse as a
134+ // #83: a certificate without SANs and with a CN that does not parse as a
135 // hostname is accepted in a constrained chain.
136 {
137 roots: []constraintsSpec{
138@@ -1522,7 +1578,7 @@ var nameConstraintsTests = []nameConstraintsTest{
139 },
140 },
141
142- // #81: a certificate with SANs and CN is accepted in a constrained chain.
143+ // #84: a certificate with SANs and CN is accepted in a constrained chain.
144 {
145 roots: []constraintsSpec{
146 {
147diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go
148index 0788210..cfe4c86 100644
149--- a/src/crypto/x509/parser.go
150+++ b/src/crypto/x509/parser.go
151@@ -391,14 +391,10 @@ func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string
152 if err := isIA5String(email); err != nil {
153 return errors.New("x509: SAN rfc822Name is malformed")
154 }
155- parsed, ok := parseRFC2821Mailbox(email)
156- if !ok || (ok && !domainNameValid(parsed.domain, false)) {
157- return errors.New("x509: SAN rfc822Name is malformed")
158- }
159 emailAddresses = append(emailAddresses, email)
160 case nameTypeDNS:
161 name := string(data)
162- if err := isIA5String(name); err != nil || (err == nil && !domainNameValid(name, false)) {
163+ if err := isIA5String(name); err != nil {
164 return errors.New("x509: SAN dNSName is malformed")
165 }
166 dnsNames = append(dnsNames, string(name))
167@@ -408,9 +404,12 @@ func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string
168 return errors.New("x509: SAN uniformResourceIdentifier is malformed")
169 }
170 uri, err := url.Parse(uriStr)
171- if err != nil || (err == nil && uri.Host != "" && !domainNameValid(uri.Host, false)) {
172+ if err != nil {
173 return fmt.Errorf("x509: cannot parse URI %q: %s", uriStr, err)
174 }
175+ if len(uri.Host) > 0 && !domainNameValid(uri.Host, false) {
176+ return fmt.Errorf("x509: cannot parse URI %q: invalid domain", uriStr)
177+ }
178 uris = append(uris, uri)
179 case nameTypeIP:
180 switch len(data) {
181@@ -990,36 +989,58 @@ func ParseCertificates(der []byte) ([]*Certificate, error) {
182 return certs, nil
183 }
184
185-// domainNameValid does minimal domain name validity checking. In particular it
186-// enforces the following properties:
187-// - names cannot have the trailing period
188-// - names can only have a leading period if constraint is true
189-// - names must be <= 253 characters
190-// - names cannot have empty labels
191-// - names cannot labels that are longer than 63 characters
192-//
193-// Note that this does not enforce the LDH requirements for domain names.
194+// domainNameValid is an alloc-less version of the checks that
195+// domainToReverseLabels does.
196 func domainNameValid(s string, constraint bool) bool {
197- if len(s) == 0 && constraint {
198+ // TODO(#75835): This function omits a number of checks which we
199+ // really should be doing to enforce that domain names are valid names per
200+ // RFC 1034. We previously enabled these checks, but this broke a
201+ // significant number of certificates we previously considered valid, and we
202+ // happily create via CreateCertificate (et al). We should enable these
203+ // checks, but will need to gate them behind a GODEBUG.
204+ //
205+ // I have left the checks we previously enabled, noted with "TODO(#75835)" so
206+ // that we can easily re-enable them once we unbreak everyone.
207+
208+ // TODO(#75835): this should only be true for constraints.
209+ if len(s) == 0 {
210 return true
211 }
212- if len(s) == 0 || (!constraint && s[0] == '.') || s[len(s)-1] == '.' || len(s) > 253 {
213+
214+ // Do not allow trailing period (FQDN format is not allowed in SANs or
215+ // constraints).
216+ if s[len(s)-1] == '.' {
217 return false
218 }
219+
220+ // TODO(#75835): domains must have at least one label, cannot have
221+ // a leading empty label, and cannot be longer than 253 characters.
222+ // if len(s) == 0 || (!constraint && s[0] == '.') || len(s) > 253 {
223+ // return false
224+ // }
225+
226 lastDot := -1
227 if constraint && s[0] == '.' {
228 s = s[1:]
229 }
230
231 for i := 0; i <= len(s); i++ {
232+ if i < len(s) && (s[i] < 33 || s[i] > 126) {
233+ // Invalid character.
234+ return false
235+ }
236 if i == len(s) || s[i] == '.' {
237 labelLen := i
238 if lastDot >= 0 {
239 labelLen -= lastDot + 1
240 }
241- if labelLen == 0 || labelLen > 63 {
242+ if labelLen == 0 {
243 return false
244 }
245+ // TODO(#75835): labels cannot be longer than 63 characters.
246+ // if labelLen > 63 {
247+ // return false
248+ // }
249 lastDot = i
250 }
251 }
252diff --git a/src/crypto/x509/parser_test.go b/src/crypto/x509/parser_test.go
253index 95ed116..662e305 100644
254--- a/src/crypto/x509/parser_test.go
255+++ b/src/crypto/x509/parser_test.go
256@@ -4,6 +4,9 @@
257 package x509
258
259 import (
260+ "crypto/ecdsa"
261+ "crypto/elliptic"
262+ "crypto/rand"
263 "encoding/asn1"
264 "strings"
265 "testing"
266@@ -109,7 +112,31 @@ func TestDomainNameValid(t *testing.T) {
267 constraint bool
268 valid bool
269 }{
270- {"empty name, name", "", false, false},
271+ // TODO(#75835): these tests are for stricter name validation, which we
272+ // had to disable. Once we reenable these strict checks, behind a
273+ // GODEBUG, we should add them back in.
274+ // {"empty name, name", "", false, false},
275+ // {"254 char label, name", strings.Repeat("a.a", 84) + "aaa", false, false},
276+ // {"254 char label, constraint", strings.Repeat("a.a", 84) + "aaa", true, false},
277+ // {"253 char label, name", strings.Repeat("a.a", 84) + "aa", false, false},
278+ // {"253 char label, constraint", strings.Repeat("a.a", 84) + "aa", true, false},
279+ // {"64 char single label, name", strings.Repeat("a", 64), false, false},
280+ // {"64 char single label, constraint", strings.Repeat("a", 64), true, false},
281+ // {"64 char label, name", "a." + strings.Repeat("a", 64), false, false},
282+ // {"64 char label, constraint", "a." + strings.Repeat("a", 64), true, false},
283+
284+ // TODO(#75835): these are the inverse of the tests above, they should be removed
285+ // once the strict checking is enabled.
286+ {"254 char label, name", strings.Repeat("a.a", 84) + "aaa", false, true},
287+ {"254 char label, constraint", strings.Repeat("a.a", 84) + "aaa", true, true},
288+ {"253 char label, name", strings.Repeat("a.a", 84) + "aa", false, true},
289+ {"253 char label, constraint", strings.Repeat("a.a", 84) + "aa", true, true},
290+ {"64 char single label, name", strings.Repeat("a", 64), false, true},
291+ {"64 char single label, constraint", strings.Repeat("a", 64), true, true},
292+ {"64 char label, name", "a." + strings.Repeat("a", 64), false, true},
293+ {"64 char label, constraint", "a." + strings.Repeat("a", 64), true, true},
294+
295+ // Check we properly enforce properties of domain names.
296 {"empty name, constraint", "", true, true},
297 {"empty label, name", "a..a", false, false},
298 {"empty label, constraint", "a..a", true, false},
299@@ -123,23 +150,60 @@ func TestDomainNameValid(t *testing.T) {
300 {"trailing period, constraint", "a.", true, false},
301 {"bare label, name", "a", false, true},
302 {"bare label, constraint", "a", true, true},
303- {"254 char label, name", strings.Repeat("a.a", 84) + "aaa", false, false},
304- {"254 char label, constraint", strings.Repeat("a.a", 84) + "aaa", true, false},
305- {"253 char label, name", strings.Repeat("a.a", 84) + "aa", false, false},
306- {"253 char label, constraint", strings.Repeat("a.a", 84) + "aa", true, false},
307- {"64 char single label, name", strings.Repeat("a", 64), false, false},
308- {"64 char single label, constraint", strings.Repeat("a", 64), true, false},
309 {"63 char single label, name", strings.Repeat("a", 63), false, true},
310 {"63 char single label, constraint", strings.Repeat("a", 63), true, true},
311- {"64 char label, name", "a." + strings.Repeat("a", 64), false, false},
312- {"64 char label, constraint", "a." + strings.Repeat("a", 64), true, false},
313 {"63 char label, name", "a." + strings.Repeat("a", 63), false, true},
314 {"63 char label, constraint", "a." + strings.Repeat("a", 63), true, true},
315 } {
316 t.Run(tc.name, func(t *testing.T) {
317- if tc.valid != domainNameValid(tc.dnsName, tc.constraint) {
318+ valid := domainNameValid(tc.dnsName, tc.constraint)
319+ if tc.valid != valid {
320 t.Errorf("domainNameValid(%q, %t) = %v; want %v", tc.dnsName, tc.constraint, !tc.valid, tc.valid)
321 }
322+ // Also check that we enforce the same properties as domainToReverseLabels
323+ trimmedName := tc.dnsName
324+ if tc.constraint && len(trimmedName) > 1 && trimmedName[0] == '.' {
325+ trimmedName = trimmedName[1:]
326+ }
327+ _, revValid := domainToReverseLabels(trimmedName)
328+ if valid != revValid {
329+ t.Errorf("domainNameValid(%q, %t) = %t != domainToReverseLabels(%q) = %t", tc.dnsName, tc.constraint, valid, trimmedName, revValid)
330+ }
331 })
332 }
333 }
334+
335+func TestRoundtripWeirdSANs(t *testing.T) {
336+ // TODO(#75835): check that certificates we create with CreateCertificate that have malformed SAN values
337+ // can be parsed by ParseCertificate. We should eventually restrict this, but for now we have to maintain
338+ // this property as people have been relying on it.
339+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
340+ if err != nil {
341+ t.Fatal(err)
342+ }
343+ badNames := []string{
344+ "baredomain",
345+ "baredomain.",
346+ strings.Repeat("a", 255),
347+ strings.Repeat("a", 65) + ".com",
348+ }
349+ tmpl := &Certificate{
350+ EmailAddresses: badNames,
351+ DNSNames: badNames,
352+ }
353+ b, err := CreateCertificate(rand.Reader, tmpl, tmpl, &k.PublicKey, k)
354+ if err != nil {
355+ t.Fatal(err)
356+ }
357+ _, err = ParseCertificate(b)
358+ if err != nil {
359+ t.Fatalf("Couldn't roundtrip certificate: %v", err)
360+ }
361+}
362+
363+func FuzzDomainNameValid(f *testing.F) {
364+ f.Fuzz(func(t *testing.T, data string) {
365+ domainNameValid(data, false)
366+ domainNameValid(data, true)
367+ })
368+}
369diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
370index fb2f4b2..99f38a0 100644
371--- a/src/crypto/x509/verify.go
372+++ b/src/crypto/x509/verify.go
373@@ -390,7 +390,7 @@ func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) {
374 return reverseLabels, true
375 }
376
377-func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) {
378+func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
379 // If the constraint contains an @, then it specifies an exact mailbox
380 // name.
381 if strings.Contains(constraint, "@") {
382@@ -403,10 +403,10 @@ func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, erro
383
384 // Otherwise the constraint is like a DNS constraint of the domain part
385 // of the mailbox.
386- return matchDomainConstraint(mailbox.domain, constraint)
387+ return matchDomainConstraint(mailbox.domain, constraint, reversedDomainsCache, reversedConstraintsCache)
388 }
389
390-func matchURIConstraint(uri *url.URL, constraint string) (bool, error) {
391+func matchURIConstraint(uri *url.URL, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
392 // From RFC 5280, Section 4.2.1.10:
393 // “a uniformResourceIdentifier that does not include an authority
394 // component with a host name specified as a fully qualified domain
395@@ -433,7 +433,7 @@ func matchURIConstraint(uri *url.URL, constraint string) (bool, error) {
396 return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
397 }
398
399- return matchDomainConstraint(host, constraint)
400+ return matchDomainConstraint(host, constraint, reversedDomainsCache, reversedConstraintsCache)
401 }
402
403 func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
404@@ -450,16 +450,21 @@ func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
405 return true, nil
406 }
407
408-func matchDomainConstraint(domain, constraint string) (bool, error) {
409+func matchDomainConstraint(domain, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
410 // The meaning of zero length constraints is not specified, but this
411 // code follows NSS and accepts them as matching everything.
412 if len(constraint) == 0 {
413 return true, nil
414 }
415
416- domainLabels, ok := domainToReverseLabels(domain)
417- if !ok {
418- return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain)
419+ domainLabels, found := reversedDomainsCache[domain]
420+ if !found {
421+ var ok bool
422+ domainLabels, ok = domainToReverseLabels(domain)
423+ if !ok {
424+ return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain)
425+ }
426+ reversedDomainsCache[domain] = domainLabels
427 }
428
429 // RFC 5280 says that a leading period in a domain name means that at
430@@ -473,9 +478,14 @@ func matchDomainConstraint(domain, constraint string) (bool, error) {
431 constraint = constraint[1:]
432 }
433
434- constraintLabels, ok := domainToReverseLabels(constraint)
435- if !ok {
436- return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint)
437+ constraintLabels, found := reversedConstraintsCache[constraint]
438+ if !found {
439+ var ok bool
440+ constraintLabels, ok = domainToReverseLabels(constraint)
441+ if !ok {
442+ return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint)
443+ }
444+ reversedConstraintsCache[constraint] = constraintLabels
445 }
446
447 if len(domainLabels) < len(constraintLabels) ||
448@@ -598,6 +608,19 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
449 leaf = currentChain[0]
450 }
451
452+ // Each time we do constraint checking, we need to check the constraints in
453+ // the current certificate against all of the names that preceded it. We
454+ // reverse these names using domainToReverseLabels, which is a relatively
455+ // expensive operation. Since we check each name against each constraint,
456+ // this requires us to do N*C calls to domainToReverseLabels (where N is the
457+ // total number of names that preceed the certificate, and C is the total
458+ // number of constraints in the certificate). By caching the results of
459+ // calling domainToReverseLabels, we can reduce that to N+C calls at the
460+ // cost of keeping all of the parsed names and constraints in memory until
461+ // we return from isValid.
462+ reversedDomainsCache := map[string][]string{}
463+ reversedConstraintsCache := map[string][]string{}
464+
465 if (certType == intermediateCertificate || certType == rootCertificate) &&
466 c.hasNameConstraints() && leaf.hasSANExtension() {
467 err := forEachSAN(leaf.getSANExtension(), func(tag int, data []byte) error {
468@@ -611,20 +634,20 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
469
470 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
471 func(parsedName, constraint interface{}) (bool, error) {
472- return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string))
473+ return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
474 }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil {
475 return err
476 }
477
478 case nameTypeDNS:
479 name := string(data)
480- if _, ok := domainToReverseLabels(name); !ok {
481+ if !domainNameValid(name, false) {
482 return fmt.Errorf("x509: cannot parse dnsName %q", name)
483 }
484
485 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
486 func(parsedName, constraint interface{}) (bool, error) {
487- return matchDomainConstraint(parsedName.(string), constraint.(string))
488+ return matchDomainConstraint(parsedName.(string), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
489 }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil {
490 return err
491 }
492@@ -638,7 +661,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
493
494 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri,
495 func(parsedName, constraint interface{}) (bool, error) {
496- return matchURIConstraint(parsedName.(*url.URL), constraint.(string))
497+ return matchURIConstraint(parsedName.(*url.URL), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
498 }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil {
499 return err
500 }
501diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
502index 9da39ca..31e8149 100644
503--- a/src/crypto/x509/verify_test.go
504+++ b/src/crypto/x509/verify_test.go
505@@ -1648,7 +1648,7 @@ var nameConstraintTests = []struct {
506
507 func TestNameConstraints(t *testing.T) {
508 for i, test := range nameConstraintTests {
509- result, err := matchDomainConstraint(test.domain, test.constraint)
510+ result, err := matchDomainConstraint(test.domain, test.constraint, map[string][]string{}, map[string][]string{})
511
512 if err != nil && !test.expectError {
513 t.Errorf("unexpected error for test #%d: domain=%s, constraint=%s, err=%s", i, test.domain, test.constraint, err)
514--
5152.25.1
516
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2025-61727.patch b/meta/recipes-devtools/go/go-1.18/CVE-2025-61727.patch
new file mode 100644
index 0000000000..23dc35b8b8
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.18/CVE-2025-61727.patch
@@ -0,0 +1,229 @@
1From 04db77a423cac75bb82cc9a6859991ae9c016344 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Mon, 24 Nov 2025 08:46:08 -0800
4Subject: [PATCH] [release-branch.go1.24] crypto/x509: excluded subdomain
5 constraints preclude wildcard SANs
6
7When evaluating name constraints in a certificate chain, the presence of
8an excluded subdomain constraint (e.g., excluding "test.example.com")
9should preclude the use of a wildcard SAN (e.g., "*.example.com").
10
11Fixes #76442
12Fixes #76463
13Fixes CVE-2025-61727
14
15Change-Id: I42a0da010cb36d2ec9d1239ae3f61cf25eb78bba
16Reviewed-on: https://go-review.googlesource.com/c/go/+/724401
17Reviewed-by: Nicholas Husin <husin@google.com>
18Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
19LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
20Reviewed-by: Nicholas Husin <nsh@golang.org>
21Reviewed-by: Neal Patel <nealpatel@google.com>
22
23Upstream-Status: Backport [https://github.com/golang/go/commit/04db77a423cac75bb82cc9a6859991ae9c016344]
24CVE: CVE-2025-61727
25Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
26---
27 src/crypto/x509/name_constraints_test.go | 34 ++++++++++++++++++++
28 src/crypto/x509/verify.go | 40 +++++++++++++++---------
29 src/crypto/x509/verify_test.go | 2 +-
30 3 files changed, 60 insertions(+), 16 deletions(-)
31
32diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go
33index c59a7dc..963bc5a 100644
34--- a/src/crypto/x509/name_constraints_test.go
35+++ b/src/crypto/x509/name_constraints_test.go
36@@ -1595,6 +1595,40 @@ var nameConstraintsTests = []nameConstraintsTest{
37 cn: "foo.bar",
38 },
39 },
40+ // #87: subdomain excluded constraints preclude wildcard names
41+ {
42+ roots: []constraintsSpec{
43+ {
44+ bad: []string{"dns:foo.example.com"},
45+ },
46+ },
47+ intermediates: [][]constraintsSpec{
48+ {
49+ {},
50+ },
51+ },
52+ leaf: leafSpec{
53+ sans: []string{"dns:*.example.com"},
54+ },
55+ expectedError: "\"*.example.com\" is excluded by constraint \"foo.example.com\"",
56+ },
57+ // #88: wildcard names are not matched by subdomain permitted constraints
58+ {
59+ roots: []constraintsSpec{
60+ {
61+ ok: []string{"dns:foo.example.com"},
62+ },
63+ },
64+ intermediates: [][]constraintsSpec{
65+ {
66+ {},
67+ },
68+ },
69+ leaf: leafSpec{
70+ sans: []string{"dns:*.example.com"},
71+ },
72+ expectedError: "\"*.example.com\" is not permitted",
73+ },
74 }
75
76 func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
77diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
78index 99f38a0..88260ee 100644
79--- a/src/crypto/x509/verify.go
80+++ b/src/crypto/x509/verify.go
81@@ -390,7 +390,7 @@ func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) {
82 return reverseLabels, true
83 }
84
85-func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
86+func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string, excluded bool, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
87 // If the constraint contains an @, then it specifies an exact mailbox
88 // name.
89 if strings.Contains(constraint, "@") {
90@@ -403,10 +403,10 @@ func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string, reversedDom
91
92 // Otherwise the constraint is like a DNS constraint of the domain part
93 // of the mailbox.
94- return matchDomainConstraint(mailbox.domain, constraint, reversedDomainsCache, reversedConstraintsCache)
95+ return matchDomainConstraint(mailbox.domain, constraint, excluded, reversedDomainsCache, reversedConstraintsCache)
96 }
97
98-func matchURIConstraint(uri *url.URL, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
99+func matchURIConstraint(uri *url.URL, constraint string, excluded bool, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
100 // From RFC 5280, Section 4.2.1.10:
101 // “a uniformResourceIdentifier that does not include an authority
102 // component with a host name specified as a fully qualified domain
103@@ -433,7 +433,7 @@ func matchURIConstraint(uri *url.URL, constraint string, reversedDomainsCache ma
104 return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
105 }
106
107- return matchDomainConstraint(host, constraint, reversedDomainsCache, reversedConstraintsCache)
108+ return matchDomainConstraint(host, constraint, excluded, reversedDomainsCache, reversedConstraintsCache)
109 }
110
111 func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
112@@ -450,7 +450,7 @@ func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
113 return true, nil
114 }
115
116-func matchDomainConstraint(domain, constraint string, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
117+func matchDomainConstraint(domain, constraint string, excluded bool, reversedDomainsCache map[string][]string, reversedConstraintsCache map[string][]string) (bool, error) {
118 // The meaning of zero length constraints is not specified, but this
119 // code follows NSS and accepts them as matching everything.
120 if len(constraint) == 0 {
121@@ -467,6 +467,11 @@ func matchDomainConstraint(domain, constraint string, reversedDomainsCache map[s
122 reversedDomainsCache[domain] = domainLabels
123 }
124
125+ wildcardDomain := false
126+ if len(domain) > 0 && domain[0] == '*' {
127+ wildcardDomain = true
128+ }
129+
130 // RFC 5280 says that a leading period in a domain name means that at
131 // least one label must be prepended, but only for URI and email
132 // constraints, not DNS constraints. The code also supports that
133@@ -493,6 +498,11 @@ func matchDomainConstraint(domain, constraint string, reversedDomainsCache map[s
134 return false, nil
135 }
136
137+ if excluded && wildcardDomain && len(domainLabels) > 1 && len(constraintLabels) > 0 {
138+ domainLabels = domainLabels[:len(domainLabels)-1]
139+ constraintLabels = constraintLabels[:len(constraintLabels)-1]
140+ }
141+
142 for i, constraintLabel := range constraintLabels {
143 if !strings.EqualFold(constraintLabel, domainLabels[i]) {
144 return false, nil
145@@ -512,7 +522,7 @@ func (c *Certificate) checkNameConstraints(count *int,
146 nameType string,
147 name string,
148 parsedName interface{},
149- match func(parsedName, constraint interface{}) (match bool, err error),
150+ match func(parsedName, constraint interface{}, excluded bool) (match bool, err error),
151 permitted, excluded interface{}) error {
152
153 excludedValue := reflect.ValueOf(excluded)
154@@ -524,7 +534,7 @@ func (c *Certificate) checkNameConstraints(count *int,
155
156 for i := 0; i < excludedValue.Len(); i++ {
157 constraint := excludedValue.Index(i).Interface()
158- match, err := match(parsedName, constraint)
159+ match, err := match(parsedName, constraint, true)
160 if err != nil {
161 return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
162 }
163@@ -546,7 +556,7 @@ func (c *Certificate) checkNameConstraints(count *int,
164 constraint := permittedValue.Index(i).Interface()
165
166 var err error
167- if ok, err = match(parsedName, constraint); err != nil {
168+ if ok, err = match(parsedName, constraint, false); err != nil {
169 return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()}
170 }
171
172@@ -633,8 +643,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
173 }
174
175 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
176- func(parsedName, constraint interface{}) (bool, error) {
177- return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
178+ func(parsedName, constraint interface{}, excluded bool) (bool, error) {
179+ return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string), excluded, reversedDomainsCache, reversedConstraintsCache)
180 }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil {
181 return err
182 }
183@@ -646,8 +656,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
184 }
185
186 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
187- func(parsedName, constraint interface{}) (bool, error) {
188- return matchDomainConstraint(parsedName.(string), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
189+ func(parsedName, constraint interface{}, excluded bool) (bool, error) {
190+ return matchDomainConstraint(parsedName.(string), constraint.(string), excluded, reversedDomainsCache, reversedConstraintsCache)
191 }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil {
192 return err
193 }
194@@ -660,8 +670,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
195 }
196
197 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri,
198- func(parsedName, constraint interface{}) (bool, error) {
199- return matchURIConstraint(parsedName.(*url.URL), constraint.(string), reversedDomainsCache, reversedConstraintsCache)
200+ func(parsedName, constraint interface{}, excluded bool) (bool, error) {
201+ return matchURIConstraint(parsedName.(*url.URL), constraint.(string), excluded, reversedDomainsCache, reversedConstraintsCache)
202 }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil {
203 return err
204 }
205@@ -673,7 +683,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
206 }
207
208 if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip,
209- func(parsedName, constraint interface{}) (bool, error) {
210+ func(parsedName, constraint interface{}, _ bool) (bool, error) {
211 return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet))
212 }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil {
213 return err
214diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
215index 31e8149..5f7c834 100644
216--- a/src/crypto/x509/verify_test.go
217+++ b/src/crypto/x509/verify_test.go
218@@ -1648,7 +1648,7 @@ var nameConstraintTests = []struct {
219
220 func TestNameConstraints(t *testing.T) {
221 for i, test := range nameConstraintTests {
222- result, err := matchDomainConstraint(test.domain, test.constraint, map[string][]string{}, map[string][]string{})
223+ result, err := matchDomainConstraint(test.domain, test.constraint, false, map[string][]string{}, map[string][]string{})
224
225 if err != nil && !test.expectError {
226 t.Errorf("unexpected error for test #%d: domain=%s, constraint=%s, err=%s", i, test.domain, test.constraint, err)
227--
2282.25.1
229
diff --git a/meta/recipes-devtools/go/go-1.18/CVE-2025-61729.patch b/meta/recipes-devtools/go/go-1.18/CVE-2025-61729.patch
new file mode 100644
index 0000000000..6fdc2fd426
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.18/CVE-2025-61729.patch
@@ -0,0 +1,172 @@
1From 3a842bd5c6aa8eefa13c0174de3ab361e50bd672 Mon Sep 17 00:00:00 2001
2From: "Nicholas S. Husin" <nsh@golang.org>
3Date: Mon, 24 Nov 2025 14:56:23 -0500
4Subject: [PATCH] [release-branch.go1.24] crypto/x509: prevent
5 HostnameError.Error() from consuming excessive resource
6
7Constructing HostnameError.Error() takes O(N^2) runtime due to using a
8string concatenation in a loop. Additionally, there is no limit on how
9many names are included in the error message. As a result, a malicious
10attacker could craft a certificate with an infinite amount of names to
11unfairly consume resource.
12
13To remediate this, we will now use strings.Builder to construct the
14error message, preventing O(N^2) runtime. When a certificate has 100 or
15more names, we will also not print each name individually.
16
17Thanks to Philippe Antoine (Catena cyber) for reporting this issue.
18
19Updates #76445
20Fixes #76460
21Fixes CVE-2025-61729
22
23Change-Id: I6343776ec3289577abc76dad71766c491c1a7c81
24Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3000
25Reviewed-by: Neal Patel <nealpatel@google.com>
26Reviewed-by: Damien Neil <dneil@google.com>
27Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3220
28Reviewed-by: Roland Shoemaker <bracewell@google.com>
29Reviewed-on: https://go-review.googlesource.com/c/go/+/725820
30Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
31TryBot-Bypass: Dmitri Shuralyov <dmitshur@golang.org>
32Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
33Reviewed-by: Mark Freeman <markfreeman@google.com>
34
35Upstream-Status: Backport [https://github.com/golang/go/commit/3a842bd5c6aa8eefa13c0174de3ab361e50bd672]
36CVE: CVE-2025-61729
37Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
38---
39 src/crypto/x509/verify.go | 21 ++++++++++-----
40 src/crypto/x509/verify_test.go | 47 ++++++++++++++++++++++++++++++++++
41 2 files changed, 61 insertions(+), 7 deletions(-)
42
43diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
44index 88260ee..c167191 100644
45--- a/src/crypto/x509/verify.go
46+++ b/src/crypto/x509/verify.go
47@@ -97,31 +97,38 @@ type HostnameError struct {
48
49 func (h HostnameError) Error() string {
50 c := h.Certificate
51+ maxNamesIncluded := 100
52
53 if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) {
54 return "x509: certificate relies on legacy Common Name field, use SANs instead"
55 }
56
57- var valid string
58+ var valid strings.Builder
59 if ip := net.ParseIP(h.Host); ip != nil {
60 // Trying to validate an IP
61 if len(c.IPAddresses) == 0 {
62 return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
63 }
64+ if len(c.IPAddresses) >= maxNamesIncluded {
65+ return fmt.Sprintf("x509: certificate is valid for %d IP SANs, but none matched %s", len(c.IPAddresses), h.Host)
66+ }
67 for _, san := range c.IPAddresses {
68- if len(valid) > 0 {
69- valid += ", "
70+ if valid.Len() > 0 {
71+ valid.WriteString(", ")
72 }
73- valid += san.String()
74+ valid.WriteString(san.String())
75 }
76 } else {
77- valid = strings.Join(c.DNSNames, ", ")
78+ if len(c.DNSNames) >= maxNamesIncluded {
79+ return fmt.Sprintf("x509: certificate is valid for %d names, but none matched %s", len(c.DNSNames), h.Host)
80+ }
81+ valid.WriteString(strings.Join(c.DNSNames, ", "))
82 }
83
84- if len(valid) == 0 {
85+ if valid.Len() == 0 {
86 return "x509: certificate is not valid for any names, but wanted to match " + h.Host
87 }
88- return "x509: certificate is valid for " + valid + ", not " + h.Host
89+ return "x509: certificate is valid for " + valid.String() + ", not " + h.Host
90 }
91
92 // UnknownAuthorityError results when the certificate issuer is unknown
93diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
94index 5f7c834..c2c2025 100644
95--- a/src/crypto/x509/verify_test.go
96+++ b/src/crypto/x509/verify_test.go
97@@ -9,11 +9,14 @@ import (
98 "crypto/ecdsa"
99 "crypto/elliptic"
100 "crypto/rand"
101+ "crypto/rsa"
102 "crypto/x509/pkix"
103 "encoding/pem"
104 "errors"
105 "fmt"
106+ "log"
107 "math/big"
108+ "net"
109 "runtime"
110 "strings"
111 "testing"
112@@ -70,6 +73,26 @@ var verifyTests = []verifyTest{
113
114 errorCallback: expectHostnameError("certificate is valid for"),
115 },
116+ {
117+ name: "TooManyDNS",
118+ leaf: generatePEMCertWithRepeatSAN(1677615892, 200, "fake.dns"),
119+ roots: []string{generatePEMCertWithRepeatSAN(1677615892, 200, "fake.dns")},
120+ currentTime: 1677615892,
121+ dnsName: "www.example.com",
122+ systemSkip: true, // does not chain to a system root
123+
124+ errorCallback: expectHostnameError("certificate is valid for 200 names, but none matched"),
125+ },
126+ {
127+ name: "TooManyIPs",
128+ leaf: generatePEMCertWithRepeatSAN(1677615892, 150, "4.3.2.1"),
129+ roots: []string{generatePEMCertWithRepeatSAN(1677615892, 150, "4.3.2.1")},
130+ currentTime: 1677615892,
131+ dnsName: "1.2.3.4",
132+ systemSkip: true, // does not chain to a system root
133+
134+ errorCallback: expectHostnameError("certificate is valid for 150 IP SANs, but none matched"),
135+ },
136 {
137 name: "IPMissing",
138 leaf: googleLeaf,
139@@ -584,6 +607,30 @@ func nameToKey(name *pkix.Name) string {
140 return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
141 }
142
143+func generatePEMCertWithRepeatSAN(currentTime int64, count int, san string) string {
144+ cert := Certificate{
145+ NotBefore: time.Unix(currentTime, 0),
146+ NotAfter: time.Unix(currentTime, 0),
147+ }
148+ if ip := net.ParseIP(san); ip != nil {
149+ cert.IPAddresses = slices.Repeat([]net.IP{ip}, count)
150+ } else {
151+ cert.DNSNames = slices.Repeat([]string{san}, count)
152+ }
153+ privKey, err := rsa.GenerateKey(rand.Reader, 4096)
154+ if err != nil {
155+ log.Fatal(err)
156+ }
157+ certBytes, err := CreateCertificate(rand.Reader, &cert, &cert, &privKey.PublicKey, privKey)
158+ if err != nil {
159+ log.Fatal(err)
160+ }
161+ return string(pem.EncodeToMemory(&pem.Block{
162+ Type: "CERTIFICATE",
163+ Bytes: certBytes,
164+ }))
165+}
166+
167 const geoTrustRoot = `-----BEGIN CERTIFICATE-----
168 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
169 MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
170--
1712.25.1
172
diff --git a/meta/recipes-devtools/go/go-1.21/CVE-2023-39323.patch b/meta/recipes-devtools/go/go-1.21/CVE-2023-39323.patch
new file mode 100644
index 0000000000..613c91706b
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.21/CVE-2023-39323.patch
@@ -0,0 +1,55 @@
1From 5e0a62c44fbaff6443bffe67911370bc0ea25f6d Mon Sep 17 00:00:00 2001
2From: Ian Lance Taylor <iant@golang.org>
3Date: Wed, 20 Sep 2023 16:16:29 -0700
4Subject: [PATCH] cmd/compile: use absolute file name in isCgo check
5
6For #23672
7Fixes #63211
8Fixes CVE-2023-39323
9
10Change-Id: I4586a69e1b2560036afec29d53e53cf25e6c7352
11Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2032884
12Reviewed-by: Matthew Dempsky <mdempsky@google.com>
13Reviewed-by: Roland Shoemaker <bracewell@google.com>
14Reviewed-on: https://go-review.googlesource.com/c/go/+/534158
15Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
16Reviewed-by: Ian Lance Taylor <iant@google.com>
17LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
18Auto-Submit: Ian Lance Taylor <iant@google.com>
19
20Upstream-Status: Backport
21CVE: CVE-2023-39323
22
23Reference to upstream patch:
24https://github.com/golang/go/commit/e7c142a19d8b3944c2f1b9ab7fd94c63d8d0c555
25
26Backport patch to fix CVE-2023-39323 and drop the modifications of test codes.
27
28Signed-off-by: Libo Chen <libo.chen.cn@windriver.com>
29---
30 src/cmd/compile/internal/noder/noder.go | 8 +++++++-
31 1 file changed, 7 insertions(+), 1 deletion(-)
32
33diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go
34index 5fcad096c2..f35e065a31 100644
35--- a/src/cmd/compile/internal/noder/noder.go
36+++ b/src/cmd/compile/internal/noder/noder.go
37@@ -1690,8 +1690,14 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
38 // contain cgo directives, and for security reasons
39 // (primarily misuse of linker flags), other files are not.
40 // See golang.org/issue/23672.
41+// Note that cmd/go ignores files whose names start with underscore,
42+// so the only _cgo_ files we will see from cmd/go are generated by cgo.
43+// It's easy to bypass this check by calling the compiler directly;
44+// we only protect against uses by cmd/go.
45 func isCgoGeneratedFile(pos syntax.Pos) bool {
46- return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Filename()))), "_cgo_")
47+ // We need the absolute file, independent of //line directives,
48+ // so we call pos.Base().Pos().Base().
49+ return strings.HasPrefix(filepath.Base(filepath.Clean(fileh(pos.Base().Pos().Base().Filename()))), "_cgo_")
50 }
51
52 // safeArg reports whether arg is a "safe" command-line argument,
53--
542.34.1
55
diff --git a/meta/recipes-devtools/pseudo/files/0001-configure-Prune-PIE-flags.patch b/meta/recipes-devtools/pseudo/files/0001-configure-Prune-PIE-flags.patch
deleted file mode 100644
index 43504eaab9..0000000000
--- a/meta/recipes-devtools/pseudo/files/0001-configure-Prune-PIE-flags.patch
+++ /dev/null
@@ -1,44 +0,0 @@
1From b5545c08e6c674c49aef14b47a56a3e92df4d2a7 Mon Sep 17 00:00:00 2001
2From: Khem Raj <raj.khem@gmail.com>
3Date: Wed, 17 Feb 2016 07:36:34 +0000
4Subject: [pseudo][PATCH] configure: Prune PIE flags
5
6LDFLAGS are not taken from environment and CFLAGS is used for LDFLAGS
7however when using security options -fpie and -pie options are coming
8as part of ARCH_FLAGS and they get into LDFLAGS of shared objects as
9well so we end up with conflicting options -shared -pie, which gold
10rejects outright and bfd linker lets the one appearning last in cmdline
11take effect. This create quite a unpleasant situation in OE when
12security flags are enabled and gold or not-gold options are used
13it errors out but errors are not same.
14
15Anyway, with this patch we filter pie options from ARCH_FLAGS
16ouright and take control of generating PIC objects
17
18Helps with errors like
19
20| /mnt/oe/build/tmp-glibc/sysroots/x86_64-linux/usr/libexec/x86_64-oe-linux/gcc/x86_64-oe-linux/5.3.0/ld: pseudo_client.o: relocation R_X86_64_PC32 against symbol `pseudo_util_debug_flags' can not be used when making a shared object; recompile with -fPIC
21| /mnt/oe/build/tmp-glibc/sysroots/x86_64-linux/usr/libexec/x86_64-oe-linux/gcc/x86_64-oe-linux/5.3.0/ld: final link failed: Bad value
22| collect2: error: ld returned 1 exit status
23| make: *** [lib/pseudo/lib64/libpseudo.so] Error 1
24
25Signed-off-by: Khem Raj <raj.khem@gmail.com>
26---
27Upstream-Status: Submitted
28
29 configure | 2 ++
30 1 file changed, 2 insertions(+)
31
32diff --git a/configure b/configure
33index e5ef9ce..83b0890 100755
34--- a/configure
35+++ b/configure
36@@ -339,3 +339,5 @@ sed -e '
37 s,@ARCH@,'"$opt_arch"',g
38 s,@BITS@,'"$opt_bits"',g
39 ' < Makefile.in > Makefile
40+
41+sed -i -e 's/\-[f]*pie//g' Makefile
42--
431.8.3.1
44
diff --git a/meta/recipes-devtools/pseudo/files/glibc238.patch b/meta/recipes-devtools/pseudo/files/glibc238.patch
deleted file mode 100644
index dfb5c283f6..0000000000
--- a/meta/recipes-devtools/pseudo/files/glibc238.patch
+++ /dev/null
@@ -1,65 +0,0 @@
1glibc 2.38 would include __isoc23_strtol and similar symbols. This is trggerd by
2_GNU_SOURCE but we have to set that for other definitions. Therefore play with defines
3to turn this off within pseudo_wrappers.c. Elsewhere we can switch to _DEFAULT_SOURCE
4rather than _GNU_SOURCE.
5
6Upstream-Status: Pending
7
8Index: git/pseudo_wrappers.c
9===================================================================
10--- git.orig/pseudo_wrappers.c
11+++ git/pseudo_wrappers.c
12@@ -6,6 +6,18 @@
13 * SPDX-License-Identifier: LGPL-2.1-only
14 *
15 */
16+/* glibc 2.38 would include __isoc23_strtol and similar symbols. This is trggerd by
17+ * _GNU_SOURCE but we have to set that for other definitions. Therefore play with defines
18+ * to turn this off.
19+ */
20+#include <features.h>
21+#undef __GLIBC_USE_ISOC2X
22+#undef __GLIBC_USE_C2X_STRTOL
23+#define __GLIBC_USE_C2X_STRTOL 0
24+#undef __GLIBC_USE_ISOC23
25+#undef __GLIBC_USE_C23_STRTOL
26+#define __GLIBC_USE_C23_STRTOL 0
27+
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <limits.h>
31Index: git/pseudo_util.c
32===================================================================
33--- git.orig/pseudo_util.c
34+++ git/pseudo_util.c
35@@ -8,6 +8,17 @@
36 */
37 /* we need access to RTLD_NEXT for a horrible workaround */
38 #define _GNU_SOURCE
39+/* glibc 2.38 would include __isoc23_strtol and similar symbols. This is trggerd by
40+ * _GNU_SOURCE but we have to set that for other definitions. Therefore play with defines
41+ * to turn this off.
42+ */
43+#include <features.h>
44+#undef __GLIBC_USE_ISOC2X
45+#undef __GLIBC_USE_C2X_STRTOL
46+#define __GLIBC_USE_C2X_STRTOL 0
47+#undef __GLIBC_USE_ISOC23
48+#undef __GLIBC_USE_C23_STRTOL
49+#define __GLIBC_USE_C23_STRTOL 0
50
51 #include <ctype.h>
52 #include <errno.h>
53Index: git/pseudo_client.c
54===================================================================
55--- git.orig/pseudo_client.c
56+++ git/pseudo_client.c
57@@ -6,7 +6,7 @@
58 * SPDX-License-Identifier: LGPL-2.1-only
59 *
60 */
61-#define _GNU_SOURCE
62+#define _DEFAULT_SOURCE
63
64 #include <stdio.h>
65 #include <signal.h>
diff --git a/meta/recipes-devtools/pseudo/files/older-glibc-symbols.patch b/meta/recipes-devtools/pseudo/files/older-glibc-symbols.patch
index c453b5f735..f42b32b8d9 100644
--- a/meta/recipes-devtools/pseudo/files/older-glibc-symbols.patch
+++ b/meta/recipes-devtools/pseudo/files/older-glibc-symbols.patch
@@ -28,10 +28,10 @@ diff --git a/Makefile.in b/Makefile.in
28@@ -120,7 +120,7 @@ $(PSEUDODB): pseudodb.o $(SHOBJS) $(DBOBJS) pseudo_ipc.o | $(BIN) 28@@ -120,7 +120,7 @@ $(PSEUDODB): pseudodb.o $(SHOBJS) $(DBOBJS) pseudo_ipc.o | $(BIN)
29 libpseudo: $(LIBPSEUDO) 29 libpseudo: $(LIBPSEUDO)
30 30
31 $(LIBPSEUDO): $(WRAPOBJS) pseudo_client.o pseudo_ipc.o $(SHOBJS) | $(LIB) 31 $(LIBPSEUDO): $(WRAPOBJS) pseudo_client.o pseudo_client_scanf.o pseudo_ipc.o $(SHOBJS) | $(LIB)
32- $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -shared -o $(LIBPSEUDO) \ 32- $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -shared -o $(LIBPSEUDO) \
33+ $(CC) $(CFLAGS) -Lprebuilt/$(shell uname -m)-linux/lib/ $(CFLAGS_PSEUDO) -shared -o $(LIBPSEUDO) \ 33+ $(CC) $(CFLAGS) -Lprebuilt/$(shell uname -m)-linux/lib/ $(CFLAGS_PSEUDO) -shared -o $(LIBPSEUDO) \
34 pseudo_client.o pseudo_ipc.o \ 34 pseudo_client.o pseudo_client_scanf.o pseudo_ipc.o \
35 $(WRAPOBJS) $(SHOBJS) $(LDFLAGS) $(CLIENT_LDFLAGS) 35 $(WRAPOBJS) $(SHOBJS) $(LDFLAGS) $(CLIENT_LDFLAGS)
36 36
37diff --git a/pseudo_wrappers.c b/pseudo_wrappers.c 37diff --git a/pseudo_wrappers.c b/pseudo_wrappers.c
diff --git a/meta/recipes-devtools/pseudo/pseudo.inc b/meta/recipes-devtools/pseudo/pseudo.inc
index 7e09b6d58c..9c191560fb 100644
--- a/meta/recipes-devtools/pseudo/pseudo.inc
+++ b/meta/recipes-devtools/pseudo/pseudo.inc
@@ -156,3 +156,10 @@ do_install:append:class-nativesdk () {
156} 156}
157 157
158BBCLASSEXTEND = "native nativesdk" 158BBCLASSEXTEND = "native nativesdk"
159
160# Setscene tasks which run under fakeroot must not be executed before
161# pseudo-native and *all* its runtime dependencies are available in the
162# sysroot.
163PSEUDO_SETSCENE_DEPS = ""
164PSEUDO_SETSCENE_DEPS:class-native = "sqlite3-native:do_populate_sysroot"
165do_populate_sysroot_setscene[depends] += "${PSEUDO_SETSCENE_DEPS}"
diff --git a/meta/recipes-devtools/pseudo/pseudo_git.bb b/meta/recipes-devtools/pseudo/pseudo_git.bb
index 405d2340ae..dae4f4bc84 100644
--- a/meta/recipes-devtools/pseudo/pseudo_git.bb
+++ b/meta/recipes-devtools/pseudo/pseudo_git.bb
@@ -1,8 +1,6 @@
1require pseudo.inc 1require pseudo.inc
2 2
3SRC_URI = "git://git.yoctoproject.org/pseudo;branch=master \ 3SRC_URI = "git://git.yoctoproject.org/pseudo;branch=master \
4 file://0001-configure-Prune-PIE-flags.patch \
5 file://glibc238.patch \
6 file://fallback-passwd \ 4 file://fallback-passwd \
7 file://fallback-group \ 5 file://fallback-group \
8 " 6 "
@@ -14,9 +12,9 @@ SRC_URI:append:class-nativesdk = " \
14 file://older-glibc-symbols.patch" 12 file://older-glibc-symbols.patch"
15SRC_URI[prebuilt.sha256sum] = "ed9f456856e9d86359f169f46a70ad7be4190d6040282b84c8d97b99072485aa" 13SRC_URI[prebuilt.sha256sum] = "ed9f456856e9d86359f169f46a70ad7be4190d6040282b84c8d97b99072485aa"
16 14
17SRCREV = "28dcefb809ce95db997811b5662f0b893b9923e0" 15SRCREV = "125b020dd2bc46baa37a80784704e382732357b4"
18S = "${WORKDIR}/git" 16S = "${WORKDIR}/git"
19PV = "1.9.0+git${SRCPV}" 17PV = "1.9.2+git"
20 18
21# largefile and 64bit time_t support adds these macros via compiler flags globally 19# largefile and 64bit time_t support adds these macros via compiler flags globally
22# remove them for pseudo since pseudo intercepts some of the functions which will be 20# remove them for pseudo since pseudo intercepts some of the functions which will be
diff --git a/meta/recipes-devtools/python/python3-urllib3/CVE-2025-66418.patch b/meta/recipes-devtools/python/python3-urllib3/CVE-2025-66418.patch
new file mode 100644
index 0000000000..b490019d87
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-urllib3/CVE-2025-66418.patch
@@ -0,0 +1,74 @@
1From 24d7b67eac89f94e11003424bcf0d8f7b72222a8 Mon Sep 17 00:00:00 2001
2From: Illia Volochii <illia.volochii@gmail.com>
3Date: Fri, 5 Dec 2025 16:41:33 +0200
4Subject: [PATCH] Merge commit from fork
5
6* Add a hard-coded limit for the decompression chain
7
8* Reuse new list
9
10CVE: CVE-2025-66418
11Upstream-Status: Backport [https://github.com/urllib3/urllib3/commit/24d7b67eac89f94e11003424bcf0d8f7b72222a8]
12Signed-off-by: Peter Marko <peter.marko@siemens.com>
13---
14 changelog/GHSA-gm62-xv2j-4w53.security.rst | 4 ++++
15 src/urllib3/response.py | 12 +++++++++++-
16 test/test_response.py | 10 ++++++++++
17 3 files changed, 25 insertions(+), 1 deletion(-)
18 create mode 100644 changelog/GHSA-gm62-xv2j-4w53.security.rst
19
20diff --git a/changelog/GHSA-gm62-xv2j-4w53.security.rst b/changelog/GHSA-gm62-xv2j-4w53.security.rst
21new file mode 100644
22index 00000000..6646eaa3
23--- /dev/null
24+++ b/changelog/GHSA-gm62-xv2j-4w53.security.rst
25@@ -0,0 +1,4 @@
26+Fixed a security issue where an attacker could compose an HTTP response with
27+virtually unlimited links in the ``Content-Encoding`` header, potentially
28+leading to a denial of service (DoS) attack by exhausting system resources
29+during decoding. The number of allowed chained encodings is now limited to 5.
30diff --git a/src/urllib3/response.py b/src/urllib3/response.py
31index 4ba42136..069f726c 100644
32--- a/src/urllib3/response.py
33+++ b/src/urllib3/response.py
34@@ -135,8 +135,18 @@ class MultiDecoder(object):
35 they were applied.
36 """
37
38+ # Maximum allowed number of chained HTTP encodings in the
39+ # Content-Encoding header.
40+ max_decode_links = 5
41+
42 def __init__(self, modes):
43- self._decoders = [_get_decoder(m.strip()) for m in modes.split(",")]
44+ encodings = [m.strip() for m in modes.split(",")]
45+ if len(encodings) > self.max_decode_links:
46+ raise DecodeError(
47+ "Too many content encodings in the chain: "
48+ f"{len(encodings)} > {self.max_decode_links}"
49+ )
50+ self._decoders = [_get_decoder(e) for e in encodings]
51
52 def flush(self):
53 return self._decoders[0].flush()
54diff --git a/test/test_response.py b/test/test_response.py
55index 9592fdd9..d824ae70 100644
56--- a/test/test_response.py
57+++ b/test/test_response.py
58@@ -295,6 +295,16 @@ class TestResponse(object):
59
60 assert r.data == b"foo"
61
62+ def test_read_multi_decoding_too_many_links(self) -> None:
63+ fp = BytesIO(b"foo")
64+ with pytest.raises(
65+ DecodeError, match="Too many content encodings in the chain: 6 > 5"
66+ ):
67+ HTTPResponse(
68+ fp,
69+ headers={"content-encoding": "gzip, deflate, br, zstd, gzip, deflate"},
70+ )
71+
72 def test_body_blob(self):
73 resp = HTTPResponse(b"foo")
74 assert resp.data == b"foo"
diff --git a/meta/recipes-devtools/python/python3-urllib3_1.26.20.bb b/meta/recipes-devtools/python/python3-urllib3_1.26.20.bb
index 58988e4205..1f1132d5b5 100644
--- a/meta/recipes-devtools/python/python3-urllib3_1.26.20.bb
+++ b/meta/recipes-devtools/python/python3-urllib3_1.26.20.bb
@@ -9,6 +9,7 @@ inherit pypi setuptools3
9 9
10SRC_URI += " \ 10SRC_URI += " \
11 file://CVE-2025-50181.patch \ 11 file://CVE-2025-50181.patch \
12 file://CVE-2025-66418.patch \
12" 13"
13 14
14RDEPENDS:${PN} += "\ 15RDEPENDS:${PN} += "\
diff --git a/meta/recipes-devtools/python/python3/CVE-2025-13836.patch b/meta/recipes-devtools/python/python3/CVE-2025-13836.patch
new file mode 100644
index 0000000000..c4387b6019
--- /dev/null
+++ b/meta/recipes-devtools/python/python3/CVE-2025-13836.patch
@@ -0,0 +1,163 @@
1From 289f29b0fe38baf2d7cb5854f4bb573cc34a6a15 Mon Sep 17 00:00:00 2001
2From: "Miss Islington (bot)"
3 <31488909+miss-islington@users.noreply.github.com>
4Date: Fri, 5 Dec 2025 16:21:57 +0100
5Subject: [PATCH] [3.13] gh-119451: Fix a potential denial of service in
6 http.client (GH-119454) (#142139)
7
8gh-119451: Fix a potential denial of service in http.client (GH-119454)
9
10Reading the whole body of the HTTP response could cause OOM if
11the Content-Length value is too large even if the server does not send
12a large amount of data. Now the HTTP client reads large data by chunks,
13therefore the amount of consumed memory is proportional to the amount
14of sent data.
15(cherry picked from commit 5a4c4a033a4a54481be6870aa1896fad732555b5)
16
17CVE: CVE-2025-13836
18Upstream-Status: Backport [https://github.com/python/cpython/commit/289f29b0fe38baf2d7cb5854f4bb573cc34a6a15]
19Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
20---
21 Lib/http/client.py | 28 ++++++--
22 Lib/test/test_httplib.py | 66 +++++++++++++++++++
23 ...-05-23-11-47-48.gh-issue-119451.qkJe9-.rst | 5 ++
24 3 files changed, 95 insertions(+), 4 deletions(-)
25 create mode 100644 Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst
26
27diff --git a/Lib/http/client.py b/Lib/http/client.py
28index d1b7b10..c8ab5b7 100644
29--- a/Lib/http/client.py
30+++ b/Lib/http/client.py
31@@ -111,6 +111,11 @@ responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()}
32 _MAXLINE = 65536
33 _MAXHEADERS = 100
34
35+# Data larger than this will be read in chunks, to prevent extreme
36+# overallocation.
37+_MIN_READ_BUF_SIZE = 1 << 20
38+
39+
40 # Header name/value ABNF (http://tools.ietf.org/html/rfc7230#section-3.2)
41 #
42 # VCHAR = %x21-7E
43@@ -628,10 +633,25 @@ class HTTPResponse(io.BufferedIOBase):
44 reading. If the bytes are truly not available (due to EOF), then the
45 IncompleteRead exception can be used to detect the problem.
46 """
47- data = self.fp.read(amt)
48- if len(data) < amt:
49- raise IncompleteRead(data, amt-len(data))
50- return data
51+ cursize = min(amt, _MIN_READ_BUF_SIZE)
52+ data = self.fp.read(cursize)
53+ if len(data) >= amt:
54+ return data
55+ if len(data) < cursize:
56+ raise IncompleteRead(data, amt - len(data))
57+
58+ data = io.BytesIO(data)
59+ data.seek(0, 2)
60+ while True:
61+ # This is a geometric increase in read size (never more than
62+ # doubling out the current length of data per loop iteration).
63+ delta = min(cursize, amt - cursize)
64+ data.write(self.fp.read(delta))
65+ if data.tell() >= amt:
66+ return data.getvalue()
67+ cursize += delta
68+ if data.tell() < cursize:
69+ raise IncompleteRead(data.getvalue(), amt - data.tell())
70
71 def _safe_readinto(self, b):
72 """Same as _safe_read, but for reading into a buffer."""
73diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
74index 77152cf..89ec5f6 100644
75--- a/Lib/test/test_httplib.py
76+++ b/Lib/test/test_httplib.py
77@@ -1226,6 +1226,72 @@ class BasicTest(TestCase):
78 thread.join()
79 self.assertEqual(result, b"proxied data\n")
80
81+ def test_large_content_length(self):
82+ serv = socket.create_server((HOST, 0))
83+ self.addCleanup(serv.close)
84+
85+ def run_server():
86+ [conn, address] = serv.accept()
87+ with conn:
88+ while conn.recv(1024):
89+ conn.sendall(
90+ b"HTTP/1.1 200 Ok\r\n"
91+ b"Content-Length: %d\r\n"
92+ b"\r\n" % size)
93+ conn.sendall(b'A' * (size//3))
94+ conn.sendall(b'B' * (size - size//3))
95+
96+ thread = threading.Thread(target=run_server)
97+ thread.start()
98+ self.addCleanup(thread.join, 1.0)
99+
100+ conn = client.HTTPConnection(*serv.getsockname())
101+ try:
102+ for w in range(15, 27):
103+ size = 1 << w
104+ conn.request("GET", "/")
105+ with conn.getresponse() as response:
106+ self.assertEqual(len(response.read()), size)
107+ finally:
108+ conn.close()
109+ thread.join(1.0)
110+
111+ def test_large_content_length_truncated(self):
112+ serv = socket.create_server((HOST, 0))
113+ self.addCleanup(serv.close)
114+
115+ def run_server():
116+ while True:
117+ [conn, address] = serv.accept()
118+ with conn:
119+ conn.recv(1024)
120+ if not size:
121+ break
122+ conn.sendall(
123+ b"HTTP/1.1 200 Ok\r\n"
124+ b"Content-Length: %d\r\n"
125+ b"\r\n"
126+ b"Text" % size)
127+
128+ thread = threading.Thread(target=run_server)
129+ thread.start()
130+ self.addCleanup(thread.join, 1.0)
131+
132+ conn = client.HTTPConnection(*serv.getsockname())
133+ try:
134+ for w in range(18, 65):
135+ size = 1 << w
136+ conn.request("GET", "/")
137+ with conn.getresponse() as response:
138+ self.assertRaises(client.IncompleteRead, response.read)
139+ conn.close()
140+ finally:
141+ conn.close()
142+ size = 0
143+ conn.request("GET", "/")
144+ conn.close()
145+ thread.join(1.0)
146+
147 def test_putrequest_override_domain_validation(self):
148 """
149 It should be possible to override the default validation
150diff --git a/Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst b/Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst
151new file mode 100644
152index 0000000..6d6f25c
153--- /dev/null
154+++ b/Misc/NEWS.d/next/Security/2024-05-23-11-47-48.gh-issue-119451.qkJe9-.rst
155@@ -0,0 +1,5 @@
156+Fix a potential memory denial of service in the :mod:`http.client` module.
157+When connecting to a malicious server, it could cause
158+an arbitrary amount of memory to be allocated.
159+This could have led to symptoms including a :exc:`MemoryError`, swapping, out
160+of memory (OOM) killed processes or containers, or even system crashes.
161--
1622.50.1
163
diff --git a/meta/recipes-devtools/python/python3_3.10.19.bb b/meta/recipes-devtools/python/python3_3.10.19.bb
index 6f23d258c1..5140445ad8 100644
--- a/meta/recipes-devtools/python/python3_3.10.19.bb
+++ b/meta/recipes-devtools/python/python3_3.10.19.bb
@@ -38,6 +38,7 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \
38 file://0001-test_storlines-skip-due-to-load-variability.patch \ 38 file://0001-test_storlines-skip-due-to-load-variability.patch \
39 file://0001-gh-107811-tarfile-treat-overflow-in-UID-GID-as-failu.patch \ 39 file://0001-gh-107811-tarfile-treat-overflow-in-UID-GID-as-failu.patch \
40 file://CVE-2025-6075.patch \ 40 file://CVE-2025-6075.patch \
41 file://CVE-2025-13836.patch \
41 " 42 "
42 43
43SRC_URI:append:class-native = " \ 44SRC_URI:append:class-native = " \
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index fd1a8647df..764f0e110a 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -129,6 +129,7 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
129 file://CVE-2024-3446-0006.patch \ 129 file://CVE-2024-3446-0006.patch \
130 file://CVE-2024-3447.patch \ 130 file://CVE-2024-3447.patch \
131 file://CVE-2024-8354.patch \ 131 file://CVE-2024-8354.patch \
132 file://CVE-2025-12464.patch \
132 " 133 "
133UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" 134UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
134 135
@@ -168,6 +169,9 @@ CVE_CHECK_IGNORE += "CVE-2023-1386"
168# virtio-snd was implemented in 8.2.0, so version 6.2.0 is not yet affected 169# virtio-snd was implemented in 8.2.0, so version 6.2.0 is not yet affected
169CVE_CHECK_IGNORE += "CVE-2024-7730" 170CVE_CHECK_IGNORE += "CVE-2024-7730"
170 171
172# These issues were introduced in v10.0.0-rc0
173CVE_CHECK_IGNORE += "CVE-2025-54566 CVE-2025-54567"
174
171COMPATIBLE_HOST:mipsarchn32 = "null" 175COMPATIBLE_HOST:mipsarchn32 = "null"
172COMPATIBLE_HOST:mipsarchn64 = "null" 176COMPATIBLE_HOST:mipsarchn64 = "null"
173COMPATIBLE_HOST:riscv32 = "null" 177COMPATIBLE_HOST:riscv32 = "null"
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2025-12464.patch b/meta/recipes-devtools/qemu/qemu/CVE-2025-12464.patch
new file mode 100644
index 0000000000..6099fc79cd
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2025-12464.patch
@@ -0,0 +1,70 @@
1From a01344d9d78089e9e585faaeb19afccff2050abf Mon Sep 17 00:00:00 2001
2From: Peter Maydell <peter.maydell@linaro.org>
3Date: Tue, 28 Oct 2025 16:00:42 +0000
4Subject: [PATCH] net: pad packets to minimum length in qemu_receive_packet()
5
6In commits like 969e50b61a28 ("net: Pad short frames to minimum size
7before sending from SLiRP/TAP") we switched away from requiring
8network devices to handle short frames to instead having the net core
9code do the padding of short frames out to the ETH_ZLEN minimum size.
10We then dropped the code for handling short frames from the network
11devices in a series of commits like 140eae9c8f7 ("hw/net: e1000:
12Remove the logic of padding short frames in the receive path").
13
14This missed one route where the device's receive code can still see a
15short frame: if the device is in loopback mode and it transmits a
16short frame via the qemu_receive_packet() function, this will be fed
17back into its own receive code without being padded.
18
19Add the padding logic to qemu_receive_packet().
20
21This fixes a buffer overrun which can be triggered in the
22e1000_receive_iov() logic via the loopback code path.
23
24Other devices that use qemu_receive_packet() to implement loopback
25are cadence_gem, dp8393x, lan9118, msf2-emac, pcnet, rtl8139
26and sungem.
27
28Cc: qemu-stable@nongnu.org
29Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3043
30Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
31Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32Signed-off-by: Jason Wang <jasowang@redhat.com>
33
34CVE: CVE-2025-12464
35
36Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/a01344d9d7]
37
38Signed-off-by: Kai Kang <kai.kang@windriver.com>
39---
40 net/net.c | 10 ++++++++++
41 1 file changed, 10 insertions(+)
42
43diff --git a/net/net.c b/net/net.c
44index 27e0d27807..8aefdb3424 100644
45--- a/net/net.c
46+++ b/net/net.c
47@@ -775,10 +775,20 @@ ssize_t qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
48
49 ssize_t qemu_receive_packet(NetClientState *nc, const uint8_t *buf, int size)
50 {
51+ uint8_t min_pkt[ETH_ZLEN];
52+ size_t min_pktsz = sizeof(min_pkt);
53+
54 if (!qemu_can_receive_packet(nc)) {
55 return 0;
56 }
57
58+ if (net_peer_needs_padding(nc)) {
59+ if (eth_pad_short_frame(min_pkt, &min_pktsz, buf, size)) {
60+ buf = min_pkt;
61+ size = min_pktsz;
62+ }
63+ }
64+
65 return qemu_net_queue_receive(nc->incoming_queue, buf, size);
66 }
67
68--
692.47.1
70
diff --git a/meta/recipes-devtools/rsync/files/CVE-2025-10158.patch b/meta/recipes-devtools/rsync/files/CVE-2025-10158.patch
new file mode 100644
index 0000000000..cba7002870
--- /dev/null
+++ b/meta/recipes-devtools/rsync/files/CVE-2025-10158.patch
@@ -0,0 +1,36 @@
1From a8fabf850c3c5164520c307199e9abc5ded45e4c Mon Sep 17 00:00:00 2001
2From: Andrew Tridgell <andrew@tridgell.net>
3Date: Sat, 23 Aug 2025 17:26:53 +1000
4Subject: [PATCH] fixed an invalid access to files array
5
6this was found by Calum Hutton from Rapid7. It is a real bug, but
7analysis shows it can't be leverged into an exploit. Worth fixing
8though.
9
10Many thanks to Calum and Rapid7 for finding and reporting this
11
12CVE: CVE-2025-10158
13
14Upstream-Status: Backport [https://github.com/RsyncProject/rsync/commit/797e17fc4a6f15e3b1756538a9f812b63942686f]
15
16Signed-off-by: Liyin Zhang <liyin.zhang.cn@windriver.com>
17---
18 sender.c | 2 ++
19 1 file changed, 2 insertions(+)
20
21diff --git a/sender.c b/sender.c
22index a4d46c39..b1588b70 100644
23--- a/sender.c
24+++ b/sender.c
25@@ -262,6 +262,8 @@ void send_files(int f_in, int f_out)
26
27 if (ndx - cur_flist->ndx_start >= 0)
28 file = cur_flist->files[ndx - cur_flist->ndx_start];
29+ else if (cur_flist->parent_ndx < 0)
30+ exit_cleanup(RERR_PROTOCOL);
31 else
32 file = dir_flist->files[cur_flist->parent_ndx];
33 if (F_PATHNAME(file)) {
34--
352.35.5
36
diff --git a/meta/recipes-devtools/rsync/rsync_3.2.7.bb b/meta/recipes-devtools/rsync/rsync_3.2.7.bb
index 37e79e1e56..e3dd1702ec 100644
--- a/meta/recipes-devtools/rsync/rsync_3.2.7.bb
+++ b/meta/recipes-devtools/rsync/rsync_3.2.7.bb
@@ -27,6 +27,7 @@ SRC_URI = "https://download.samba.org/pub/${BPN}/src/${BP}.tar.gz \
27 file://CVE-2024-12087-0003.patch \ 27 file://CVE-2024-12087-0003.patch \
28 file://CVE-2024-12088.patch \ 28 file://CVE-2024-12088.patch \
29 file://CVE-2024-12747.patch \ 29 file://CVE-2024-12747.patch \
30 file://CVE-2025-10158.patch \
30 " 31 "
31 32
32SRC_URI[sha256sum] = "4e7d9d3f6ed10878c58c5fb724a67dacf4b6aac7340b13e488fb2dc41346f2bb" 33SRC_URI[sha256sum] = "4e7d9d3f6ed10878c58c5fb724a67dacf4b6aac7340b13e488fb2dc41346f2bb"
diff --git a/meta/recipes-extended/cups/cups.inc b/meta/recipes-extended/cups/cups.inc
index cba4406720..f70c4e7026 100644
--- a/meta/recipes-extended/cups/cups.inc
+++ b/meta/recipes-extended/cups/cups.inc
@@ -27,6 +27,9 @@ SRC_URI = "https://github.com/OpenPrinting/cups/releases/download/v${PV}/cups-${
27 file://CVE-2024-47175-5.patch \ 27 file://CVE-2024-47175-5.patch \
28 file://CVE-2025-58060.patch \ 28 file://CVE-2025-58060.patch \
29 file://CVE-2025-58364.patch \ 29 file://CVE-2025-58364.patch \
30 file://CVE-2025-58436.patch \
31 file://CVE-2025-61915.patch \
32 file://0001-conf.c-Fix-stopping-scheduler-on-unknown-directive.patch \
30 " 33 "
31 34
32UPSTREAM_CHECK_URI = "https://github.com/OpenPrinting/cups/releases" 35UPSTREAM_CHECK_URI = "https://github.com/OpenPrinting/cups/releases"
diff --git a/meta/recipes-extended/cups/cups/0001-conf.c-Fix-stopping-scheduler-on-unknown-directive.patch b/meta/recipes-extended/cups/cups/0001-conf.c-Fix-stopping-scheduler-on-unknown-directive.patch
new file mode 100644
index 0000000000..572a8941f4
--- /dev/null
+++ b/meta/recipes-extended/cups/cups/0001-conf.c-Fix-stopping-scheduler-on-unknown-directive.patch
@@ -0,0 +1,43 @@
1From 277d3b1c49895f070bbf4b73cada011d71fbf9f3 Mon Sep 17 00:00:00 2001
2From: Zdenek Dohnal <zdohnal@redhat.com>
3Date: Thu, 4 Dec 2025 09:04:37 +0100
4Subject: [PATCH] conf.c: Fix stopping scheduler on unknown directive
5
6Change the return value to do not trigger stopping the scheduler in case
7of unknown directive, because stopping the scheduler on config errors
8should only happen in case of syntax errors.
9
10Upstream-Status: Backport [https://github.com/OpenPrinting/cups/commit/277d3b1c49895f070bbf4b73cada011d71fbf9f3]
11Signed-off-by: Peter Marko <peter.marko@siemens.com>
12---
13 scheduler/conf.c | 14 +++++++-------
14 1 file changed, 7 insertions(+), 7 deletions(-)
15
16diff --git a/scheduler/conf.c b/scheduler/conf.c
17index 7d6da0252..0e7be0ef4 100644
18--- a/scheduler/conf.c
19+++ b/scheduler/conf.c
20@@ -2695,16 +2695,16 @@ parse_variable(
21 {
22 /*
23 * Unknown directive! Output an error message and continue...
24+ *
25+ * Return value 1 is on purpose - we ignore unknown directives to log
26+ * error, but do not stop the scheduler in case error in configuration
27+ * is set to be fatal.
28 */
29
30- if (!value)
31- cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d of %s.",
32- line, linenum, filename);
33- else
34- cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d of %s.",
35- line, linenum, filename);
36+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown directive %s on line %d of %s.",
37+ line, linenum, filename);
38
39- return (0);
40+ return (1);
41 }
42
43 switch (var->type)
diff --git a/meta/recipes-extended/cups/cups/CVE-2025-58436.patch b/meta/recipes-extended/cups/cups/CVE-2025-58436.patch
new file mode 100644
index 0000000000..388c5e57b5
--- /dev/null
+++ b/meta/recipes-extended/cups/cups/CVE-2025-58436.patch
@@ -0,0 +1,630 @@
1From 5d414f1f91bdca118413301b148f0b188eb1cdc6 Mon Sep 17 00:00:00 2001
2From: Zdenek Dohnal <zdohnal@redhat.com>
3Date: Mon, 13 Oct 2025 10:16:48 +0200
4Subject: [PATCH] Fix unresponsive cupsd process caused by a slow client
5
6If client is very slow, it will slow cupsd process for other clients.
7The fix is the best effort without turning scheduler cupsd into
8multithreaded process which would be too complex and error-prone when
9backporting to 2.4.x series.
10
11The fix for unencrypted communication is to follow up on communication
12only if there is the whole line on input, and the waiting time is
13guarded by timeout.
14
15Encrypted communication now starts after we have the whole client hello
16packet, which conflicts with optional upgrade support to HTTPS via
17methods other than method OPTIONS, so this optional support defined in
18RFC 2817, section 3.1 is removed. Too slow or incomplete requests are
19handled by connection timeout.
20
21Fixes CVE-2025-58436
22
23CVE: CVE-2025-58436
24Upstream-Status: Backport [https://github.com/OpenPrinting/cups/commit/5d414f1f91bdca118413301b148f0b188eb1cdc6]
25Signed-off-by: Peter Marko <peter.marko@siemens.com>
26---
27 cups/http-private.h | 7 +-
28 cups/http.c | 80 +++++++++++++-------
29 cups/tls-openssl.c | 15 +++-
30 scheduler/client.c | 178 ++++++++++++++++++++++++++++----------------
31 scheduler/client.h | 3 +
32 scheduler/select.c | 12 +++
33 6 files changed, 198 insertions(+), 97 deletions(-)
34
35diff --git a/cups/http-private.h b/cups/http-private.h
36index d9854faed..2d9035032 100644
37--- a/cups/http-private.h
38+++ b/cups/http-private.h
39@@ -120,6 +120,7 @@ extern "C" {
40 * Constants...
41 */
42
43+# define _HTTP_MAX_BUFFER 32768 /* Size of read buffer */
44 # define _HTTP_MAX_SBUFFER 65536 /* Size of (de)compression buffer */
45 # define _HTTP_RESOLVE_DEFAULT 0 /* Just resolve with default options */
46 # define _HTTP_RESOLVE_STDERR 1 /* Log resolve progress to stderr */
47@@ -231,8 +232,8 @@ struct _http_s /**** HTTP connection structure ****/
48 http_encoding_t data_encoding; /* Chunked or not */
49 int _data_remaining;/* Number of bytes left (deprecated) */
50 int used; /* Number of bytes used in buffer */
51- char buffer[HTTP_MAX_BUFFER];
52- /* Buffer for incoming data */
53+ char _buffer[HTTP_MAX_BUFFER];
54+ /* Old read buffer (deprecated) */
55 int _auth_type; /* Authentication in use (deprecated) */
56 unsigned char _md5_state[88]; /* MD5 state (deprecated) */
57 char nonce[HTTP_MAX_VALUE];
58@@ -306,6 +307,8 @@ struct _http_s /**** HTTP connection structure ****/
59 /* Allocated field values */
60 *default_fields[HTTP_FIELD_MAX];
61 /* Default field values, if any */
62+ char buffer[_HTTP_MAX_BUFFER];
63+ /* Read buffer */
64 };
65 # endif /* !_HTTP_NO_PRIVATE */
66
67diff --git a/cups/http.c b/cups/http.c
68index 7a42cb3d6..214e45158 100644
69--- a/cups/http.c
70+++ b/cups/http.c
71@@ -53,7 +53,7 @@ static http_t *http_create(const char *host, int port,
72 static void http_debug_hex(const char *prefix, const char *buffer,
73 int bytes);
74 #endif /* DEBUG */
75-static ssize_t http_read(http_t *http, char *buffer, size_t length);
76+static ssize_t http_read(http_t *http, char *buffer, size_t length, int timeout);
77 static ssize_t http_read_buffered(http_t *http, char *buffer, size_t length);
78 static ssize_t http_read_chunk(http_t *http, char *buffer, size_t length);
79 static int http_send(http_t *http, http_state_t request,
80@@ -1188,7 +1188,7 @@ httpGets(char *line, /* I - Line to read into */
81 return (NULL);
82 }
83
84- bytes = http_read(http, http->buffer + http->used, (size_t)(HTTP_MAX_BUFFER - http->used));
85+ bytes = http_read(http, http->buffer + http->used, (size_t)(_HTTP_MAX_BUFFER - http->used), http->wait_value);
86
87 DEBUG_printf(("4httpGets: read " CUPS_LLFMT " bytes.", CUPS_LLCAST bytes));
88
89@@ -1706,24 +1706,13 @@ httpPeek(http_t *http, /* I - HTTP connection */
90
91 ssize_t buflen; /* Length of read for buffer */
92
93- if (!http->blocking)
94- {
95- while (!httpWait(http, http->wait_value))
96- {
97- if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
98- continue;
99-
100- return (0);
101- }
102- }
103-
104 if ((size_t)http->data_remaining > sizeof(http->buffer))
105 buflen = sizeof(http->buffer);
106 else
107 buflen = (ssize_t)http->data_remaining;
108
109 DEBUG_printf(("2httpPeek: Reading %d bytes into buffer.", (int)buflen));
110- bytes = http_read(http, http->buffer, (size_t)buflen);
111+ bytes = http_read(http, http->buffer, (size_t)buflen, http->wait_value);
112
113 DEBUG_printf(("2httpPeek: Read " CUPS_LLFMT " bytes into buffer.",
114 CUPS_LLCAST bytes));
115@@ -1744,9 +1733,9 @@ httpPeek(http_t *http, /* I - HTTP connection */
116 int zerr; /* Decompressor error */
117 z_stream stream; /* Copy of decompressor stream */
118
119- if (http->used > 0 && ((z_stream *)http->stream)->avail_in < HTTP_MAX_BUFFER)
120+ if (http->used > 0 && ((z_stream *)http->stream)->avail_in < _HTTP_MAX_BUFFER)
121 {
122- size_t buflen = HTTP_MAX_BUFFER - ((z_stream *)http->stream)->avail_in;
123+ size_t buflen = _HTTP_MAX_BUFFER - ((z_stream *)http->stream)->avail_in;
124 /* Number of bytes to copy */
125
126 if (((z_stream *)http->stream)->avail_in > 0 &&
127@@ -2004,7 +1993,7 @@ httpRead2(http_t *http, /* I - HTTP connection */
128
129 if (bytes == 0)
130 {
131- ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in;
132+ ssize_t buflen = _HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in;
133 /* Additional bytes for buffer */
134
135 if (buflen > 0)
136@@ -2754,7 +2743,7 @@ int /* O - 1 to continue, 0 to stop */
137 _httpUpdate(http_t *http, /* I - HTTP connection */
138 http_status_t *status) /* O - Current HTTP status */
139 {
140- char line[32768], /* Line from connection... */
141+ char line[_HTTP_MAX_BUFFER], /* Line from connection... */
142 *value; /* Pointer to value on line */
143 http_field_t field; /* Field index */
144 int major, minor; /* HTTP version numbers */
145@@ -2762,12 +2751,46 @@ _httpUpdate(http_t *http, /* I - HTTP connection */
146
147 DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", (void *)http, (void *)status, httpStateString(http->state)));
148
149+ /* When doing non-blocking I/O, make sure we have a whole line... */
150+ if (!http->blocking)
151+ {
152+ ssize_t bytes; /* Bytes "peeked" from connection */
153+
154+ /* See whether our read buffer is full... */
155+ DEBUG_printf(("2_httpUpdate: used=%d", http->used));
156+
157+ if (http->used > 0 && !memchr(http->buffer, '\n', (size_t)http->used) && (size_t)http->used < sizeof(http->buffer))
158+ {
159+ /* No, try filling in more data... */
160+ if ((bytes = http_read(http, http->buffer + http->used, sizeof(http->buffer) - (size_t)http->used, /*timeout*/0)) > 0)
161+ {
162+ DEBUG_printf(("2_httpUpdate: Read %d bytes.", (int)bytes));
163+ http->used += (int)bytes;
164+ }
165+ }
166+
167+ /* Peek at the incoming data... */
168+ if (!http->used || !memchr(http->buffer, '\n', (size_t)http->used))
169+ {
170+ /* Don't have a full line, tell the reader to try again when there is more data... */
171+ DEBUG_puts("1_htttpUpdate: No newline in buffer yet.");
172+ if ((size_t)http->used == sizeof(http->buffer))
173+ *status = HTTP_STATUS_ERROR;
174+ else
175+ *status = HTTP_STATUS_CONTINUE;
176+ return (0);
177+ }
178+
179+ DEBUG_puts("2_httpUpdate: Found newline in buffer.");
180+ }
181+
182 /*
183 * Grab a single line from the connection...
184 */
185
186 if (!httpGets(line, sizeof(line), http))
187 {
188+ DEBUG_puts("1_httpUpdate: Error reading request line.");
189 *status = HTTP_STATUS_ERROR;
190 return (0);
191 }
192@@ -4089,7 +4112,8 @@ http_debug_hex(const char *prefix, /* I - Prefix for line */
193 static ssize_t /* O - Number of bytes read or -1 on error */
194 http_read(http_t *http, /* I - HTTP connection */
195 char *buffer, /* I - Buffer */
196- size_t length) /* I - Maximum bytes to read */
197+ size_t length, /* I - Maximum bytes to read */
198+ int timeout) /* I - Wait timeout */
199 {
200 ssize_t bytes; /* Bytes read */
201
202@@ -4098,7 +4122,7 @@ http_read(http_t *http, /* I - HTTP connection */
203
204 if (!http->blocking || http->timeout_value > 0.0)
205 {
206- while (!httpWait(http, http->wait_value))
207+ while (!_httpWait(http, timeout, 1))
208 {
209 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
210 continue;
211@@ -4201,7 +4225,7 @@ http_read_buffered(http_t *http, /* I - HTTP connection */
212 else
213 bytes = (ssize_t)length;
214
215- DEBUG_printf(("8http_read: Grabbing %d bytes from input buffer.",
216+ DEBUG_printf(("8http_read_buffered: Grabbing %d bytes from input buffer.",
217 (int)bytes));
218
219 memcpy(buffer, http->buffer, (size_t)bytes);
220@@ -4211,7 +4235,7 @@ http_read_buffered(http_t *http, /* I - HTTP connection */
221 memmove(http->buffer, http->buffer + bytes, (size_t)http->used);
222 }
223 else
224- bytes = http_read(http, buffer, length);
225+ bytes = http_read(http, buffer, length, http->wait_value);
226
227 return (bytes);
228 }
229@@ -4557,15 +4581,15 @@ http_set_timeout(int fd, /* I - File descriptor */
230 static void
231 http_set_wait(http_t *http) /* I - HTTP connection */
232 {
233- if (http->blocking)
234- {
235- http->wait_value = (int)(http->timeout_value * 1000);
236+ http->wait_value = (int)(http->timeout_value * 1000);
237
238- if (http->wait_value <= 0)
239+ if (http->wait_value <= 0)
240+ {
241+ if (http->blocking)
242 http->wait_value = 60000;
243+ else
244+ http->wait_value = 1000;
245 }
246- else
247- http->wait_value = 10000;
248 }
249
250
251diff --git a/cups/tls-openssl.c b/cups/tls-openssl.c
252index 9fcbe0af3..f746f4cba 100644
253--- a/cups/tls-openssl.c
254+++ b/cups/tls-openssl.c
255@@ -180,12 +180,14 @@ cupsMakeServerCredentials(
256 // Save them...
257 if ((bio = BIO_new_file(keyfile, "wb")) == NULL)
258 {
259+ DEBUG_printf(("1cupsMakeServerCredentials: Unable to create private key file '%s': %s", keyfile, strerror(errno)));
260 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
261 goto done;
262 }
263
264 if (!PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL))
265 {
266+ DEBUG_puts("1cupsMakeServerCredentials: PEM_write_bio_PrivateKey failed.");
267 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write private key."), 1);
268 BIO_free(bio);
269 goto done;
270@@ -195,12 +197,14 @@ cupsMakeServerCredentials(
271
272 if ((bio = BIO_new_file(crtfile, "wb")) == NULL)
273 {
274+ DEBUG_printf(("1cupsMakeServerCredentials: Unable to create certificate file '%s': %s", crtfile, strerror(errno)));
275 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
276 goto done;
277 }
278
279 if (!PEM_write_bio_X509(bio, cert))
280 {
281+ DEBUG_puts("1cupsMakeServerCredentials: PEM_write_bio_X509 failed.");
282 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to write X.509 certificate."), 1);
283 BIO_free(bio);
284 goto done;
285@@ -1044,10 +1048,10 @@ _httpTLSStart(http_t *http) // I - Connection to server
286
287 if (!cupsMakeServerCredentials(tls_keypath, cn, 0, NULL, time(NULL) + 365 * 86400))
288 {
289- DEBUG_puts("4_httpTLSStart: cupsMakeServerCredentials failed.");
290+ DEBUG_printf(("4_httpTLSStart: cupsMakeServerCredentials failed: %s", cupsLastErrorString()));
291 http->error = errno = EINVAL;
292 http->status = HTTP_STATUS_ERROR;
293- _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1);
294+// _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to create server credentials."), 1);
295 SSL_CTX_free(context);
296
297 return (-1);
298@@ -1272,14 +1276,17 @@ http_bio_read(BIO *h, // I - BIO data
299
300 http = (http_t *)BIO_get_data(h);
301
302- if (!http->blocking)
303+ if (!http->blocking || http->timeout_value > 0.0)
304 {
305 /*
306 * Make sure we have data before we read...
307 */
308
309- if (!_httpWait(http, 10000, 0))
310+ while (!_httpWait(http, http->wait_value, 0))
311 {
312+ if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
313+ continue;
314+
315 #ifdef WIN32
316 http->error = WSAETIMEDOUT;
317 #else
318diff --git a/scheduler/client.c b/scheduler/client.c
319index f0349a6c9..9593c9138 100644
320--- a/scheduler/client.c
321+++ b/scheduler/client.c
322@@ -34,11 +34,11 @@
323
324 static int check_if_modified(cupsd_client_t *con,
325 struct stat *filestats);
326+#ifdef HAVE_TLS
327+static int check_start_tls(cupsd_client_t *con);
328+#endif /* HAVE_TLS */
329 static int compare_clients(cupsd_client_t *a, cupsd_client_t *b,
330 void *data);
331-#ifdef HAVE_TLS
332-static int cupsd_start_tls(cupsd_client_t *con, http_encryption_t e);
333-#endif /* HAVE_TLS */
334 static char *get_file(cupsd_client_t *con, struct stat *filestats,
335 char *filename, size_t len);
336 static http_status_t install_cupsd_conf(cupsd_client_t *con);
337@@ -360,14 +360,20 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
338 if (lis->encryption == HTTP_ENCRYPTION_ALWAYS)
339 {
340 /*
341- * https connection; go secure...
342+ * HTTPS connection, force TLS negotiation...
343 */
344
345- if (cupsd_start_tls(con, HTTP_ENCRYPTION_ALWAYS))
346- cupsdCloseClient(con);
347+ con->tls_start = time(NULL);
348+ con->encryption = HTTP_ENCRYPTION_ALWAYS;
349 }
350 else
351+ {
352+ /*
353+ * HTTP connection, but check for HTTPS negotiation on first data...
354+ */
355+
356 con->auto_ssl = 1;
357+ }
358 #endif /* HAVE_TLS */
359 }
360
361@@ -597,17 +603,46 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
362
363 con->auto_ssl = 0;
364
365- if (recv(httpGetFd(con->http), buf, 1, MSG_PEEK) == 1 &&
366- (!buf[0] || !strchr("DGHOPT", buf[0])))
367+ if (recv(httpGetFd(con->http), buf, 5, MSG_PEEK) == 5 && buf[0] == 0x16 && buf[1] == 3 && buf[2])
368 {
369 /*
370- * Encrypt this connection...
371+ * Client hello record, encrypt this connection...
372 */
373
374- cupsdLogClient(con, CUPSD_LOG_DEBUG2, "Saw first byte %02X, auto-negotiating SSL/TLS session.", buf[0] & 255);
375+ cupsdLogClient(con, CUPSD_LOG_DEBUG2, "Saw client hello record, auto-negotiating TLS session.");
376+ con->tls_start = time(NULL);
377+ con->encryption = HTTP_ENCRYPTION_ALWAYS;
378+ }
379+ }
380
381- if (cupsd_start_tls(con, HTTP_ENCRYPTION_ALWAYS))
382- cupsdCloseClient(con);
383+ if (con->tls_start)
384+ {
385+ /*
386+ * Try negotiating TLS...
387+ */
388+
389+ int tls_status = check_start_tls(con);
390+
391+ if (tls_status < 0)
392+ {
393+ /*
394+ * TLS negotiation failed, close the connection.
395+ */
396+
397+ cupsdCloseClient(con);
398+ return;
399+ }
400+ else if (tls_status == 0)
401+ {
402+ /*
403+ * Nothing to do yet...
404+ */
405+
406+ if ((time(NULL) - con->tls_start) > 5)
407+ {
408+ // Timeout, close the connection...
409+ cupsdCloseClient(con);
410+ }
411
412 return;
413 }
414@@ -771,9 +806,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
415 * Parse incoming parameters until the status changes...
416 */
417
418- while ((status = httpUpdate(con->http)) == HTTP_STATUS_CONTINUE)
419- if (!httpGetReady(con->http))
420- break;
421+ status = httpUpdate(con->http);
422
423 if (status != HTTP_STATUS_OK && status != HTTP_STATUS_CONTINUE)
424 {
425@@ -935,11 +968,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
426 return;
427 }
428
429- if (cupsd_start_tls(con, HTTP_ENCRYPTION_REQUIRED))
430- {
431- cupsdCloseClient(con);
432- return;
433- }
434+ con->tls_start = time(NULL);
435+ con->tls_upgrade = 1;
436+ con->encryption = HTTP_ENCRYPTION_REQUIRED;
437+ return;
438 #else
439 if (!cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE))
440 {
441@@ -978,32 +1010,11 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */
442 if (!_cups_strcasecmp(httpGetField(con->http, HTTP_FIELD_CONNECTION),
443 "Upgrade") && !httpIsEncrypted(con->http))
444 {
445-#ifdef HAVE_TLS
446- /*
447- * Do encryption stuff...
448- */
449-
450- httpClearFields(con->http);
451-
452- if (!cupsdSendHeader(con, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL,
453- CUPSD_AUTH_NONE))
454- {
455- cupsdCloseClient(con);
456- return;
457- }
458-
459- if (cupsd_start_tls(con, HTTP_ENCRYPTION_REQUIRED))
460- {
461- cupsdCloseClient(con);
462- return;
463- }
464-#else
465 if (!cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE))
466 {
467 cupsdCloseClient(con);
468 return;
469 }
470-#endif /* HAVE_TLS */
471 }
472
473 if ((status = cupsdIsAuthorized(con, NULL)) != HTTP_STATUS_OK)
474@@ -2631,6 +2642,69 @@ check_if_modified(
475 }
476
477
478+#ifdef HAVE_TLS
479+/*
480+ * 'check_start_tls()' - Start encryption on a connection.
481+ */
482+
483+static int /* O - 0 to continue, 1 on success, -1 on error */
484+check_start_tls(cupsd_client_t *con) /* I - Client connection */
485+{
486+ unsigned char chello[4096]; /* Client hello record */
487+ ssize_t chello_bytes; /* Bytes read/peeked */
488+ int chello_len; /* Length of record */
489+
490+
491+ /*
492+ * See if we have a good and complete client hello record...
493+ */
494+
495+ if ((chello_bytes = recv(httpGetFd(con->http), (char *)chello, sizeof(chello), MSG_PEEK)) < 5)
496+ return (0); /* Not enough bytes (yet) */
497+
498+ if (chello[0] != 0x016 || chello[1] != 3 || chello[2] == 0)
499+ return (-1); /* Not a TLS Client Hello record */
500+
501+ chello_len = (chello[3] << 8) | chello[4];
502+
503+ if ((chello_len + 5) > chello_bytes)
504+ return (0); /* Not enough bytes yet */
505+
506+ /*
507+ * OK, we do, try negotiating...
508+ */
509+
510+ con->tls_start = 0;
511+
512+ if (httpEncryption(con->http, con->encryption))
513+ {
514+ cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to encrypt connection: %s", cupsLastErrorString());
515+ return (-1);
516+ }
517+
518+ cupsdLogClient(con, CUPSD_LOG_DEBUG, "Connection now encrypted.");
519+
520+ if (con->tls_upgrade)
521+ {
522+ // Respond to the original OPTIONS command...
523+ con->tls_upgrade = 0;
524+
525+ httpClearFields(con->http);
526+ httpClearCookie(con->http);
527+ httpSetField(con->http, HTTP_FIELD_CONTENT_LENGTH, "0");
528+
529+ if (!cupsdSendHeader(con, HTTP_STATUS_OK, NULL, CUPSD_AUTH_NONE))
530+ {
531+ cupsdCloseClient(con);
532+ return (-1);
533+ }
534+ }
535+
536+ return (1);
537+}
538+#endif /* HAVE_TLS */
539+
540+
541 /*
542 * 'compare_clients()' - Compare two client connections.
543 */
544@@ -2651,28 +2725,6 @@ compare_clients(cupsd_client_t *a, /* I - First client */
545 }
546
547
548-#ifdef HAVE_TLS
549-/*
550- * 'cupsd_start_tls()' - Start encryption on a connection.
551- */
552-
553-static int /* O - 0 on success, -1 on error */
554-cupsd_start_tls(cupsd_client_t *con, /* I - Client connection */
555- http_encryption_t e) /* I - Encryption mode */
556-{
557- if (httpEncryption(con->http, e))
558- {
559- cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to encrypt connection: %s",
560- cupsLastErrorString());
561- return (-1);
562- }
563-
564- cupsdLogClient(con, CUPSD_LOG_DEBUG, "Connection now encrypted.");
565- return (0);
566-}
567-#endif /* HAVE_TLS */
568-
569-
570 /*
571 * 'get_file()' - Get a filename and state info.
572 */
573diff --git a/scheduler/client.h b/scheduler/client.h
574index 9fe4e2ea6..2939ce997 100644
575--- a/scheduler/client.h
576+++ b/scheduler/client.h
577@@ -51,6 +51,9 @@ struct cupsd_client_s
578 cups_lang_t *language; /* Language to use */
579 #ifdef HAVE_TLS
580 int auto_ssl; /* Automatic test for SSL/TLS */
581+ time_t tls_start; /* Do TLS negotiation? */
582+ int tls_upgrade; /* Doing TLS upgrade via OPTIONS? */
583+ http_encryption_t encryption; /* Type of TLS negotiation */
584 #endif /* HAVE_TLS */
585 http_addr_t clientaddr; /* Client's server address */
586 char clientname[256];/* Client's server name for connection */
587diff --git a/scheduler/select.c b/scheduler/select.c
588index 2e64f2a7e..ac6205c51 100644
589--- a/scheduler/select.c
590+++ b/scheduler/select.c
591@@ -408,6 +408,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
592
593 cupsd_in_select = 1;
594
595+ // Prevent 100% CPU by releasing control before the kevent call...
596+ usleep(1);
597+
598 if (timeout >= 0 && timeout < 86400)
599 {
600 ktimeout.tv_sec = timeout;
601@@ -454,6 +457,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
602 struct epoll_event *event; /* Current event */
603
604
605+ // Prevent 100% CPU by releasing control before the epoll_wait call...
606+ usleep(1);
607+
608 if (timeout >= 0 && timeout < 86400)
609 nfds = epoll_wait(cupsd_epoll_fd, cupsd_epoll_events, MaxFDs,
610 timeout * 1000);
611@@ -546,6 +552,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
612 }
613 }
614
615+ // Prevent 100% CPU by releasing control before the poll call...
616+ usleep(1);
617+
618 if (timeout >= 0 && timeout < 86400)
619 nfds = poll(cupsd_pollfds, (nfds_t)count, timeout * 1000);
620 else
621@@ -599,6 +608,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */
622 cupsd_current_input = cupsd_global_input;
623 cupsd_current_output = cupsd_global_output;
624
625+ // Prevent 100% CPU by releasing control before the select call...
626+ usleep(1);
627+
628 if (timeout >= 0 && timeout < 86400)
629 {
630 stimeout.tv_sec = timeout;
diff --git a/meta/recipes-extended/cups/cups/CVE-2025-61915.patch b/meta/recipes-extended/cups/cups/CVE-2025-61915.patch
new file mode 100644
index 0000000000..bdab24e028
--- /dev/null
+++ b/meta/recipes-extended/cups/cups/CVE-2025-61915.patch
@@ -0,0 +1,487 @@
1From db8d560262c22a21ee1e55dfd62fa98d9359bcb0 Mon Sep 17 00:00:00 2001
2From: Zdenek Dohnal <zdohnal@redhat.com>
3Date: Fri, 21 Nov 2025 07:36:36 +0100
4Subject: [PATCH] Fix various issues in cupsd
5
6Various issues were found by @SilverPlate3, recognized as CVE-2025-61915:
7
8- out of bound write when handling IPv6 addresses,
9- cupsd crash caused by null dereference when ErrorPolicy value is empty,
10
11On the top of that, Mike Sweet noticed vulnerability via domain socket,
12exploitable locally if attacker has access to domain socket and knows username
13of user within a group which is present in CUPS system groups:
14
15- rewrite of cupsd.conf via PeerCred authorization via domain socket
16
17The last vulnerability is fixed by introducing PeerCred directive for cups-files.conf,
18which controls whether PeerCred is enabled/disabled for user in CUPS system groups.
19
20Fixes CVE-2025-61915
21
22CVE: CVE-2025-61915
23Upstream-Status: Backport [https://github.com/OpenPrinting/cups/commit/db8d560262c22a21ee1e55dfd62fa98d9359bcb0]
24Signed-off-by: Peter Marko <peter.marko@siemens.com>
25---
26 conf/cups-files.conf.in | 3 ++
27 config-scripts/cups-defaults.m4 | 9 +++++
28 config.h.in | 7 ++++
29 configure | 22 ++++++++++
30 doc/help/man-cups-files.conf.html | 9 ++++-
31 man/cups-files.conf.5 | 17 ++++++--
32 scheduler/auth.c | 8 +++-
33 scheduler/auth.h | 7 ++++
34 scheduler/client.c | 2 +-
35 scheduler/conf.c | 60 ++++++++++++++++++++++++----
36 test/run-stp-tests.sh | 2 +-
37 vcnet/config.h | 7 ++++
38 xcode/CUPS.xcodeproj/project.pbxproj | 2 -
39 xcode/config.h | 7 ++++
40 14 files changed, 145 insertions(+), 17 deletions(-)
41
42diff --git a/conf/cups-files.conf.in b/conf/cups-files.conf.in
43index f96f745ae..6db139297 100644
44--- a/conf/cups-files.conf.in
45+++ b/conf/cups-files.conf.in
46@@ -19,6 +19,9 @@
47 SystemGroup @CUPS_SYSTEM_GROUPS@
48 @CUPS_SYSTEM_AUTHKEY@
49
50+# Are Unix domain socket peer credentials used for authorization?
51+PeerCred @CUPS_PEER_CRED@
52+
53 # User that is substituted for unauthenticated (remote) root accesses...
54 #RemoteRoot remroot
55
56diff --git a/config-scripts/cups-defaults.m4 b/config-scripts/cups-defaults.m4
57index 999a8849d..fc9ba4a02 100644
58--- a/config-scripts/cups-defaults.m4
59+++ b/config-scripts/cups-defaults.m4
60@@ -129,6 +129,15 @@ AC_ARG_WITH([log_level], AS_HELP_STRING([--with-log-level], [set default LogLeve
61 AC_SUBST([CUPS_LOG_LEVEL])
62 AC_DEFINE_UNQUOTED([CUPS_DEFAULT_LOG_LEVEL], ["$CUPS_LOG_LEVEL"], [Default LogLevel value.])
63
64+dnl Default PeerCred
65+AC_ARG_WITH([peer_cred], AS_HELP_STRING([--with-peer-cred], [set default PeerCred value (on/off/root-only), default=on]), [
66+ CUPS_PEER_CRED="$withval"
67+], [
68+ CUPS_PEER_CRED="on"
69+])
70+AC_SUBST([CUPS_PEER_CRED])
71+AC_DEFINE_UNQUOTED([CUPS_DEFAULT_PEER_CRED], ["$CUPS_PEER_CRED"], [Default PeerCred value.])
72+
73 dnl Default AccessLogLevel
74 AC_ARG_WITH(access_log_level, [ --with-access-log-level set default AccessLogLevel value, default=none],
75 CUPS_ACCESS_LOG_LEVEL="$withval",
76diff --git a/config.h.in b/config.h.in
77index 207df66a7..37c279088 100644
78--- a/config.h.in
79+++ b/config.h.in
80@@ -86,6 +86,13 @@
81 #define CUPS_DEFAULT_ERROR_POLICY "stop-printer"
82
83
84+/*
85+ * Default PeerCred value...
86+ */
87+
88+#define CUPS_DEFAULT_PEER_CRED "on"
89+
90+
91 /*
92 * Default MaxCopies value...
93 */
94diff --git a/configure b/configure
95index a38ebded9..1721634ba 100755
96--- a/configure
97+++ b/configure
98@@ -672,6 +672,7 @@ CUPS_BROWSING
99 CUPS_SYNC_ON_CLOSE
100 CUPS_PAGE_LOG_FORMAT
101 CUPS_ACCESS_LOG_LEVEL
102+CUPS_PEER_CRED
103 CUPS_LOG_LEVEL
104 CUPS_FATAL_ERRORS
105 CUPS_ERROR_POLICY
106@@ -925,6 +926,7 @@ with_max_log_size
107 with_error_policy
108 with_fatal_errors
109 with_log_level
110+with_peer_cred
111 with_access_log_level
112 enable_page_logging
113 enable_sync_on_close
114@@ -1659,6 +1661,8 @@ Optional Packages:
115 --with-error-policy set default ErrorPolicy value, default=stop-printer
116 --with-fatal-errors set default FatalErrors value, default=config
117 --with-log-level set default LogLevel value, default=warn
118+ --with-peer-cred set default PeerCred value (on/off/root-only),
119+ default=on
120 --with-access-log-level set default AccessLogLevel value, default=none
121 --with-local-protocols set default BrowseLocalProtocols, default=""
122 --with-cups-user set default user for CUPS
123@@ -11652,6 +11656,24 @@ printf "%s\n" "#define CUPS_DEFAULT_LOG_LEVEL \"$CUPS_LOG_LEVEL\"" >>confdefs.h
124
125
126
127+# Check whether --with-peer_cred was given.
128+if test ${with_peer_cred+y}
129+then :
130+ withval=$with_peer_cred;
131+ CUPS_PEER_CRED="$withval"
132+
133+else $as_nop
134+
135+ CUPS_PEER_CRED="on"
136+
137+fi
138+
139+
140+
141+printf "%s\n" "#define CUPS_DEFAULT_PEER_CRED \"$CUPS_PEER_CRED\"" >>confdefs.h
142+
143+
144+
145 # Check whether --with-access_log_level was given.
146 if test ${with_access_log_level+y}
147 then :
148diff --git a/doc/help/man-cups-files.conf.html b/doc/help/man-cups-files.conf.html
149index 440f033d5..5a9ddefeb 100644
150--- a/doc/help/man-cups-files.conf.html
151+++ b/doc/help/man-cups-files.conf.html
152@@ -119,6 +119,13 @@ The default is "/var/log/cups/page_log".
153 <dt><a name="PassEnv"></a><b>PassEnv </b><i>variable </i>[ ... <i>variable </i>]
154 <dd style="margin-left: 5.0em">Passes the specified environment variable(s) to child processes.
155 Note: the standard CUPS filter and backend environment variables cannot be overridden using this directive.
156+<dt><a name="PeerCred"></a><b>PeerCred off</b>
157+<dd style="margin-left: 5.0em"><dt><b>PeerCred on</b>
158+<dd style="margin-left: 5.0em"><dt><b>PeerCred root-only</b>
159+<dd style="margin-left: 5.0em">Specifies whether peer credentials are used for authorization when communicating over the UNIX domain socket.
160+When <b>on</b>, the peer credentials of any user are accepted for authorization.
161+The value <b>off</b> disables the use of peer credentials entirely, while the value <b>root-only</b> allows peer credentials only for the root user.
162+Note: for security reasons, the <b>on</b> setting is reduced to <b>root-only</b> for authorization of PUT requests.
163 <dt><a name="RemoteRoot"></a><b>RemoteRoot </b><i>username</i>
164 <dd style="margin-left: 5.0em">Specifies the username that is associated with unauthenticated accesses by clients claiming to be the root user.
165 The default is "remroot".
166@@ -199,7 +206,7 @@ command is used instead.
167 <a href="man-subscriptions.conf.html?TOPIC=Man+Pages"><b>subscriptions.conf</b>(5),</a>
168 CUPS Online Help (<a href="http://localhost:631/help">http://localhost:631/help</a>)
169 <h2 class="title"><a name="COPYRIGHT">Copyright</a></h2>
170-Copyright &copy; 2020-2022 by OpenPrinting.
171+Copyright &copy; 2020-2025 by OpenPrinting.
172
173 </body>
174 </html>
175diff --git a/man/cups-files.conf.5 b/man/cups-files.conf.5
176index ec16c9e13..18ce2be00 100644
177--- a/man/cups-files.conf.5
178+++ b/man/cups-files.conf.5
179@@ -1,14 +1,14 @@
180 .\"
181 .\" cups-files.conf man page for CUPS.
182 .\"
183-.\" Copyright © 2020-2022 by OpenPrinting.
184+.\" Copyright © 2020-2025 by OpenPrinting.
185 .\" Copyright © 2007-2019 by Apple Inc.
186 .\" Copyright © 1997-2006 by Easy Software Products.
187 .\"
188 .\" Licensed under Apache License v2.0. See the file "LICENSE" for more
189 .\" information.
190 .\"
191-.TH cups-files.conf 5 "CUPS" "2021-03-06" "OpenPrinting"
192+.TH cups-files.conf 5 "CUPS" "2025-10-08" "OpenPrinting"
193 .SH NAME
194 cups\-files.conf \- file and directory configuration file for cups
195 .SH DESCRIPTION
196@@ -166,6 +166,17 @@ The default is "/var/log/cups/page_log".
197 \fBPassEnv \fIvariable \fR[ ... \fIvariable \fR]
198 Passes the specified environment variable(s) to child processes.
199 Note: the standard CUPS filter and backend environment variables cannot be overridden using this directive.
200+.\"#PeerCred
201+.TP 5
202+\fBPeerCred off\fR
203+.TP 5
204+\fBPeerCred on\fR
205+.TP 5
206+\fBPeerCred root-only\fR
207+Specifies whether peer credentials are used for authorization when communicating over the UNIX domain socket.
208+When \fBon\fR, the peer credentials of any user are accepted for authorization.
209+The value \fBoff\fR disables the use of peer credentials entirely, while the value \fBroot-only\fR allows peer credentials only for the root user.
210+Note: for security reasons, the \fBon\fR setting is reduced to \fBroot-only\fR for authorization of PUT requests.
211 .\"#RemoteRoot
212 .TP 5
213 \fBRemoteRoot \fIusername\fR
214@@ -278,4 +289,4 @@ command is used instead.
215 .BR subscriptions.conf (5),
216 CUPS Online Help (http://localhost:631/help)
217 .SH COPYRIGHT
218-Copyright \[co] 2020-2022 by OpenPrinting.
219+Copyright \[co] 2020-2025 by OpenPrinting.
220diff --git a/scheduler/auth.c b/scheduler/auth.c
221index 3c9aa72aa..bd0d28a0e 100644
222--- a/scheduler/auth.c
223+++ b/scheduler/auth.c
224@@ -398,7 +398,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
225 }
226 #endif /* HAVE_AUTHORIZATION_H */
227 #if defined(SO_PEERCRED) && defined(AF_LOCAL)
228- else if (!strncmp(authorization, "PeerCred ", 9) &&
229+ else if (PeerCred != CUPSD_PEERCRED_OFF && !strncmp(authorization, "PeerCred ", 9) &&
230 con->http->hostaddr->addr.sa_family == AF_LOCAL && con->best)
231 {
232 /*
233@@ -441,6 +441,12 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
234 }
235 #endif /* HAVE_AUTHORIZATION_H */
236
237+ if ((PeerCred == CUPSD_PEERCRED_ROOTONLY || httpGetState(con->http) == HTTP_STATE_PUT_RECV) && strcmp(authorization + 9, "root"))
238+ {
239+ cupsdLogClient(con, CUPSD_LOG_INFO, "User \"%s\" is not allowed to use peer credentials.", authorization + 9);
240+ return;
241+ }
242+
243 if ((pwd = getpwnam(authorization + 9)) == NULL)
244 {
245 cupsdLogClient(con, CUPSD_LOG_ERROR, "User \"%s\" does not exist.", authorization + 9);
246diff --git a/scheduler/auth.h b/scheduler/auth.h
247index ee98e92c7..fdf71213f 100644
248--- a/scheduler/auth.h
249+++ b/scheduler/auth.h
250@@ -50,6 +50,10 @@
251 #define CUPSD_AUTH_LIMIT_ALL 127 /* Limit all requests */
252 #define CUPSD_AUTH_LIMIT_IPP 128 /* Limit IPP requests */
253
254+#define CUPSD_PEERCRED_OFF 0 /* Don't allow PeerCred authorization */
255+#define CUPSD_PEERCRED_ON 1 /* Allow PeerCred authorization for all users */
256+#define CUPSD_PEERCRED_ROOTONLY 2 /* Allow PeerCred authorization for root user */
257+
258 #define IPP_ANY_OPERATION (ipp_op_t)0
259 /* Any IPP operation */
260 #define IPP_BAD_OPERATION (ipp_op_t)-1
261@@ -107,6 +111,9 @@ typedef struct cupsd_client_s cupsd_client_t;
262
263 VAR cups_array_t *Locations VALUE(NULL);
264 /* Authorization locations */
265+VAR int PeerCred VALUE(CUPSD_PEERCRED_ON);
266+ /* Allow PeerCred authorization? */
267+
268 #ifdef HAVE_TLS
269 VAR http_encryption_t DefaultEncryption VALUE(HTTP_ENCRYPT_REQUIRED);
270 /* Default encryption for authentication */
271diff --git a/scheduler/client.c b/scheduler/client.c
272index 9593c9138..d961c15db 100644
273--- a/scheduler/client.c
274+++ b/scheduler/client.c
275@@ -2143,7 +2143,7 @@ cupsdSendHeader(
276 auth_size = sizeof(auth_str) - (size_t)(auth_key - auth_str);
277
278 #if defined(SO_PEERCRED) && defined(AF_LOCAL)
279- if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
280+ if (PeerCred != CUPSD_PEERCRED_OFF && httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL)
281 {
282 strlcpy(auth_key, ", PeerCred", auth_size);
283 auth_key += 10;
284diff --git a/scheduler/conf.c b/scheduler/conf.c
285index db4104ec5..7d6da0252 100644
286--- a/scheduler/conf.c
287+++ b/scheduler/conf.c
288@@ -47,6 +47,7 @@ typedef enum
289 {
290 CUPSD_VARTYPE_INTEGER, /* Integer option */
291 CUPSD_VARTYPE_TIME, /* Time interval option */
292+ CUPSD_VARTYPE_NULLSTRING, /* String option or NULL/empty string */
293 CUPSD_VARTYPE_STRING, /* String option */
294 CUPSD_VARTYPE_BOOLEAN, /* Boolean option */
295 CUPSD_VARTYPE_PATHNAME, /* File/directory name option */
296@@ -69,7 +70,7 @@ static const cupsd_var_t cupsd_vars[] =
297 {
298 { "AutoPurgeJobs", &JobAutoPurge, CUPSD_VARTYPE_BOOLEAN },
299 #ifdef HAVE_DNSSD
300- { "BrowseDNSSDSubTypes", &DNSSDSubTypes, CUPSD_VARTYPE_STRING },
301+ { "BrowseDNSSDSubTypes", &DNSSDSubTypes, CUPSD_VARTYPE_NULLSTRING },
302 #endif /* HAVE_DNSSD */
303 { "BrowseWebIF", &BrowseWebIF, CUPSD_VARTYPE_BOOLEAN },
304 { "Browsing", &Browsing, CUPSD_VARTYPE_BOOLEAN },
305@@ -120,7 +121,7 @@ static const cupsd_var_t cupsd_vars[] =
306 { "MaxSubscriptionsPerPrinter",&MaxSubscriptionsPerPrinter, CUPSD_VARTYPE_INTEGER },
307 { "MaxSubscriptionsPerUser", &MaxSubscriptionsPerUser, CUPSD_VARTYPE_INTEGER },
308 { "MultipleOperationTimeout", &MultipleOperationTimeout, CUPSD_VARTYPE_TIME },
309- { "PageLogFormat", &PageLogFormat, CUPSD_VARTYPE_STRING },
310+ { "PageLogFormat", &PageLogFormat, CUPSD_VARTYPE_NULLSTRING },
311 { "PreserveJobFiles", &JobFiles, CUPSD_VARTYPE_TIME },
312 { "PreserveJobHistory", &JobHistory, CUPSD_VARTYPE_TIME },
313 { "ReloadTimeout", &ReloadTimeout, CUPSD_VARTYPE_TIME },
314@@ -777,6 +778,13 @@ cupsdReadConfiguration(void)
315 IdleExitTimeout = 60;
316 #endif /* HAVE_ONDEMAND */
317
318+ if (!strcmp(CUPS_DEFAULT_PEER_CRED, "off"))
319+ PeerCred = CUPSD_PEERCRED_OFF;
320+ else if (!strcmp(CUPS_DEFAULT_PEER_CRED, "root-only"))
321+ PeerCred = CUPSD_PEERCRED_ROOTONLY;
322+ else
323+ PeerCred = CUPSD_PEERCRED_ON;
324+
325 /*
326 * Setup environment variables...
327 */
328@@ -1826,7 +1834,7 @@ get_addr_and_mask(const char *value, /* I - String from config file */
329
330 family = AF_INET6;
331
332- for (i = 0, ptr = value + 1; *ptr && i < 8; i ++)
333+ for (i = 0, ptr = value + 1; *ptr && i >= 0 && i < 8; i ++)
334 {
335 if (*ptr == ']')
336 break;
337@@ -1975,7 +1983,7 @@ get_addr_and_mask(const char *value, /* I - String from config file */
338 #ifdef AF_INET6
339 if (family == AF_INET6)
340 {
341- if (i > 128)
342+ if (i < 0 || i > 128)
343 return (0);
344
345 i = 128 - i;
346@@ -2009,7 +2017,7 @@ get_addr_and_mask(const char *value, /* I - String from config file */
347 else
348 #endif /* AF_INET6 */
349 {
350- if (i > 32)
351+ if (i < 0 || i > 32)
352 return (0);
353
354 mask[0] = 0xffffffff;
355@@ -2919,7 +2927,17 @@ parse_variable(
356 cupsdSetString((char **)var->ptr, temp);
357 break;
358
359+ case CUPSD_VARTYPE_NULLSTRING :
360+ cupsdSetString((char **)var->ptr, value);
361+ break;
362+
363 case CUPSD_VARTYPE_STRING :
364+ if (!value)
365+ {
366+ cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value for %s on line %d of %s.", line, linenum, filename);
367+ return (0);
368+ }
369+
370 cupsdSetString((char **)var->ptr, value);
371 break;
372 }
373@@ -3447,9 +3465,10 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */
374 line, value ? " " : "", value ? value : "", linenum,
375 ConfigurationFile, CupsFilesFile);
376 }
377- else
378- parse_variable(ConfigurationFile, linenum, line, value,
379- sizeof(cupsd_vars) / sizeof(cupsd_vars[0]), cupsd_vars);
380+ else if (!parse_variable(ConfigurationFile, linenum, line, value,
381+ sizeof(cupsd_vars) / sizeof(cupsd_vars[0]), cupsd_vars) &&
382+ (FatalErrors & CUPSD_FATAL_CONFIG))
383+ return (0);
384 }
385
386 return (1);
387@@ -3609,6 +3628,31 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */
388 break;
389 }
390 }
391+ else if (!_cups_strcasecmp(line, "PeerCred") && value)
392+ {
393+ /*
394+ * PeerCred {off,on,root-only}
395+ */
396+
397+ if (!_cups_strcasecmp(value, "off"))
398+ {
399+ PeerCred = CUPSD_PEERCRED_OFF;
400+ }
401+ else if (!_cups_strcasecmp(value, "on"))
402+ {
403+ PeerCred = CUPSD_PEERCRED_ON;
404+ }
405+ else if (!_cups_strcasecmp(value, "root-only"))
406+ {
407+ PeerCred = CUPSD_PEERCRED_ROOTONLY;
408+ }
409+ else
410+ {
411+ cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown PeerCred \"%s\" on line %d of %s.", value, linenum, CupsFilesFile);
412+ if (FatalErrors & CUPSD_FATAL_CONFIG)
413+ return (0);
414+ }
415+ }
416 else if (!_cups_strcasecmp(line, "PrintcapFormat") && value)
417 {
418 /*
419diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh
420index 1c447edd7..8d677db71 100755
421--- a/test/run-stp-tests.sh
422+++ b/test/run-stp-tests.sh
423@@ -512,7 +512,7 @@ fi
424
425 cat >$BASE/cups-files.conf <<EOF
426 FileDevice yes
427-Printcap
428+Printcap $BASE/printcap
429 User $user
430 ServerRoot $BASE
431 StateDir $BASE
432diff --git a/vcnet/config.h b/vcnet/config.h
433index dbc6f05d5..317c956a6 100644
434--- a/vcnet/config.h
435+++ b/vcnet/config.h
436@@ -169,6 +169,13 @@ typedef unsigned long useconds_t;
437 #define CUPS_DEFAULT_ERROR_POLICY "stop-printer"
438
439
440+/*
441+ * Default PeerCred value...
442+ */
443+
444+#define CUPS_DEFAULT_PEER_CRED "on"
445+
446+
447 /*
448 * Default MaxCopies value...
449 */
450diff --git a/xcode/CUPS.xcodeproj/project.pbxproj b/xcode/CUPS.xcodeproj/project.pbxproj
451index 597946440..54ac652a1 100644
452--- a/xcode/CUPS.xcodeproj/project.pbxproj
453+++ b/xcode/CUPS.xcodeproj/project.pbxproj
454@@ -3434,7 +3434,6 @@
455 72220FB313330BCE00FCA411 /* mime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = mime.c; path = ../scheduler/mime.c; sourceTree = "<group>"; };
456 72220FB413330BCE00FCA411 /* mime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mime.h; path = ../scheduler/mime.h; sourceTree = "<group>"; };
457 72220FB513330BCE00FCA411 /* type.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = type.c; path = ../scheduler/type.c; sourceTree = "<group>"; };
458- 7226369B18AE6D19004ED309 /* org.cups.cups-lpd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "org.cups.cups-lpd.plist"; path = "../scheduler/org.cups.cups-lpd.plist"; sourceTree = SOURCE_ROOT; };
459 7226369C18AE6D19004ED309 /* org.cups.cupsd.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = org.cups.cupsd.plist; path = ../scheduler/org.cups.cupsd.plist; sourceTree = SOURCE_ROOT; };
460 7226369D18AE73BB004ED309 /* config.h.in */ = {isa = PBXFileReference; lastKnownFileType = text; name = config.h.in; path = ../config.h.in; sourceTree = "<group>"; };
461 722A24EE2178D00C000CAB20 /* debug-internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "debug-internal.h"; path = "../cups/debug-internal.h"; sourceTree = "<group>"; };
462@@ -5056,7 +5055,6 @@
463 isa = PBXGroup;
464 children = (
465 72E65BDC18DC852700097E89 /* Makefile */,
466- 7226369B18AE6D19004ED309 /* org.cups.cups-lpd.plist */,
467 72E65BD518DC818400097E89 /* org.cups.cups-lpd.plist.in */,
468 7226369C18AE6D19004ED309 /* org.cups.cupsd.plist */,
469 72220F6913330B0C00FCA411 /* auth.c */,
470diff --git a/xcode/config.h b/xcode/config.h
471index e0ddd09dc..caec083ca 100644
472--- a/xcode/config.h
473+++ b/xcode/config.h
474@@ -88,6 +88,13 @@
475 #define CUPS_DEFAULT_ERROR_POLICY "stop-printer"
476
477
478+/*
479+ * Default PeerCred value...
480+ */
481+
482+#define CUPS_DEFAULT_PEER_CRED "on"
483+
484+
485 /*
486 * Default MaxCopies value...
487 */
diff --git a/meta/recipes-extended/libarchive/libarchive/CVE-2025-60753.patch b/meta/recipes-extended/libarchive/libarchive/CVE-2025-60753-01.patch
index 604e0421be..604e0421be 100644
--- a/meta/recipes-extended/libarchive/libarchive/CVE-2025-60753.patch
+++ b/meta/recipes-extended/libarchive/libarchive/CVE-2025-60753-01.patch
diff --git a/meta/recipes-extended/libarchive/libarchive/CVE-2025-60753-02.patch b/meta/recipes-extended/libarchive/libarchive/CVE-2025-60753-02.patch
new file mode 100644
index 0000000000..525ee2462c
--- /dev/null
+++ b/meta/recipes-extended/libarchive/libarchive/CVE-2025-60753-02.patch
@@ -0,0 +1,46 @@
1From cfb02de558d843dc5355c4aa2aeb4af49f88bdb9 Mon Sep 17 00:00:00 2001
2From: Martin Matuska <martin@matuska.de>
3Date: Mon, 8 Dec 2025 21:40:46 +0100
4Subject: [PATCH] tar: fix off-bounds read resulting from #2787 (3150539ed)
5
6CVE: CVE-2025-60753
7Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/cfb02de558d843dc5355c4aa2aeb4af49f88bdb9]
8Signed-off-by: Peter Marko <peter.marko@siemens.com>
9---
10 tar/subst.c | 16 ++++++++--------
11 1 file changed, 8 insertions(+), 8 deletions(-)
12
13diff --git a/tar/subst.c b/tar/subst.c
14index a466f653..53497ad0 100644
15--- a/tar/subst.c
16+++ b/tar/subst.c
17@@ -239,7 +239,7 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result,
18
19 char isEnd = 0;
20 do {
21- isEnd = *name == '\0';
22+ isEnd = *name == '\0';
23 if (regexec(&rule->re, name, 10, matches, 0))
24 break;
25
26@@ -294,13 +294,13 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result,
27
28 realloc_strcat(result, rule->result + j);
29 if (matches[0].rm_eo > 0) {
30- name += matches[0].rm_eo;
31- } else {
32- // We skip a character because the match is 0-length
33- // so we need to add it to the output
34- realloc_strncat(result, name, 1);
35- name += 1;
36- }
37+ name += matches[0].rm_eo;
38+ } else if (!isEnd) {
39+ // We skip a character because the match is 0-length
40+ // so we need to add it to the output
41+ realloc_strncat(result, name, 1);
42+ name += 1;
43+ }
44 } while (rule->global && !isEnd); // Testing one step after because sed et al. run 0-length patterns a last time on the empty string at the end
45 }
46
diff --git a/meta/recipes-extended/libarchive/libarchive_3.6.2.bb b/meta/recipes-extended/libarchive/libarchive_3.6.2.bb
index 66f30ec89b..e74326b40f 100644
--- a/meta/recipes-extended/libarchive/libarchive_3.6.2.bb
+++ b/meta/recipes-extended/libarchive/libarchive_3.6.2.bb
@@ -48,7 +48,8 @@ SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz \
48 file://0001-Merge-pull-request-2749-from-KlaraSystems-des-tempdi.patch \ 48 file://0001-Merge-pull-request-2749-from-KlaraSystems-des-tempdi.patch \
49 file://0001-Merge-pull-request-2753-from-KlaraSystems-des-temp-f.patch \ 49 file://0001-Merge-pull-request-2753-from-KlaraSystems-des-temp-f.patch \
50 file://0001-Merge-pull-request-2768-from-Commandoss-master.patch \ 50 file://0001-Merge-pull-request-2768-from-Commandoss-master.patch \
51 file://CVE-2025-60753.patch \ 51 file://CVE-2025-60753-01.patch \
52 file://CVE-2025-60753-02.patch \
52 " 53 "
53UPSTREAM_CHECK_URI = "http://libarchive.org/" 54UPSTREAM_CHECK_URI = "http://libarchive.org/"
54 55
diff --git a/meta/recipes-support/curl/curl/CVE-2025-14017.patch b/meta/recipes-support/curl/curl/CVE-2025-14017.patch
new file mode 100644
index 0000000000..a18e1d74dd
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2025-14017.patch
@@ -0,0 +1,115 @@
1From 39d1976b7f709a516e3243338ebc0443bdd8d56d Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Thu, 4 Dec 2025 00:14:20 +0100
4Subject: [PATCH] ldap: call ldap_init() before setting the options
5
6Closes #19830
7
8CVE: CVE-2025-14017
9Upstream-Status: Backport [https://github.com/curl/curl/commit/39d1976b7f709a516e3243338ebc0443bdd8d56d]
10Signed-off-by: Peter Marko <peter.marko@siemens.com>
11---
12 lib/ldap.c | 49 +++++++++++++++++++------------------------------
13 1 file changed, 19 insertions(+), 30 deletions(-)
14
15diff --git a/lib/ldap.c b/lib/ldap.c
16index 63b2cbc414..0911a9239a 100644
17--- a/lib/ldap.c
18+++ b/lib/ldap.c
19@@ -333,16 +333,29 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
20 passwd = conn->passwd;
21 }
22
23+#ifdef USE_WIN32_LDAP
24+ if(ldap_ssl)
25+ server = ldap_sslinit(host, (int)conn->port, 1);
26+ else
27+#else
28+ server = ldap_init(host, (int)conn->port);
29+#endif
30+ if(!server) {
31+ failf(data, "LDAP local: Cannot connect to %s:%ld",
32+ conn->host.dispname, conn->port);
33+ result = CURLE_COULDNT_CONNECT;
34+ goto quit;
35+ }
36+
37 #ifdef LDAP_OPT_NETWORK_TIMEOUT
38- ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
39+ ldap_set_option(server, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
40 #endif
41- ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
42+ ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
43
44 if(ldap_ssl) {
45 #ifdef HAVE_LDAP_SSL
46 #ifdef USE_WIN32_LDAP
47 /* Win32 LDAP SDK doesn't support insecure mode without CA! */
48- server = ldap_sslinit(host, (int)conn->port, 1);
49 ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
50 #else
51 int ldap_option;
52@@ -410,7 +423,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
53 goto quit;
54 }
55 infof(data, "LDAP local: using PEM CA cert: %s", ldap_ca);
56- rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca);
57+ rc = ldap_set_option(server, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca);
58 if(rc != LDAP_SUCCESS) {
59 failf(data, "LDAP local: ERROR setting PEM CA cert: %s",
60 ldap_err2string(rc));
61@@ -422,20 +435,13 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
62 else
63 ldap_option = LDAP_OPT_X_TLS_NEVER;
64
65- rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option);
66+ rc = ldap_set_option(server, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option);
67 if(rc != LDAP_SUCCESS) {
68 failf(data, "LDAP local: ERROR setting cert verify mode: %s",
69 ldap_err2string(rc));
70 result = CURLE_SSL_CERTPROBLEM;
71 goto quit;
72 }
73- server = ldap_init(host, (int)conn->port);
74- if(!server) {
75- failf(data, "LDAP local: Cannot connect to %s:%ld",
76- conn->host.dispname, conn->port);
77- result = CURLE_COULDNT_CONNECT;
78- goto quit;
79- }
80 ldap_option = LDAP_OPT_X_TLS_HARD;
81 rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option);
82 if(rc != LDAP_SUCCESS) {
83@@ -444,15 +450,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
84 result = CURLE_SSL_CERTPROBLEM;
85 goto quit;
86 }
87-/*
88- rc = ldap_start_tls_s(server, NULL, NULL);
89- if(rc != LDAP_SUCCESS) {
90- failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s",
91- ldap_err2string(rc));
92- result = CURLE_SSL_CERTPROBLEM;
93- goto quit;
94- }
95-*/
96 #else
97 /* we should probably never come up to here since configure
98 should check in first place if we can support LDAP SSL/TLS */
99@@ -469,15 +466,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done)
100 result = CURLE_NOT_BUILT_IN;
101 goto quit;
102 }
103- else {
104- server = ldap_init(host, (int)conn->port);
105- if(!server) {
106- failf(data, "LDAP local: Cannot connect to %s:%ld",
107- conn->host.dispname, conn->port);
108- result = CURLE_COULDNT_CONNECT;
109- goto quit;
110- }
111- }
112+
113 #ifdef USE_WIN32_LDAP
114 ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
115 rc = ldap_win_bind(data, server, user, passwd);
diff --git a/meta/recipes-support/curl/curl/CVE-2025-15079.patch b/meta/recipes-support/curl/curl/CVE-2025-15079.patch
new file mode 100644
index 0000000000..47fa518309
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2025-15079.patch
@@ -0,0 +1,32 @@
1From adca486c125d9a6d9565b9607a19dce803a8b479 Mon Sep 17 00:00:00 2001
2From: Daniel Stenberg <daniel@haxx.se>
3Date: Wed, 24 Dec 2025 17:47:03 +0100
4Subject: [PATCH] libssh: set both knownhosts options to the same file
5
6Reported-by: Harry Sintonen
7
8Closes #20092
9
10CVE: CVE-2025-15079
11Upstream-Status: Backport [https://github.com/curl/curl/commit/adca486c125d9a6d9565b9607a19dce803a8b479]
12Signed-off-by: Peter Marko <peter.marko@siemens.com>
13---
14 lib/vssh/libssh.c | 5 +++++
15 1 file changed, 5 insertions(+)
16
17diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
18index 7d5905c83d..98c109ab59 100644
19--- a/lib/vssh/libssh.c
20+++ b/lib/vssh/libssh.c
21@@ -2224,6 +2224,11 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
22 infof(data, "Known hosts: %s", data->set.str[STRING_SSH_KNOWNHOSTS]);
23 rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_KNOWNHOSTS,
24 data->set.str[STRING_SSH_KNOWNHOSTS]);
25+ if(rc == SSH_OK)
26+ /* libssh has two separate options for this. Set both to the same file
27+ to avoid surprises */
28+ rc = ssh_options_set(ssh->ssh_session, SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
29+ data->set.str[STRING_SSH_KNOWNHOSTS]);
30 if(rc != SSH_OK) {
31 failf(data, "Could not set known hosts file path");
32 return CURLE_FAILED_INIT;
diff --git a/meta/recipes-support/curl/curl/CVE-2025-15224.patch b/meta/recipes-support/curl/curl/CVE-2025-15224.patch
new file mode 100644
index 0000000000..36f5f1b93a
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2025-15224.patch
@@ -0,0 +1,31 @@
1From 16d5f2a5660c61cc27bd5f1c7f512391d1c927aa Mon Sep 17 00:00:00 2001
2From: Harry Sintonen <sintonen@iki.fi>
3Date: Mon, 29 Dec 2025 16:56:39 +0100
4Subject: [PATCH] libssh: require private key or user-agent for public key auth
5
6Closes #20110
7
8CVE: CVE-2025-15224
9Upstream-Status: Backport [https://github.com/curl/curl/commit/16d5f2a5660c61cc27bd5f1c7f512391d1c927aa]
10Signed-off-by: Peter Marko <peter.marko@siemens.com>
11---
12 lib/vssh/libssh.c | 6 +++++-
13 1 file changed, 5 insertions(+), 1 deletion(-)
14
15diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c
16index 5d5125b526..bde6355f73 100644
17--- a/lib/vssh/libssh.c
18+++ b/lib/vssh/libssh.c
19@@ -741,7 +741,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block)
20 }
21
22 sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL);
23- if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
24+ /* For public key auth we need either the private key or
25+ CURLSSH_AUTH_AGENT. */
26+ if((sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) &&
27+ (data->set.str[STRING_SSH_PRIVATE_KEY] ||
28+ (data->set.ssh_auth_types & CURLSSH_AUTH_AGENT))) {
29 state(data, SSH_AUTH_PKEY_INIT);
30 infof(data, "Authentication using SSH public key file");
31 }
diff --git a/meta/recipes-support/curl/curl_7.82.0.bb b/meta/recipes-support/curl/curl_7.82.0.bb
index 2326392a4f..72bd1a2088 100644
--- a/meta/recipes-support/curl/curl_7.82.0.bb
+++ b/meta/recipes-support/curl/curl_7.82.0.bb
@@ -67,6 +67,9 @@ SRC_URI = "https://curl.se/download/${BP}.tar.xz \
67 file://CVE-2024-11053-0002.patch \ 67 file://CVE-2024-11053-0002.patch \
68 file://CVE-2025-0167.patch \ 68 file://CVE-2025-0167.patch \
69 file://CVE-2025-9086.patch \ 69 file://CVE-2025-9086.patch \
70 file://CVE-2025-14017.patch \
71 file://CVE-2025-15079.patch \
72 file://CVE-2025-15224.patch \
70 " 73 "
71SRC_URI[sha256sum] = "0aaa12d7bd04b0966254f2703ce80dd5c38dbbd76af0297d3d690cdce58a583c" 74SRC_URI[sha256sum] = "0aaa12d7bd04b0966254f2703ce80dd5c38dbbd76af0297d3d690cdce58a583c"
72 75
diff --git a/meta/recipes-support/gnupg/gnupg/CVE-2025-68973.patch b/meta/recipes-support/gnupg/gnupg/CVE-2025-68973.patch
new file mode 100644
index 0000000000..1d5225361b
--- /dev/null
+++ b/meta/recipes-support/gnupg/gnupg/CVE-2025-68973.patch
@@ -0,0 +1,108 @@
1From 4ecc5122f20e10c17172ed72f4fa46c784b5fb48 Mon Sep 17 00:00:00 2001
2From: Werner Koch <wk@gnupg.org>
3Date: Thu, 23 Oct 2025 11:36:04 +0200
4Subject: [PATCH] gpg: Fix possible memory corruption in the armor parser.
5
6* g10/armor.c (armor_filter): Fix faulty double increment.
7
8* common/iobuf.c (underflow_target): Assert that the filter
9implementations behave well.
10--
11
12This fixes a bug in a code path which can only be reached with special
13crafted input data and would then error out at an upper layer due to
14corrupt input (every second byte in the buffer is unitialized
15garbage). No fuzzing has yet hit this case and we don't have a test
16case for this code path. However memory corruption can never be
17tolerated as it always has the protential for remode code execution.
18
19Reported-by: 8b79fe4dd0581c1cd000e1fbecba9f39e16a396a
20Fixes-commit: c27c7416d5148865a513e007fb6f0a34993a6073
21which fixed
22Fixes-commit: 7d0efec7cf5ae110c99511abc32587ff0c45b14f
23Backported-from-master: 115d138ba599328005c5321c0ef9f00355838ca9
24
25The bug was introduced on 1999-01-07 by me:
26* armor.c: Rewrote large parts.
27which I fixed on 1999-03-02 but missed to fix the other case:
28* armor.c (armor_filter): Fixed armor bypassing.
29
30Below is base64+gzipped test data which can be used with valgrind to
31show access to uninitalized memory in write(2) in the unpatched code.
32
33--8<---------------cut here---------------start------------->8---
34H4sICIDd+WgCA3h4AO3QMQ6CQBCG0djOKbY3G05gscYFSRAJt/AExp6Di0cQG0ze
35a//MV0zOq3Pt+jFN3ZTKfLvP9ZLafqifJUe8juOjeZbVtSkbRPmRgICAgICAgICA
36gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
37gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
38gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
39gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
40gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
41gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
42gICAgICAgICAgICAgICAgICAgICAgICAgMCXF6dYDgAAAAAAAAAAAAAAAAAAAAAA
43AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7E14AAAAA
44AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
45AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
46AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
47AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwZ94aieId3+8EAA==
48--8<---------------cut here---------------end--------------->8---
49
50CVE: CVE-2025-68973
51Upstream-Status: Backport [https://github.com/gpg/gnupg/commit/4ecc5122f20e10c17172ed72f4fa46c784b5fb48]
52Signed-off-by: Peter Marko <peter.marko@siemens.com>
53---
54 common/iobuf.c | 8 +++++++-
55 g10/armor.c | 4 ++--
56 2 files changed, 9 insertions(+), 3 deletions(-)
57
58diff --git a/common/iobuf.c b/common/iobuf.c
59index 748e6935d..2497713c1 100644
60--- a/common/iobuf.c
61+++ b/common/iobuf.c
62@@ -2041,6 +2041,8 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
63 rc = 0;
64 else
65 {
66+ size_t tmplen;
67+
68 /* If no buffered data and drain buffer has been setup, and drain
69 * buffer is largish, read data directly to drain buffer. */
70 if (a->d.len == 0
71@@ -2053,8 +2055,10 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
72 log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes, to external drain)\n",
73 a->no, a->subno, (ulong)len);
74
75- rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
76+ tmplen = len; /* Used to check for bugs in the filter. */
77+ rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
78 a->e_d.buf, &len);
79+ log_assert (len <= tmplen);
80 a->e_d.used = len;
81 len = 0;
82 }
83@@ -2064,8 +2068,10 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
84 log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes)\n",
85 a->no, a->subno, (ulong)len);
86
87+ tmplen = len; /* Used to check for bugs in the filter. */
88 rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
89 &a->d.buf[a->d.len], &len);
90+ log_assert (len <= tmplen);
91 }
92 }
93 a->d.len += len;
94diff --git a/g10/armor.c b/g10/armor.c
95index 81af15339..f8cfa86db 100644
96--- a/g10/armor.c
97+++ b/g10/armor.c
98@@ -1312,8 +1312,8 @@ armor_filter( void *opaque, int control,
99 n = 0;
100 if( afx->buffer_len ) {
101 /* Copy the data from AFX->BUFFER to BUF. */
102- for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
103- buf[n++] = afx->buffer[afx->buffer_pos++];
104+ for(; n < size && afx->buffer_pos < afx->buffer_len;)
105+ buf[n++] = afx->buffer[afx->buffer_pos++];
106 if( afx->buffer_pos >= afx->buffer_len )
107 afx->buffer_len = 0;
108 }
diff --git a/meta/recipes-support/gnupg/gnupg_2.3.7.bb b/meta/recipes-support/gnupg/gnupg_2.3.7.bb
index 27b2d3682a..f52ae921d4 100644
--- a/meta/recipes-support/gnupg/gnupg_2.3.7.bb
+++ b/meta/recipes-support/gnupg/gnupg_2.3.7.bb
@@ -23,6 +23,7 @@ SRC_URI = "${GNUPG_MIRROR}/${BPN}/${BPN}-${PV}.tar.bz2 \
23 file://CVE-2025-30258-0003.patch \ 23 file://CVE-2025-30258-0003.patch \
24 file://CVE-2025-30258-0004.patch \ 24 file://CVE-2025-30258-0004.patch \
25 file://CVE-2025-30258-0005.patch \ 25 file://CVE-2025-30258-0005.patch \
26 file://CVE-2025-68973.patch \
26 " 27 "
27SRC_URI:append:class-native = " file://0001-configure.ac-use-a-custom-value-for-the-location-of-.patch \ 28SRC_URI:append:class-native = " file://0001-configure.ac-use-a-custom-value-for-the-location-of-.patch \
28 file://relocate.patch" 29 file://relocate.patch"
diff --git a/meta/recipes-support/libsoup/libsoup/CVE-2025-12105.patch b/meta/recipes-support/libsoup/libsoup/CVE-2025-12105.patch
new file mode 100644
index 0000000000..9426ef3001
--- /dev/null
+++ b/meta/recipes-support/libsoup/libsoup/CVE-2025-12105.patch
@@ -0,0 +1,34 @@
1From 465410f833e4288ad053b4e18d5fa6c3be3148e1 Mon Sep 17 00:00:00 2001
2From: Eugene Mutavchi <Ievgen_Mutavchi@comcast.com>
3Date: Fri, 10 Oct 2025 16:24:27 +0000
4Subject: [PATCH] fix 'heap-use-after-free' caused by 'finishing' queue item
5 twice
6
7CVE: CVE-2025-12105
8Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libsoup/-/commit/9ba1243a24e442fa5ec44684617a4480027da960]
9
10Signed-off-by: Changqing Li <changqing.li@windriver.com>
11---
12 libsoup/soup-session.c | 6 ++++--
13 1 file changed, 4 insertions(+), 2 deletions(-)
14
15diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
16index 5f2929f..b9f3e42 100644
17--- a/libsoup/soup-session.c
18+++ b/libsoup/soup-session.c
19@@ -3093,8 +3093,10 @@ run_until_read_done (SoupMessage *msg,
20 if (soup_message_io_in_progress (msg))
21 soup_message_io_finished (msg);
22 item->paused = FALSE;
23- item->state = SOUP_MESSAGE_FINISHING;
24- soup_session_process_queue_item (item->session, item, NULL, FALSE);
25+ if (item->state != SOUP_MESSAGE_FINISHED) {
26+ item->state = SOUP_MESSAGE_FINISHING;
27+ soup_session_process_queue_item (item->session, item, NULL, FALSE);
28+ }
29 }
30 async_send_request_return_result (item, NULL, error);
31 }
32--
332.34.1
34
diff --git a/meta/recipes-support/libsoup/libsoup_3.0.7.bb b/meta/recipes-support/libsoup/libsoup_3.0.7.bb
index af8554aa78..0f82736727 100644
--- a/meta/recipes-support/libsoup/libsoup_3.0.7.bb
+++ b/meta/recipes-support/libsoup/libsoup_3.0.7.bb
@@ -45,6 +45,7 @@ SRC_URI = "${GNOME_MIRROR}/libsoup/${SHRT_VER}/libsoup-${PV}.tar.xz \
45 file://CVE-2025-46421.patch \ 45 file://CVE-2025-46421.patch \
46 file://CVE-2025-4948.patch \ 46 file://CVE-2025-4948.patch \
47 file://CVE-2025-4945.patch \ 47 file://CVE-2025-4945.patch \
48 file://CVE-2025-12105.patch \
48 " 49 "
49SRC_URI[sha256sum] = "ebdf90cf3599c11acbb6818a9d9e3fc9d2c68e56eb829b93962972683e1bf7c8" 50SRC_URI[sha256sum] = "ebdf90cf3599c11acbb6818a9d9e3fc9d2c68e56eb829b93962972683e1bf7c8"
50 51
diff --git a/meta/recipes-support/libxslt/libxslt/CVE-2025-11731.patch b/meta/recipes-support/libxslt/libxslt/CVE-2025-11731.patch
new file mode 100644
index 0000000000..19702af6cb
--- /dev/null
+++ b/meta/recipes-support/libxslt/libxslt/CVE-2025-11731.patch
@@ -0,0 +1,42 @@
1From fe508f201efb9ea37bfbe95413b8b28251497de3 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= <drott@chromium.org>
3Date: Wed, 27 Aug 2025 14:28:40 +0300
4Subject: [PATCH] End function node ancestor search at document
5
6Avoids dereferencing a non-existent ->ns property on an
7XML_DOCUMENT_NODE pointer.
8
9Fixes #151.
10
11CVE: CVE-2025-11731
12
13Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/libxslt/-/commit/fe508f201efb9ea37bfbe95413b8b28251497de3]
14
15Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
16---
17 libexslt/functions.c | 9 +++++++--
18 1 file changed, 7 insertions(+), 2 deletions(-)
19
20diff --git a/libexslt/functions.c b/libexslt/functions.c
21index 8d35a7ae..a54ee70c 100644
22--- a/libexslt/functions.c
23+++ b/libexslt/functions.c
24@@ -617,8 +617,13 @@ exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
25 * instanciation of a func:result element.
26 */
27 for (test = inst->parent; test != NULL; test = test->parent) {
28- if (IS_XSLT_ELEM(test) &&
29- IS_XSLT_NAME(test, "stylesheet")) {
30+ if (/* Traversal has reached the top-level document without
31+ * finding a func:function ancestor. */
32+ (test != NULL && test->type == XML_DOCUMENT_NODE) ||
33+ /* Traversal reached a stylesheet-namespace node,
34+ * and has left the function namespace. */
35+ (IS_XSLT_ELEM(test) &&
36+ IS_XSLT_NAME(test, "stylesheet"))) {
37 xsltGenericError(xsltGenericErrorContext,
38 "func:result element not a descendant "
39 "of a func:function\n");
40--
412.34.1
42
diff --git a/meta/recipes-support/libxslt/libxslt_1.1.35.bb b/meta/recipes-support/libxslt/libxslt_1.1.35.bb
index fc1fafbf19..4f86069d77 100644
--- a/meta/recipes-support/libxslt/libxslt_1.1.35.bb
+++ b/meta/recipes-support/libxslt/libxslt_1.1.35.bb
@@ -22,6 +22,7 @@ SRC_URI = "${GNOME_MIRROR}/libxslt/1.1/libxslt-${PV}.tar.xz \
22 file://CVE-2023-40403-004.patch \ 22 file://CVE-2023-40403-004.patch \
23 file://CVE-2023-40403-005.patch \ 23 file://CVE-2023-40403-005.patch \
24 file://CVE-2025-7424.patch \ 24 file://CVE-2025-7424.patch \
25 file://CVE-2025-11731.patch \
25 " 26 "
26 27
27SRC_URI[sha256sum] = "8247f33e9a872c6ac859aa45018bc4c4d00b97e2feac9eebc10c93ce1f34dd79" 28SRC_URI[sha256sum] = "8247f33e9a872c6ac859aa45018bc4c4d00b97e2feac9eebc10c93ce1f34dd79"