summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
Diffstat (limited to 'meta')
-rw-r--r--meta/classes/spdx-common.bbclass3
-rw-r--r--meta/lib/oe/lsb.py2
-rw-r--r--meta/lib/oe/spdx30_tasks.py12
-rw-r--r--meta/recipes-connectivity/inetutils/inetutils/CVE-2026-28372.patch86
-rw-r--r--meta/recipes-connectivity/inetutils/inetutils/CVE-2026-32746.patch40
-rw-r--r--meta/recipes-connectivity/inetutils/inetutils_2.5.bb2
-rw-r--r--meta/recipes-core/images/build-appliance-image_15.0.0.bb2
-rwxr-xr-xmeta/recipes-core/systemd/systemd-systemctl/systemctl7
-rw-r--r--meta/recipes-devtools/go/go/CVE-2025-61726.patch21
-rw-r--r--meta/recipes-devtools/python/python3-cryptography/CVE-2026-26007.patch149
-rw-r--r--meta/recipes-devtools/python/python3-cryptography_42.0.5.bb1
-rw-r--r--meta/recipes-devtools/python/python3-pip/CVE-2026-1703.patch37
-rw-r--r--meta/recipes-devtools/python/python3-pip_24.0.bb13
-rw-r--r--meta/recipes-devtools/python/python3-pyopenssl/CVE-2026-27448.patch124
-rw-r--r--meta/recipes-devtools/python/python3-pyopenssl/CVE-2026-27459.patch109
-rw-r--r--meta/recipes-devtools/python/python3-pyopenssl_24.0.0.bb5
-rw-r--r--meta/recipes-devtools/python/python3-setuptools_69.1.1.bb9
-rw-r--r--meta/recipes-extended/timezone/timezone.inc6
-rw-r--r--meta/recipes-graphics/freetype/freetype/CVE-2026-23865.patch54
-rw-r--r--meta/recipes-graphics/freetype/freetype_2.13.2.bb1
-rw-r--r--meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.02.04.bb (renamed from meta/recipes-kernel/wireless-regdb/wireless-regdb_2025.10.07.bb)2
-rw-r--r--meta/recipes-multimedia/libtiff/tiff_4.6.0.bb2
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-1.patch61
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-2.patch30
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-3.patch45
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-4.patch200
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-5.patch500
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-6.patch119
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-7.patch150
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-8.patch105
-rw-r--r--meta/recipes-support/gnutls/gnutls/CVE-2025-14831-9.patch421
-rw-r--r--meta/recipes-support/gnutls/gnutls_3.8.4.bb9
32 files changed, 2306 insertions, 21 deletions
diff --git a/meta/classes/spdx-common.bbclass b/meta/classes/spdx-common.bbclass
index 713a7fc651..ca0416d1c7 100644
--- a/meta/classes/spdx-common.bbclass
+++ b/meta/classes/spdx-common.bbclass
@@ -26,6 +26,7 @@ SPDX_TOOL_VERSION ??= "1.0"
26SPDXRUNTIMEDEPLOY = "${SPDXDIR}/runtime-deploy" 26SPDXRUNTIMEDEPLOY = "${SPDXDIR}/runtime-deploy"
27 27
28SPDX_INCLUDE_SOURCES ??= "0" 28SPDX_INCLUDE_SOURCES ??= "0"
29SPDX_INCLUDE_COMPILED_SOURCES ??= "0"
29 30
30SPDX_UUID_NAMESPACE ??= "sbom.openembedded.org" 31SPDX_UUID_NAMESPACE ??= "sbom.openembedded.org"
31SPDX_NAMESPACE_PREFIX ??= "http://spdx.org/spdxdocs" 32SPDX_NAMESPACE_PREFIX ??= "http://spdx.org/spdxdocs"
@@ -40,6 +41,8 @@ SPDX_MULTILIB_SSTATE_ARCHS ??= "${SSTATE_ARCHS}"
40python () { 41python () {
41 from oe.cve_check import extend_cve_status 42 from oe.cve_check import extend_cve_status
42 extend_cve_status(d) 43 extend_cve_status(d)
44 if d.getVar("SPDX_INCLUDE_COMPILED_SOURCES") == "1":
45 d.setVar("SPDX_INCLUDE_SOURCES", "1")
43} 46}
44 47
45def create_spdx_source_deps(d): 48def create_spdx_source_deps(d):
diff --git a/meta/lib/oe/lsb.py b/meta/lib/oe/lsb.py
index 3ec03e5042..1fc3b968a0 100644
--- a/meta/lib/oe/lsb.py
+++ b/meta/lib/oe/lsb.py
@@ -16,7 +16,7 @@ def get_os_release():
16 key, val = line.rstrip().split('=', 1) 16 key, val = line.rstrip().split('=', 1)
17 except ValueError: 17 except ValueError:
18 continue 18 continue
19 data[key.strip()] = val.strip('"') 19 data[key.strip()] = val.strip('"\'')
20 return data 20 return data
21 21
22def release_dict_osr(): 22def release_dict_osr():
diff --git a/meta/lib/oe/spdx30_tasks.py b/meta/lib/oe/spdx30_tasks.py
index a8970dcca0..9c422d1757 100644
--- a/meta/lib/oe/spdx30_tasks.py
+++ b/meta/lib/oe/spdx30_tasks.py
@@ -145,6 +145,8 @@ def add_package_files(
145 ignore_dirs=[], 145 ignore_dirs=[],
146 ignore_top_level_dirs=[], 146 ignore_top_level_dirs=[],
147): 147):
148 import oe.spdx
149
148 source_date_epoch = d.getVar("SOURCE_DATE_EPOCH") 150 source_date_epoch = d.getVar("SOURCE_DATE_EPOCH")
149 if source_date_epoch: 151 if source_date_epoch:
150 source_date_epoch = int(source_date_epoch) 152 source_date_epoch = int(source_date_epoch)
@@ -156,6 +158,11 @@ def add_package_files(
156 bb.note(f"Skip {topdir}") 158 bb.note(f"Skip {topdir}")
157 return spdx_files 159 return spdx_files
158 160
161 check_compiled_sources = d.getVar("SPDX_INCLUDE_COMPILED_SOURCES") == "1"
162 if check_compiled_sources:
163 compiled_sources, types = oe.spdx.get_compiled_sources(d)
164 bb.debug(1, f"Total compiled files: {len(compiled_sources)}")
165
159 for subdir, dirs, files in os.walk(topdir, onerror=walk_error): 166 for subdir, dirs, files in os.walk(topdir, onerror=walk_error):
160 dirs[:] = [d for d in dirs if d not in ignore_dirs] 167 dirs[:] = [d for d in dirs if d not in ignore_dirs]
161 if subdir == str(topdir): 168 if subdir == str(topdir):
@@ -171,6 +178,11 @@ def add_package_files(
171 filename = str(filepath.relative_to(topdir)) 178 filename = str(filepath.relative_to(topdir))
172 file_purposes = get_purposes(filepath) 179 file_purposes = get_purposes(filepath)
173 180
181 # Check if file is compiled
182 if check_compiled_sources:
183 if not oe.spdx.is_compiled_source(filename, compiled_sources, types):
184 continue
185
174 spdx_file = objset.new_file( 186 spdx_file = objset.new_file(
175 get_spdxid(file_counter), 187 get_spdxid(file_counter),
176 filename, 188 filename,
diff --git a/meta/recipes-connectivity/inetutils/inetutils/CVE-2026-28372.patch b/meta/recipes-connectivity/inetutils/inetutils/CVE-2026-28372.patch
new file mode 100644
index 0000000000..4e6bf0c87c
--- /dev/null
+++ b/meta/recipes-connectivity/inetutils/inetutils/CVE-2026-28372.patch
@@ -0,0 +1,86 @@
1From 4db2f19f4caac03c7f4da6363c140bd70df31386 Mon Sep 17 00:00:00 2001
2From: Erik Auerswald <auerswal@unix-ag.uni-kl.de>
3Date: Sun, 15 Feb 2026 15:38:50 +0100
4Subject: [PATCH] telnetd: don't allow systemd service credentials
5
6The login(1) implementation of util-linux added support for
7systemd service credentials in release 2.40. This allows to
8bypass authentication by specifying a directory name in the
9environment variable CREDENTIALS_DIRECTORY. If this directory
10contains a file named 'login.noauth' with the content of 'yes',
11login(1) skips authentication.
12
13GNU Inetutils telnetd supports to set arbitrary environment
14variables using the 'Environment' and 'New Environment'
15Telnet options. This allows specifying a directory containing
16'login.noauth'. A local user can create such a directory
17and file, and, e.g., specify the user name 'root' to escalate
18privileges.
19
20This problem was reported by Ron Ben Yizhak in
21<https://lists.gnu.org/archive/html/bug-inetutils/2026-02/msg00000.html>.
22
23This commit clears CREDENTIALS_DIRECTORY from the environment
24before executing login(1) to implement a simple fix that can
25be backported easily.
26
27* NEWS.md: Mention fix.
28* THANKS: Mention Ron Ben Yizhak.
29* telnetd/pty.c: Clear CREDENTIALS_DIRECTORY from the environment
30before executing 'login'.
31
32CVE: CVE-2026-28372
33Upstream-Status: Backport [https://cgit.git.savannah.gnu.org/cgit/inetutils.git/commit/?id=4db2f19f4caac03c7f4da6363c140bd70df31386]
34Signed-off-by: Peter Marko <peter.marko@siemens.com>
35---
36 NEWS | 5 +++++
37 THANKS | 1 +
38 telnetd/pty.c | 8 ++++++++
39 3 files changed, 14 insertions(+)
40
41diff --git a/NEWS b/NEWS
42index 877ca53b..f5172a71 100644
43--- a/NEWS
44+++ b/NEWS
45@@ -1,5 +1,10 @@
46 GNU inetutils NEWS -- history of user-visible changes.
47
48+** Prevent privilege escalation via telnetd abusing systemd service
49+credentials support added to the login(1) implementation of util-linux
50+in release 2.40. Reported by Ron Ben Yizhak in
51+<https://lists.gnu.org/archive/html/bug-inetutils/2026-02/msg00000.html>.
52+
53 * Noteworthy changes in release 2.5 (2023-12-29) [stable]
54
55 ** ftpd, rcp, rlogin, rsh, rshd, uucpd
56diff --git a/THANKS b/THANKS
57index 8d1d3dbb..ef5f6063 100644
58--- a/THANKS
59+++ b/THANKS
60@@ -9,6 +9,7 @@ In particular:
61 NIIBE Yutaka (Security fixes & making talk finally work)
62 Nathan Neulinger (tftpd)
63 Thomas Bushnell (sockaddr sin_len field)
64+ Ron Ben Yizhak (reported privilege escalation via telnetd)
65
66 Please see version control logs and ChangeLog.? for full credits.
67
68diff --git a/telnetd/pty.c b/telnetd/pty.c
69index c727e7be..f3518049 100644
70--- a/telnetd/pty.c
71+++ b/telnetd/pty.c
72@@ -130,6 +130,14 @@ start_login (char *host, int autologin, char *name)
73 if (!cmd)
74 fatal (net, "can't expand login command line");
75 argcv_get (cmd, "", &argc, &argv);
76+
77+ /* util-linux's "login" introduced an authentication bypass method
78+ * via environment variable "CREDENTIALS_DIRECTORY" in version 2.40.
79+ * Clear it from the environment before executing "login" to prevent
80+ * abuse via Telnet.
81+ */
82+ unsetenv ("CREDENTIALS_DIRECTORY");
83+
84 execv (argv[0], argv);
85 syslog (LOG_ERR, "%s: %m\n", cmd);
86 fatalperror (net, cmd);
diff --git a/meta/recipes-connectivity/inetutils/inetutils/CVE-2026-32746.patch b/meta/recipes-connectivity/inetutils/inetutils/CVE-2026-32746.patch
new file mode 100644
index 0000000000..0e55f3f0a4
--- /dev/null
+++ b/meta/recipes-connectivity/inetutils/inetutils/CVE-2026-32746.patch
@@ -0,0 +1,40 @@
1From 6864598a29b652a6b69a958f5cd1318aa2b258af Mon Sep 17 00:00:00 2001
2From: Collin Funk <collin.funk1@gmail.com>
3Date: Wed, 11 Mar 2026 23:06:46 -0700
4Subject: [PATCH] telnetd: fix stack buffer overflow processing SLC suboption triplets
5
6Previously a client could write past the end of an internal buffer using
7an SLC suboption with many triplets using function octets greater than
818, possibly leading to remote code execution. Reported by Adiel Sol,
9Arad Inbar, Erez Cohen, Nir Somech, Ben Grinberg, Daniel Lubel at DREAM
10Security Research Team at:
11<https://lists.gnu.org/r/bug-inetutils/2026-03/msg00031.html>.
12
13* telnetd/slc.c (add_slc): Return early if writing the tuple would lead
14us to writing past the end of the buffer.
15* NEWS.md: Mention the fix.
16
17Upstream-Status: Backport [https://cgit.git.savannah.gnu.org/cgit/inetutils.git/commit/?id=6864598a29b652a6b69a958f5cd1318aa2b258af]
18CVE: CVE-2026-32746
19Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
20---
21 telnetd/slc.c | 3 +++
22 1 file changed, 3 insertions(+)
23
24diff --git a/telnetd/slc.c b/telnetd/slc.c
25index b3cc117..9d6bad1 100644
26--- a/telnetd/slc.c
27+++ b/telnetd/slc.c
28@@ -162,6 +162,9 @@ get_slc_defaults (void)
29 void
30 add_slc (register char func, register char flag, register cc_t val)
31 {
32+ /* Do nothing if the entire triplet cannot fit in the buffer. */
33+ if (slcbuf + sizeof slcbuf - slcptr <= 6)
34+ return;
35
36 if ((*slcptr++ = (unsigned char) func) == 0xff)
37 *slcptr++ = 0xff;
38--
392.43.0
40
diff --git a/meta/recipes-connectivity/inetutils/inetutils_2.5.bb b/meta/recipes-connectivity/inetutils/inetutils_2.5.bb
index 486878022f..29ff62379d 100644
--- a/meta/recipes-connectivity/inetutils/inetutils_2.5.bb
+++ b/meta/recipes-connectivity/inetutils/inetutils_2.5.bb
@@ -20,6 +20,8 @@ SRC_URI = "${GNU_MIRROR}/inetutils/inetutils-${PV}.tar.xz \
20 file://tftpd.xinetd.inetutils \ 20 file://tftpd.xinetd.inetutils \
21 file://CVE-2026-24061-1.patch \ 21 file://CVE-2026-24061-1.patch \
22 file://CVE-2026-24061-2.patch \ 22 file://CVE-2026-24061-2.patch \
23 file://CVE-2026-28372.patch \
24 file://CVE-2026-32746.patch \
23 " 25 "
24 26
25inherit autotools gettext update-alternatives texinfo 27inherit autotools gettext update-alternatives texinfo
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 c970020b02..85521b6026 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
@@ -26,7 +26,7 @@ inherit core-image setuptools3 features_check
26 26
27REQUIRED_DISTRO_FEATURES += "xattr" 27REQUIRED_DISTRO_FEATURES += "xattr"
28 28
29SRCREV ?= "06210079b2e10d6d3fb943afe87864267e329821" 29SRCREV ?= "f4877d8e682ed22e339fe6c07f3ffa28e50c7b98"
30SRC_URI = "git://git.yoctoproject.org/poky;branch=scarthgap \ 30SRC_URI = "git://git.yoctoproject.org/poky;branch=scarthgap \
31 file://Yocto_Build_Appliance.vmx \ 31 file://Yocto_Build_Appliance.vmx \
32 file://Yocto_Build_Appliance.vmxf \ 32 file://Yocto_Build_Appliance.vmxf \
diff --git a/meta/recipes-core/systemd/systemd-systemctl/systemctl b/meta/recipes-core/systemd/systemd-systemctl/systemctl
index 2229bc7b6d..b9e04a9070 100755
--- a/meta/recipes-core/systemd/systemd-systemctl/systemctl
+++ b/meta/recipes-core/systemd/systemd-systemctl/systemctl
@@ -202,7 +202,8 @@ class SystemdUnit():
202 try: 202 try:
203 for dependent in config.get('Install', prop): 203 for dependent in config.get('Install', prop):
204 # expand any %i to instance (ignoring escape sequence %%) 204 # expand any %i to instance (ignoring escape sequence %%)
205 dependent = re.sub("([^%](%%)*)%i", "\\g<1>{}".format(instance), dependent) 205 if instance is not None:
206 dependent = re.sub("([^%](%%)*)%i", "\\g<1>{}".format(re.escape(instance)), dependent)
206 wants = systemdir / "{}.{}".format(dependent, dirstem) / service 207 wants = systemdir / "{}.{}".format(dependent, dirstem) / service
207 add_link(wants, target) 208 add_link(wants, target)
208 209
@@ -212,13 +213,13 @@ class SystemdUnit():
212 def enable(self, units_enabled=[]): 213 def enable(self, units_enabled=[]):
213 # if we're enabling an instance, first extract the actual instance 214 # if we're enabling an instance, first extract the actual instance
214 # then figure out what the template unit is 215 # then figure out what the template unit is
215 template = re.match(r"[^@]+@(?P<instance>[^\.]*)\.", self.unit) 216 template = re.match(r"[^@]+@(?P<instance>.*)\.", self.unit)
216 instance_unit_name = None 217 instance_unit_name = None
217 if template: 218 if template:
218 instance = template.group('instance') 219 instance = template.group('instance')
219 if instance != "": 220 if instance != "":
220 instance_unit_name = self.unit 221 instance_unit_name = self.unit
221 unit = re.sub(r"@[^\.]*\.", "@.", self.unit, 1) 222 unit = re.sub(r"@{}\.".format(re.escape(instance)), "@.", self.unit, 1)
222 else: 223 else:
223 instance = None 224 instance = None
224 unit = self.unit 225 unit = self.unit
diff --git a/meta/recipes-devtools/go/go/CVE-2025-61726.patch b/meta/recipes-devtools/go/go/CVE-2025-61726.patch
index ab053ff55c..bdd10bc933 100644
--- a/meta/recipes-devtools/go/go/CVE-2025-61726.patch
+++ b/meta/recipes-devtools/go/go/CVE-2025-61726.patch
@@ -1,4 +1,4 @@
1From 85050ca6146f3edb50ded0a352ab9edbd635effc Mon Sep 17 00:00:00 2001 1From bf06767a9ac737387eee77c7eedd67c65e853ac2 Mon Sep 17 00:00:00 2001
2From: Damien Neil <dneil@google.com> 2From: Damien Neil <dneil@google.com>
3Date: Mon, 3 Nov 2025 14:28:47 -0800 3Date: Mon, 3 Nov 2025 14:28:47 -0800
4Subject: [PATCH] [release-branch.go1.24] net/url: add urlmaxqueryparams 4Subject: [PATCH] [release-branch.go1.24] net/url: add urlmaxqueryparams
@@ -36,6 +36,7 @@ Reviewed-by: Junyang Shao <shaojunyang@google.com>
36TryBot-Bypass: Michael Pratt <mpratt@google.com> 36TryBot-Bypass: Michael Pratt <mpratt@google.com>
37(cherry picked from commit 85c794ddce26a092b0ea68d0fca79028b5069d5a) 37(cherry picked from commit 85c794ddce26a092b0ea68d0fca79028b5069d5a)
38Signed-off-by: Deepak Rathore <deeratho@cisco.com> 38Signed-off-by: Deepak Rathore <deeratho@cisco.com>
39Signed-off-by: Eduardo Ferreira <eduardo.barbosa@toradex.com>
39--- 40---
40 doc/godebug.md | 7 +++++ 41 doc/godebug.md | 7 +++++
41 src/internal/godebugs/table.go | 1 + 42 src/internal/godebugs/table.go | 1 +
@@ -45,7 +46,7 @@ Signed-off-by: Deepak Rathore <deeratho@cisco.com>
45 5 files changed, 85 insertions(+) 46 5 files changed, 85 insertions(+)
46 47
47diff --git a/doc/godebug.md b/doc/godebug.md 48diff --git a/doc/godebug.md b/doc/godebug.md
48index ae4f0576b4..635597ea42 100644 49index ae4f057..635597e 100644
49--- a/doc/godebug.md 50--- a/doc/godebug.md
50+++ b/doc/godebug.md 51+++ b/doc/godebug.md
51@@ -126,6 +126,13 @@ for example, 52@@ -126,6 +126,13 @@ for example,
@@ -63,19 +64,19 @@ index ae4f0576b4..635597ea42 100644
63 to concerns around VCS injection attacks. This behavior can be renabled with the 64 to concerns around VCS injection attacks. This behavior can be renabled with the
64 setting `allowmultiplevcs=1`. 65 setting `allowmultiplevcs=1`.
65diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go 66diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go
66index 33dcd81fc3..4ae043053c 100644 67index 33dcd81..7178df6 100644
67--- a/src/internal/godebugs/table.go 68--- a/src/internal/godebugs/table.go
68+++ b/src/internal/godebugs/table.go 69+++ b/src/internal/godebugs/table.go
69@@ -52,6 +52,7 @@ var All = []Info{ 70@@ -51,6 +51,7 @@ var All = []Info{
71 {Name: "tlsmaxrsasize", Package: "crypto/tls"},
70 {Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"}, 72 {Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"},
71 {Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"}, 73 {Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"},
72 {Name: "x509sha1", Package: "crypto/x509"},
73+ {Name: "urlmaxqueryparams", Package: "net/url", Changed: 24, Old: "0"}, 74+ {Name: "urlmaxqueryparams", Package: "net/url", Changed: 24, Old: "0"},
75 {Name: "x509sha1", Package: "crypto/x509"},
74 {Name: "x509usefallbackroots", Package: "crypto/x509"}, 76 {Name: "x509usefallbackroots", Package: "crypto/x509"},
75 {Name: "x509usepolicies", Package: "crypto/x509"}, 77 {Name: "x509usepolicies", Package: "crypto/x509"},
76 {Name: "zipinsecurepath", Package: "archive/zip"},
77diff --git a/src/net/url/url.go b/src/net/url/url.go 78diff --git a/src/net/url/url.go b/src/net/url/url.go
78index d2ae03232f..5219e3c130 100644 79index d2ae032..cdca468 100644
79--- a/src/net/url/url.go 80--- a/src/net/url/url.go
80+++ b/src/net/url/url.go 81+++ b/src/net/url/url.go
81@@ -13,6 +13,7 @@ package url 82@@ -13,6 +13,7 @@ package url
@@ -118,7 +119,7 @@ index d2ae03232f..5219e3c130 100644
118 var key string 119 var key string
119 key, query, _ = strings.Cut(query, "&") 120 key, query, _ = strings.Cut(query, "&")
120diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go 121diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
121index fef236e40a..b2f8bd95fc 100644 122index fef236e..b2f8bd9 100644
122--- a/src/net/url/url_test.go 123--- a/src/net/url/url_test.go
123+++ b/src/net/url/url_test.go 124+++ b/src/net/url/url_test.go
124@@ -1488,6 +1488,54 @@ func TestParseQuery(t *testing.T) { 125@@ -1488,6 +1488,54 @@ func TestParseQuery(t *testing.T) {
@@ -177,7 +178,7 @@ index fef236e40a..b2f8bd95fc 100644
177 url *URL 178 url *URL
178 out string 179 out string
179diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go 180diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go
180index 517ec0e0a4..335f7873b3 100644 181index 517ec0e..88d6d8c 100644
181--- a/src/runtime/metrics/doc.go 182--- a/src/runtime/metrics/doc.go
182+++ b/src/runtime/metrics/doc.go 183+++ b/src/runtime/metrics/doc.go
183@@ -328,6 +328,11 @@ Below is the full list of supported metrics, ordered lexicographically. 184@@ -328,6 +328,11 @@ Below is the full list of supported metrics, ordered lexicographically.
@@ -193,4 +194,4 @@ index 517ec0e0a4..335f7873b3 100644
193 The number of non-default behaviors executed by the crypto/x509 194 The number of non-default behaviors executed by the crypto/x509
194 package due to a non-default GODEBUG=x509sha1=... setting. 195 package due to a non-default GODEBUG=x509sha1=... setting.
195-- 196--
1962.35.6 1972.34.1
diff --git a/meta/recipes-devtools/python/python3-cryptography/CVE-2026-26007.patch b/meta/recipes-devtools/python/python3-cryptography/CVE-2026-26007.patch
new file mode 100644
index 0000000000..fb76bbfca3
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-cryptography/CVE-2026-26007.patch
@@ -0,0 +1,149 @@
1From 42c914929b52eb16421a4ef1f7e09c8f9fdab7db Mon Sep 17 00:00:00 2001
2From: Paul Kehrer <paul.l.kehrer@gmail.com>
3Date: Wed, 18 Mar 2026 16:01:03 +0900
4Subject: [PATCH] EC check key on cofactor > 1
5
6An attacker could create a malicious public key that reveals portions of
7your private key when using certain uncommon elliptic curves (binary
8curves). This version now includes additional security checks to
9prevent this attack. This issue only affects binary elliptic curves,
10which are rarely used in real-world applications. Credit to **XlabAI
11Team of Tencent Xuanwu Lab and Atuin Automated Vulnerability Discovery
12Engine** for reporting the issue. **CVE-2026-26007**
13
14This is a partial backport of upstream commit
150eebb9dbb6343d9bc1d91e5a2482ed4e054a6d8c, to only include what's
16relevant for CVE-2026-26007.
17
18CVE: CVE-2026-26007
19
20Origin: backport, https://github.com/pyca/cryptography/commit/0eebb9dbb6343d9bc1d91e5a2482ed4e054a6d8c
21Reference: https://salsa.debian.org/python-team/packages/python-cryptography/-/commit/464e7ca3b0b4493d5906d0c3685de71fda770c59
22
23Signed-off-by: Nguyen Dat Tho <tho3.nguyen@lge.com>
24Signed-off-by: Paul Kehrer <paul.l.kehrer@gmail.com>
25Co-authored-by: Alex Gaynor <alex.gaynor@gmail.com>
26
27Upstream-Status: Backport [Backport from https://github.com/pyca/cryptography/commit/0eebb9dbb6343d9bc1d91e5a2482ed4e054a6d8c]
28---
29 src/rust/src/backend/ec.rs | 39 ++++++++++++++++++++----------
30 tests/hazmat/primitives/test_ec.py | 37 ++++++++++++++++++++++++++++
31 2 files changed, 63 insertions(+), 13 deletions(-)
32
33diff --git a/src/rust/src/backend/ec.rs b/src/rust/src/backend/ec.rs
34index 6a224b49f..27fced086 100644
35--- a/src/rust/src/backend/ec.rs
36+++ b/src/rust/src/backend/ec.rs
37@@ -155,12 +155,9 @@ pub(crate) fn public_key_from_pkey(
38 ) -> CryptographyResult<ECPublicKey> {
39 let ec = pkey.ec_key()?;
40 let curve = py_curve_from_curve(py, ec.group())?;
41- check_key_infinity(&ec)?;
42- Ok(ECPublicKey {
43- pkey: pkey.to_owned(),
44- curve: curve.into(),
45- })
46+ ECPublicKey::new(pkey.to_owned(), curve.into())
47 }
48+
49 #[pyo3::prelude::pyfunction]
50 fn generate_private_key(
51 py: pyo3::Python<'_>,
52@@ -215,10 +212,7 @@ fn from_public_bytes(
53 let ec = openssl::ec::EcKey::from_public_key(&curve, &point)?;
54 let pkey = openssl::pkey::PKey::from_ec_key(ec)?;
55
56- Ok(ECPublicKey {
57- pkey,
58- curve: py_curve.into(),
59- })
60+ ECPublicKey::new(pkey, py_curve.into())
61 }
62
63 #[pyo3::prelude::pymethods]
64@@ -357,6 +351,28 @@ impl ECPrivateKey {
65 }
66 }
67
68+impl ECPublicKey {
69+ fn new(
70+ pkey: openssl::pkey::PKey<openssl::pkey::Public>,
71+ curve: pyo3::Py<pyo3::PyAny>,
72+ ) -> CryptographyResult<ECPublicKey> {
73+ let ec = pkey.ec_key()?;
74+ check_key_infinity(&ec)?;
75+ let mut bn_ctx = openssl::bn::BigNumContext::new()?;
76+ let mut cofactor = openssl::bn::BigNum::new()?;
77+ ec.group().cofactor(&mut cofactor, &mut bn_ctx)?;
78+ let one = openssl::bn::BigNum::from_u32(1)?;
79+ if cofactor != one {
80+ ec.check_key().map_err(|_| {
81+ pyo3::exceptions::PyValueError::new_err(
82+ "Invalid EC key (key out of range, infinity, etc.)",
83+ )
84+ })?;
85+ }
86+
87+ Ok(ECPublicKey { pkey, curve })
88+ }
89+}
90 #[pyo3::prelude::pymethods]
91 impl ECPublicKey {
92 #[getter]
93@@ -591,10 +607,7 @@ impl EllipticCurvePublicNumbers {
94
95 let pkey = openssl::pkey::PKey::from_ec_key(public_key)?;
96
97- Ok(ECPublicKey {
98- pkey,
99- curve: self.curve.clone_ref(py),
100- })
101+ ECPublicKey::new(pkey, self.curve.clone_ref(py))
102 }
103
104 fn __eq__(
105diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py
106index 334e76dcc..f7f2242f6 100644
107--- a/tests/hazmat/primitives/test_ec.py
108+++ b/tests/hazmat/primitives/test_ec.py
109@@ -1340,3 +1340,40 @@ class TestECDH:
110
111 with pytest.raises(ValueError):
112 key.exchange(ec.ECDH(), public_key)
113+
114+
115+def test_invalid_sect_public_keys(backend):
116+ _skip_curve_unsupported(backend, ec.SECT571K1())
117+ public_numbers = ec.EllipticCurvePublicNumbers(1, 1, ec.SECT571K1())
118+ with pytest.raises(ValueError):
119+ public_numbers.public_key()
120+
121+ point = binascii.unhexlify(
122+ b"0400000000000000000000000000000000000000000000000000000000000000000"
123+ b"0000000000000000000000000000000000000000000000000000000000000000000"
124+ b"0000000000010000000000000000000000000000000000000000000000000000000"
125+ b"0000000000000000000000000000000000000000000000000000000000000000000"
126+ b"0000000000000000000001"
127+ )
128+ with pytest.raises(ValueError):
129+ ec.EllipticCurvePublicKey.from_encoded_point(ec.SECT571K1(), point)
130+
131+ der = binascii.unhexlify(
132+ b"3081a7301006072a8648ce3d020106052b810400260381920004000000000000000"
133+ b"0000000000000000000000000000000000000000000000000000000000000000000"
134+ b"0000000000000000000000000000000000000000000000000000000000000100000"
135+ b"0000000000000000000000000000000000000000000000000000000000000000000"
136+ b"0000000000000000000000000000000000000000000000000000000000000000000"
137+ b"00001"
138+ )
139+ with pytest.raises(ValueError):
140+ serialization.load_der_public_key(der)
141+
142+ pem = textwrap.dedent("""-----BEGIN PUBLIC KEY-----
143+ MIGnMBAGByqGSM49AgEGBSuBBAAmA4GSAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
144+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
145+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
146+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE=
147+ -----END PUBLIC KEY-----""").encode()
148+ with pytest.raises(ValueError):
149+ serialization.load_pem_public_key(pem)
diff --git a/meta/recipes-devtools/python/python3-cryptography_42.0.5.bb b/meta/recipes-devtools/python/python3-cryptography_42.0.5.bb
index 732f925d92..c4573fa689 100644
--- a/meta/recipes-devtools/python/python3-cryptography_42.0.5.bb
+++ b/meta/recipes-devtools/python/python3-cryptography_42.0.5.bb
@@ -11,6 +11,7 @@ LDSHARED += "-pthread"
11SRC_URI[sha256sum] = "6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1" 11SRC_URI[sha256sum] = "6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1"
12 12
13SRC_URI += "file://0001-pyproject.toml-remove-benchmark-disable-option.patch \ 13SRC_URI += "file://0001-pyproject.toml-remove-benchmark-disable-option.patch \
14 file://CVE-2026-26007.patch \
14 file://check-memfree.py \ 15 file://check-memfree.py \
15 file://run-ptest \ 16 file://run-ptest \
16 " 17 "
diff --git a/meta/recipes-devtools/python/python3-pip/CVE-2026-1703.patch b/meta/recipes-devtools/python/python3-pip/CVE-2026-1703.patch
new file mode 100644
index 0000000000..1470b7c541
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-pip/CVE-2026-1703.patch
@@ -0,0 +1,37 @@
1From 4c651b70d60ed91b13663bcda9b3ed41748d0124 Mon Sep 17 00:00:00 2001
2From: Seth Michael Larson <seth@python.org>
3Date: Fri, 30 Jan 2026 09:49:11 -0600
4Subject: [PATCH] Use os.path.commonpath() instead of commonprefix()
5
6Upstream-Status: Backport [https://github.com/pypa/pip/commit/4c651b70d60ed91b13663bcda9b3ed41748d0124]
7CVE: CVE-2026-1703
8Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
9---
10 news/+1ee322a1.bugfix.rst | 1 +
11 src/pip/_internal/utils/unpacking.py | 2 +-
12 2 files changed, 2 insertions(+), 1 deletion(-)
13 create mode 100644 news/+1ee322a1.bugfix.rst
14
15diff --git a/news/+1ee322a1.bugfix.rst b/news/+1ee322a1.bugfix.rst
16new file mode 100644
17index 0000000..edb1b32
18--- /dev/null
19+++ b/news/+1ee322a1.bugfix.rst
20@@ -0,0 +1 @@
21+Use a path-segment prefix comparison, not char-by-char.
22diff --git a/src/pip/_internal/utils/unpacking.py b/src/pip/_internal/utils/unpacking.py
23index 78b5c13..0b26525 100644
24--- a/src/pip/_internal/utils/unpacking.py
25+++ b/src/pip/_internal/utils/unpacking.py
26@@ -81,7 +81,7 @@ def is_within_directory(directory: str, target: str) -> bool:
27 abs_directory = os.path.abspath(directory)
28 abs_target = os.path.abspath(target)
29
30- prefix = os.path.commonprefix([abs_directory, abs_target])
31+ prefix = os.path.commonpath([abs_directory, abs_target])
32 return prefix == abs_directory
33
34
35--
362.43.0
37
diff --git a/meta/recipes-devtools/python/python3-pip_24.0.bb b/meta/recipes-devtools/python/python3-pip_24.0.bb
index be4a29500a..cf123a5d23 100644
--- a/meta/recipes-devtools/python/python3-pip_24.0.bb
+++ b/meta/recipes-devtools/python/python3-pip_24.0.bb
@@ -31,7 +31,9 @@ LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=63ec52baf95163b597008bb46db68030 \
31 31
32inherit pypi python_setuptools_build_meta 32inherit pypi python_setuptools_build_meta
33 33
34SRC_URI += "file://no_shebang_mangling.patch" 34SRC_URI += "file://no_shebang_mangling.patch \
35 file://CVE-2026-1703.patch \
36 "
35 37
36SRC_URI[sha256sum] = "ea9bd1a847e8c5774a5777bb398c19e80bcd4e2aa16a4b301b718fe6f593aba2" 38SRC_URI[sha256sum] = "ea9bd1a847e8c5774a5777bb398c19e80bcd4e2aa16a4b301b718fe6f593aba2"
37 39
@@ -39,6 +41,15 @@ do_install:append() {
39 rm -f ${D}/${bindir}/pip 41 rm -f ${D}/${bindir}/pip
40} 42}
41 43
44do_install:append(){
45 # pip vendors distlib which ships Windows launcher templates (*.exe).
46 # Keep them only when building for a Windows (mingw) host.
47 case "${HOST_OS}" in
48 mingw32|mingw64) ;;
49 *) rm -f ${D}${PYTHON_SITEPACKAGES_DIR}/pip/_vendor/distlib/*.exe ;;
50 esac
51}
52
42RDEPENDS:${PN} = "\ 53RDEPENDS:${PN} = "\
43 python3-compile \ 54 python3-compile \
44 python3-io \ 55 python3-io \
diff --git a/meta/recipes-devtools/python/python3-pyopenssl/CVE-2026-27448.patch b/meta/recipes-devtools/python/python3-pyopenssl/CVE-2026-27448.patch
new file mode 100644
index 0000000000..87f46b4cb0
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-pyopenssl/CVE-2026-27448.patch
@@ -0,0 +1,124 @@
1From d41a814759a9fb49584ca8ab3f7295de49a85aa0 Mon Sep 17 00:00:00 2001
2From: Alex Gaynor <alex.gaynor@gmail.com>
3Date: Mon, 16 Feb 2026 21:04:37 -0500
4Subject: [PATCH] Handle exceptions in set_tlsext_servername_callback callbacks
5 (#1478)
6
7When the servername callback raises an exception, call sys.excepthook
8with the exception info and return SSL_TLSEXT_ERR_ALERT_FATAL to abort
9the handshake. Previously, exceptions would propagate uncaught through
10the CFFI callback boundary.
11
12https://claude.ai/code/session_01P7y1XmWkdtC5UcmZwGDvGi
13
14Co-authored-by: Claude <noreply@anthropic.com>
15
16Upstream-Status: Backport [https://github.com/pyca/pyopenssl/commit/d41a814759a9fb49584ca8ab3f7295de49a85aa0]
17CVE: CVE-2026-27448
18Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
19---
20 CHANGELOG.rst | 1 +
21 src/OpenSSL/SSL.py | 7 ++++++-
22 tests/test_ssl.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++
23 3 files changed, 57 insertions(+), 1 deletion(-)
24
25diff --git a/CHANGELOG.rst b/CHANGELOG.rst
26index 6e23770..12e60e4 100644
27--- a/CHANGELOG.rst
28+++ b/CHANGELOG.rst
29@@ -18,6 +18,7 @@ Changes:
30
31 - Added ``OpenSSL.SSL.Connection.get_selected_srtp_profile`` to determine which SRTP profile was negotiated.
32 `#1279 <https://github.com/pyca/pyopenssl/pull/1279>`_.
33+- ``Context.set_tlsext_servername_callback`` now handles exceptions raised in the callback by calling ``sys.excepthook`` and returning a fatal TLS alert. Previously, exceptions were silently swallowed and the handshake would proceed as if the callback had succeeded.
34
35 23.3.0 (2023-10-25)
36 -------------------
37diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py
38index 4db5240..a6263c4 100644
39--- a/src/OpenSSL/SSL.py
40+++ b/src/OpenSSL/SSL.py
41@@ -1,5 +1,6 @@
42 import os
43 import socket
44+import sys
45 import typing
46 from errno import errorcode
47 from functools import partial, wraps
48@@ -1567,7 +1568,11 @@ class Context:
49
50 @wraps(callback)
51 def wrapper(ssl, alert, arg):
52- callback(Connection._reverse_mapping[ssl])
53+ try:
54+ callback(Connection._reverse_mapping[ssl])
55+ except Exception:
56+ sys.excepthook(*sys.exc_info())
57+ return _lib.SSL_TLSEXT_ERR_ALERT_FATAL
58 return 0
59
60 self._tlsext_servername_callback = _ffi.callback(
61diff --git a/tests/test_ssl.py b/tests/test_ssl.py
62index ca5bf83..55489b9 100644
63--- a/tests/test_ssl.py
64+++ b/tests/test_ssl.py
65@@ -1855,6 +1855,56 @@ class TestServerNameCallback:
66
67 assert args == [(server, b"foo1.example.com")]
68
69+ def test_servername_callback_exception(
70+ self, monkeypatch: pytest.MonkeyPatch
71+ ) -> None:
72+ """
73+ When the callback passed to `Context.set_tlsext_servername_callback`
74+ raises an exception, ``sys.excepthook`` is called with the exception
75+ and the handshake fails with an ``Error``.
76+ """
77+ exc = TypeError("server name callback failed")
78+
79+ def servername(conn: Connection) -> None:
80+ raise exc
81+
82+ excepthook_calls: list[
83+ tuple[type[BaseException], BaseException, object]
84+ ] = []
85+
86+ def custom_excepthook(
87+ exc_type: type[BaseException],
88+ exc_value: BaseException,
89+ exc_tb: object,
90+ ) -> None:
91+ excepthook_calls.append((exc_type, exc_value, exc_tb))
92+
93+ context = Context(SSLv23_METHOD)
94+ context.set_tlsext_servername_callback(servername)
95+
96+ # Necessary to actually accept the connection
97+ context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
98+ context.use_certificate(
99+ load_certificate(FILETYPE_PEM, server_cert_pem)
100+ )
101+
102+ # Do a little connection to trigger the logic
103+ server = Connection(context, None)
104+ server.set_accept_state()
105+
106+ client = Connection(Context(SSLv23_METHOD), None)
107+ client.set_connect_state()
108+ client.set_tlsext_host_name(b"foo1.example.com")
109+
110+ monkeypatch.setattr(sys, "excepthook", custom_excepthook)
111+ with pytest.raises(Error):
112+ interact_in_memory(server, client)
113+
114+ assert len(excepthook_calls) == 1
115+ assert excepthook_calls[0][0] is TypeError
116+ assert excepthook_calls[0][1] is exc
117+ assert excepthook_calls[0][2] is not None
118+
119
120 class TestApplicationLayerProtoNegotiation:
121 """
122--
1232.43.0
124
diff --git a/meta/recipes-devtools/python/python3-pyopenssl/CVE-2026-27459.patch b/meta/recipes-devtools/python/python3-pyopenssl/CVE-2026-27459.patch
new file mode 100644
index 0000000000..f75540f96e
--- /dev/null
+++ b/meta/recipes-devtools/python/python3-pyopenssl/CVE-2026-27459.patch
@@ -0,0 +1,109 @@
1From 57f09bb4bb051d3bc2a1abd36e9525313d5cd408 Mon Sep 17 00:00:00 2001
2From: Alex Gaynor <alex.gaynor@gmail.com>
3Date: Wed, 18 Feb 2026 07:46:15 -0500
4Subject: [PATCH] Fix buffer overflow in DTLS cookie generation callback
5 (#1479)
6
7The cookie generate callback copied user-returned bytes into a
8fixed-size native buffer without enforcing a maximum length. A
9callback returning more than DTLS1_COOKIE_LENGTH bytes would overflow
10the OpenSSL-provided buffer, corrupting adjacent memory.
11
12Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
13
14Upstream-Status: Backport [https://github.com/pyca/pyopenssl/commit/57f09bb4bb051d3bc2a1abd36e9525313d5cd408]
15CVE: CVE-2026-27459
16Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
17---
18 CHANGELOG.rst | 1 +
19 src/OpenSSL/SSL.py | 7 +++++++
20 tests/test_ssl.py | 38 ++++++++++++++++++++++++++++++++++++++
21 3 files changed, 46 insertions(+)
22
23diff --git a/CHANGELOG.rst b/CHANGELOG.rst
24index 12e60e4..6041fdc 100644
25--- a/CHANGELOG.rst
26+++ b/CHANGELOG.rst
27@@ -16,6 +16,7 @@ Deprecations:
28 Changes:
29 ^^^^^^^^
30
31+- Properly raise an error if a DTLS cookie callback returned a cookie longer than ``DTLS1_COOKIE_LENGTH`` bytes. Previously this would result in a buffer-overflow.
32 - Added ``OpenSSL.SSL.Connection.get_selected_srtp_profile`` to determine which SRTP profile was negotiated.
33 `#1279 <https://github.com/pyca/pyopenssl/pull/1279>`_.
34 - ``Context.set_tlsext_servername_callback`` now handles exceptions raised in the callback by calling ``sys.excepthook`` and returning a fatal TLS alert. Previously, exceptions were silently swallowed and the handshake would proceed as if the callback had succeeded.
35diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py
36index a6263c4..2e4da78 100644
37--- a/src/OpenSSL/SSL.py
38+++ b/src/OpenSSL/SSL.py
39@@ -691,11 +691,18 @@ class _CookieGenerateCallbackHelper(_CallbackExceptionHelper):
40 def __init__(self, callback):
41 _CallbackExceptionHelper.__init__(self)
42
43+ max_cookie_len = getattr(_lib, "DTLS1_COOKIE_LENGTH", 255)
44+
45 @wraps(callback)
46 def wrapper(ssl, out, outlen):
47 try:
48 conn = Connection._reverse_mapping[ssl]
49 cookie = callback(conn)
50+ if len(cookie) > max_cookie_len:
51+ raise ValueError(
52+ f"Cookie too long (got {len(cookie)} bytes, "
53+ f"max {max_cookie_len})"
54+ )
55 out[0 : len(cookie)] = cookie
56 outlen[0] = len(cookie)
57 return 1
58diff --git a/tests/test_ssl.py b/tests/test_ssl.py
59index 55489b9..683e368 100644
60--- a/tests/test_ssl.py
61+++ b/tests/test_ssl.py
62@@ -4560,6 +4560,44 @@ class TestDTLS:
63 def test_it_works_with_srtp(self):
64 self._test_handshake_and_data(srtp_profile=b"SRTP_AES128_CM_SHA1_80")
65
66+ def test_cookie_generate_too_long(self) -> None:
67+ s_ctx = Context(DTLS_METHOD)
68+
69+ def generate_cookie(ssl: Connection) -> bytes:
70+ return b"\x00" * 256
71+
72+ def verify_cookie(ssl: Connection, cookie: bytes) -> bool:
73+ return True
74+
75+ s_ctx.set_cookie_generate_callback(generate_cookie)
76+ s_ctx.set_cookie_verify_callback(verify_cookie)
77+ s_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
78+ s_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
79+ s_ctx.set_options(OP_NO_QUERY_MTU)
80+ s = Connection(s_ctx)
81+ s.set_accept_state()
82+
83+ c_ctx = Context(DTLS_METHOD)
84+ c_ctx.set_options(OP_NO_QUERY_MTU)
85+ c = Connection(c_ctx)
86+ c.set_connect_state()
87+
88+ c.set_ciphertext_mtu(1500)
89+ s.set_ciphertext_mtu(1500)
90+
91+ # Client sends ClientHello
92+ try:
93+ c.do_handshake()
94+ except SSL.WantReadError:
95+ pass
96+ chunk = c.bio_read(self.LARGE_BUFFER)
97+ s.bio_write(chunk)
98+
99+ # Server tries DTLSv1_listen, which triggers cookie generation.
100+ # The oversized cookie should raise ValueError.
101+ with pytest.raises(ValueError, match="Cookie too long"):
102+ s.DTLSv1_listen()
103+
104 def test_timeout(self, monkeypatch):
105 c_ctx = Context(DTLS_METHOD)
106 c = Connection(c_ctx)
107--
1082.43.0
109
diff --git a/meta/recipes-devtools/python/python3-pyopenssl_24.0.0.bb b/meta/recipes-devtools/python/python3-pyopenssl_24.0.0.bb
index 116f214bfa..94a70aa17d 100644
--- a/meta/recipes-devtools/python/python3-pyopenssl_24.0.0.bb
+++ b/meta/recipes-devtools/python/python3-pyopenssl_24.0.0.bb
@@ -10,6 +10,11 @@ SRC_URI[sha256sum] = "6aa33039a93fffa4563e655b61d11364d01264be8ccb49906101e02a33
10PYPI_PACKAGE = "pyOpenSSL" 10PYPI_PACKAGE = "pyOpenSSL"
11inherit pypi setuptools3 11inherit pypi setuptools3
12 12
13SRC_URI += " \
14 file://CVE-2026-27448.patch \
15 file://CVE-2026-27459.patch \
16"
17
13PACKAGES =+ "${PN}-tests" 18PACKAGES =+ "${PN}-tests"
14FILES:${PN}-tests = "${libdir}/${PYTHON_DIR}/site-packages/OpenSSL/test" 19FILES:${PN}-tests = "${libdir}/${PYTHON_DIR}/site-packages/OpenSSL/test"
15 20
diff --git a/meta/recipes-devtools/python/python3-setuptools_69.1.1.bb b/meta/recipes-devtools/python/python3-setuptools_69.1.1.bb
index 46b2f0ab00..00f83056db 100644
--- a/meta/recipes-devtools/python/python3-setuptools_69.1.1.bb
+++ b/meta/recipes-devtools/python/python3-setuptools_69.1.1.bb
@@ -19,6 +19,15 @@ SRC_URI += " \
19 19
20SRC_URI[sha256sum] = "5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8" 20SRC_URI[sha256sum] = "5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"
21 21
22do_install:append() {
23 # setuptools ships Windows launcher executables (cli*.exe, gui*.exe).
24 # Keep them only when building for a Windows (mingw) host.
25 case "${HOST_OS}" in
26 mingw32|mingw64) ;;
27 *) rm -f ${D}${PYTHON_SITEPACKAGES_DIR}/setuptools/*.exe ;;
28 esac
29}
30
22DEPENDS += "python3" 31DEPENDS += "python3"
23 32
24RDEPENDS:${PN} = "\ 33RDEPENDS:${PN} = "\
diff --git a/meta/recipes-extended/timezone/timezone.inc b/meta/recipes-extended/timezone/timezone.inc
index f21bedf4fc..35f22d5a15 100644
--- a/meta/recipes-extended/timezone/timezone.inc
+++ b/meta/recipes-extended/timezone/timezone.inc
@@ -6,7 +6,7 @@ SECTION = "base"
6LICENSE = "PD & BSD-3-Clause" 6LICENSE = "PD & BSD-3-Clause"
7LIC_FILES_CHKSUM = "file://LICENSE;md5=c679c9d6b02bc2757b3eaf8f53c43fba" 7LIC_FILES_CHKSUM = "file://LICENSE;md5=c679c9d6b02bc2757b3eaf8f53c43fba"
8 8
9PV = "2025b" 9PV = "2025c"
10 10
11SRC_URI =" http://www.iana.org/time-zones/repository/releases/tzcode${PV}.tar.gz;name=tzcode;subdir=tz \ 11SRC_URI =" http://www.iana.org/time-zones/repository/releases/tzcode${PV}.tar.gz;name=tzcode;subdir=tz \
12 http://www.iana.org/time-zones/repository/releases/tzdata${PV}.tar.gz;name=tzdata;subdir=tz \ 12 http://www.iana.org/time-zones/repository/releases/tzdata${PV}.tar.gz;name=tzdata;subdir=tz \
@@ -16,5 +16,5 @@ S = "${WORKDIR}/tz"
16 16
17UPSTREAM_CHECK_URI = "http://www.iana.org/time-zones" 17UPSTREAM_CHECK_URI = "http://www.iana.org/time-zones"
18 18
19SRC_URI[tzcode.sha256sum] = "05f8fedb3525ee70d49c87d3fae78a8a0dbae4fe87aa565c65cda9948ae135ec" 19SRC_URI[tzcode.sha256sum] = "697ebe6625444aef5080f58e49d03424bbb52e08bf483d3ddb5acf10cbd15740"
20SRC_URI[tzdata.sha256sum] = "11810413345fc7805017e27ea9fa4885fd74cd61b2911711ad038f5d28d71474" 20SRC_URI[tzdata.sha256sum] = "4aa79e4effee53fc4029ffe5f6ebe97937282ebcdf386d5d2da91ce84142f957"
diff --git a/meta/recipes-graphics/freetype/freetype/CVE-2026-23865.patch b/meta/recipes-graphics/freetype/freetype/CVE-2026-23865.patch
new file mode 100644
index 0000000000..aa0d4326f8
--- /dev/null
+++ b/meta/recipes-graphics/freetype/freetype/CVE-2026-23865.patch
@@ -0,0 +1,54 @@
1From fc85a255849229c024c8e65f536fe1875d84841c Mon Sep 17 00:00:00 2001
2From: Werner Lemberg <wl@gnu.org>
3Date: Sat, 3 Jan 2026 08:07:57 +0100
4Subject: [PATCH] [ttgxvar] Check for overflow in array size computation.
5
6Problem reported and analyzed by povcfe <povcfe2sec@gmail.com>.
7
8Fixes issue #1382.
9
10* src/truetype/ttgxvar.c (tt_var_load_item_variation_store): Do it.
11
12Upstream-Status: Backport [https://gitlab.com/freetype/freetype/-/commit/fc85a255849229c024c8e65f536fe1875d84841c]
13CVE: CVE-2026-23865
14Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
15---
16 src/truetype/ttgxvar.c | 15 ++++++++++++++-
17 1 file changed, 14 insertions(+), 1 deletion(-)
18
19diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
20index 2ff40c9e8..96ddc04c8 100644
21--- a/src/truetype/ttgxvar.c
22+++ b/src/truetype/ttgxvar.c
23@@ -628,6 +628,7 @@
24 FT_UShort word_delta_count;
25 FT_UInt region_idx_count;
26 FT_UInt per_region_size;
27+ FT_UInt delta_set_size;
28
29
30 if ( FT_STREAM_SEEK( offset + dataOffsetArray[i] ) )
31@@ -697,7 +698,19 @@
32 if ( long_words )
33 per_region_size *= 2;
34
35- if ( FT_NEW_ARRAY( varData->deltaSet, per_region_size * item_count ) )
36+ /* Check for overflow (we actually test whether the */
37+ /* multiplication of two unsigned values wraps around). */
38+ delta_set_size = per_region_size * item_count;
39+ if ( per_region_size &&
40+ delta_set_size / per_region_size != item_count )
41+ {
42+ FT_TRACE2(( "tt_var_load_item_variation_store:"
43+ " bad delta set array size\n" ));
44+ error = FT_THROW( Array_Too_Large );
45+ goto Exit;
46+ }
47+
48+ if ( FT_NEW_ARRAY( varData->deltaSet, delta_set_size ) )
49 goto Exit;
50 if ( FT_Stream_Read( stream,
51 varData->deltaSet,
52--
53GitLab
54
diff --git a/meta/recipes-graphics/freetype/freetype_2.13.2.bb b/meta/recipes-graphics/freetype/freetype_2.13.2.bb
index ce7a615a3c..e053fef3b5 100644
--- a/meta/recipes-graphics/freetype/freetype_2.13.2.bb
+++ b/meta/recipes-graphics/freetype/freetype_2.13.2.bb
@@ -15,6 +15,7 @@ LIC_FILES_CHKSUM = "file://LICENSE.TXT;md5=843b6efc16f6b1652ec97f89d5a516c0 \
15 15
16SRC_URI = "${SAVANNAH_NONGNU_MIRROR}/${BPN}/${BP}.tar.xz \ 16SRC_URI = "${SAVANNAH_NONGNU_MIRROR}/${BPN}/${BP}.tar.xz \
17 file://CVE-2025-27363.patch \ 17 file://CVE-2025-27363.patch \
18 file://CVE-2026-23865.patch \
18" 19"
19SRC_URI[sha256sum] = "12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d" 20SRC_URI[sha256sum] = "12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d"
20 21
diff --git a/meta/recipes-kernel/wireless-regdb/wireless-regdb_2025.10.07.bb b/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.02.04.bb
index 68ae3b0464..2f7c816043 100644
--- a/meta/recipes-kernel/wireless-regdb/wireless-regdb_2025.10.07.bb
+++ b/meta/recipes-kernel/wireless-regdb/wireless-regdb_2026.02.04.bb
@@ -5,7 +5,7 @@ LICENSE = "ISC"
5LIC_FILES_CHKSUM = "file://LICENSE;md5=07c4f6dea3845b02a18dc00c8c87699c" 5LIC_FILES_CHKSUM = "file://LICENSE;md5=07c4f6dea3845b02a18dc00c8c87699c"
6 6
7SRC_URI = "https://www.kernel.org/pub/software/network/${BPN}/${BP}.tar.xz" 7SRC_URI = "https://www.kernel.org/pub/software/network/${BPN}/${BP}.tar.xz"
8SRC_URI[sha256sum] = "d4c872a44154604c869f5851f7d21d818d492835d370af7f58de8847973801c3" 8SRC_URI[sha256sum] = "0ff48a5cd9e9cfe8e815a24e023734919e9a3b7ad2f039243ad121cf5aabf6c6"
9 9
10inherit bin_package allarch 10inherit bin_package allarch
11 11
diff --git a/meta/recipes-multimedia/libtiff/tiff_4.6.0.bb b/meta/recipes-multimedia/libtiff/tiff_4.6.0.bb
index 777783d7cc..07540692fc 100644
--- a/meta/recipes-multimedia/libtiff/tiff_4.6.0.bb
+++ b/meta/recipes-multimedia/libtiff/tiff_4.6.0.bb
@@ -29,7 +29,7 @@ CVE_STATUS[CVE-2015-7313] = "fixed-version: Tested with check from https://secur
29CVE_STATUS[CVE-2023-3164] = "cpe-incorrect: Issue only affects the tiffcrop tool not compiled by default since 4.6.0" 29CVE_STATUS[CVE-2023-3164] = "cpe-incorrect: Issue only affects the tiffcrop tool not compiled by default since 4.6.0"
30 30
31CVE_STATUS_GROUPS += "CVE_STATUS_REMOVED_TOOLS" 31CVE_STATUS_GROUPS += "CVE_STATUS_REMOVED_TOOLS"
32CVE_STATUS_REMOVED_TOOLS = "CVE-2024-13978 CVE-2025-8176 CVE-2025-8177 CVE-2025-8534 CVE-2025-8851 CVE-2025-8961" 32CVE_STATUS_REMOVED_TOOLS = "CVE-2024-13978 CVE-2025-8176 CVE-2025-8177 CVE-2025-8534 CVE-2025-8851 CVE-2025-8961 CVE-2025-61143 CVE-2025-61144 CVE-2025-61145"
33CVE_STATUS_REMOVED_TOOLS[status] = "cpe-incorrect: tools affected by these CVEs are not present in this release" 33CVE_STATUS_REMOVED_TOOLS[status] = "cpe-incorrect: tools affected by these CVEs are not present in this release"
34 34
35inherit autotools multilib_header 35inherit autotools multilib_header
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-1.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-1.patch
new file mode 100644
index 0000000000..ae52a43a2c
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-1.patch
@@ -0,0 +1,61 @@
1From 0b2377dfccd99be641bf3f1a0de9f0dc8dc0d4b1 Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Mon, 26 Jan 2026 19:02:27 +0100
4Subject: [PATCH] x509/name_constraints: use actual zeroes in universal exclude
5 IP NC
6
7Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
8
9Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/0b2377dfccd99be641bf3f1a0de9f0dc8dc0d4b1]
10CVE: CVE-2025-14831
11Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
12---
13 lib/x509/name_constraints.c | 9 +++++----
14 1 file changed, 5 insertions(+), 4 deletions(-)
15
16--- a/lib/x509/name_constraints.c
17+++ b/lib/x509/name_constraints.c
18@@ -61,7 +61,7 @@ struct gnutls_name_constraints_st {
19
20 static struct name_constraints_node_st *
21 name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type,
22- unsigned char *data, unsigned int size);
23+ const unsigned char *data, unsigned int size);
24
25 static int
26 name_constraints_node_list_add(struct name_constraints_node_list_st *list,
27@@ -285,7 +285,7 @@ static void name_constraints_node_free(s
28 -*/
29 static struct name_constraints_node_st *
30 name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type,
31- unsigned char *data, unsigned int size)
32+ const unsigned char *data, unsigned int size)
33 {
34 struct name_constraints_node_st *tmp;
35 int ret;
36@@ -339,6 +339,7 @@ static int name_constraints_node_list_in
37 struct name_constraints_node_list_st removed = { .data = NULL,
38 .size = 0,
39 .capacity = 0 };
40+ static const unsigned char universal_ip[32] = { 0 };
41
42 /* temporary array to see, if we need to add universal excluded constraints
43 * (see phase 3 for details)
44@@ -471,7 +472,7 @@ static int name_constraints_node_list_in
45 case GNUTLS_SAN_IPADDRESS:
46 // add universal restricted range for IPv4
47 tmp = name_constraints_node_new(
48- nc, GNUTLS_SAN_IPADDRESS, NULL, 8);
49+ nc, GNUTLS_SAN_IPADDRESS, universal_ip, 8);
50 if (tmp == NULL) {
51 gnutls_assert();
52 ret = GNUTLS_E_MEMORY_ERROR;
53@@ -484,7 +485,7 @@ static int name_constraints_node_list_in
54 }
55 // add universal restricted range for IPv6
56 tmp = name_constraints_node_new(
57- nc, GNUTLS_SAN_IPADDRESS, NULL, 32);
58+ nc, GNUTLS_SAN_IPADDRESS, universal_ip, 32);
59 if (tmp == NULL) {
60 gnutls_assert();
61 ret = GNUTLS_E_MEMORY_ERROR;
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-2.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-2.patch
new file mode 100644
index 0000000000..0d34032554
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-2.patch
@@ -0,0 +1,30 @@
1From 85d6348a30c74d4ee3710e0f4652f634eaad6914 Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Mon, 26 Jan 2026 19:10:58 +0100
4Subject: [PATCH] tests/name-constraints-ip: stop swallowing errors...
5
6... now when it started to pass
7
8Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
9
10Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/85d6348a30c74d4ee3710e0f4652f634eaad6914]
11CVE: CVE-2025-14831
12Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
13---
14 tests/name-constraints-ip.c | 2 +-
15 1 file changed, 1 insertion(+), 1 deletion(-)
16
17diff --git a/tests/name-constraints-ip.c b/tests/name-constraints-ip.c
18index 7a196088dc..a0cf172b7f 100644
19--- a/tests/name-constraints-ip.c
20+++ b/tests/name-constraints-ip.c
21@@ -772,5 +772,5 @@ int main(int argc, char **argv)
22 cmocka_unit_test_setup_teardown(
23 check_ipv4v6_single_constraint_each, setup, teardown)
24 };
25- cmocka_run_group_tests(tests, NULL, NULL);
26+ return cmocka_run_group_tests(tests, NULL, NULL);
27 }
28--
29GitLab
30
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-3.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-3.patch
new file mode 100644
index 0000000000..ed4a7da3c7
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-3.patch
@@ -0,0 +1,45 @@
1From c28475413f82e1f34295d5c039f0c0a4ca2ee526 Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Mon, 26 Jan 2026 20:14:33 +0100
4Subject: [PATCH] x509/name_constraints: reject some malformed domain names
5
6Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
7
8Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/c28475413f82e1f34295d5c039f0c0a4ca2ee526]
9CVE: CVE-2025-14831
10Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
11---
12 lib/x509/name_constraints.c | 17 +++++++++++++++++
13 1 file changed, 17 insertions(+)
14
15diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
16index d07482e3c9..9783d92851 100644
17--- a/lib/x509/name_constraints.c
18+++ b/lib/x509/name_constraints.c
19@@ -159,6 +159,23 @@ static int validate_name_constraints_node(gnutls_x509_subject_alt_name_t type,
20 return gnutls_assert_val(GNUTLS_E_MALFORMED_CIDR);
21 }
22
23+ /* Validate DNS names and email addresses for malformed input */
24+ if (type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME) {
25+ unsigned int i;
26+ if (name->size == 0)
27+ return GNUTLS_E_SUCCESS;
28+
29+ /* reject names with consecutive dots... */
30+ for (i = 0; i + 1 < name->size; i++) {
31+ if (name->data[i] == '.' && name->data[i + 1] == '.')
32+ return gnutls_assert_val(
33+ GNUTLS_E_ILLEGAL_PARAMETER);
34+ }
35+ /* ... or names consisting exclusively of dots */
36+ if (name->size == 1 && name->data[0] == '.')
37+ return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
38+ }
39+
40 return GNUTLS_E_SUCCESS;
41 }
42
43--
44GitLab
45
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-4.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-4.patch
new file mode 100644
index 0000000000..99ec9c5e9a
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-4.patch
@@ -0,0 +1,200 @@
1From 6db7da7fcfe230f445b1edbb56e2a8346120c891 Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Thu, 5 Feb 2026 13:22:10 +0100
4Subject: [PATCH] x509/name_constraints: name_constraints_node_add_{new,copy}
5
6Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
7
8Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/6db7da7fcfe230f445b1edbb56e2a8346120c891]
9CVE: CVE-2025-14831
10Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
11---
12 lib/x509/name_constraints.c | 112 ++++++++++++++++--------------------
13 1 file changed, 51 insertions(+), 61 deletions(-)
14
15--- a/lib/x509/name_constraints.c
16+++ b/lib/x509/name_constraints.c
17@@ -86,6 +86,38 @@ name_constraints_node_list_add(struct na
18 return 0;
19 }
20
21+static int
22+name_constraints_node_add_new(gnutls_x509_name_constraints_t nc,
23+ struct name_constraints_node_list_st *list,
24+ unsigned type, const unsigned char *data,
25+ unsigned int size)
26+{
27+ struct name_constraints_node_st *node;
28+ int ret;
29+ node = name_constraints_node_new(nc, type, data, size);
30+ if (node == NULL) {
31+ gnutls_assert();
32+ return GNUTLS_E_MEMORY_ERROR;
33+ }
34+ ret = name_constraints_node_list_add(list, node);
35+ if (ret < 0) {
36+ gnutls_assert();
37+ return ret;
38+ }
39+ return GNUTLS_E_SUCCESS;
40+}
41+
42+static int
43+name_constraints_node_add_copy(gnutls_x509_name_constraints_t nc,
44+ struct name_constraints_node_list_st *dest,
45+ const struct name_constraints_node_st *src)
46+{
47+ if (!src)
48+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
49+ return name_constraints_node_add_new(nc, dest, src->type,
50+ src->name.data, src->name.size);
51+}
52+
53 // for documentation see the implementation
54 static int name_constraints_intersect_nodes(
55 gnutls_x509_name_constraints_t nc,
56@@ -188,7 +220,6 @@ static int extract_name_constraints(gnut
57 unsigned indx;
58 gnutls_datum_t tmp = { NULL, 0 };
59 unsigned int type;
60- struct name_constraints_node_st *node;
61
62 for (indx = 1;; indx++) {
63 snprintf(tmpstr, sizeof(tmpstr), "%s.?%u.base", vstr, indx);
64@@ -231,15 +262,9 @@ static int extract_name_constraints(gnut
65 goto cleanup;
66 }
67
68- node = name_constraints_node_new(nc, type, tmp.data, tmp.size);
69+ ret = name_constraints_node_add_new(nc, nodes, type, tmp.data,
70+ tmp.size);
71 _gnutls_free_datum(&tmp);
72- if (node == NULL) {
73- gnutls_assert();
74- ret = GNUTLS_E_MEMORY_ERROR;
75- goto cleanup;
76- }
77-
78- ret = name_constraints_node_list_add(nodes, node);
79 if (ret < 0) {
80 gnutls_assert();
81 goto cleanup;
82@@ -459,14 +484,7 @@ static int name_constraints_node_list_in
83 // Beware: also copies nodes other than DNS, email, IP,
84 // since their counterpart may have been moved in phase 1.
85 if (!used) {
86- tmp = name_constraints_node_new(
87- nc, t2->type, t2->name.data, t2->name.size);
88- if (tmp == NULL) {
89- gnutls_assert();
90- ret = GNUTLS_E_MEMORY_ERROR;
91- goto cleanup;
92- }
93- ret = name_constraints_node_list_add(permitted, tmp);
94+ ret = name_constraints_node_add_copy(nc, permitted, t2);
95 if (ret < 0) {
96 gnutls_assert();
97 goto cleanup;
98@@ -488,27 +506,17 @@ static int name_constraints_node_list_in
99 switch (type) {
100 case GNUTLS_SAN_IPADDRESS:
101 // add universal restricted range for IPv4
102- tmp = name_constraints_node_new(
103- nc, GNUTLS_SAN_IPADDRESS, universal_ip, 8);
104- if (tmp == NULL) {
105- gnutls_assert();
106- ret = GNUTLS_E_MEMORY_ERROR;
107- goto cleanup;
108- }
109- ret = name_constraints_node_list_add(excluded, tmp);
110+ ret = name_constraints_node_add_new(
111+ nc, excluded, GNUTLS_SAN_IPADDRESS,
112+ universal_ip, 8);
113 if (ret < 0) {
114 gnutls_assert();
115 goto cleanup;
116 }
117 // add universal restricted range for IPv6
118- tmp = name_constraints_node_new(
119- nc, GNUTLS_SAN_IPADDRESS, universal_ip, 32);
120- if (tmp == NULL) {
121- gnutls_assert();
122- ret = GNUTLS_E_MEMORY_ERROR;
123- goto cleanup;
124- }
125- ret = name_constraints_node_list_add(excluded, tmp);
126+ ret = name_constraints_node_add_new(
127+ nc, excluded, GNUTLS_SAN_IPADDRESS,
128+ universal_ip, 32);
129 if (ret < 0) {
130 gnutls_assert();
131 goto cleanup;
132@@ -516,13 +524,8 @@ static int name_constraints_node_list_in
133 break;
134 case GNUTLS_SAN_DNSNAME:
135 case GNUTLS_SAN_RFC822NAME:
136- tmp = name_constraints_node_new(nc, type, NULL, 0);
137- if (tmp == NULL) {
138- gnutls_assert();
139- ret = GNUTLS_E_MEMORY_ERROR;
140- goto cleanup;
141- }
142- ret = name_constraints_node_list_add(excluded, tmp);
143+ ret = name_constraints_node_add_new(nc, excluded, type,
144+ NULL, 0);
145 if (ret < 0) {
146 gnutls_assert();
147 goto cleanup;
148@@ -544,20 +547,13 @@ static int name_constraints_node_list_co
149 struct name_constraints_node_list_st *nodes,
150 const struct name_constraints_node_list_st *nodes2)
151 {
152+ int ret;
153+
154 for (size_t i = 0; i < nodes2->size; i++) {
155- const struct name_constraints_node_st *node = nodes2->data[i];
156- struct name_constraints_node_st *tmp;
157- int ret;
158-
159- tmp = name_constraints_node_new(nc, node->type, node->name.data,
160- node->name.size);
161- if (tmp == NULL) {
162- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
163- }
164- ret = name_constraints_node_list_add(nodes, tmp);
165+ ret = name_constraints_node_add_copy(nc, nodes,
166+ nodes2->data[i]);
167 if (ret < 0) {
168- name_constraints_node_free(tmp);
169- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
170+ return gnutls_assert_val(ret);
171 }
172 }
173
174@@ -687,7 +683,6 @@ static int name_constraints_add(gnutls_x
175 gnutls_x509_subject_alt_name_t type,
176 const gnutls_datum_t *name, unsigned permitted)
177 {
178- struct name_constraints_node_st *tmp;
179 struct name_constraints_node_list_st *nodes;
180 int ret;
181
182@@ -697,15 +692,10 @@ static int name_constraints_add(gnutls_x
183
184 nodes = permitted ? &nc->permitted : &nc->excluded;
185
186- tmp = name_constraints_node_new(nc, type, name->data, name->size);
187- if (tmp == NULL)
188- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
189-
190- ret = name_constraints_node_list_add(nodes, tmp);
191- if (ret < 0) {
192- name_constraints_node_free(tmp);
193+ ret = name_constraints_node_add_new(nc, nodes, type, name->data,
194+ name->size);
195+ if (ret < 0)
196 return gnutls_assert_val(ret);
197- }
198
199 return 0;
200 }
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-5.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-5.patch
new file mode 100644
index 0000000000..7c5ffdf6d8
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-5.patch
@@ -0,0 +1,500 @@
1From 094accd3ebec17ead6c391757eaa18763b72d83f Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Mon, 26 Jan 2026 20:16:36 +0100
4Subject: [PATCH] x509/name_constraints: introduce a rich comparator
5
6These are preparatory changes before implementing N * log N intersection
7over sorted lists of constraints.
8
9Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
10
11Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/094accd3ebec17ead6c391757eaa18763b72d83f]
12CVE: CVE-2025-14831
13Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
14---
15 lib/x509/name_constraints.c | 411 ++++++++++++++++++++++++++++--------
16 1 file changed, 320 insertions(+), 91 deletions(-)
17
18--- a/lib/x509/name_constraints.c
19+++ b/lib/x509/name_constraints.c
20@@ -39,6 +39,9 @@
21 #include "ip.h"
22 #include "ip-in-cidr.h"
23 #include "intprops.h"
24+#include "minmax.h"
25+
26+#include <string.h>
27
28 #define MAX_NC_CHECKS (1 << 20)
29
30@@ -63,6 +66,282 @@ static struct name_constraints_node_st *
31 name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type,
32 const unsigned char *data, unsigned int size);
33
34+/* An enum for "rich" comparisons that not only let us sort name constraints,
35+ * children-before-parent, but also subsume them during intersection. */
36+enum name_constraint_relation {
37+ NC_SORTS_BEFORE = -2, /* unrelated constraints */
38+ NC_INCLUDED_BY = -1, /* nc1 is included by nc2 / children sort first */
39+ NC_EQUAL = 0, /* exact match */
40+ NC_INCLUDES = 1, /* nc1 includes nc2 / parents sort last */
41+ NC_SORTS_AFTER = 2 /* unrelated constraints */
42+};
43+
44+/* A helper to compare just a pair of strings with this rich comparison */
45+static enum name_constraint_relation
46+compare_strings(const void *n1, size_t n1_len, const void *n2, size_t n2_len)
47+{
48+ int r = memcmp(n1, n2, MIN(n1_len, n2_len));
49+ if (r < 0)
50+ return NC_SORTS_BEFORE;
51+ if (r > 0)
52+ return NC_SORTS_AFTER;
53+ if (n1_len < n2_len)
54+ return NC_SORTS_BEFORE;
55+ if (n1_len > n2_len)
56+ return NC_SORTS_AFTER;
57+ return NC_EQUAL;
58+}
59+
60+/* Rich-compare DNS names. Example order/relationships:
61+ * z.x.a INCLUDED_BY x.a BEFORE y.a INCLUDED_BY a BEFORE x.b BEFORE y.b */
62+static enum name_constraint_relation compare_dns_names(const gnutls_datum_t *n1,
63+ const gnutls_datum_t *n2)
64+{
65+ enum name_constraint_relation rel;
66+ unsigned int i, j, i_end, j_end;
67+
68+ /* start from the end of each name */
69+ i = i_end = n1->size;
70+ j = j_end = n2->size;
71+
72+ /* skip the trailing dots for the comparison */
73+ while (i && n1->data[i - 1] == '.')
74+ i_end = i = i - 1;
75+ while (j && n2->data[j - 1] == '.')
76+ j_end = j = j - 1;
77+
78+ while (1) {
79+ // rewind back to beginning or an after-dot position
80+ while (i && n1->data[i - 1] != '.')
81+ i--;
82+ while (j && n2->data[j - 1] != '.')
83+ j--;
84+
85+ rel = compare_strings(&n1->data[i], i_end - i, &n2->data[j],
86+ j_end - j);
87+ if (rel == NC_SORTS_BEFORE) /* x.a BEFORE y.a */
88+ return NC_SORTS_BEFORE;
89+ if (rel == NC_SORTS_AFTER) /* y.a AFTER x.a */
90+ return NC_SORTS_AFTER;
91+ if (!i && j) /* x.a INCLUDES z.x.a */
92+ return NC_INCLUDES;
93+ if (i && !j) /* z.x.a INCLUDED_BY x.a */
94+ return NC_INCLUDED_BY;
95+
96+ if (!i && !j) /* r == 0, we ran out of components to compare */
97+ return NC_EQUAL;
98+ /* r == 0, i && j: step back past a dot and keep comparing */
99+ i_end = i = i - 1;
100+ j_end = j = j - 1;
101+
102+ /* support for non-standard ".gr INCLUDES example.gr" [1] */
103+ if (!i && j) /* .a INCLUDES x.a */
104+ return NC_INCLUDES;
105+ if (i && !j) /* x.a INCLUDED_BY .a */
106+ return NC_INCLUDED_BY;
107+ }
108+}
109+/* [1] https://mailarchive.ietf.org/arch/msg/saag/Bw6PtreW0G7aEG7SikfzKHES4VA */
110+
111+/* Rich-compare email name constraints. Example order/relationships:
112+ * z@x.a INCLUDED_BY x.a BEFORE y.a INCLUDED_BY a BEFORE x@b BEFORE y@b */
113+static enum name_constraint_relation compare_emails(const gnutls_datum_t *n1,
114+ const gnutls_datum_t *n2)
115+{
116+ enum name_constraint_relation domains_rel;
117+ unsigned int i, j, i_end, j_end;
118+ gnutls_datum_t d1, d2; /* borrow from n1 and n2 */
119+
120+ /* start from the end of each name */
121+ i = i_end = n1->size;
122+ j = j_end = n2->size;
123+
124+ /* rewind to @s to look for domains */
125+ while (i && n1->data[i - 1] != '@')
126+ i--;
127+ d1.size = i_end - i;
128+ d1.data = &n1->data[i];
129+ while (j && n2->data[j - 1] != '@')
130+ j--;
131+ d2.size = j_end - j;
132+ d2.data = &n2->data[j];
133+
134+ domains_rel = compare_dns_names(&d1, &d2);
135+
136+ /* email constraint semantics differ from DNS
137+ * DNS: x.a INCLUDED_BY a
138+ * Email: x.a INCLUDED_BY .a BEFORE a */
139+ if (domains_rel == NC_INCLUDED_BY || domains_rel == NC_INCLUDES) {
140+ bool d1_has_dot = (d1.size > 0 && d1.data[0] == '.');
141+ bool d2_has_dot = (d2.size > 0 && d2.data[0] == '.');
142+ /* a constraint without a dot is exact, excluding subdomains */
143+ if (!d2_has_dot && domains_rel == NC_INCLUDED_BY)
144+ domains_rel = NC_SORTS_BEFORE; /* x.a BEFORE a */
145+ if (!d1_has_dot && domains_rel == NC_INCLUDES)
146+ domains_rel = NC_SORTS_AFTER; /* a AFTER x.a */
147+ }
148+
149+ if (!i && !j) { /* both are domains-only */
150+ return domains_rel;
151+ } else if (i && !j) { /* n1 is email, n2 is domain */
152+ switch (domains_rel) {
153+ case NC_SORTS_AFTER:
154+ return NC_SORTS_AFTER;
155+ case NC_SORTS_BEFORE:
156+ return NC_SORTS_BEFORE;
157+ case NC_INCLUDES: /* n2 is more specific, a@x.a AFTER z.x.a */
158+ return NC_SORTS_AFTER;
159+ case NC_EQUAL: /* subdomains match, z@x.a INCLUDED_BY x.a */
160+ case NC_INCLUDED_BY: /* n1 is more specific */
161+ return NC_INCLUDED_BY;
162+ }
163+ } else if (!i && j) { /* n1 is domain, n2 is email */
164+ switch (domains_rel) {
165+ case NC_SORTS_AFTER:
166+ return NC_SORTS_AFTER;
167+ case NC_SORTS_BEFORE:
168+ return NC_SORTS_BEFORE;
169+ case NC_INCLUDES: /* n2 is more specific, a AFTER z@x.a */
170+ return NC_SORTS_AFTER;
171+ case NC_EQUAL: /* subdomains match, x.a INCLUDES z@x.a */
172+ return NC_INCLUDES;
173+ case NC_INCLUDED_BY: /* n1 is more specific, x.a BEFORE z@a */
174+ return NC_SORTS_BEFORE;
175+ }
176+ } else if (i && j) { /* both are emails */
177+ switch (domains_rel) {
178+ case NC_SORTS_AFTER:
179+ return NC_SORTS_AFTER;
180+ case NC_SORTS_BEFORE:
181+ return NC_SORTS_BEFORE;
182+ case NC_INCLUDES: // n2 is more specific
183+ return NC_SORTS_AFTER;
184+ case NC_INCLUDED_BY: // n1 is more specific
185+ return NC_SORTS_BEFORE;
186+ case NC_EQUAL: // only case when we need to look before the @
187+ break; // see below for readability
188+ }
189+ }
190+
191+ /* i && j, both are emails, domain names match, compare up to @ */
192+ return compare_strings(n1->data, i - 1, n2->data, j - 1);
193+}
194+
195+/* Rich-compare IP address constraints. Example order/relationships:
196+ * 10.0.0.0/24 INCLUDED_BY 10.0.0.0/16 BEFORE 1::1/128 INCLUDED_BY 1::1/127 */
197+static enum name_constraint_relation compare_ip_ncs(const gnutls_datum_t *n1,
198+ const gnutls_datum_t *n2)
199+{
200+ unsigned int len, i;
201+ int r;
202+ const unsigned char *ip1, *ip2, *mask1, *mask2;
203+ unsigned char masked11[16], masked22[16], masked12[16], masked21[16];
204+
205+ if (n1->size < n2->size)
206+ return NC_SORTS_BEFORE;
207+ if (n1->size > n2->size)
208+ return NC_SORTS_AFTER;
209+ len = n1->size / 2; /* 4 for IPv4, 16 for IPv6 */
210+
211+ /* data is a concatenation of prefix and mask */
212+ ip1 = n1->data;
213+ ip2 = n2->data;
214+ mask1 = n1->data + len;
215+ mask2 = n2->data + len;
216+ for (i = 0; i < len; i++) {
217+ masked11[i] = ip1[i] & mask1[i];
218+ masked22[i] = ip2[i] & mask2[i];
219+ masked12[i] = ip1[i] & mask2[i];
220+ masked21[i] = ip2[i] & mask1[i];
221+ }
222+
223+ r = memcmp(mask1, mask2, len);
224+ if (r < 0 && !memcmp(masked11, masked21, len)) /* prefix1 < prefix2 */
225+ return NC_INCLUDES; /* ip1 & mask1 == ip2 & mask1 */
226+ if (r > 0 && !memcmp(masked12, masked22, len)) /* prefix1 > prefix2 */
227+ return NC_INCLUDED_BY; /* ip1 & mask2 == ip2 & mask2 */
228+
229+ r = memcmp(masked11, masked22, len);
230+ if (r < 0)
231+ return NC_SORTS_BEFORE;
232+ else if (r > 0)
233+ return NC_SORTS_AFTER;
234+ return NC_EQUAL;
235+}
236+
237+static inline bool is_supported_type(unsigned type)
238+{
239+ return type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME ||
240+ type == GNUTLS_SAN_IPADDRESS;
241+}
242+
243+/* Universal comparison for name constraint nodes.
244+ * Unsupported types sort before supported types to allow early handling.
245+ * NULL represents end-of-list and sorts after everything else. */
246+static enum name_constraint_relation
247+compare_name_constraint_nodes(const struct name_constraints_node_st *n1,
248+ const struct name_constraints_node_st *n2)
249+{
250+ bool n1_supported, n2_supported;
251+
252+ if (!n1 && !n2)
253+ return NC_EQUAL;
254+ if (!n1)
255+ return NC_SORTS_AFTER;
256+ if (!n2)
257+ return NC_SORTS_BEFORE;
258+
259+ n1_supported = is_supported_type(n1->type);
260+ n2_supported = is_supported_type(n2->type);
261+
262+ /* unsupported types bubble up (sort first). intersect relies on this */
263+ if (!n1_supported && n2_supported)
264+ return NC_SORTS_BEFORE;
265+ if (n1_supported && !n2_supported)
266+ return NC_SORTS_AFTER;
267+
268+ /* next, sort by type */
269+ if (n1->type < n2->type)
270+ return NC_SORTS_BEFORE;
271+ if (n1->type > n2->type)
272+ return NC_SORTS_AFTER;
273+
274+ /* now look deeper */
275+ switch (n1->type) {
276+ case GNUTLS_SAN_DNSNAME:
277+ return compare_dns_names(&n1->name, &n2->name);
278+ case GNUTLS_SAN_RFC822NAME:
279+ return compare_emails(&n1->name, &n2->name);
280+ case GNUTLS_SAN_IPADDRESS:
281+ return compare_ip_ncs(&n1->name, &n2->name);
282+ default:
283+ /* unsupported types: stable lexicographic order */
284+ return compare_strings(n1->name.data, n1->name.size,
285+ n2->name.data, n2->name.size);
286+ }
287+}
288+
289+/* qsort-compatible wrapper */
290+static int compare_name_constraint_nodes_qsort(const void *a, const void *b)
291+{
292+ const struct name_constraints_node_st *const *n1 = a;
293+ const struct name_constraints_node_st *const *n2 = b;
294+ enum name_constraint_relation rel;
295+
296+ rel = compare_name_constraint_nodes(*n1, *n2);
297+ switch (rel) {
298+ case NC_SORTS_BEFORE:
299+ case NC_INCLUDED_BY:
300+ return -1;
301+ case NC_SORTS_AFTER:
302+ case NC_INCLUDES:
303+ return 1;
304+ case NC_EQUAL:
305+ default:
306+ return 0;
307+ }
308+}
309+
310 static int
311 name_constraints_node_list_add(struct name_constraints_node_list_st *list,
312 struct name_constraints_node_st *node)
313@@ -420,9 +699,7 @@ static int name_constraints_node_list_in
314 }
315 }
316
317- if (found != NULL && (t->type == GNUTLS_SAN_DNSNAME ||
318- t->type == GNUTLS_SAN_RFC822NAME ||
319- t->type == GNUTLS_SAN_IPADDRESS)) {
320+ if (found != NULL && is_supported_type(t->type)) {
321 /* move node from PERMITTED to REMOVED */
322 ret = name_constraints_node_list_add(&removed, t);
323 if (ret < 0) {
324@@ -824,61 +1101,14 @@ cleanup:
325 return ret;
326 }
327
328-static unsigned ends_with(const gnutls_datum_t *str,
329- const gnutls_datum_t *suffix)
330-{
331- unsigned char *tree;
332- unsigned int treelen;
333-
334- if (suffix->size >= str->size)
335- return 0;
336-
337- tree = suffix->data;
338- treelen = suffix->size;
339- if ((treelen > 0) && (tree[0] == '.')) {
340- tree++;
341- treelen--;
342- }
343-
344- if (memcmp(str->data + str->size - treelen, tree, treelen) == 0 &&
345- str->data[str->size - treelen - 1] == '.')
346- return 1; /* match */
347-
348- return 0;
349-}
350-
351-static unsigned email_ends_with(const gnutls_datum_t *str,
352- const gnutls_datum_t *suffix)
353-{
354- if (suffix->size >= str->size) {
355- return 0;
356- }
357-
358- if (suffix->size > 0 && memcmp(str->data + str->size - suffix->size,
359- suffix->data, suffix->size) != 0) {
360- return 0;
361- }
362-
363- if (suffix->size > 1 && suffix->data[0] == '.') { /* .domain.com */
364- return 1; /* match */
365- } else if (str->data[str->size - suffix->size - 1] == '@') {
366- return 1; /* match */
367- }
368-
369- return 0;
370-}
371-
372 static unsigned dnsname_matches(const gnutls_datum_t *name,
373 const gnutls_datum_t *suffix)
374 {
375 _gnutls_hard_log("matching %.*s with DNS constraint %.*s\n", name->size,
376 name->data, suffix->size, suffix->data);
377
378- if (suffix->size == name->size &&
379- memcmp(suffix->data, name->data, suffix->size) == 0)
380- return 1; /* match */
381-
382- return ends_with(name, suffix);
383+ enum name_constraint_relation rel = compare_dns_names(name, suffix);
384+ return rel == NC_EQUAL || rel == NC_INCLUDED_BY;
385 }
386
387 static unsigned email_matches(const gnutls_datum_t *name,
388@@ -887,11 +1117,8 @@ static unsigned email_matches(const gnut
389 _gnutls_hard_log("matching %.*s with e-mail constraint %.*s\n",
390 name->size, name->data, suffix->size, suffix->data);
391
392- if (suffix->size == name->size &&
393- memcmp(suffix->data, name->data, suffix->size) == 0)
394- return 1; /* match */
395-
396- return email_ends_with(name, suffix);
397+ enum name_constraint_relation rel = compare_emails(name, suffix);
398+ return rel == NC_EQUAL || rel == NC_INCLUDED_BY;
399 }
400
401 /*-
402@@ -915,8 +1142,7 @@ static int name_constraints_intersect_no
403 // presume empty intersection
404 struct name_constraints_node_st *intersection = NULL;
405 const struct name_constraints_node_st *to_copy = NULL;
406- unsigned iplength = 0;
407- unsigned byte;
408+ enum name_constraint_relation rel;
409
410 *_intersection = NULL;
411
412@@ -925,32 +1151,49 @@ static int name_constraints_intersect_no
413 }
414 switch (node1->type) {
415 case GNUTLS_SAN_DNSNAME:
416- if (!dnsname_matches(&node2->name, &node1->name))
417+ rel = compare_dns_names(&node1->name, &node2->name);
418+ switch (rel) {
419+ case NC_EQUAL: // equal means doesn't matter which one
420+ case NC_INCLUDES: // node2 is more specific
421+ to_copy = node2;
422+ break;
423+ case NC_INCLUDED_BY: // node1 is more specific
424+ to_copy = node1;
425+ break;
426+ case NC_SORTS_BEFORE: // no intersection
427+ case NC_SORTS_AFTER: // no intersection
428 return GNUTLS_E_SUCCESS;
429- to_copy = node2;
430+ }
431 break;
432 case GNUTLS_SAN_RFC822NAME:
433- if (!email_matches(&node2->name, &node1->name))
434+ rel = compare_emails(&node1->name, &node2->name);
435+ switch (rel) {
436+ case NC_EQUAL: // equal means doesn't matter which one
437+ case NC_INCLUDES: // node2 is more specific
438+ to_copy = node2;
439+ break;
440+ case NC_INCLUDED_BY: // node1 is more specific
441+ to_copy = node1;
442+ break;
443+ case NC_SORTS_BEFORE: // no intersection
444+ case NC_SORTS_AFTER: // no intersection
445 return GNUTLS_E_SUCCESS;
446- to_copy = node2;
447+ }
448 break;
449 case GNUTLS_SAN_IPADDRESS:
450- if (node1->name.size != node2->name.size)
451+ rel = compare_ip_ncs(&node1->name, &node2->name);
452+ switch (rel) {
453+ case NC_EQUAL: // equal means doesn't matter which one
454+ case NC_INCLUDES: // node2 is more specific
455+ to_copy = node2;
456+ break;
457+ case NC_INCLUDED_BY: // node1 is more specific
458+ to_copy = node1;
459+ break;
460+ case NC_SORTS_BEFORE: // no intersection
461+ case NC_SORTS_AFTER: // no intersection
462 return GNUTLS_E_SUCCESS;
463- iplength = node1->name.size / 2;
464- for (byte = 0; byte < iplength; byte++) {
465- if (((node1->name.data[byte] ^
466- node2->name.data[byte]) // XOR of addresses
467- & node1->name.data[byte +
468- iplength] // AND mask from nc1
469- & node2->name.data[byte +
470- iplength]) // AND mask from nc2
471- != 0) {
472- // CIDRS do not intersect
473- return GNUTLS_E_SUCCESS;
474- }
475 }
476- to_copy = node2;
477 break;
478 default:
479 // for other types, we don't know how to do the intersection, assume empty
480@@ -967,20 +1210,6 @@ static int name_constraints_intersect_no
481 intersection = *_intersection;
482
483 assert(intersection->name.data != NULL);
484-
485- if (intersection->type == GNUTLS_SAN_IPADDRESS) {
486- // make sure both IP addresses are correctly masked
487- _gnutls_mask_ip(intersection->name.data,
488- intersection->name.data + iplength,
489- iplength);
490- _gnutls_mask_ip(node1->name.data,
491- node1->name.data + iplength, iplength);
492- // update intersection, if necessary (we already know one is subset of other)
493- for (byte = 0; byte < 2 * iplength; byte++) {
494- intersection->name.data[byte] |=
495- node1->name.data[byte];
496- }
497- }
498 }
499
500 return GNUTLS_E_SUCCESS;
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-6.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-6.patch
new file mode 100644
index 0000000000..6dc599dd9f
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-6.patch
@@ -0,0 +1,119 @@
1From bc62fbb946085527b4b1c02f337dd10c68c54690 Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Wed, 4 Feb 2026 09:09:46 +0100
4Subject: [PATCH] x509/name_constraints: add sorted_view in preparation...
5
6... for actually using it later for performance gains.
7
8Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
9
10Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/bc62fbb946085527b4b1c02f337dd10c68c54690]
11CVE: CVE-2025-14831
12Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
13---
14 lib/x509/name_constraints.c | 62 ++++++++++++++++++++++++++++++-------
15 1 file changed, 51 insertions(+), 11 deletions(-)
16
17--- a/lib/x509/name_constraints.c
18+++ b/lib/x509/name_constraints.c
19@@ -54,6 +54,9 @@ struct name_constraints_node_list_st {
20 struct name_constraints_node_st **data;
21 size_t size;
22 size_t capacity;
23+ /* sorted-on-demand view, valid only when dirty == false */
24+ bool dirty;
25+ struct name_constraints_node_st **sorted_view;
26 };
27
28 struct gnutls_name_constraints_st {
29@@ -342,6 +345,37 @@ static int compare_name_constraint_nodes
30 }
31 }
32
33+/* Bring the sorted view up to date with the list data; clear the dirty flag. */
34+static int ensure_sorted(struct name_constraints_node_list_st *list)
35+{
36+ struct name_constraints_node_st **new_data;
37+
38+ if (!list->dirty)
39+ return GNUTLS_E_SUCCESS;
40+ if (!list->size) {
41+ list->dirty = false;
42+ return GNUTLS_E_SUCCESS;
43+ }
44+
45+ /* reallocate sorted view to match current size */
46+ new_data =
47+ _gnutls_reallocarray(list->sorted_view, list->size,
48+ sizeof(struct name_constraints_node_st *));
49+ if (!new_data)
50+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
51+ list->sorted_view = new_data;
52+
53+ /* copy pointers and sort in-place */
54+ memcpy(list->sorted_view, list->data,
55+ list->size * sizeof(struct name_constraints_node_st *));
56+ qsort(list->sorted_view, list->size,
57+ sizeof(struct name_constraints_node_st *),
58+ compare_name_constraint_nodes_qsort);
59+
60+ list->dirty = false;
61+ return GNUTLS_E_SUCCESS;
62+}
63+
64 static int
65 name_constraints_node_list_add(struct name_constraints_node_list_st *list,
66 struct name_constraints_node_st *node)
67@@ -361,10 +395,23 @@ name_constraints_node_list_add(struct na
68 list->capacity = new_capacity;
69 list->data = new_data;
70 }
71+ list->dirty = true;
72 list->data[list->size++] = node;
73 return 0;
74 }
75
76+static void
77+name_constraints_node_list_clear(struct name_constraints_node_list_st *list)
78+{
79+ gnutls_free(list->data);
80+ gnutls_free(list->sorted_view);
81+ list->data = NULL;
82+ list->sorted_view = NULL;
83+ list->capacity = 0;
84+ list->size = 0;
85+ list->dirty = false;
86+}
87+
88 static int
89 name_constraints_node_add_new(gnutls_x509_name_constraints_t nc,
90 struct name_constraints_node_list_st *list,
91@@ -711,6 +758,7 @@ static int name_constraints_node_list_in
92 permitted->data[i] =
93 permitted->data[permitted->size - 1];
94 permitted->size--;
95+ permitted->dirty = true;
96 continue;
97 }
98 i++;
99@@ -905,17 +953,9 @@ void _gnutls_x509_name_constraints_clear
100 struct name_constraints_node_st *node = nc->nodes.data[i];
101 name_constraints_node_free(node);
102 }
103- gnutls_free(nc->nodes.data);
104- nc->nodes.capacity = 0;
105- nc->nodes.size = 0;
106-
107- gnutls_free(nc->permitted.data);
108- nc->permitted.capacity = 0;
109- nc->permitted.size = 0;
110-
111- gnutls_free(nc->excluded.data);
112- nc->excluded.capacity = 0;
113- nc->excluded.size = 0;
114+ name_constraints_node_list_clear(&nc->nodes);
115+ name_constraints_node_list_clear(&nc->permitted);
116+ name_constraints_node_list_clear(&nc->excluded);
117 }
118
119 /**
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-7.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-7.patch
new file mode 100644
index 0000000000..846862007f
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-7.patch
@@ -0,0 +1,150 @@
1From 80db5e90fa18d3e34bb91dd027bdf76d31e93dcd Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Wed, 4 Feb 2026 13:30:08 +0100
4Subject: [PATCH] x509/name_constraints: implement
5 name_constraints_node_list_union
6
7Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
8
9Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/80db5e90fa18d3e34bb91dd027bdf76d31e93dcd]
10CVE: CVE-2025-14831
11Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
12---
13 lib/x509/name_constraints.c | 98 ++++++++++++++++++++++++++++++++-----
14 1 file changed, 86 insertions(+), 12 deletions(-)
15
16--- a/lib/x509/name_constraints.c
17+++ b/lib/x509/name_constraints.c
18@@ -41,6 +41,7 @@
19 #include "intprops.h"
20 #include "minmax.h"
21
22+#include <assert.h>
23 #include <string.h>
24
25 #define MAX_NC_CHECKS (1 << 20)
26@@ -867,22 +868,95 @@ cleanup:
27 return ret;
28 }
29
30-static int name_constraints_node_list_concat(
31- gnutls_x509_name_constraints_t nc,
32- struct name_constraints_node_list_st *nodes,
33- const struct name_constraints_node_list_st *nodes2)
34+static int
35+name_constraints_node_list_union(gnutls_x509_name_constraints_t nc,
36+ struct name_constraints_node_list_st *nodes,
37+ struct name_constraints_node_list_st *nodes2)
38 {
39 int ret;
40+ size_t i = 0, j = 0;
41+ struct name_constraints_node_st *nc1;
42+ const struct name_constraints_node_st *nc2;
43+ enum name_constraint_relation rel;
44+ struct name_constraints_node_list_st result = { 0 };
45+
46+ if (nodes2->size == 0) /* nothing to do */
47+ return GNUTLS_E_SUCCESS;
48+
49+ ret = ensure_sorted(nodes);
50+ if (ret < 0) {
51+ gnutls_assert();
52+ goto cleanup;
53+ }
54+ ret = ensure_sorted(nodes2);
55+ if (ret < 0) {
56+ gnutls_assert();
57+ goto cleanup;
58+ }
59+
60+ /* traverse both lists in a single pass and merge them w/o duplicates */
61+ while (i < nodes->size || j < nodes2->size) {
62+ nc1 = (i < nodes->size) ? nodes->sorted_view[i] : NULL;
63+ nc2 = (j < nodes2->size) ? nodes2->sorted_view[j] : NULL;
64
65- for (size_t i = 0; i < nodes2->size; i++) {
66- ret = name_constraints_node_add_copy(nc, nodes,
67- nodes2->data[i]);
68+ rel = compare_name_constraint_nodes(nc1, nc2);
69+ switch (rel) {
70+ case NC_SORTS_BEFORE:
71+ assert(nc1 != NULL); /* comparator-guaranteed */
72+ ret = name_constraints_node_list_add(&result, nc1);
73+ i++;
74+ break;
75+ case NC_SORTS_AFTER:
76+ assert(nc2 != NULL); /* comparator-guaranteed */
77+ ret = name_constraints_node_add_copy(nc, &result, nc2);
78+ j++;
79+ break;
80+ case NC_INCLUDES: /* nc1 is broader, shallow-copy it */
81+ assert(nc1 != NULL && nc2 != NULL); /* comparator */
82+ ret = name_constraints_node_list_add(&result, nc1);
83+ i++;
84+ j++;
85+ break;
86+ case NC_INCLUDED_BY: /* nc2 is broader, deep-copy it */
87+ assert(nc1 != NULL && nc2 != NULL); /* comparator */
88+ ret = name_constraints_node_add_copy(nc, &result, nc2);
89+ i++;
90+ j++;
91+ break;
92+ case NC_EQUAL:
93+ assert(nc1 != NULL && nc2 != NULL); /* loop condition */
94+ ret = name_constraints_node_list_add(&result, nc1);
95+ i++;
96+ j++;
97+ break;
98+ }
99 if (ret < 0) {
100- return gnutls_assert_val(ret);
101+ gnutls_assert();
102+ goto cleanup;
103 }
104 }
105
106- return 0;
107+ gnutls_free(nodes->data);
108+ gnutls_free(nodes->sorted_view);
109+ nodes->data = result.data;
110+ nodes->sorted_view = NULL;
111+ nodes->size = result.size;
112+ nodes->capacity = result.capacity;
113+ nodes->dirty = true;
114+ /* since we know it's sorted, populate sorted_view almost for free */
115+ nodes->sorted_view = gnutls_calloc(
116+ nodes->size, sizeof(struct name_constraints_node_st *));
117+ if (!nodes->sorted_view)
118+ return GNUTLS_E_SUCCESS; /* we tried, no harm done */
119+ memcpy(nodes->sorted_view, nodes->data,
120+ nodes->size * sizeof(struct name_constraints_node_st *));
121+ nodes->dirty = false;
122+
123+ result.data = NULL;
124+ return GNUTLS_E_SUCCESS;
125+cleanup:
126+ name_constraints_node_list_clear(&result);
127+ return gnutls_assert_val(ret);
128 }
129
130 /**
131@@ -1023,7 +1097,7 @@ static int name_constraints_add(gnutls_x
132 * @nc2: The name constraints to be merged with
133 *
134 * This function will merge the provided name constraints structures
135- * as per RFC5280 p6.1.4. That is, the excluded constraints will be appended,
136+ * as per RFC5280 p6.1.4. That is, the excluded constraints will be unioned,
137 * and permitted will be intersected. The intersection assumes that @nc
138 * is the root CA constraints.
139 *
140@@ -1045,8 +1119,8 @@ int _gnutls_x509_name_constraints_merge(
141 return ret;
142 }
143
144- ret = name_constraints_node_list_concat(nc, &nc->excluded,
145- &nc2->excluded);
146+ ret = name_constraints_node_list_union(nc, &nc->excluded,
147+ &nc2->excluded);
148 if (ret < 0) {
149 gnutls_assert();
150 return ret;
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-8.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-8.patch
new file mode 100644
index 0000000000..9beca76a35
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-8.patch
@@ -0,0 +1,105 @@
1From d0ac999620c8c0aeb6939e1e92d884ca8e40b759 Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Wed, 4 Feb 2026 18:31:37 +0100
4Subject: [PATCH] x509/name_constraints: make types_with_empty_intersection a
5 bitmask
6
7Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
8
9Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/d0ac999620c8c0aeb6939e1e92d884ca8e40b759]
10CVE: CVE-2025-14831
11Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
12---
13 lib/x509/name_constraints.c | 39 +++++++++++++++++++++++++++----------
14 1 file changed, 29 insertions(+), 10 deletions(-)
15
16--- a/lib/x509/name_constraints.c
17+++ b/lib/x509/name_constraints.c
18@@ -275,6 +275,7 @@ static enum name_constraint_relation com
19
20 static inline bool is_supported_type(unsigned type)
21 {
22+ /* all of these should be under GNUTLS_SAN_MAX (intersect bitmasks) */
23 return type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME ||
24 type == GNUTLS_SAN_IPADDRESS;
25 }
26@@ -683,6 +684,21 @@ name_constraints_node_new(gnutls_x509_na
27 return tmp;
28 }
29
30+static int
31+name_constraints_node_list_union(gnutls_x509_name_constraints_t nc,
32+ struct name_constraints_node_list_st *nodes,
33+ struct name_constraints_node_list_st *nodes2);
34+
35+#define type_bitmask_t uint8_t /* increase if GNUTLS_SAN_MAX grows */
36+#define type_bitmask_set(mask, t) ((mask) |= (1u << (t)))
37+#define type_bitmask_clr(mask, t) ((mask) &= ~(1u << (t)))
38+#define type_bitmask_in(mask, t) ((mask) & (1u << (t)))
39+/* C99-compatible compile-time assertions; gnutls_int.h undefines verify */
40+typedef char assert_san_max[(GNUTLS_SAN_MAX < 8) ? 1 : -1];
41+typedef char assert_dnsname[(GNUTLS_SAN_DNSNAME <= GNUTLS_SAN_MAX) ? 1 : -1];
42+typedef char assert_rfc822[(GNUTLS_SAN_RFC822NAME <= GNUTLS_SAN_MAX) ? 1 : -1];
43+typedef char assert_ipaddr[(GNUTLS_SAN_IPADDRESS <= GNUTLS_SAN_MAX) ? 1 : -1];
44+
45 /*-
46 * @brief name_constraints_node_list_intersect:
47 * @nc: %gnutls_x509_name_constraints_t
48@@ -710,12 +726,9 @@ static int name_constraints_node_list_in
49 .capacity = 0 };
50 static const unsigned char universal_ip[32] = { 0 };
51
52- /* temporary array to see, if we need to add universal excluded constraints
53- * (see phase 3 for details)
54- * indexed directly by (gnutls_x509_subject_alt_name_t enum - 1) */
55- unsigned char types_with_empty_intersection[GNUTLS_SAN_MAX];
56- memset(types_with_empty_intersection, 0,
57- sizeof(types_with_empty_intersection));
58+ /* bitmask to see if we need to add universal excluded constraints
59+ * (see phase 3 for details) */
60+ type_bitmask_t types_with_empty_intersection = 0;
61
62 if (permitted->size == 0 || permitted2->size == 0)
63 return 0;
64@@ -741,7 +754,8 @@ static int name_constraints_node_list_in
65 // note the possibility of empty intersection for this type
66 // if we add something to the intersection in phase 2,
67 // we will reset this flag back to 0 then
68- types_with_empty_intersection[t->type - 1] = 1;
69+ type_bitmask_set(types_with_empty_intersection,
70+ t->type);
71 found = t2;
72 break;
73 }
74@@ -795,8 +809,8 @@ static int name_constraints_node_list_in
75 GNUTLS_E_INTERNAL_ERROR);
76 }
77 // we will not add universal excluded constraint for this type
78- types_with_empty_intersection[tmp->type - 1] =
79- 0;
80+ type_bitmask_clr(types_with_empty_intersection,
81+ tmp->type);
82 // add intersection node to PERMITTED
83 ret = name_constraints_node_list_add(permitted,
84 tmp);
85@@ -824,7 +838,7 @@ static int name_constraints_node_list_in
86 * excluded constraint with universal wildcard
87 * (since the intersection of permitted is now empty). */
88 for (type = 1; type <= GNUTLS_SAN_MAX; type++) {
89- if (types_with_empty_intersection[type - 1] == 0)
90+ if (!type_bitmask_in(types_with_empty_intersection, type))
91 continue;
92 _gnutls_hard_log(
93 "Adding universal excluded name constraint for type %d.\n",
94@@ -868,6 +882,11 @@ cleanup:
95 return ret;
96 }
97
98+#undef type_bitmask_t
99+#undef type_bitmask_set
100+#undef type_bitmask_clr
101+#undef type_bitmask_in
102+
103 static int
104 name_constraints_node_list_union(gnutls_x509_name_constraints_t nc,
105 struct name_constraints_node_list_st *nodes,
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-9.patch b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-9.patch
new file mode 100644
index 0000000000..eefc1b76e0
--- /dev/null
+++ b/meta/recipes-support/gnutls/gnutls/CVE-2025-14831-9.patch
@@ -0,0 +1,421 @@
1From d6054f0016db05fb5c82177ddbd0a4e8331059a1 Mon Sep 17 00:00:00 2001
2From: Alexander Sosedkin <asosedkin@redhat.com>
3Date: Wed, 4 Feb 2026 20:03:49 +0100
4Subject: [PATCH] x509/name_constraints: name_constraints_node_list_intersect
5 over sorted
6
7Fixes: #1773
8Fixes: GNUTLS-SA-2026-02-09-2
9Fixes: CVE-2025-14831
10
11Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
12
13Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/d6054f0016db05fb5c82177ddbd0a4e8331059a1]
14CVE: CVE-2025-14831
15Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
16---
17 lib/x509/name_constraints.c | 347 ++++++++++++++----------------------
18 1 file changed, 135 insertions(+), 212 deletions(-)
19
20diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c
21index d1006eb..04722bd 100644
22--- a/lib/x509/name_constraints.c
23+++ b/lib/x509/name_constraints.c
24@@ -446,13 +446,6 @@ name_constraints_node_add_copy(gnutls_x509_name_constraints_t nc,
25 src->name.data, src->name.size);
26 }
27
28-// for documentation see the implementation
29-static int name_constraints_intersect_nodes(
30- gnutls_x509_name_constraints_t nc,
31- const struct name_constraints_node_st *node1,
32- const struct name_constraints_node_st *node2,
33- struct name_constraints_node_st **intersection);
34-
35 /*-
36 * _gnutls_x509_name_constraints_is_empty:
37 * @nc: name constraints structure
38@@ -716,129 +709,143 @@ typedef char assert_ipaddr[(GNUTLS_SAN_IPADDRESS <= GNUTLS_SAN_MAX) ? 1 : -1];
39 static int name_constraints_node_list_intersect(
40 gnutls_x509_name_constraints_t nc,
41 struct name_constraints_node_list_st *permitted,
42- const struct name_constraints_node_list_st *permitted2,
43+ struct name_constraints_node_list_st *permitted2,
44 struct name_constraints_node_list_st *excluded)
45 {
46- struct name_constraints_node_st *tmp;
47- int ret, type, used;
48- struct name_constraints_node_list_st removed = { .data = NULL,
49- .size = 0,
50- .capacity = 0 };
51+ struct name_constraints_node_st *nc1, *nc2;
52+ struct name_constraints_node_list_st result = { 0 };
53+ struct name_constraints_node_list_st unsupp2 = { 0 };
54+ enum name_constraint_relation rel;
55+ unsigned type;
56+ int ret = GNUTLS_E_SUCCESS;
57+ size_t i, j, p1_unsupp = 0, p2_unsupp = 0;
58+ type_bitmask_t universal_exclude_needed = 0;
59+ type_bitmask_t types_in_p1 = 0, types_in_p2 = 0;
60 static const unsigned char universal_ip[32] = { 0 };
61
62- /* bitmask to see if we need to add universal excluded constraints
63- * (see phase 3 for details) */
64- type_bitmask_t types_with_empty_intersection = 0;
65-
66 if (permitted->size == 0 || permitted2->size == 0)
67- return 0;
68+ return GNUTLS_E_SUCCESS;
69
70- /* Phase 1
71- * For each name in PERMITTED, if a PERMITTED2 does not contain a name
72- * with the same type, move the original name to REMOVED.
73- * Do this also for node of unknown type (not DNS, email, IP) */
74- for (size_t i = 0; i < permitted->size;) {
75- struct name_constraints_node_st *t = permitted->data[i];
76- const struct name_constraints_node_st *found = NULL;
77-
78- for (size_t j = 0; j < permitted2->size; j++) {
79- const struct name_constraints_node_st *t2 =
80- permitted2->data[j];
81- if (t->type == t2->type) {
82- // check bounds (we will use 't->type' as index)
83- if (t->type > GNUTLS_SAN_MAX || t->type == 0) {
84- gnutls_assert();
85- ret = GNUTLS_E_INTERNAL_ERROR;
86- goto cleanup;
87- }
88- // note the possibility of empty intersection for this type
89- // if we add something to the intersection in phase 2,
90- // we will reset this flag back to 0 then
91- type_bitmask_set(types_with_empty_intersection,
92- t->type);
93- found = t2;
94- break;
95- }
96+ /* make sorted views of the arrays */
97+ ret = ensure_sorted(permitted);
98+ if (ret < 0) {
99+ gnutls_assert();
100+ goto cleanup;
101+ }
102+ ret = ensure_sorted(permitted2);
103+ if (ret < 0) {
104+ gnutls_assert();
105+ goto cleanup;
106+ }
107+
108+ /* deal with the leading unsupported types first: count, then union */
109+ while (p1_unsupp < permitted->size &&
110+ !is_supported_type(permitted->sorted_view[p1_unsupp]->type))
111+ p1_unsupp++;
112+ while (p2_unsupp < permitted2->size &&
113+ !is_supported_type(permitted2->sorted_view[p2_unsupp]->type))
114+ p2_unsupp++;
115+ if (p1_unsupp) { /* copy p1 unsupported type pointers into result */
116+ result.data = gnutls_calloc(
117+ p1_unsupp, sizeof(struct name_constraints_node_st *));
118+ if (!result.data) {
119+ ret = GNUTLS_E_MEMORY_ERROR;
120+ gnutls_assert();
121+ goto cleanup;
122 }
123+ memcpy(result.data, permitted->sorted_view,
124+ p1_unsupp * sizeof(struct name_constraints_node_st *));
125+ result.size = result.capacity = p1_unsupp;
126+ result.dirty = true;
127+ }
128+ if (p2_unsupp) { /* union will make deep copies from p2 */
129+ unsupp2.data = permitted2->sorted_view; /* so, just alias */
130+ unsupp2.size = unsupp2.capacity = p2_unsupp;
131+ unsupp2.dirty = false; /* we know it's sorted */
132+ unsupp2.sorted_view = permitted2->sorted_view;
133+ ret = name_constraints_node_list_union(nc, &result, &unsupp2);
134+ if (ret < 0) {
135+ gnutls_assert();
136+ goto cleanup;
137+ }
138+ }
139
140- if (found != NULL && is_supported_type(t->type)) {
141- /* move node from PERMITTED to REMOVED */
142- ret = name_constraints_node_list_add(&removed, t);
143- if (ret < 0) {
144- gnutls_assert();
145- goto cleanup;
146- }
147- /* remove node by swapping */
148- if (i < permitted->size - 1)
149- permitted->data[i] =
150- permitted->data[permitted->size - 1];
151- permitted->size--;
152- permitted->dirty = true;
153- continue;
154+ /* with that out of the way, pre-compute the supported types we have */
155+ for (i = p1_unsupp; i < permitted->size; i++) {
156+ type = permitted->sorted_view[i]->type;
157+ if (type < 1 || type > GNUTLS_SAN_MAX) {
158+ ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
159+ goto cleanup;
160+ }
161+ type_bitmask_set(types_in_p1, type);
162+ }
163+ for (j = p2_unsupp; j < permitted2->size; j++) {
164+ type = permitted2->sorted_view[j]->type;
165+ if (type < 1 || type > GNUTLS_SAN_MAX) {
166+ ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
167+ goto cleanup;
168 }
169- i++;
170+ type_bitmask_set(types_in_p2, type);
171 }
172+ /* universal excludes might be needed for types intersecting to empty */
173+ universal_exclude_needed = types_in_p1 & types_in_p2;
174+
175+ /* go through supported type NCs and intersect in a single pass */
176+ i = p1_unsupp;
177+ j = p2_unsupp;
178+ while (i < permitted->size || j < permitted2->size) {
179+ nc1 = (i < permitted->size) ? permitted->sorted_view[i] : NULL;
180+ nc2 = (j < permitted2->size) ? permitted2->sorted_view[j] :
181+ NULL;
182+ rel = compare_name_constraint_nodes(nc1, nc2);
183
184- /* Phase 2
185- * iterate through all combinations from PERMITTED2 and PERMITTED
186- * and create intersections of nodes with same type */
187- for (size_t i = 0; i < permitted2->size; i++) {
188- const struct name_constraints_node_st *t2 = permitted2->data[i];
189-
190- // current PERMITTED2 node has not yet been used for any intersection
191- // (and is not in REMOVED either)
192- used = 0;
193- for (size_t j = 0; j < removed.size; j++) {
194- const struct name_constraints_node_st *t =
195- removed.data[j];
196- // save intersection of name constraints into tmp
197- ret = name_constraints_intersect_nodes(nc, t, t2, &tmp);
198- if (ret < 0) {
199- gnutls_assert();
200- goto cleanup;
201- }
202- used = 1;
203- // if intersection is not empty
204- if (tmp !=
205- NULL) { // intersection for this type is not empty
206- // check bounds
207- if (tmp->type > GNUTLS_SAN_MAX ||
208- tmp->type == 0) {
209- gnutls_free(tmp);
210- return gnutls_assert_val(
211- GNUTLS_E_INTERNAL_ERROR);
212- }
213- // we will not add universal excluded constraint for this type
214- type_bitmask_clr(types_with_empty_intersection,
215- tmp->type);
216- // add intersection node to PERMITTED
217- ret = name_constraints_node_list_add(permitted,
218- tmp);
219- if (ret < 0) {
220- gnutls_assert();
221- goto cleanup;
222- }
223- }
224+ switch (rel) {
225+ case NC_SORTS_BEFORE:
226+ assert(nc1 != NULL); /* comparator-guaranteed */
227+ /* if nothing to intersect with, shallow-copy nc1 */
228+ if (!type_bitmask_in(types_in_p2, nc1->type))
229+ ret = name_constraints_node_list_add(&result,
230+ nc1);
231+ i++; /* otherwise skip nc1 */
232+ break;
233+ case NC_SORTS_AFTER:
234+ assert(nc2 != NULL); /* comparator-guaranteed */
235+ /* if nothing to intersect with, deep-copy nc2 */
236+ if (!type_bitmask_in(types_in_p1, nc2->type))
237+ ret = name_constraints_node_add_copy(
238+ nc, &result, nc2);
239+ j++; /* otherwise skip nc2 */
240+ break;
241+ case NC_INCLUDED_BY: /* add nc1, shallow-copy */
242+ assert(nc1 != NULL && nc2 != NULL); /* comparator */
243+ type_bitmask_clr(universal_exclude_needed, nc1->type);
244+ ret = name_constraints_node_list_add(&result, nc1);
245+ i++;
246+ break;
247+ case NC_INCLUDES: /* pick nc2, deep-copy */
248+ assert(nc1 != NULL && nc2 != NULL); /* comparator */
249+ type_bitmask_clr(universal_exclude_needed, nc2->type);
250+ ret = name_constraints_node_add_copy(nc, &result, nc2);
251+ j++;
252+ break;
253+ case NC_EQUAL: /* pick whichever: nc1, shallow-copy */
254+ assert(nc1 != NULL && nc2 != NULL); /* loop condition */
255+ type_bitmask_clr(universal_exclude_needed, nc1->type);
256+ ret = name_constraints_node_list_add(&result, nc1);
257+ i++;
258+ j++;
259+ break;
260 }
261- // if the node from PERMITTED2 was not used for intersection, copy it to DEST
262- // Beware: also copies nodes other than DNS, email, IP,
263- // since their counterpart may have been moved in phase 1.
264- if (!used) {
265- ret = name_constraints_node_add_copy(nc, permitted, t2);
266- if (ret < 0) {
267- gnutls_assert();
268- goto cleanup;
269- }
270+ if (ret < 0) {
271+ gnutls_assert();
272+ goto cleanup;
273 }
274 }
275
276- /* Phase 3
277- * For each type: If we have empty permitted name constraints now
278- * and we didn't have at the beginning, we have to add a new
279- * excluded constraint with universal wildcard
280- * (since the intersection of permitted is now empty). */
281+ /* finishing touch: add universal excluded constraints for types where
282+ * both lists had constraints, but all intersections ended up empty */
283 for (type = 1; type <= GNUTLS_SAN_MAX; type++) {
284- if (!type_bitmask_in(types_with_empty_intersection, type))
285+ if (!type_bitmask_in(universal_exclude_needed, type))
286 continue;
287 _gnutls_hard_log(
288 "Adding universal excluded name constraint for type %d.\n",
289@@ -871,14 +878,24 @@ static int name_constraints_node_list_intersect(
290 goto cleanup;
291 }
292 break;
293- default: // do nothing, at least one node was already moved in phase 1
294- break;
295+ default: /* unsupported type; should be unreacheable */
296+ ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
297+ goto cleanup;
298 }
299 }
300- ret = GNUTLS_E_SUCCESS;
301
302+ gnutls_free(permitted->data);
303+ gnutls_free(permitted->sorted_view);
304+ permitted->data = result.data;
305+ permitted->sorted_view = NULL;
306+ permitted->size = result.size;
307+ permitted->capacity = result.capacity;
308+ permitted->dirty = true;
309+
310+ result.data = NULL;
311+ ret = GNUTLS_E_SUCCESS;
312 cleanup:
313- gnutls_free(removed.data);
314+ name_constraints_node_list_clear(&result);
315 return ret;
316 }
317
318@@ -1254,100 +1271,6 @@ static unsigned email_matches(const gnutls_datum_t *name,
319 return rel == NC_EQUAL || rel == NC_INCLUDED_BY;
320 }
321
322-/*-
323- * name_constraints_intersect_nodes:
324- * @nc1: name constraints node 1
325- * @nc2: name constraints node 2
326- * @_intersection: newly allocated node with intersected constraints,
327- * NULL if the intersection is empty
328- *
329- * Inspect 2 name constraints nodes (of possibly different types) and allocate
330- * a new node with intersection of given constraints.
331- *
332- * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
333- -*/
334-static int name_constraints_intersect_nodes(
335- gnutls_x509_name_constraints_t nc,
336- const struct name_constraints_node_st *node1,
337- const struct name_constraints_node_st *node2,
338- struct name_constraints_node_st **_intersection)
339-{
340- // presume empty intersection
341- struct name_constraints_node_st *intersection = NULL;
342- const struct name_constraints_node_st *to_copy = NULL;
343- enum name_constraint_relation rel;
344-
345- *_intersection = NULL;
346-
347- if (node1->type != node2->type) {
348- return GNUTLS_E_SUCCESS;
349- }
350- switch (node1->type) {
351- case GNUTLS_SAN_DNSNAME:
352- rel = compare_dns_names(&node1->name, &node2->name);
353- switch (rel) {
354- case NC_EQUAL: // equal means doesn't matter which one
355- case NC_INCLUDES: // node2 is more specific
356- to_copy = node2;
357- break;
358- case NC_INCLUDED_BY: // node1 is more specific
359- to_copy = node1;
360- break;
361- case NC_SORTS_BEFORE: // no intersection
362- case NC_SORTS_AFTER: // no intersection
363- return GNUTLS_E_SUCCESS;
364- }
365- break;
366- case GNUTLS_SAN_RFC822NAME:
367- rel = compare_emails(&node1->name, &node2->name);
368- switch (rel) {
369- case NC_EQUAL: // equal means doesn't matter which one
370- case NC_INCLUDES: // node2 is more specific
371- to_copy = node2;
372- break;
373- case NC_INCLUDED_BY: // node1 is more specific
374- to_copy = node1;
375- break;
376- case NC_SORTS_BEFORE: // no intersection
377- case NC_SORTS_AFTER: // no intersection
378- return GNUTLS_E_SUCCESS;
379- }
380- break;
381- case GNUTLS_SAN_IPADDRESS:
382- rel = compare_ip_ncs(&node1->name, &node2->name);
383- switch (rel) {
384- case NC_EQUAL: // equal means doesn't matter which one
385- case NC_INCLUDES: // node2 is more specific
386- to_copy = node2;
387- break;
388- case NC_INCLUDED_BY: // node1 is more specific
389- to_copy = node1;
390- break;
391- case NC_SORTS_BEFORE: // no intersection
392- case NC_SORTS_AFTER: // no intersection
393- return GNUTLS_E_SUCCESS;
394- }
395- break;
396- default:
397- // for other types, we don't know how to do the intersection, assume empty
398- return GNUTLS_E_SUCCESS;
399- }
400-
401- // copy existing node if applicable
402- if (to_copy != NULL) {
403- *_intersection = name_constraints_node_new(nc, to_copy->type,
404- to_copy->name.data,
405- to_copy->name.size);
406- if (*_intersection == NULL)
407- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
408- intersection = *_intersection;
409-
410- assert(intersection->name.data != NULL);
411- }
412-
413- return GNUTLS_E_SUCCESS;
414-}
415-
416 /*
417 * Returns: true if the certification is acceptable, and false otherwise.
418 */
419--
4202.43.0
421
diff --git a/meta/recipes-support/gnutls/gnutls_3.8.4.bb b/meta/recipes-support/gnutls/gnutls_3.8.4.bb
index 026ae650f6..ccb6a2b4b2 100644
--- a/meta/recipes-support/gnutls/gnutls_3.8.4.bb
+++ b/meta/recipes-support/gnutls/gnutls_3.8.4.bb
@@ -34,6 +34,15 @@ SRC_URI = "https://www.gnupg.org/ftp/gcrypt/gnutls/v${SHRT_VER}/gnutls-${PV}.tar
34 file://CVE-2025-32990.patch \ 34 file://CVE-2025-32990.patch \
35 file://CVE-2025-6395.patch \ 35 file://CVE-2025-6395.patch \
36 file://CVE-2025-9820.patch \ 36 file://CVE-2025-9820.patch \
37 file://CVE-2025-14831-1.patch \
38 file://CVE-2025-14831-2.patch \
39 file://CVE-2025-14831-3.patch \
40 file://CVE-2025-14831-4.patch \
41 file://CVE-2025-14831-5.patch \
42 file://CVE-2025-14831-6.patch \
43 file://CVE-2025-14831-7.patch \
44 file://CVE-2025-14831-8.patch \
45 file://CVE-2025-14831-9.patch \
37 " 46 "
38 47
39SRC_URI[sha256sum] = "2bea4e154794f3f00180fa2a5c51fe8b005ac7a31cd58bd44cdfa7f36ebc3a9b" 48SRC_URI[sha256sum] = "2bea4e154794f3f00180fa2a5c51fe8b005ac7a31cd58bd44cdfa7f36ebc3a9b"