mirror of
https://git.yoctoproject.org/poky
synced 2026-03-12 02:09:39 +01:00
Compare commits
51 Commits
yocto-5.0.
...
scarthgap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d50718f90 | ||
|
|
92de6a134a | ||
|
|
06210079b2 | ||
|
|
b43070b570 | ||
|
|
9796c90d54 | ||
|
|
ee156de13e | ||
|
|
795acd093a | ||
|
|
bf30db97f7 | ||
|
|
ef014bdb96 | ||
|
|
ce6c389607 | ||
|
|
40ae5e31a4 | ||
|
|
74492c96b7 | ||
|
|
01a3d9d7ae | ||
|
|
d3ad12659a | ||
|
|
0e148ac345 | ||
|
|
e1fb45c7b3 | ||
|
|
fd826a83c7 | ||
|
|
ac842282aa | ||
|
|
6eea44a7fe | ||
|
|
113e92bd8b | ||
|
|
dbdc8de0ef | ||
|
|
fa64e0279b | ||
|
|
d95e14f86c | ||
|
|
119ec1b846 | ||
|
|
c4da6ca1c2 | ||
|
|
5e5234a7de | ||
|
|
e44ffb5b15 | ||
|
|
5f5a2976b2 | ||
|
|
c13443407a | ||
|
|
a231c49abc | ||
|
|
e333b43a69 | ||
|
|
242963f4cd | ||
|
|
dde29170e3 | ||
|
|
b16633f3c6 | ||
|
|
7ba05c3301 | ||
|
|
1997141268 | ||
|
|
2adde7bee1 | ||
|
|
3ad8559850 | ||
|
|
2c30acaf10 | ||
|
|
7754aa3731 | ||
|
|
40a0b2c80d | ||
|
|
77f60c1165 | ||
|
|
6c2a243d6c | ||
|
|
df890007b4 | ||
|
|
4ed95c6c7b | ||
|
|
4c8f687fe6 | ||
|
|
34deee3e52 | ||
|
|
49dc4dd983 | ||
|
|
0d954471b5 | ||
|
|
a57370d30c | ||
|
|
65c3ebea05 |
@@ -68,7 +68,7 @@ epub: $(PNGs)
|
||||
# Unable to read an entire line---bufsize=200000. Please increase buf_size in texmf.cnf.
|
||||
latexpdf: $(PDFs)
|
||||
$(SOURCEDIR)/set_versions.py
|
||||
buf_size=10000000 $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
buf_size=10000000 LATEXMKOPTS="-silent" $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
all: html epub latexpdf
|
||||
|
||||
|
||||
@@ -564,12 +564,12 @@ variable to specify the format:
|
||||
|
||||
PACKAGE_CLASSES ?= "package_packageformat"
|
||||
|
||||
where packageformat can be "ipk", "rpm",
|
||||
"deb", or "tar" which are the supported package formats.
|
||||
where packageformat can be "ipk", "rpm", or
|
||||
"deb" which are the supported package formats.
|
||||
|
||||
.. note::
|
||||
|
||||
Because the Yocto Project supports four different package formats,
|
||||
Because the Yocto Project supports three different package formats,
|
||||
you can set the variable with more than one argument. However, the
|
||||
OpenEmbedded build system only uses the first argument when
|
||||
creating an image or Software Development Kit (SDK).
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 214 KiB |
@@ -3429,9 +3429,9 @@ The variables used by this class are:
|
||||
rebuilding the FIT image containing the kernel.
|
||||
|
||||
See U-Boot's documentation for details about `verified boot
|
||||
<https://source.denx.de/u-boot/u-boot/-/blob/master/doc/uImage.FIT/verified-boot.txt>`__
|
||||
<https://docs.u-boot.org/en/latest/usage/fit/verified-boot.html>`__
|
||||
and the `signature process
|
||||
<https://source.denx.de/u-boot/u-boot/-/blob/master/doc/uImage.FIT/signature.txt>`__.
|
||||
<https://docs.u-boot.org/en/latest/usage/fit/signature.html>`__.
|
||||
|
||||
See also the description of :ref:`ref-classes-kernel-fitimage` class, which this class
|
||||
imitates.
|
||||
|
||||
@@ -71,10 +71,8 @@ supported on the following distributions:
|
||||
- Fedora 41
|
||||
- Rocky Linux 8
|
||||
- Rocky Linux 9
|
||||
- Ubuntu 20.04 (LTS)
|
||||
- Ubuntu 22.04 (LTS)
|
||||
- Ubuntu 24.04 (LTS)
|
||||
- Ubuntu 24.10
|
||||
|
||||
The following distribution versions are still tested, even though the
|
||||
organizations publishing them no longer make updates publicly available:
|
||||
@@ -86,7 +84,6 @@ organizations publishing them no longer make updates publicly available:
|
||||
|
||||
- Fedora 39
|
||||
- Fedora 40
|
||||
- Ubuntu 20.04 (LTS)
|
||||
|
||||
Note that the Yocto Project doesn't have access to private updates
|
||||
that some of these versions may have. Therefore, our testing has
|
||||
@@ -103,7 +100,9 @@ tested on former revisions of "&DISTRO_NAME;", but no longer are:
|
||||
- Fedora 38
|
||||
- OpenSUSE Leap 15.4
|
||||
- Ubuntu 18.04
|
||||
- Ubuntu 20.04
|
||||
- Ubuntu 23.04
|
||||
- Ubuntu 24.10
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ contact us with other suggestions.
|
||||
function of a particular part of the workflow gives you an idea of what might
|
||||
be going wrong.
|
||||
|
||||
.. image:: figures/yp-how-it-works-new-diagram.png
|
||||
.. image:: overview-manual/svg/yp-flow-diagram.*
|
||||
:width: 100%
|
||||
|
||||
#. **Know that you can generate a dependency graph and learn how to do it:**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
DISTRO = "poky"
|
||||
DISTRO_NAME = "Poky (Yocto Project Reference Distro)"
|
||||
DISTRO_VERSION = "5.0.15"
|
||||
DISTRO_VERSION = "5.0.16"
|
||||
DISTRO_CODENAME = "scarthgap"
|
||||
SDK_VENDOR = "-pokysdk"
|
||||
SDK_VERSION = "${@d.getVar('DISTRO_VERSION').replace('snapshot-${METADATA_REVISION}', 'snapshot')}"
|
||||
@@ -42,6 +42,7 @@ SANITY_TESTED_DISTROS ?= " \
|
||||
fedora-38 \n \
|
||||
fedora-39 \n \
|
||||
fedora-40 \n \
|
||||
fedora-41 \n \
|
||||
centosstream-8 \n \
|
||||
debian-11 \n \
|
||||
debian-12 \n \
|
||||
@@ -51,6 +52,7 @@ SANITY_TESTED_DISTROS ?= " \
|
||||
almalinux-8.10 \n \
|
||||
almalinux-9.2 \n \
|
||||
almalinux-9.4 \n \
|
||||
rocky-8 \n \
|
||||
rocky-9 \n \
|
||||
"
|
||||
# add poky sanity bbclass
|
||||
|
||||
@@ -841,7 +841,7 @@ result: $result
|
||||
metadata revisions:
|
||||
END
|
||||
cat ${BUILDHISTORY_DIR}/metadata-revs >> $commitmsgfile
|
||||
git commit $commitopts -F $commitmsgfile --author "${BUILDHISTORY_COMMIT_AUTHOR}" > /dev/null
|
||||
git commit --no-gpg-sign $commitopts -F $commitmsgfile --author "${BUILDHISTORY_COMMIT_AUTHOR}" > /dev/null
|
||||
rm $commitmsgfile
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ python do_go_vendor() {
|
||||
if os.path.exists(vendor_dir):
|
||||
# Nothing to do except re-establish link to actual vendor folder
|
||||
if not os.path.exists(linkname):
|
||||
os.symlink(vendor_dir, linkname)
|
||||
oe.path.relsymlink(vendor_dir, linkname)
|
||||
return
|
||||
|
||||
bb.utils.mkdirhier(vendor_dir)
|
||||
@@ -202,10 +202,10 @@ python do_go_vendor() {
|
||||
symlink_target = os.path.join(source_dir, *['src', go_import, replaced_path])
|
||||
symlink_name = os.path.join(vendor_dir, vendored_name)
|
||||
bb.debug(1, "vendored name %s, symlink name %s" % (vendored_name, symlink_name))
|
||||
os.symlink(symlink_target, symlink_name)
|
||||
oe.path.relsymlink(symlink_target, symlink_name)
|
||||
|
||||
# Create a symlink to the actual directory
|
||||
os.symlink(vendor_dir, linkname)
|
||||
oe.path.relsymlink(vendor_dir, linkname)
|
||||
}
|
||||
|
||||
addtask go_vendor before do_patch after do_unpack
|
||||
|
||||
@@ -811,12 +811,14 @@ def create_spdx(d):
|
||||
|
||||
if d.getVar("SPDX_INCLUDE_PACKAGECONFIG", True) != "0":
|
||||
packageconfig = (d.getVar("PACKAGECONFIG") or "").split()
|
||||
all_features = (d.getVarFlags("PACKAGECONFIG") or {}).keys()
|
||||
all_features = set((d.getVarFlags("PACKAGECONFIG") or {}).keys())
|
||||
blacklisted_features = {"doc"}
|
||||
|
||||
if all_features:
|
||||
enabled = set(packageconfig)
|
||||
all_features_set = set(all_features)
|
||||
disabled = all_features_set - enabled
|
||||
disabled = all_features - enabled
|
||||
all_features -= disabled & blacklisted_features
|
||||
disabled -= blacklisted_features
|
||||
|
||||
for feature in sorted(all_features):
|
||||
status = "enabled" if feature in enabled else "disabled"
|
||||
|
||||
@@ -12,6 +12,7 @@ import os
|
||||
import sys
|
||||
import unittest
|
||||
import hashlib
|
||||
import filecmp
|
||||
|
||||
from glob import glob
|
||||
from shutil import rmtree, copy
|
||||
@@ -1662,6 +1663,70 @@ class ModifyTests(WicTestCase):
|
||||
runCmd("wic cp %s:2/etc/fstab %s -n %s" % (images[0], testfile.name, sysroot))
|
||||
self.assertTrue(os.stat(testfile.name).st_size > 0, msg="Filesize not as expected %s" % os.stat(testfile.name).st_size)
|
||||
|
||||
# prepare directory structure
|
||||
testdir = os.path.join(self.resultdir, "wic-test-cp-ext-dir")
|
||||
testsubdir = os.path.join(testdir, "subdir")
|
||||
os.makedirs(testsubdir)
|
||||
|
||||
# add a file in the top-level of the directory
|
||||
src_file = os.path.join(testdir, "topfile.txt")
|
||||
with open(src_file, "w") as f:
|
||||
f.write("top-level\n")
|
||||
|
||||
# add file in the subdir
|
||||
src_subfile = os.path.join(testsubdir, "subfile.txt")
|
||||
with open(src_subfile, "w") as f:
|
||||
f.write("sub-level\n")
|
||||
|
||||
# copy directory to the partition root
|
||||
runCmd("wic cp %s %s:2/ -n %s" % (testdir, images[0], sysroot))
|
||||
basedir = os.path.basename(testdir)
|
||||
|
||||
# check if directory is there at partition root
|
||||
result = runCmd("wic ls %s:2/ -n %s" % (images[0], sysroot))
|
||||
root_entries = set(line.split()[-1] for line in result.output.split('\n') if line)
|
||||
self.assertIn(basedir, root_entries, msg="Expected directory not present at root: %s" % root_entries)
|
||||
|
||||
# list INSIDE the copied directory
|
||||
result = runCmd("wic ls %s:2/%s/ -n %s" % (images[0], basedir, sysroot))
|
||||
self.assertEqual(0, result.status,
|
||||
msg="wic ls inside copied directory failed. Output:\n%s" % result.output)
|
||||
self.assertNotIn("Ext2 inode is not a directory", result.output,
|
||||
msg="Regression detected (inode not a directory). Output:\n%s" % result.output)
|
||||
|
||||
inside_entries = set(line.split()[-1] for line in result.output.split('\n') if line)
|
||||
self.assertTrue(set(["subdir", "topfile.txt"]).issubset(inside_entries),
|
||||
msg="Expected entries missing inside dir: %s" % inside_entries)
|
||||
|
||||
# list inside the subdir
|
||||
result = runCmd("wic ls %s:2/%s/subdir/ -n %s" % (images[0], basedir, sysroot))
|
||||
self.assertEqual(0, result.status,
|
||||
msg="wic ls inside copied subdir failed. Output:\n%s" % result.output)
|
||||
self.assertNotIn("Ext2 inode is not a directory", result.output,
|
||||
msg="Regression detected (inode not a directory). Output:\n%s" % result.output)
|
||||
|
||||
sub_entries = set(line.split()[-1] for line in result.output.split('\n') if line)
|
||||
self.assertIn("subfile.txt", sub_entries, msg="Expected file missing in subdir: %s" % sub_entries)
|
||||
|
||||
# copy directory from the partition and compare with original
|
||||
outparent = os.path.join(self.resultdir, "wic-test-cp-ext-out")
|
||||
os.makedirs(outparent)
|
||||
runCmd("wic cp %s:2/%s %s -n %s" % (images[0], basedir, outparent, sysroot))
|
||||
|
||||
copied_dir = os.path.join(outparent, basedir)
|
||||
self.assertTrue(os.path.isdir(copied_dir), msg="Copied-back directory not created: %s" % copied_dir)
|
||||
|
||||
copied_file = os.path.join(copied_dir, "topfile.txt")
|
||||
copied_subfile = os.path.join(copied_dir, "subdir", "subfile.txt")
|
||||
|
||||
self.assertTrue(os.path.isfile(copied_file), msg="Missing copied-back file: %s" % copied_file)
|
||||
self.assertTrue(os.path.isfile(copied_subfile), msg="Missing copied-back subfile: %s" % copied_subfile)
|
||||
|
||||
self.assertTrue(filecmp.cmp(src_file, copied_file, shallow=False),
|
||||
msg="topfile.txt differs after round-trip copy")
|
||||
self.assertTrue(filecmp.cmp(src_subfile, copied_subfile, shallow=False),
|
||||
msg="subfile.txt differs after round-trip copy")
|
||||
|
||||
|
||||
def test_wic_rm_ext(self):
|
||||
"""Test removing files from the ext partition."""
|
||||
|
||||
@@ -14,17 +14,7 @@ PE = "1"
|
||||
# repo during parse
|
||||
SRCREV = "866ca972d6c3cabeaf6dbac431e8e08bb30b3c8e"
|
||||
|
||||
SRC_URI = "git://source.denx.de/u-boot/u-boot.git;protocol=https;branch=master \
|
||||
file://CVE-2024-57254.patch \
|
||||
file://CVE-2024-57255.patch \
|
||||
file://CVE-2024-57256.patch \
|
||||
file://CVE-2024-57257.patch \
|
||||
file://CVE-2024-57258-1.patch \
|
||||
file://CVE-2024-57258-2.patch \
|
||||
file://CVE-2024-57258-3.patch \
|
||||
file://CVE-2024-57259.patch \
|
||||
file://CVE-2024-42040.patch \
|
||||
"
|
||||
SRC_URI = "git://source.denx.de/u-boot/u-boot.git;protocol=https;branch=master"
|
||||
|
||||
S = "${WORKDIR}/git"
|
||||
B = "${WORKDIR}/build"
|
||||
|
||||
@@ -3,3 +3,13 @@ require u-boot.inc
|
||||
|
||||
DEPENDS += "bc-native dtc-native python3-pyelftools-native"
|
||||
|
||||
SRC_URI += "file://CVE-2024-57254.patch \
|
||||
file://CVE-2024-57255.patch \
|
||||
file://CVE-2024-57256.patch \
|
||||
file://CVE-2024-57257.patch \
|
||||
file://CVE-2024-57258-1.patch \
|
||||
file://CVE-2024-57258-2.patch \
|
||||
file://CVE-2024-57258-3.patch \
|
||||
file://CVE-2024-57259.patch \
|
||||
file://CVE-2024-42040.patch \
|
||||
"
|
||||
|
||||
@@ -37,6 +37,10 @@ SRC_URI = "${GITHUB_BASE_URI}/download/v${PV}/avahi-${PV}.tar.gz \
|
||||
file://CVE-2023-38473.patch \
|
||||
file://CVE-2024-52616.patch \
|
||||
file://CVE-2024-52615.patch \
|
||||
file://CVE-2025-68276.patch \
|
||||
file://CVE-2025-68468.patch \
|
||||
file://CVE-2025-68471.patch \
|
||||
file://CVE-2026-24401.patch \
|
||||
"
|
||||
|
||||
GITHUB_BASE_URI = "https://github.com/avahi/avahi/releases/"
|
||||
|
||||
65
meta/recipes-connectivity/avahi/files/CVE-2025-68276.patch
Normal file
65
meta/recipes-connectivity/avahi/files/CVE-2025-68276.patch
Normal file
@@ -0,0 +1,65 @@
|
||||
From 8ec85459d8e6e59cc14457e16fb7ba171901f90e Mon Sep 17 00:00:00 2001
|
||||
From: Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Date: Wed, 17 Dec 2025 08:11:23 +0000
|
||||
Subject: [PATCH] core: refuse to create wide-area record browsers when
|
||||
wide-area is off
|
||||
|
||||
It fixes a bug where it was possible for unprivileged local users to
|
||||
crash avahi-daemon (with wide-area disabled) by creating record browsers
|
||||
with the AVAHI_LOOKUP_USE_WIDE_AREA flag set via D-Bus (either by calling
|
||||
the RecordBrowserNew method directly or by creating hostname/address/service
|
||||
resolvers/browsers that create those browsers internally themselves).
|
||||
|
||||
```
|
||||
$ gdbus call --system --dest org.freedesktop.Avahi --object-path / --method org.freedesktop.Avahi.Server.ResolveHostName -- -1 -1 yo.local -1 1
|
||||
Error: GDBus.Error:org.freedesktop.DBus.Error.NoReply: Message recipient disconnected from message bus without replying
|
||||
```
|
||||
```
|
||||
dbus-protocol.c: interface=org.freedesktop.Avahi.Server, path=/, member=ResolveHostName
|
||||
avahi-daemon: wide-area.c:725: avahi_wide_area_scan_cache: Assertion `e' failed.
|
||||
==307948==
|
||||
==307948== Process terminating with default action of signal 6 (SIGABRT)
|
||||
==307948== at 0x4B3630C: __pthread_kill_implementation (pthread_kill.c:44)
|
||||
==307948== by 0x4ADF921: raise (raise.c:26)
|
||||
==307948== by 0x4AC74AB: abort (abort.c:77)
|
||||
==307948== by 0x4AC741F: __assert_fail_base.cold (assert.c:118)
|
||||
==307948== by 0x48D8B85: avahi_wide_area_scan_cache (wide-area.c:725)
|
||||
==307948== by 0x48C8953: lookup_scan_cache (browse.c:351)
|
||||
==307948== by 0x48C8B1B: lookup_go (browse.c:386)
|
||||
==307948== by 0x48C9148: defer_callback (browse.c:516)
|
||||
==307948== by 0x48AEA0E: expiration_event (timeeventq.c:94)
|
||||
==307948== by 0x489D3AE: timeout_callback (simple-watch.c:447)
|
||||
==307948== by 0x489D787: avahi_simple_poll_dispatch (simple-watch.c:563)
|
||||
==307948== by 0x489D91E: avahi_simple_poll_iterate (simple-watch.c:605)
|
||||
==307948==
|
||||
```
|
||||
|
||||
wide-area has been disabled by default since
|
||||
9c4214146738146e454f098264690e8e884c39bd (v0.9-rc2).
|
||||
|
||||
https://github.com/avahi/avahi/security/advisories/GHSA-mhf3-865v-g5rc
|
||||
|
||||
CVE: CVE-2025-68276
|
||||
Upstream-Status: Backport [https://github.com/avahi/avahi/commit/2d48e42d44a183f26a4d12d1f5d41abb9b7c6355]
|
||||
(cherry picked from commit 2d48e42d44a183f26a4d12d1f5d41abb9b7c6355)
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
avahi-core/browse.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/avahi-core/browse.c b/avahi-core/browse.c
|
||||
index e8a915e..59d53cb 100644
|
||||
--- a/avahi-core/browse.c
|
||||
+++ b/avahi-core/browse.c
|
||||
@@ -541,6 +541,11 @@ AvahiSRecordBrowser *avahi_s_record_browser_prepare(
|
||||
AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
|
||||
AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !(flags & AVAHI_LOOKUP_USE_WIDE_AREA) || !(flags & AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS);
|
||||
|
||||
+ if ((flags & AVAHI_LOOKUP_USE_WIDE_AREA) && !server->wide_area_lookup_engine) {
|
||||
+ avahi_server_set_errno(server, AVAHI_ERR_NOT_SUPPORTED);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
if (!(b = avahi_new(AvahiSRecordBrowser, 1))) {
|
||||
avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
|
||||
return NULL;
|
||||
32
meta/recipes-connectivity/avahi/files/CVE-2025-68468.patch
Normal file
32
meta/recipes-connectivity/avahi/files/CVE-2025-68468.patch
Normal file
@@ -0,0 +1,32 @@
|
||||
From 483f83828cfda965fac914ff1b39c63c256372b2 Mon Sep 17 00:00:00 2001
|
||||
From: Hugo Muis <198191869+friendlyhugo@users.noreply.github.com>
|
||||
Date: Sun, 2 Mar 2025 18:06:24 +0100
|
||||
Subject: [PATCH] core: fix DoS bug by removing incorrect assertion
|
||||
|
||||
Closes https://github.com/avahi/avahi/issues/683
|
||||
|
||||
CVE: CVE-2025-68468
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://github.com/avahi/avahi/commit/f66be13d7f31a3ef806d226bf8b67240179d309a]
|
||||
|
||||
Signed-off-by: Amaury Couderc <amaury.couderc@est.tech>
|
||||
---
|
||||
avahi-core/browse.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/avahi-core/browse.c b/avahi-core/browse.c
|
||||
index 86e4432..79595fe 100644
|
||||
--- a/avahi-core/browse.c
|
||||
+++ b/avahi-core/browse.c
|
||||
@@ -295,7 +295,6 @@ static void lookup_multicast_callback(
|
||||
lookup_drop_cname(l, interface, protocol, 0, r);
|
||||
else {
|
||||
/* It's a normal record, so let's call the user callback */
|
||||
- assert(avahi_key_equal(b->key, l->key));
|
||||
|
||||
b->callback(b, interface, protocol, event, r, flags, b->userdata);
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
36
meta/recipes-connectivity/avahi/files/CVE-2025-68471.patch
Normal file
36
meta/recipes-connectivity/avahi/files/CVE-2025-68471.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 4e84c1d6eb2f54d1643bd7ce62817c722ca36d25 Mon Sep 17 00:00:00 2001
|
||||
From: Hugo Muis <198191869+friendlyhugo@users.noreply.github.com>
|
||||
Date: Sun, 2 Mar 2025 18:06:24 +0100
|
||||
Subject: [PATCH] core: fix DoS bug by changing assert to return
|
||||
|
||||
Closes https://github.com/avahi/avahi/issues/678
|
||||
|
||||
CVE: CVE-2025-68471
|
||||
|
||||
Upstream-Status: Backport
|
||||
[https://github.com/avahi/avahi/commit/9c6eb53bf2e290aed84b1f207e3ce35c54cc0aa1]
|
||||
|
||||
Signed-off-by: Amaury Couderc <amaury.couderc@est.tech>
|
||||
---
|
||||
avahi-core/browse.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/avahi-core/browse.c b/avahi-core/browse.c
|
||||
index 2941e57..86e4432 100644
|
||||
--- a/avahi-core/browse.c
|
||||
+++ b/avahi-core/browse.c
|
||||
@@ -320,7 +320,10 @@ static int lookup_start(AvahiSRBLookup *l) {
|
||||
assert(l);
|
||||
|
||||
assert(!(l->flags & AVAHI_LOOKUP_USE_WIDE_AREA) != !(l->flags & AVAHI_LOOKUP_USE_MULTICAST));
|
||||
- assert(!l->wide_area && !l->multicast);
|
||||
+ if (l->wide_area || l->multicast) {
|
||||
+ /* Avoid starting a duplicate lookup */
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
if (l->flags & AVAHI_LOOKUP_USE_WIDE_AREA) {
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
74
meta/recipes-connectivity/avahi/files/CVE-2026-24401.patch
Normal file
74
meta/recipes-connectivity/avahi/files/CVE-2026-24401.patch
Normal file
@@ -0,0 +1,74 @@
|
||||
From 5eea2640324928c15936b7a2bcbf8ea0de7b08f7 Mon Sep 17 00:00:00 2001
|
||||
From: Hugo Muis <198191869+friendlyhugo@users.noreply.github.com>
|
||||
Date: Sun, 2 Mar 2025 18:06:24 +0100
|
||||
Subject: [PATCH] core: fix uncontrolled recursion bug using a simple loop
|
||||
detection algorithm
|
||||
|
||||
Closes https://github.com/avahi/avahi/issues/501
|
||||
|
||||
CVE: CVE-2026-24401
|
||||
Upstream-Status: Backport [https://github.com/avahi/avahi/commit/78eab31128479f06e30beb8c1cbf99dd921e2524]
|
||||
(cherry picked from commit 78eab31128479f06e30beb8c1cbf99dd921e2524)
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
avahi-core/browse.c | 40 ++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 40 insertions(+)
|
||||
|
||||
diff --git a/avahi-core/browse.c b/avahi-core/browse.c
|
||||
index f461083..975b3e9 100644
|
||||
--- a/avahi-core/browse.c
|
||||
+++ b/avahi-core/browse.c
|
||||
@@ -401,6 +401,40 @@ static int lookup_go(AvahiSRBLookup *l) {
|
||||
return n;
|
||||
}
|
||||
|
||||
+static int lookup_exists_in_path(AvahiSRBLookup* lookup, AvahiSRBLookup* from, AvahiSRBLookup* to) {
|
||||
+ AvahiRList* rl;
|
||||
+ if (from == to)
|
||||
+ return 0;
|
||||
+ for (rl = from->cname_lookups; rl; rl = rl->rlist_next) {
|
||||
+ int r = lookup_exists_in_path(lookup, rl->data, to);
|
||||
+ if (r == 1) {
|
||||
+ /* loop detected, propagate result */
|
||||
+ return r;
|
||||
+ } else if (r == 0) {
|
||||
+ /* is loop detected? */
|
||||
+ return lookup == from;
|
||||
+ } else {
|
||||
+ /* `to` not found, continue */
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ /* no path found */
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+static int cname_would_create_loop(AvahiSRBLookup* l, AvahiSRBLookup* n) {
|
||||
+ int ret;
|
||||
+ if (l == n)
|
||||
+ /* Loop to self */
|
||||
+ return 1;
|
||||
+
|
||||
+ ret = lookup_exists_in_path(n, l->record_browser->root_lookup, l);
|
||||
+
|
||||
+ /* Path to n always exists */
|
||||
+ assert(ret != -1);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void lookup_handle_cname(AvahiSRBLookup *l, AvahiIfIndex interface, AvahiProtocol protocol, AvahiLookupFlags flags, AvahiRecord *r) {
|
||||
AvahiKey *k;
|
||||
AvahiSRBLookup *n;
|
||||
@@ -420,6 +454,12 @@ static void lookup_handle_cname(AvahiSRBLookup *l, AvahiIfIndex interface, Avahi
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (cname_would_create_loop(l, n)) {
|
||||
+ /* CNAME loops are not allowed */
|
||||
+ lookup_unref(n);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
l->cname_lookups = avahi_rlist_prepend(l->cname_lookups, lookup_ref(n));
|
||||
|
||||
lookup_go(n);
|
||||
@@ -20,7 +20,7 @@ SRC_URI = "https://ftp.isc.org/isc/bind9/${PV}/${BPN}-${PV}.tar.xz \
|
||||
file://0001-avoid-start-failure-with-bind-user.patch \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "6ddc1d981511c4da0b203b0513af131e5d15e5f1c261145736fe1f35dd1fe79d"
|
||||
SRC_URI[sha256sum] = "81f5035a25c576af1a93f0061cf70bde6d00a0c7bd1274abf73f5b5389a6f82d"
|
||||
|
||||
UPSTREAM_CHECK_URI = "https://ftp.isc.org/isc/bind9/"
|
||||
# follow the ESV versions divisible by 2
|
||||
@@ -5,8 +5,8 @@ SECTION = "network"
|
||||
LICENSE = "PD"
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=87964579b2a8ece4bc6744d2dc9a8b04"
|
||||
|
||||
SRCREV = "55ba955d53305df96123534488fd160ea882b4dd"
|
||||
PV = "20240407"
|
||||
SRCREV = "18cb97517d9c831e1d2ec057e62d04fd3665e10f"
|
||||
PV = "20251101"
|
||||
PE = "1"
|
||||
|
||||
SRC_URI = "git://gitlab.gnome.org/GNOME/mobile-broadband-provider-info.git;protocol=https;branch=main"
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
From 1f08e54bad32843044fe8a675948d65e3b4ece65 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Kubec <kubec@openssl.org>
|
||||
Date: Fri, 9 Jan 2026 14:33:24 +0100
|
||||
Subject: [PATCH] ossl_quic_get_cipher_by_char(): Add a NULL guard before
|
||||
dereferencing SSL_CIPHER
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Fixes CVE-2025-15468
|
||||
|
||||
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
|
||||
Reviewed-by: Tomas Mraz <tomas@openssl.org>
|
||||
MergeDate: Mon Jan 26 19:36:04 2026
|
||||
(cherry picked from commit 293b55de0c434a99d0e744d0521170ca280606a9)
|
||||
|
||||
CVE: CVE-2025-15468
|
||||
Upstream-Status: Backport [https://github.com/openssl/openssl/commit/1f08e54bad32843044fe8a675948d65e3b4ece65]
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
ssl/quic/quic_impl.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c
|
||||
index 98b6a0a..4abde64 100644
|
||||
--- a/ssl/quic/quic_impl.c
|
||||
+++ b/ssl/quic/quic_impl.c
|
||||
@@ -3646,6 +3646,8 @@ const SSL_CIPHER *ossl_quic_get_cipher_by_char(const unsigned char *p)
|
||||
{
|
||||
const SSL_CIPHER *ciph = ssl3_get_cipher_by_char(p);
|
||||
|
||||
+ if (ciph == NULL)
|
||||
+ return NULL;
|
||||
if ((ciph->algorithm2 & SSL_QUIC) == 0)
|
||||
return NULL;
|
||||
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
From 41be0f216404f14457bbf3b9cc488dba60b49296 Mon Sep 17 00:00:00 2001
|
||||
From: Norbert Pocs <norbertp@openssl.org>
|
||||
Date: Thu, 11 Dec 2025 12:49:00 +0100
|
||||
Subject: [PATCH] Check return code of UTF8_putc
|
||||
|
||||
Signed-off-by: Norbert Pocs <norbertp@openssl.org>
|
||||
|
||||
Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
|
||||
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
|
||||
(Merged from https://github.com/openssl/openssl/pull/29376)
|
||||
|
||||
CVE: CVE-2025-69419
|
||||
Upstream-Status: Backport [https://github.com/openssl/openssl/commit/41be0f216404f14457bbf3b9cc488dba60b49296]
|
||||
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
|
||||
---
|
||||
crypto/asn1/a_strex.c | 6 ++++--
|
||||
crypto/pkcs12/p12_utl.c | 11 +++++++++--
|
||||
2 files changed, 13 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/crypto/asn1/a_strex.c b/crypto/asn1/a_strex.c
|
||||
index f64e352..7d76700 100644
|
||||
--- a/crypto/asn1/a_strex.c
|
||||
+++ b/crypto/asn1/a_strex.c
|
||||
@@ -204,8 +204,10 @@ static int do_buf(unsigned char *buf, int buflen,
|
||||
orflags = CHARTYPE_LAST_ESC_2253;
|
||||
if (type & BUF_TYPE_CONVUTF8) {
|
||||
unsigned char utfbuf[6];
|
||||
- int utflen;
|
||||
- utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
|
||||
+ int utflen = UTF8_putc(utfbuf, sizeof(utfbuf), c);
|
||||
+
|
||||
+ if (utflen < 0)
|
||||
+ return -1; /* error happened with UTF8 */
|
||||
for (i = 0; i < utflen; i++) {
|
||||
/*
|
||||
* We don't need to worry about setting orflags correctly
|
||||
diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c
|
||||
index a96623f..b109dab 100644
|
||||
--- a/crypto/pkcs12/p12_utl.c
|
||||
+++ b/crypto/pkcs12/p12_utl.c
|
||||
@@ -206,8 +206,15 @@ char *OPENSSL_uni2utf8(const unsigned char *uni, int unilen)
|
||||
/* re-run the loop emitting UTF-8 string */
|
||||
for (asclen = 0, i = 0; i < unilen; ) {
|
||||
j = bmp_to_utf8(asctmp+asclen, uni+i, unilen-i);
|
||||
- if (j == 4) i += 4;
|
||||
- else i += 2;
|
||||
+ /* when UTF8_putc fails */
|
||||
+ if (j < 0) {
|
||||
+ OPENSSL_free(asctmp);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (j == 4)
|
||||
+ i += 4;
|
||||
+ else
|
||||
+ i += 2;
|
||||
asclen += j;
|
||||
}
|
||||
|
||||
--
|
||||
2.50.1
|
||||
|
||||
@@ -13,6 +13,8 @@ SRC_URI = "https://github.com/openssl/openssl/releases/download/openssl-${PV}/op
|
||||
file://0001-Configure-do-not-tweak-mips-cflags.patch \
|
||||
file://0001-Added-handshake-history-reporting-when-test-fails.patch \
|
||||
file://CVE-2024-41996.patch \
|
||||
file://CVE-2025-15468.patch \
|
||||
file://CVE-2025-69419.patch \
|
||||
"
|
||||
|
||||
SRC_URI:append:class-nativesdk = " \
|
||||
|
||||
48
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1484-01.patch
Normal file
48
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1484-01.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
From 5ba0ed9ab2c28294713bdc56a8744ff0a446b59c Mon Sep 17 00:00:00 2001
|
||||
From: Marco Trevisan <mail@3v1n0.net>
|
||||
Date: Fri, 23 Jan 2026 18:48:30 +0100
|
||||
Subject: [PATCH] gbase64: Use gsize to prevent potential overflow
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Both g_base64_encode_step() and g_base64_encode_close() return gsize
|
||||
values, but these are summed to an int value.
|
||||
|
||||
If the sum of these returned values is bigger than MAXINT, we overflow
|
||||
while doing the null byte write.
|
||||
|
||||
Spotted by treeplus.
|
||||
Thanks to the Sovereign Tech Resilience programme from the Sovereign
|
||||
Tech Agency.
|
||||
|
||||
ID: #YWH-PGM9867-168
|
||||
Closes: #3870
|
||||
|
||||
|
||||
(cherry picked from commit 6845f7776982849a2be1d8c9b0495e389092bff2)
|
||||
|
||||
Co-authored-by: Marco Trevisan (Treviño) <mail@3v1n0.net>
|
||||
|
||||
CVE: CVE-2026-1484
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/5ba0ed9ab2c28294713bdc56a8744ff0a446b59c]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
glib/gbase64.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/gbase64.c b/glib/gbase64.c
|
||||
index 2ea4a4ef4..214b48911 100644
|
||||
--- a/glib/gbase64.c
|
||||
+++ b/glib/gbase64.c
|
||||
@@ -264,8 +264,9 @@ g_base64_encode (const guchar *data,
|
||||
gsize len)
|
||||
{
|
||||
gchar *out;
|
||||
- gint state = 0, outlen;
|
||||
+ gint state = 0;
|
||||
gint save = 0;
|
||||
+ gsize outlen;
|
||||
|
||||
g_return_val_if_fail (data != NULL || len == 0, NULL);
|
||||
|
||||
45
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1484-02.patch
Normal file
45
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1484-02.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
From 25429bd0b22222d6986d000d62b44eebf490837d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
||||
Date: Wed, 21 Jan 2026 20:09:44 +0100
|
||||
Subject: [PATCH] gbase64: Ensure that the out value is within allocated size
|
||||
|
||||
We do not want to deference or write to it
|
||||
|
||||
Related to: #3870
|
||||
|
||||
CVE: CVE-2026-1484
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/25429bd0b22222d6986d000d62b44eebf490837d]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
glib/gbase64.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/gbase64.c b/glib/gbase64.c
|
||||
index 214b48911..0141b3b07 100644
|
||||
--- a/glib/gbase64.c
|
||||
+++ b/glib/gbase64.c
|
||||
@@ -267,6 +267,7 @@ g_base64_encode (const guchar *data,
|
||||
gint state = 0;
|
||||
gint save = 0;
|
||||
gsize outlen;
|
||||
+ gsize allocsize;
|
||||
|
||||
g_return_val_if_fail (data != NULL || len == 0, NULL);
|
||||
|
||||
@@ -274,10 +275,15 @@ g_base64_encode (const guchar *data,
|
||||
+1 is needed for trailing \0, also check for unlikely integer overflow */
|
||||
g_return_val_if_fail (len < ((G_MAXSIZE - 1) / 4 - 1) * 3, NULL);
|
||||
|
||||
- out = g_malloc ((len / 3 + 1) * 4 + 1);
|
||||
+ allocsize = (len / 3 + 1) * 4 + 1;
|
||||
+ out = g_malloc (allocsize);
|
||||
|
||||
outlen = g_base64_encode_step (data, len, FALSE, out, &state, &save);
|
||||
+ g_assert (outlen <= allocsize);
|
||||
+
|
||||
outlen += g_base64_encode_close (FALSE, out + outlen, &state, &save);
|
||||
+ g_assert (outlen <= allocsize);
|
||||
+
|
||||
out[outlen] = '\0';
|
||||
|
||||
return (gchar *) out;
|
||||
44
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1485.patch
Normal file
44
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1485.patch
Normal file
@@ -0,0 +1,44 @@
|
||||
From ee5acb2cefc643450509374da2600cd3bf49a109 Mon Sep 17 00:00:00 2001
|
||||
From: Marco Trevisan <mail@3v1n0.net>
|
||||
Date: Fri, 23 Jan 2026 19:05:44 +0100
|
||||
Subject: [PATCH] gio/gcontenttype-fdo: Do not overflow if header is longer
|
||||
than MAXINT
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In case the header size is longer than MAXINT we may read and write to
|
||||
invalid locations
|
||||
|
||||
Spotted by treeplus.
|
||||
Thanks to the Sovereign Tech Resilience programme from the Sovereign
|
||||
Tech Agency.
|
||||
|
||||
ID: #YWH-PGM9867-169
|
||||
Closes: #3871
|
||||
|
||||
|
||||
(cherry picked from commit aacda5b07141b944408c79e83bcbed3b2e1e6e45)
|
||||
|
||||
Co-authored-by: Marco Trevisan (Treviño) <mail@3v1n0.net>
|
||||
|
||||
CVE: CVE-2026-1485
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/ee5acb2cefc643450509374da2600cd3bf49a109]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
gio/gcontenttype.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/gio/gcontenttype.c b/gio/gcontenttype.c
|
||||
index 230cea182..11323973a 100644
|
||||
--- a/gio/gcontenttype.c
|
||||
+++ b/gio/gcontenttype.c
|
||||
@@ -1021,7 +1021,7 @@ tree_match_free (TreeMatch *match)
|
||||
static TreeMatch *
|
||||
parse_header (gchar *line)
|
||||
{
|
||||
- gint len;
|
||||
+ size_t len;
|
||||
gchar *s;
|
||||
TreeMatch *match;
|
||||
|
||||
42
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-01.patch
Normal file
42
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-01.patch
Normal file
@@ -0,0 +1,42 @@
|
||||
From 662aa569efa65eaa4672ab0671eb8533a354cd89 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
||||
Date: Wed, 21 Jan 2026 22:00:17 +0100
|
||||
Subject: [PATCH] guniprop: Use size_t for output_marks length
|
||||
|
||||
The input string length may overflow, and this would lead to wrong
|
||||
behavior and invalid writes.
|
||||
|
||||
Spotted by treeplus.
|
||||
Thanks to the Sovereign Tech Resilience programme from the Sovereign
|
||||
Tech Agency.
|
||||
|
||||
ID: #YWH-PGM9867-171
|
||||
Closes: #3872
|
||||
|
||||
CVE: CVE-2026-1489
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/662aa569efa65eaa4672ab0671eb8533a354cd89]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
glib/guniprop.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/glib/guniprop.c b/glib/guniprop.c
|
||||
index fe0033fd6..1a0cc6408 100644
|
||||
--- a/glib/guniprop.c
|
||||
+++ b/glib/guniprop.c
|
||||
@@ -772,13 +772,13 @@ get_locale_type (void)
|
||||
return LOCALE_NORMAL;
|
||||
}
|
||||
|
||||
-static gint
|
||||
+static size_t
|
||||
output_marks (const char **p_inout,
|
||||
char *out_buffer,
|
||||
gboolean remove_dot)
|
||||
{
|
||||
const char *p = *p_inout;
|
||||
- gint len = 0;
|
||||
+ size_t len = 0;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
30
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-02.patch
Normal file
30
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-02.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
From 58356619525a1d565df8cc348e9784716f020f2f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
||||
Date: Wed, 21 Jan 2026 22:01:49 +0100
|
||||
Subject: [PATCH] guniprop: Do not convert size_t to gint
|
||||
|
||||
We were correctly using size_t in output_special_case() since commit
|
||||
362f92b69, but then we converted the value back to int
|
||||
|
||||
Related to: #3872
|
||||
|
||||
CVE: CVE-2026-1489
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/58356619525a1d565df8cc348e9784716f020f2f]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
glib/guniprop.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/glib/guniprop.c b/glib/guniprop.c
|
||||
index 1a0cc6408..fe50a287c 100644
|
||||
--- a/glib/guniprop.c
|
||||
+++ b/glib/guniprop.c
|
||||
@@ -798,7 +798,7 @@ output_marks (const char **p_inout,
|
||||
return len;
|
||||
}
|
||||
|
||||
-static gint
|
||||
+static size_t
|
||||
output_special_case (gchar *out_buffer,
|
||||
int offset,
|
||||
int type,
|
||||
290
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-03.patch
Normal file
290
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-03.patch
Normal file
@@ -0,0 +1,290 @@
|
||||
From 170dc8c4068db4c4cbf63c7d27192e230436da21 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
||||
Date: Wed, 21 Jan 2026 22:04:22 +0100
|
||||
Subject: [PATCH] guniprop: Ensure we do not overflow size in
|
||||
g_utf8_{strdown,gstrup}()
|
||||
|
||||
While this is technically not a security issue, when repeatedly adding
|
||||
to a size_t value, we can overflow and start from 0.
|
||||
|
||||
Now, while being unlikely, technically an utf8 lower or upper string can
|
||||
have a longer size than the input value, and if the output string is
|
||||
bigger than G_MAXSIZE we'd end up cutting it silently.
|
||||
|
||||
Let's instead assert each time we increase the output length
|
||||
|
||||
CVE: CVE-2026-1489
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/170dc8c4068db4c4cbf63c7d27192e230436da21]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
glib/guniprop.c | 109 +++++++++++++++++++++++++++++++-----------------
|
||||
1 file changed, 70 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/glib/guniprop.c b/glib/guniprop.c
|
||||
index fe50a287c..86020b6e0 100644
|
||||
--- a/glib/guniprop.c
|
||||
+++ b/glib/guniprop.c
|
||||
@@ -772,14 +772,36 @@ get_locale_type (void)
|
||||
return LOCALE_NORMAL;
|
||||
}
|
||||
|
||||
-static size_t
|
||||
-output_marks (const char **p_inout,
|
||||
- char *out_buffer,
|
||||
- gboolean remove_dot)
|
||||
+G_ALWAYS_INLINE static inline void
|
||||
+increase_size (size_t *sizeptr, size_t add)
|
||||
+{
|
||||
+ g_assert (G_MAXSIZE - *(sizeptr) >= add);
|
||||
+ *(sizeptr) += add;
|
||||
+}
|
||||
+
|
||||
+G_ALWAYS_INLINE static inline void
|
||||
+append_utf8_char_to_buffer (gunichar c,
|
||||
+ char *out_buffer,
|
||||
+ size_t *in_out_len)
|
||||
+{
|
||||
+ gint utf8_len;
|
||||
+ char *buffer;
|
||||
+
|
||||
+ buffer = out_buffer ? out_buffer + *(in_out_len) : NULL;
|
||||
+ utf8_len = g_unichar_to_utf8 (c, buffer);
|
||||
+
|
||||
+ g_assert (utf8_len >= 0);
|
||||
+ increase_size (in_out_len, utf8_len);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+append_mark (const char **p_inout,
|
||||
+ char *out_buffer,
|
||||
+ size_t *in_out_len,
|
||||
+ gboolean remove_dot)
|
||||
{
|
||||
const char *p = *p_inout;
|
||||
- size_t len = 0;
|
||||
-
|
||||
+
|
||||
while (*p)
|
||||
{
|
||||
gunichar c = g_utf8_get_char (p);
|
||||
@@ -787,7 +809,7 @@ output_marks (const char **p_inout,
|
||||
if (ISMARK (TYPE (c)))
|
||||
{
|
||||
if (!remove_dot || c != 0x307 /* COMBINING DOT ABOVE */)
|
||||
- len += g_unichar_to_utf8 (c, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (c, out_buffer, in_out_len);
|
||||
p = g_utf8_next_char (p);
|
||||
}
|
||||
else
|
||||
@@ -795,14 +817,14 @@ output_marks (const char **p_inout,
|
||||
}
|
||||
|
||||
*p_inout = p;
|
||||
- return len;
|
||||
}
|
||||
|
||||
-static size_t
|
||||
-output_special_case (gchar *out_buffer,
|
||||
- int offset,
|
||||
- int type,
|
||||
- int which)
|
||||
+static void
|
||||
+append_special_case (char *out_buffer,
|
||||
+ size_t *in_out_len,
|
||||
+ int offset,
|
||||
+ int type,
|
||||
+ int which)
|
||||
{
|
||||
const gchar *p = special_case_table + offset;
|
||||
gint len;
|
||||
@@ -814,10 +836,12 @@ output_special_case (gchar *out_buffer,
|
||||
p += strlen (p) + 1;
|
||||
|
||||
len = strlen (p);
|
||||
- if (out_buffer)
|
||||
- memcpy (out_buffer, p, len);
|
||||
+ g_assert (len < G_MAXSIZE - *in_out_len);
|
||||
|
||||
- return len;
|
||||
+ if (out_buffer)
|
||||
+ memcpy (out_buffer + *in_out_len, p, len);
|
||||
+
|
||||
+ increase_size (in_out_len, len);
|
||||
}
|
||||
|
||||
static gsize
|
||||
@@ -858,11 +882,13 @@ real_toupper (const gchar *str,
|
||||
decomp_len = g_unichar_fully_decompose (c, FALSE, decomp, G_N_ELEMENTS (decomp));
|
||||
for (i=0; i < decomp_len; i++)
|
||||
{
|
||||
+
|
||||
if (decomp[i] != 0x307 /* COMBINING DOT ABOVE */)
|
||||
- len += g_unichar_to_utf8 (g_unichar_toupper (decomp[i]), out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (g_unichar_toupper (decomp[i]),
|
||||
+ out_buffer, &len);
|
||||
}
|
||||
-
|
||||
- len += output_marks (&p, out_buffer ? out_buffer + len : NULL, TRUE);
|
||||
+
|
||||
+ append_mark (&p, out_buffer, &len, TRUE);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -875,17 +901,17 @@ real_toupper (const gchar *str,
|
||||
if (locale_type == LOCALE_TURKIC && c == 'i')
|
||||
{
|
||||
/* i => LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
- len += g_unichar_to_utf8 (0x130, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (0x130, out_buffer, &len);
|
||||
}
|
||||
else if (c == 0x0345) /* COMBINING GREEK YPOGEGRAMMENI */
|
||||
{
|
||||
/* Nasty, need to move it after other combining marks .. this would go away if
|
||||
* we normalized first.
|
||||
*/
|
||||
- len += output_marks (&p, out_buffer ? out_buffer + len : NULL, FALSE);
|
||||
+ append_mark (&p, out_buffer, &len, TRUE);
|
||||
|
||||
/* And output as GREEK CAPITAL LETTER IOTA */
|
||||
- len += g_unichar_to_utf8 (0x399, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (0x399, out_buffer, &len);
|
||||
}
|
||||
else if (IS (t,
|
||||
OR (G_UNICODE_LOWERCASE_LETTER,
|
||||
@@ -896,8 +922,8 @@ real_toupper (const gchar *str,
|
||||
|
||||
if (val >= 0x1000000)
|
||||
{
|
||||
- len += output_special_case (out_buffer ? out_buffer + len : NULL, val - 0x1000000, t,
|
||||
- t == G_UNICODE_LOWERCASE_LETTER ? 0 : 1);
|
||||
+ append_special_case (out_buffer, &len, val - 0x1000000, t,
|
||||
+ t == G_UNICODE_LOWERCASE_LETTER ? 0 : 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -917,7 +943,7 @@ real_toupper (const gchar *str,
|
||||
/* Some lowercase letters, e.g., U+000AA, FEMININE ORDINAL INDICATOR,
|
||||
* do not have an uppercase equivalent, in which case val will be
|
||||
* zero. */
|
||||
- len += g_unichar_to_utf8 (val ? val : c, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (val ? val : c, out_buffer, &len);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -927,7 +953,7 @@ real_toupper (const gchar *str,
|
||||
if (out_buffer)
|
||||
memcpy (out_buffer + len, last, char_len);
|
||||
|
||||
- len += char_len;
|
||||
+ increase_size (&len, char_len);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -965,6 +991,8 @@ g_utf8_strup (const gchar *str,
|
||||
* We use a two pass approach to keep memory management simple
|
||||
*/
|
||||
result_len = real_toupper (str, len, NULL, locale_type);
|
||||
+ g_assert (result_len < G_MAXSIZE);
|
||||
+
|
||||
result = g_malloc (result_len + 1);
|
||||
real_toupper (str, len, result, locale_type);
|
||||
result[result_len] = '\0';
|
||||
@@ -1022,14 +1050,15 @@ real_tolower (const gchar *str,
|
||||
{
|
||||
/* I + COMBINING DOT ABOVE => i (U+0069)
|
||||
* LATIN CAPITAL LETTER I WITH DOT ABOVE => i (U+0069) */
|
||||
- len += g_unichar_to_utf8 (0x0069, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (0x0069, out_buffer, &len);
|
||||
+
|
||||
if (combining_dot)
|
||||
p = g_utf8_next_char (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* I => LATIN SMALL LETTER DOTLESS I */
|
||||
- len += g_unichar_to_utf8 (0x131, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (0x131, out_buffer, &len);
|
||||
}
|
||||
}
|
||||
/* Introduce an explicit dot above when lowercasing capital I's and J's
|
||||
@@ -1037,19 +1066,19 @@ real_tolower (const gchar *str,
|
||||
else if (locale_type == LOCALE_LITHUANIAN &&
|
||||
(c == 0x00cc || c == 0x00cd || c == 0x0128))
|
||||
{
|
||||
- len += g_unichar_to_utf8 (0x0069, out_buffer ? out_buffer + len : NULL);
|
||||
- len += g_unichar_to_utf8 (0x0307, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (0x0069, out_buffer, &len);
|
||||
+ append_utf8_char_to_buffer (0x0307, out_buffer, &len);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0x00cc:
|
||||
- len += g_unichar_to_utf8 (0x0300, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (0x0300, out_buffer, &len);
|
||||
break;
|
||||
case 0x00cd:
|
||||
- len += g_unichar_to_utf8 (0x0301, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (0x0301, out_buffer, &len);
|
||||
break;
|
||||
case 0x0128:
|
||||
- len += g_unichar_to_utf8 (0x0303, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (0x0303, out_buffer, &len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1058,8 +1087,8 @@ real_tolower (const gchar *str,
|
||||
c == 'J' || c == G_UNICHAR_FULLWIDTH_J || c == 0x012e) &&
|
||||
has_more_above (p))
|
||||
{
|
||||
- len += g_unichar_to_utf8 (g_unichar_tolower (c), out_buffer ? out_buffer + len : NULL);
|
||||
- len += g_unichar_to_utf8 (0x0307, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (g_unichar_tolower (c), out_buffer, &len);
|
||||
+ append_utf8_char_to_buffer (0x0307, out_buffer, &len);
|
||||
}
|
||||
else if (c == 0x03A3) /* GREEK CAPITAL LETTER SIGMA */
|
||||
{
|
||||
@@ -1082,7 +1111,7 @@ real_tolower (const gchar *str,
|
||||
else
|
||||
val = 0x3c2; /* GREEK SMALL FINAL SIGMA */
|
||||
|
||||
- len += g_unichar_to_utf8 (val, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (val, out_buffer, &len);
|
||||
}
|
||||
else if (IS (t,
|
||||
OR (G_UNICODE_UPPERCASE_LETTER,
|
||||
@@ -1093,7 +1122,7 @@ real_tolower (const gchar *str,
|
||||
|
||||
if (val >= 0x1000000)
|
||||
{
|
||||
- len += output_special_case (out_buffer ? out_buffer + len : NULL, val - 0x1000000, t, 0);
|
||||
+ append_special_case (out_buffer, &len, val - 0x1000000, t, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1112,7 +1141,7 @@ real_tolower (const gchar *str,
|
||||
|
||||
/* Not all uppercase letters are guaranteed to have a lowercase
|
||||
* equivalent. If this is the case, val will be zero. */
|
||||
- len += g_unichar_to_utf8 (val ? val : c, out_buffer ? out_buffer + len : NULL);
|
||||
+ append_utf8_char_to_buffer (val ? val : c, out_buffer, &len);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1122,7 +1151,7 @@ real_tolower (const gchar *str,
|
||||
if (out_buffer)
|
||||
memcpy (out_buffer + len, last, char_len);
|
||||
|
||||
- len += char_len;
|
||||
+ increase_size (&len, char_len);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1159,6 +1188,8 @@ g_utf8_strdown (const gchar *str,
|
||||
* We use a two pass approach to keep memory management simple
|
||||
*/
|
||||
result_len = real_tolower (str, len, NULL, locale_type);
|
||||
+ g_assert (result_len < G_MAXSIZE);
|
||||
+
|
||||
result = g_malloc (result_len + 1);
|
||||
real_tolower (str, len, result, locale_type);
|
||||
result[result_len] = '\0';
|
||||
68
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-04.patch
Normal file
68
meta/recipes-core/glib-2.0/glib-2.0/CVE-2026-1489-04.patch
Normal file
@@ -0,0 +1,68 @@
|
||||
From b96966058f4291db8970ced70ee22103e63679e5 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
|
||||
Date: Fri, 23 Jan 2026 17:39:34 +0100
|
||||
Subject: [PATCH] glib/tests/unicode: Add test debug information when parsing
|
||||
input files
|
||||
|
||||
On case of failures makes it easier to understand on what line of the
|
||||
source file we're at, as it might not be clear for non-ascii chars
|
||||
|
||||
CVE: CVE-2026-1489
|
||||
Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/b96966058f4291db8970ced70ee22103e63679e5]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
glib/tests/unicode.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/glib/tests/unicode.c b/glib/tests/unicode.c
|
||||
index 90b5a98b8..44d1083dd 100644
|
||||
--- a/glib/tests/unicode.c
|
||||
+++ b/glib/tests/unicode.c
|
||||
@@ -600,6 +600,7 @@ test_casemap_and_casefold (void)
|
||||
const char *locale;
|
||||
const char *test;
|
||||
const char *expected;
|
||||
+ size_t line = 0;
|
||||
char *convert;
|
||||
char *current_locale = setlocale (LC_CTYPE, NULL);
|
||||
char *old_lc_all, *old_lc_messages, *old_lang;
|
||||
@@ -620,6 +621,7 @@ test_casemap_and_casefold (void)
|
||||
|
||||
while (fgets (buffer, sizeof (buffer), infile))
|
||||
{
|
||||
+ line++;
|
||||
if (buffer[0] == '#')
|
||||
continue;
|
||||
|
||||
@@ -662,6 +664,9 @@ test_casemap_and_casefold (void)
|
||||
|
||||
convert = g_utf8_strup (test, -1);
|
||||
expected = strings[4][0] ? strings[4] : test;
|
||||
+ g_test_message ("Converting '%s' => '%s' (line %" G_GSIZE_FORMAT ")",
|
||||
+ test, expected, line);
|
||||
+
|
||||
g_assert_cmpstr (convert, ==, expected);
|
||||
g_free (convert);
|
||||
|
||||
@@ -681,9 +686,11 @@ test_casemap_and_casefold (void)
|
||||
|
||||
infile = fopen (filename, "r");
|
||||
g_assert (infile != NULL);
|
||||
+ line = 0;
|
||||
|
||||
while (fgets (buffer, sizeof (buffer), infile))
|
||||
{
|
||||
+ line++;
|
||||
if (buffer[0] == '#')
|
||||
continue;
|
||||
|
||||
@@ -693,6 +700,9 @@ test_casemap_and_casefold (void)
|
||||
test = strings[0];
|
||||
|
||||
convert = g_utf8_casefold (test, -1);
|
||||
+ g_test_message ("Converting '%s' => '%s' (line %" G_GSIZE_FORMAT ")",
|
||||
+ test, strings[1], line);
|
||||
+
|
||||
g_assert_cmpstr (convert, ==, strings[1]);
|
||||
g_free (convert);
|
||||
|
||||
@@ -40,6 +40,13 @@ SRC_URI = "${GNOME_MIRROR}/glib/${SHRT_VER}/glib-${PV}.tar.xz \
|
||||
file://CVE-2025-14087-03.patch \
|
||||
file://CVE-2025-14512.patch \
|
||||
file://CVE-2026-0988.patch \
|
||||
file://CVE-2026-1484-01.patch \
|
||||
file://CVE-2026-1484-02.patch \
|
||||
file://CVE-2026-1485.patch \
|
||||
file://CVE-2026-1489-01.patch \
|
||||
file://CVE-2026-1489-02.patch \
|
||||
file://CVE-2026-1489-03.patch \
|
||||
file://CVE-2026-1489-04.patch \
|
||||
"
|
||||
SRC_URI:append:class-native = " file://relocate-modules.patch \
|
||||
file://0001-meson.build-do-not-enable-pidfd-features-on-native-g.patch \
|
||||
|
||||
@@ -26,7 +26,7 @@ inherit core-image setuptools3 features_check
|
||||
|
||||
REQUIRED_DISTRO_FEATURES += "xattr"
|
||||
|
||||
SRCREV ?= "99047ec235e0aa53987fa93e906d97fca3ad205e"
|
||||
SRCREV ?= "06210079b2e10d6d3fb943afe87864267e329821"
|
||||
SRC_URI = "git://git.yoctoproject.org/poky;branch=scarthgap \
|
||||
file://Yocto_Build_Appliance.vmx \
|
||||
file://Yocto_Build_Appliance.vmxf \
|
||||
|
||||
@@ -31,6 +31,16 @@ SRC_URI += "\
|
||||
file://CVE-2025-61724.patch \
|
||||
file://CVE-2025-61727.patch \
|
||||
file://CVE-2025-61729.patch \
|
||||
file://CVE-2025-61730.patch \
|
||||
file://CVE-2025-61726.patch \
|
||||
file://CVE-2025-61728.patch \
|
||||
file://CVE-2025-61731.patch \
|
||||
file://CVE-2025-68119-dependent.patch \
|
||||
file://CVE-2025-68119.patch \
|
||||
file://CVE-2025-61732.patch \
|
||||
file://CVE-2025-68121_p1.patch \
|
||||
file://CVE-2025-68121_p2.patch \
|
||||
file://CVE-2025-68121_p3.patch \
|
||||
"
|
||||
SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
|
||||
|
||||
|
||||
196
meta/recipes-devtools/go/go/CVE-2025-61726.patch
Normal file
196
meta/recipes-devtools/go/go/CVE-2025-61726.patch
Normal file
@@ -0,0 +1,196 @@
|
||||
From 85050ca6146f3edb50ded0a352ab9edbd635effc Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Mon, 3 Nov 2025 14:28:47 -0800
|
||||
Subject: [PATCH] [release-branch.go1.24] net/url: add urlmaxqueryparams
|
||||
GODEBUG to limit the number of query parameters
|
||||
|
||||
net/url does not currently limit the number of query parameters parsed by
|
||||
url.ParseQuery or URL.Query.
|
||||
|
||||
When parsing a application/x-www-form-urlencoded form,
|
||||
net/http.Request.ParseForm will parse up to 10 MB of query parameters.
|
||||
An input consisting of a large number of small, unique parameters can
|
||||
cause excessive memory consumption.
|
||||
|
||||
We now limit the number of query parameters parsed to 10000 by default.
|
||||
The limit can be adjusted by setting GODEBUG=urlmaxqueryparams=<n>.
|
||||
Setting urlmaxqueryparams to 0 disables the limit.
|
||||
|
||||
Thanks to jub0bs for reporting this issue.
|
||||
|
||||
Fixes #77101
|
||||
Fixes CVE-2025-61726
|
||||
|
||||
CVE: CVE-2025-61726
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/85c794ddce26]
|
||||
|
||||
Change-Id: Iee3374c7ee2d8586dbf158536d3ade424203ff66
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3020
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-by: Neal Patel <nealpatel@google.com>
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3326
|
||||
Reviewed-by: Roland Shoemaker <bracewell@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/736702
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
Reviewed-by: Junyang Shao <shaojunyang@google.com>
|
||||
TryBot-Bypass: Michael Pratt <mpratt@google.com>
|
||||
(cherry picked from commit 85c794ddce26a092b0ea68d0fca79028b5069d5a)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
doc/godebug.md | 7 +++++
|
||||
src/internal/godebugs/table.go | 1 +
|
||||
src/net/url/url.go | 24 +++++++++++++++++
|
||||
src/net/url/url_test.go | 48 ++++++++++++++++++++++++++++++++++
|
||||
src/runtime/metrics/doc.go | 5 ++++
|
||||
5 files changed, 85 insertions(+)
|
||||
|
||||
diff --git a/doc/godebug.md b/doc/godebug.md
|
||||
index ae4f0576b4..635597ea42 100644
|
||||
--- a/doc/godebug.md
|
||||
+++ b/doc/godebug.md
|
||||
@@ -126,6 +126,13 @@ for example,
|
||||
see the [runtime documentation](/pkg/runtime#hdr-Environment_Variables)
|
||||
and the [go command documentation](/cmd/go#hdr-Build_and_test_caching).
|
||||
|
||||
+Go 1.26 added a new `urlmaxqueryparams` setting that controls the maximum number
|
||||
+of query parameters that net/url will accept when parsing a URL-encoded query string.
|
||||
+If the number of parameters exceeds the number set in `urlmaxqueryparams`,
|
||||
+parsing will fail early. The default value is `urlmaxqueryparams=10000`.
|
||||
+Setting `urlmaxqueryparams=0`bles the limit. To avoid denial of service attacks,
|
||||
+this setting and default was backported to Go 1.25.4 and Go 1.24.10.
|
||||
+
|
||||
Go 1.23.11 disabled build information stamping when multiple VCS are detected due
|
||||
to concerns around VCS injection attacks. This behavior can be renabled with the
|
||||
setting `allowmultiplevcs=1`.
|
||||
diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go
|
||||
index 33dcd81fc3..4ae043053c 100644
|
||||
--- a/src/internal/godebugs/table.go
|
||||
+++ b/src/internal/godebugs/table.go
|
||||
@@ -52,6 +52,7 @@ var All = []Info{
|
||||
{Name: "tlsrsakex", Package: "crypto/tls", Changed: 22, Old: "1"},
|
||||
{Name: "tlsunsafeekm", Package: "crypto/tls", Changed: 22, Old: "1"},
|
||||
{Name: "x509sha1", Package: "crypto/x509"},
|
||||
+ {Name: "urlmaxqueryparams", Package: "net/url", Changed: 24, Old: "0"},
|
||||
{Name: "x509usefallbackroots", Package: "crypto/x509"},
|
||||
{Name: "x509usepolicies", Package: "crypto/x509"},
|
||||
{Name: "zipinsecurepath", Package: "archive/zip"},
|
||||
diff --git a/src/net/url/url.go b/src/net/url/url.go
|
||||
index d2ae03232f..5219e3c130 100644
|
||||
--- a/src/net/url/url.go
|
||||
+++ b/src/net/url/url.go
|
||||
@@ -13,6 +13,7 @@ package url
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
+ "internal/godebug"
|
||||
"net/netip"
|
||||
"path"
|
||||
"sort"
|
||||
@@ -958,7 +959,30 @@ func ParseQuery(query string) (Values, error) {
|
||||
return m, err
|
||||
}
|
||||
|
||||
+var urlmaxqueryparams = godebug.New("urlmaxqueryparams")
|
||||
+
|
||||
+const defaultMaxParams = 10000
|
||||
+
|
||||
+func urlParamsWithinMax(params int) bool {
|
||||
+ withinDefaultMax := params <= defaultMaxParams
|
||||
+ if urlmaxqueryparams.Value() == "" {
|
||||
+ return withinDefaultMax
|
||||
+ }
|
||||
+ customMax, err := strconv.Atoi(urlmaxqueryparams.Value())
|
||||
+ if err != nil {
|
||||
+ return withinDefaultMax
|
||||
+ }
|
||||
+ withinCustomMax := customMax == 0 || params < customMax
|
||||
+ if withinDefaultMax != withinCustomMax {
|
||||
+ urlmaxqueryparams.IncNonDefault()
|
||||
+ }
|
||||
+ return withinCustomMax
|
||||
+}
|
||||
+
|
||||
func parseQuery(m Values, query string) (err error) {
|
||||
+ if !urlParamsWithinMax(strings.Count(query, "&") + 1) {
|
||||
+ return errors.New("number of URL query parameters exceeded limit")
|
||||
+ }
|
||||
for query != "" {
|
||||
var key string
|
||||
key, query, _ = strings.Cut(query, "&")
|
||||
diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
|
||||
index fef236e40a..b2f8bd95fc 100644
|
||||
--- a/src/net/url/url_test.go
|
||||
+++ b/src/net/url/url_test.go
|
||||
@@ -1488,6 +1488,54 @@ func TestParseQuery(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+func TestParseQueryLimits(t *testing.T) {
|
||||
+ for _, test := range []struct {
|
||||
+ params int
|
||||
+ godebug string
|
||||
+ wantErr bool
|
||||
+ }{{
|
||||
+ params: 10,
|
||||
+ wantErr: false,
|
||||
+ }, {
|
||||
+ params: defaultMaxParams,
|
||||
+ wantErr: false,
|
||||
+ }, {
|
||||
+ params: defaultMaxParams + 1,
|
||||
+ wantErr: true,
|
||||
+ }, {
|
||||
+ params: 10,
|
||||
+ godebug: "urlmaxqueryparams=9",
|
||||
+ wantErr: true,
|
||||
+ }, {
|
||||
+ params: defaultMaxParams + 1,
|
||||
+ godebug: "urlmaxqueryparams=0",
|
||||
+ wantErr: false,
|
||||
+ }} {
|
||||
+ t.Setenv("GODEBUG", test.godebug)
|
||||
+ want := Values{}
|
||||
+ var b strings.Builder
|
||||
+ for i := range test.params {
|
||||
+ if i > 0 {
|
||||
+ b.WriteString("&")
|
||||
+ }
|
||||
+ p := fmt.Sprintf("p%v", i)
|
||||
+ b.WriteString(p)
|
||||
+ want[p] = []string{""}
|
||||
+ }
|
||||
+ query := b.String()
|
||||
+ got, err := ParseQuery(query)
|
||||
+ if gotErr, wantErr := err != nil, test.wantErr; gotErr != wantErr {
|
||||
+ t.Errorf("GODEBUG=%v ParseQuery(%v params) = %v, want error: %v", test.godebug, test.params, err, wantErr)
|
||||
+ }
|
||||
+ if err != nil {
|
||||
+ continue
|
||||
+ }
|
||||
+ if got, want := len(got), test.params; got != want {
|
||||
+ t.Errorf("GODEBUG=%v ParseQuery(%v params): got %v params, want %v", test.godebug, test.params, got, want)
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
type RequestURITest struct {
|
||||
url *URL
|
||||
out string
|
||||
diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go
|
||||
index 517ec0e0a4..335f7873b3 100644
|
||||
--- a/src/runtime/metrics/doc.go
|
||||
+++ b/src/runtime/metrics/doc.go
|
||||
@@ -328,6 +328,11 @@ Below is the full list of supported metrics, ordered lexicographically.
|
||||
The number of non-default behaviors executed by the crypto/tls
|
||||
package due to a non-default GODEBUG=tlsunsafeekm=... setting.
|
||||
|
||||
+ /godebug/non-default-behavior/urlmaxqueryparams:events
|
||||
+ The number of non-default behaviors executed by the net/url
|
||||
+ package due to a non-default GODEBUG=urlmaxqueryparams=...
|
||||
+ setting.
|
||||
+
|
||||
/godebug/non-default-behavior/x509sha1:events
|
||||
The number of non-default behaviors executed by the crypto/x509
|
||||
package due to a non-default GODEBUG=x509sha1=... setting.
|
||||
--
|
||||
2.35.6
|
||||
171
meta/recipes-devtools/go/go/CVE-2025-61728.patch
Normal file
171
meta/recipes-devtools/go/go/CVE-2025-61728.patch
Normal file
@@ -0,0 +1,171 @@
|
||||
From 727c39f7e6c9dc9d4a40d67f39f68ae8867a2abd Mon Sep 17 00:00:00 2001
|
||||
From: Damien Neil <dneil@google.com>
|
||||
Date: Tue, 4 Nov 2025 17:00:33 -0800
|
||||
Subject: [PATCH] [release-branch.go1.24] archive/zip: reduce CPU usage in
|
||||
index construction
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Constructing the zip index (which is done once when first opening
|
||||
a file in an archive) can consume large amounts of CPU when
|
||||
processing deeply-nested directory paths.
|
||||
|
||||
Switch to a less inefficient algorithm.
|
||||
|
||||
Thanks to Jakub Ciolek for reporting this issue.
|
||||
|
||||
goos: darwin
|
||||
goarch: arm64
|
||||
pkg: archive/zip
|
||||
cpu: Apple M4 Pro
|
||||
│ /tmp/bench.0 │ /tmp/bench.1 │
|
||||
│ sec/op │ sec/op vs base │
|
||||
ReaderOneDeepDir-14 25983.62m ± 2% 46.01m ± 2% -99.82% (p=0.000 n=8)
|
||||
ReaderManyDeepDirs-14 16.221 ± 1% 2.763 ± 6% -82.96% (p=0.000 n=8)
|
||||
ReaderManyShallowFiles-14 130.3m ± 1% 128.8m ± 2% -1.20% (p=0.003 n=8)
|
||||
geomean 3.801 253.9m -93.32%
|
||||
|
||||
Fixes #77102
|
||||
Fixes CVE-2025-61728
|
||||
|
||||
CVE: CVE-2025-61728
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/3235ef3db85c]
|
||||
|
||||
Change-Id: I2c9c864be01b2a2769eb67fbab1b250aeb8f6c42
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3060
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-by: Neal Patel <nealpatel@google.com>
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3328
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/736703
|
||||
TryBot-Bypass: Michael Pratt <mpratt@google.com>
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
Reviewed-by: Junyang Shao <shaojunyang@google.com>
|
||||
(cherry picked from commit 3235ef3db85c2d7e797b976822a7addaf6d5ca2a)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/archive/zip/reader.go | 11 ++++-
|
||||
src/archive/zip/reader_test.go | 81 ++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 91 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go
|
||||
index 60b34b76ee..8a79f5d140 100644
|
||||
--- a/src/archive/zip/reader.go
|
||||
+++ b/src/archive/zip/reader.go
|
||||
@@ -830,7 +830,16 @@ func (r *Reader) initFileList() {
|
||||
continue
|
||||
}
|
||||
|
||||
- for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
|
||||
+ dir := name
|
||||
+ for {
|
||||
+ if idx := strings.LastIndex(dir, "/"); idx < 0 {
|
||||
+ break
|
||||
+ } else {
|
||||
+ dir = dir[:idx]
|
||||
+ }
|
||||
+ if dirs[dir] {
|
||||
+ break
|
||||
+ }
|
||||
dirs[dir] = true
|
||||
}
|
||||
|
||||
diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go
|
||||
index 9a77c1aa62..278714bf49 100644
|
||||
--- a/src/archive/zip/reader_test.go
|
||||
+++ b/src/archive/zip/reader_test.go
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
+ "fmt"
|
||||
"internal/obscuretestdata"
|
||||
"io"
|
||||
"io/fs"
|
||||
@@ -1834,3 +1835,83 @@ func TestBaseOffsetPlusOverflow(t *testing.T) {
|
||||
// as the section reader offset & size were < 0.
|
||||
NewReader(bytes.NewReader(data), int64(len(data))+1875)
|
||||
}
|
||||
+
|
||||
+func BenchmarkReaderOneDeepDir(b *testing.B) {
|
||||
+ var buf bytes.Buffer
|
||||
+ zw := NewWriter(&buf)
|
||||
+
|
||||
+ for i := range 4000 {
|
||||
+ name := strings.Repeat("a/", i) + "data"
|
||||
+ zw.CreateHeader(&FileHeader{
|
||||
+ Name: name,
|
||||
+ Method: Store,
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ if err := zw.Close(); err != nil {
|
||||
+ b.Fatal(err)
|
||||
+ }
|
||||
+ data := buf.Bytes()
|
||||
+
|
||||
+ for b.Loop() {
|
||||
+ zr, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
+ if err != nil {
|
||||
+ b.Fatal(err)
|
||||
+ }
|
||||
+ zr.Open("does-not-exist")
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func BenchmarkReaderManyDeepDirs(b *testing.B) {
|
||||
+ var buf bytes.Buffer
|
||||
+ zw := NewWriter(&buf)
|
||||
+
|
||||
+ for i := range 2850 {
|
||||
+ name := fmt.Sprintf("%x", i)
|
||||
+ name = strings.Repeat("/"+name, i+1)[1:]
|
||||
+
|
||||
+ zw.CreateHeader(&FileHeader{
|
||||
+ Name: name,
|
||||
+ Method: Store,
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ if err := zw.Close(); err != nil {
|
||||
+ b.Fatal(err)
|
||||
+ }
|
||||
+ data := buf.Bytes()
|
||||
+
|
||||
+ for b.Loop() {
|
||||
+ zr, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
+ if err != nil {
|
||||
+ b.Fatal(err)
|
||||
+ }
|
||||
+ zr.Open("does-not-exist")
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func BenchmarkReaderManyShallowFiles(b *testing.B) {
|
||||
+ var buf bytes.Buffer
|
||||
+ zw := NewWriter(&buf)
|
||||
+
|
||||
+ for i := range 310000 {
|
||||
+ name := fmt.Sprintf("%v", i)
|
||||
+ zw.CreateHeader(&FileHeader{
|
||||
+ Name: name,
|
||||
+ Method: Store,
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ if err := zw.Close(); err != nil {
|
||||
+ b.Fatal(err)
|
||||
+ }
|
||||
+ data := buf.Bytes()
|
||||
+
|
||||
+ for b.Loop() {
|
||||
+ zr, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
+ if err != nil {
|
||||
+ b.Fatal(err)
|
||||
+ }
|
||||
+ zr.Open("does-not-exist")
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.35.6
|
||||
460
meta/recipes-devtools/go/go/CVE-2025-61730.patch
Normal file
460
meta/recipes-devtools/go/go/CVE-2025-61730.patch
Normal file
@@ -0,0 +1,460 @@
|
||||
From 2cfa797798cc982973d194eca3be19fb1f092556 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <roland@golang.org>
|
||||
Date: Mon, 24 Nov 2025 14:03:10 -0800
|
||||
Subject: [PATCH] [release-branch.go1.24] crypto/tls: reject trailing messages
|
||||
after client/server hello
|
||||
|
||||
For TLS 1.3, after procesesing the server/client hello, if there isn't a
|
||||
CCS message, reject the trailing messages which were appended to the
|
||||
hello messages. This prevents an on-path attacker from injecting
|
||||
plaintext messages into the handshake.
|
||||
|
||||
Additionally, check that we don't have any buffered messages before we
|
||||
switch the read traffic secret regardless, since any buffered messages
|
||||
would have been under an old key which is no longer appropriate.
|
||||
|
||||
We also invert the ordering of setting the read/write secrets so that if
|
||||
we fail when changing the read secret we send the alert using the
|
||||
correct write secret.
|
||||
|
||||
Updates #76443
|
||||
Fixes #76854
|
||||
Fixes CVE-2025-61730
|
||||
|
||||
CVE: CVE-2025-61730
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/ad2cd043db66]
|
||||
|
||||
Backport Changes:
|
||||
- In version 1.24, the doHelloRetryRequest function defined in handshake_server_tls13.go
|
||||
returns keyshare and error, but in version 1.22 it only returns error. The backport
|
||||
was adjusted accordingly and These changes were introduced by commit
|
||||
https://github.com/golang/go/commit/d0edd9acc80a in version 1.24.
|
||||
- In file src/crypto/tls/handshake_server_tls13.go, Replaced the function call
|
||||
hs.handshakeSecret.ClientHandshakeTrafficSecret(hs.transcript) with
|
||||
hs.suite.deriveSecret(hs.handshakeSecret, clientHandshakeTrafficLabel, hs.transcript).
|
||||
This change is not present in version v1.22 and it was introduced by commit
|
||||
https://github.com/golang/go/commit/743746a3a52d in version 1.24.
|
||||
|
||||
Change-Id: If6ba8ad16f48d5cd5db5574824062ad4244a5b52
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/724120
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Michael Knyszek <mknyszek@google.com>
|
||||
Reviewed-by: Daniel McCarney <daniel@binaryparadox.net>
|
||||
Reviewed-by: Coia Prant <coiaprant@gmail.com>
|
||||
(cherry picked from commit 5046bdf8a612b35a2c1a9e168054c1d5c65e7dd7)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/731961
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
(cherry picked from commit ad2cd043db66cd36e1f55359638729d2c8ff3d99)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/crypto/tls/conn.go | 39 ++++++-
|
||||
src/crypto/tls/handshake_client_tls13.go | 22 ++--
|
||||
src/crypto/tls/handshake_server_tls13.go | 39 ++++---
|
||||
src/crypto/tls/handshake_test.go | 140 +++++++++++++++++++++++
|
||||
src/crypto/tls/quic.go | 11 +-
|
||||
5 files changed, 219 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go
|
||||
index 0e4669866e..08609ce17b 100644
|
||||
--- a/src/crypto/tls/conn.go
|
||||
+++ b/src/crypto/tls/conn.go
|
||||
@@ -225,6 +225,9 @@ func (hc *halfConn) changeCipherSpec() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+// setTrafficSecret sets the traffic secret for the given encryption level. setTrafficSecret
|
||||
+// should not be called directly, but rather through the Conn setWriteTrafficSecret and
|
||||
+// setReadTrafficSecret wrapper methods.
|
||||
func (hc *halfConn) setTrafficSecret(suite *cipherSuiteTLS13, level QUICEncryptionLevel, secret []byte) {
|
||||
hc.trafficSecret = secret
|
||||
hc.level = level
|
||||
@@ -1321,9 +1324,6 @@ func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error {
|
||||
return c.in.setErrorLocked(c.sendAlert(alertInternalError))
|
||||
}
|
||||
|
||||
- newSecret := cipherSuite.nextTrafficSecret(c.in.trafficSecret)
|
||||
- c.in.setTrafficSecret(cipherSuite, QUICEncryptionLevelInitial, newSecret)
|
||||
-
|
||||
if keyUpdate.updateRequested {
|
||||
c.out.Lock()
|
||||
defer c.out.Unlock()
|
||||
@@ -1341,7 +1341,12 @@ func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error {
|
||||
}
|
||||
|
||||
newSecret := cipherSuite.nextTrafficSecret(c.out.trafficSecret)
|
||||
- c.out.setTrafficSecret(cipherSuite, QUICEncryptionLevelInitial, newSecret)
|
||||
+ c.setWriteTrafficSecret(cipherSuite, QUICEncryptionLevelInitial, newSecret)
|
||||
+ }
|
||||
+
|
||||
+ newSecret := cipherSuite.nextTrafficSecret(c.in.trafficSecret)
|
||||
+ if err := c.setReadTrafficSecret(cipherSuite, QUICEncryptionLevelInitial, newSecret); err != nil {
|
||||
+ return err
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -1572,7 +1577,9 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
|
||||
// Provide the 1-RTT read secret now that the handshake is complete.
|
||||
// The QUIC layer MUST NOT decrypt 1-RTT packets prior to completing
|
||||
// the handshake (RFC 9001, Section 5.7).
|
||||
- c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret)
|
||||
+ if err := c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
} else {
|
||||
var a alert
|
||||
c.out.Lock()
|
||||
@@ -1664,3 +1671,25 @@ func (c *Conn) VerifyHostname(host string) error {
|
||||
}
|
||||
return c.peerCertificates[0].VerifyHostname(host)
|
||||
}
|
||||
+
|
||||
+// setReadTrafficSecret sets the read traffic secret for the given encryption level. If
|
||||
+// being called at the same time as setWriteTrafficSecret, the caller must ensure the call
|
||||
+// to setWriteTrafficSecret happens first so any alerts are sent at the write level.
|
||||
+func (c *Conn) setReadTrafficSecret(suite *cipherSuiteTLS13, level QUICEncryptionLevel, secret []byte) error {
|
||||
+ // Ensure that there are no buffered handshake messages before changing the
|
||||
+ // read keys, since that can cause messages to be parsed that were encrypted
|
||||
+ // using old keys which are no longer appropriate.
|
||||
+ if c.hand.Len() != 0 {
|
||||
+ c.sendAlert(alertUnexpectedMessage)
|
||||
+ return errors.New("tls: handshake buffer not empty before setting read traffic secret")
|
||||
+ }
|
||||
+ c.in.setTrafficSecret(suite, level, secret)
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+// setWriteTrafficSecret sets the write traffic secret for the given encryption level. If
|
||||
+// being called at the same time as setReadTrafficSecret, the caller must ensure the call
|
||||
+// to setWriteTrafficSecret happens first so any alerts are sent at the write level.
|
||||
+func (c *Conn) setWriteTrafficSecret(suite *cipherSuiteTLS13, level QUICEncryptionLevel, secret []byte) {
|
||||
+ c.out.setTrafficSecret(suite, level, secret)
|
||||
+}
|
||||
diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go
|
||||
index 2f59f6888c..68ff92beda 100644
|
||||
--- a/src/crypto/tls/handshake_client_tls13.go
|
||||
+++ b/src/crypto/tls/handshake_client_tls13.go
|
||||
@@ -393,17 +393,18 @@ func (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error {
|
||||
|
||||
clientSecret := hs.suite.deriveSecret(handshakeSecret,
|
||||
clientHandshakeTrafficLabel, hs.transcript)
|
||||
- c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, clientSecret)
|
||||
+ c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, clientSecret)
|
||||
serverSecret := hs.suite.deriveSecret(handshakeSecret,
|
||||
serverHandshakeTrafficLabel, hs.transcript)
|
||||
- c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, serverSecret)
|
||||
+ if err := c.setReadTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, serverSecret); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
|
||||
if c.quic != nil {
|
||||
- if c.hand.Len() != 0 {
|
||||
- c.sendAlert(alertUnexpectedMessage)
|
||||
- }
|
||||
c.quicSetWriteSecret(QUICEncryptionLevelHandshake, hs.suite.id, clientSecret)
|
||||
- c.quicSetReadSecret(QUICEncryptionLevelHandshake, hs.suite.id, serverSecret)
|
||||
+ if err := c.quicSetReadSecret(QUICEncryptionLevelHandshake, hs.suite.id, serverSecret); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
}
|
||||
|
||||
err = c.config.writeKeyLog(keyLogLabelClientHandshake, hs.hello.random, clientSecret)
|
||||
@@ -606,7 +607,9 @@ func (hs *clientHandshakeStateTLS13) readServerFinished() error {
|
||||
clientApplicationTrafficLabel, hs.transcript)
|
||||
serverSecret := hs.suite.deriveSecret(hs.masterSecret,
|
||||
serverApplicationTrafficLabel, hs.transcript)
|
||||
- c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, serverSecret)
|
||||
+ if err := c.setReadTrafficSecret(hs.suite, QUICEncryptionLevelApplication, serverSecret); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
|
||||
err = c.config.writeKeyLog(keyLogLabelClientTraffic, hs.hello.random, hs.trafficSecret)
|
||||
if err != nil {
|
||||
@@ -702,7 +705,7 @@ func (hs *clientHandshakeStateTLS13) sendClientFinished() error {
|
||||
return err
|
||||
}
|
||||
|
||||
- c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret)
|
||||
+ c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret)
|
||||
|
||||
if !c.config.SessionTicketsDisabled && c.config.ClientSessionCache != nil {
|
||||
c.resumptionSecret = hs.suite.deriveSecret(hs.masterSecret,
|
||||
@@ -710,9 +713,6 @@ func (hs *clientHandshakeStateTLS13) sendClientFinished() error {
|
||||
}
|
||||
|
||||
if c.quic != nil {
|
||||
- if c.hand.Len() != 0 {
|
||||
- c.sendAlert(alertUnexpectedMessage)
|
||||
- }
|
||||
c.quicSetWriteSecret(QUICEncryptionLevelApplication, hs.suite.id, hs.trafficSecret)
|
||||
}
|
||||
|
||||
diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go
|
||||
index 21d798de37..5aa69e9640 100644
|
||||
--- a/src/crypto/tls/handshake_server_tls13.go
|
||||
+++ b/src/crypto/tls/handshake_server_tls13.go
|
||||
@@ -380,7 +380,9 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error {
|
||||
return err
|
||||
}
|
||||
earlyTrafficSecret := hs.suite.deriveSecret(hs.earlySecret, clientEarlyTrafficLabel, transcript)
|
||||
- c.quicSetReadSecret(QUICEncryptionLevelEarly, hs.suite.id, earlyTrafficSecret)
|
||||
+ if err := c.quicSetReadSecret(QUICEncryptionLevelEarly, hs.suite.id, earlyTrafficSecret); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
}
|
||||
|
||||
c.didResume = true
|
||||
@@ -477,6 +479,14 @@ func (hs *serverHandshakeStateTLS13) sendDummyChangeCipherSpec() error {
|
||||
func (hs *serverHandshakeStateTLS13) doHelloRetryRequest(selectedGroup CurveID) error {
|
||||
c := hs.c
|
||||
|
||||
+ // Make sure the client didn't send extra handshake messages alongside
|
||||
+ // their initial client_hello. If they sent two client_hello messages,
|
||||
+ // we will consume the second before they respond to the server_hello.
|
||||
+ if c.hand.Len() != 0 {
|
||||
+ c.sendAlert(alertUnexpectedMessage)
|
||||
+ return errors.New("tls: handshake buffer not empty before HelloRetryRequest")
|
||||
+ }
|
||||
+
|
||||
// The first ClientHello gets double-hashed into the transcript upon a
|
||||
// HelloRetryRequest. See RFC 8446, Section 4.4.1.
|
||||
if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil {
|
||||
@@ -615,19 +625,20 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
|
||||
hs.handshakeSecret = hs.suite.extract(hs.sharedKey,
|
||||
hs.suite.deriveSecret(earlySecret, "derived", nil))
|
||||
|
||||
- clientSecret := hs.suite.deriveSecret(hs.handshakeSecret,
|
||||
- clientHandshakeTrafficLabel, hs.transcript)
|
||||
- c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, clientSecret)
|
||||
serverSecret := hs.suite.deriveSecret(hs.handshakeSecret,
|
||||
serverHandshakeTrafficLabel, hs.transcript)
|
||||
- c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, serverSecret)
|
||||
+ c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, serverSecret)
|
||||
+ clientSecret := hs.suite.deriveSecret(hs.handshakeSecret,
|
||||
+ clientHandshakeTrafficLabel, hs.transcript)
|
||||
+ if err := c.setReadTrafficSecret(hs.suite, QUICEncryptionLevelHandshake, clientSecret); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
|
||||
if c.quic != nil {
|
||||
- if c.hand.Len() != 0 {
|
||||
- c.sendAlert(alertUnexpectedMessage)
|
||||
- }
|
||||
c.quicSetWriteSecret(QUICEncryptionLevelHandshake, hs.suite.id, serverSecret)
|
||||
- c.quicSetReadSecret(QUICEncryptionLevelHandshake, hs.suite.id, clientSecret)
|
||||
+ if err := c.quicSetReadSecret(QUICEncryptionLevelHandshake, hs.suite.id, clientSecret); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
}
|
||||
|
||||
err := c.config.writeKeyLog(keyLogLabelClientHandshake, hs.clientHello.random, clientSecret)
|
||||
@@ -751,13 +762,9 @@ func (hs *serverHandshakeStateTLS13) sendServerFinished() error {
|
||||
clientApplicationTrafficLabel, hs.transcript)
|
||||
serverSecret := hs.suite.deriveSecret(hs.masterSecret,
|
||||
serverApplicationTrafficLabel, hs.transcript)
|
||||
- c.out.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, serverSecret)
|
||||
+ c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelApplication, serverSecret)
|
||||
|
||||
if c.quic != nil {
|
||||
- if c.hand.Len() != 0 {
|
||||
- // TODO: Handle this in setTrafficSecret?
|
||||
- c.sendAlert(alertUnexpectedMessage)
|
||||
- }
|
||||
c.quicSetWriteSecret(QUICEncryptionLevelApplication, hs.suite.id, serverSecret)
|
||||
}
|
||||
|
||||
@@ -992,7 +999,9 @@ func (hs *serverHandshakeStateTLS13) readClientFinished() error {
|
||||
return errors.New("tls: invalid client finished hash")
|
||||
}
|
||||
|
||||
- c.in.setTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret)
|
||||
+ if err := c.setReadTrafficSecret(hs.suite, QUICEncryptionLevelApplication, hs.trafficSecret); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
|
||||
return nil
|
||||
}
|
||||
diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go
|
||||
index 27ab19ef31..4991a0e69b 100644
|
||||
--- a/src/crypto/tls/handshake_test.go
|
||||
+++ b/src/crypto/tls/handshake_test.go
|
||||
@@ -6,6 +6,7 @@ package tls
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
+ "context"
|
||||
"crypto/ed25519"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
@@ -533,3 +534,142 @@ var clientEd25519KeyPEM = testingKey(`
|
||||
-----BEGIN TESTING KEY-----
|
||||
MC4CAQAwBQYDK2VwBCIEINifzf07d9qx3d44e0FSbV4mC/xQxT644RRbpgNpin7I
|
||||
-----END TESTING KEY-----`)
|
||||
+
|
||||
+func TestServerHelloTrailingMessage(t *testing.T) {
|
||||
+ // In TLS 1.3 the change cipher spec message is optional. If a CCS message
|
||||
+ // is not sent, after reading the ServerHello, the read traffic secret is
|
||||
+ // set, and all following messages must be encrypted. If the server sends
|
||||
+ // additional unencrypted messages in a record with the ServerHello, the
|
||||
+ // client must either fail or ignore the additional messages.
|
||||
+
|
||||
+ c, s := localPipe(t)
|
||||
+ go func() {
|
||||
+ ctx := context.Background()
|
||||
+ srv := Server(s, testConfig)
|
||||
+ clientHello, _, err := srv.readClientHello(ctx)
|
||||
+ if err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+
|
||||
+ hs := serverHandshakeStateTLS13{
|
||||
+ c: srv,
|
||||
+ ctx: ctx,
|
||||
+ clientHello: clientHello,
|
||||
+ }
|
||||
+ if err := hs.processClientHello(); err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+ if err := transcriptMsg(hs.clientHello, hs.transcript); err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+
|
||||
+ record, err := concatHandshakeMessages(hs.hello, &encryptedExtensionsMsg{alpnProtocol: "h2"})
|
||||
+ if err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+
|
||||
+ if _, err := s.Write(record); err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+ srv.Close()
|
||||
+ }()
|
||||
+
|
||||
+ cli := Client(c, testConfig)
|
||||
+ expectedErr := "tls: handshake buffer not empty before setting read traffic secret"
|
||||
+ if err := cli.Handshake(); err == nil {
|
||||
+ t.Fatal("expected error from incomplete handshake, got nil")
|
||||
+ } else if err.Error() != expectedErr {
|
||||
+ t.Fatalf("expected error %q, got %q", expectedErr, err.Error())
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func TestClientHelloTrailingMessage(t *testing.T) {
|
||||
+ // Same as TestServerHelloTrailingMessage but for the client side.
|
||||
+
|
||||
+ c, s := localPipe(t)
|
||||
+ go func() {
|
||||
+ cli := Client(c, testConfig)
|
||||
+
|
||||
+ hello, _, _, err := cli.makeClientHello()
|
||||
+ if err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+
|
||||
+ record, err := concatHandshakeMessages(hello, &certificateMsgTLS13{})
|
||||
+ if err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+
|
||||
+ if _, err := c.Write(record); err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+ cli.Close()
|
||||
+ }()
|
||||
+
|
||||
+ srv := Server(s, testConfig)
|
||||
+ expectedErr := "tls: handshake buffer not empty before setting read traffic secret"
|
||||
+ if err := srv.Handshake(); err == nil {
|
||||
+ t.Fatal("expected error from incomplete handshake, got nil")
|
||||
+ } else if err.Error() != expectedErr {
|
||||
+ t.Fatalf("expected error %q, got %q", expectedErr, err.Error())
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+func TestDoubleClientHelloHRR(t *testing.T) {
|
||||
+ // If a client sends two ClientHello messages in a single record, and the
|
||||
+ // server sends a HRR after reading the first ClientHello, the server must
|
||||
+ // either fail or ignore the trailing ClientHello.
|
||||
+
|
||||
+ c, s := localPipe(t)
|
||||
+
|
||||
+ go func() {
|
||||
+ cli := Client(c, testConfig)
|
||||
+
|
||||
+ hello, _, _, err := cli.makeClientHello()
|
||||
+ if err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+ hello.keyShares = nil
|
||||
+
|
||||
+ record, err := concatHandshakeMessages(hello, hello)
|
||||
+ if err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+
|
||||
+ if _, err := c.Write(record); err != nil {
|
||||
+ testFatal(t, err)
|
||||
+ }
|
||||
+ cli.Close()
|
||||
+ }()
|
||||
+
|
||||
+ srv := Server(s, testConfig)
|
||||
+ expectedErr := "tls: handshake buffer not empty before HelloRetryRequest"
|
||||
+ if err := srv.Handshake(); err == nil {
|
||||
+ t.Fatal("expected error from incomplete handshake, got nil")
|
||||
+ } else if err.Error() != expectedErr {
|
||||
+ t.Fatalf("expected error %q, got %q", expectedErr, err.Error())
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// concatHandshakeMessages marshals and concatenates the given handshake
|
||||
+// messages into a single record.
|
||||
+func concatHandshakeMessages(msgs ...handshakeMessage) ([]byte, error) {
|
||||
+ var marshalled []byte
|
||||
+ for _, msg := range msgs {
|
||||
+ data, err := msg.marshal()
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ marshalled = append(marshalled, data...)
|
||||
+ }
|
||||
+ m := len(marshalled)
|
||||
+ outBuf := make([]byte, recordHeaderLen)
|
||||
+ outBuf[0] = byte(recordTypeHandshake)
|
||||
+ vers := VersionTLS12
|
||||
+ outBuf[1] = byte(vers >> 8)
|
||||
+ outBuf[2] = byte(vers)
|
||||
+ outBuf[3] = byte(m >> 8)
|
||||
+ outBuf[4] = byte(m)
|
||||
+ outBuf = append(outBuf, marshalled...)
|
||||
+ return outBuf, nil
|
||||
+}
|
||||
diff --git a/src/crypto/tls/quic.go b/src/crypto/tls/quic.go
|
||||
index 3518169bf7..aa14f1dadb 100644
|
||||
--- a/src/crypto/tls/quic.go
|
||||
+++ b/src/crypto/tls/quic.go
|
||||
@@ -323,13 +323,22 @@ func (c *Conn) quicReadHandshakeBytes(n int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
-func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
|
||||
+func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) error {
|
||||
+ // Ensure that there are no buffered handshake messages before changing the
|
||||
+ // read keys, since that can cause messages to be parsed that were encrypted
|
||||
+ // using old keys which are no longer appropriate.
|
||||
+ // TODO(roland): we should merge this check with the similar one in setReadTrafficSecret.
|
||||
+ if c.hand.Len() != 0 {
|
||||
+ c.sendAlert(alertUnexpectedMessage)
|
||||
+ return errors.New("tls: handshake buffer not empty before setting read traffic secret")
|
||||
+ }
|
||||
c.quic.events = append(c.quic.events, QUICEvent{
|
||||
Kind: QUICSetReadSecret,
|
||||
Level: level,
|
||||
Suite: suite,
|
||||
Data: secret,
|
||||
})
|
||||
+ return nil
|
||||
}
|
||||
|
||||
func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
|
||||
--
|
||||
2.35.6
|
||||
70
meta/recipes-devtools/go/go/CVE-2025-61731.patch
Normal file
70
meta/recipes-devtools/go/go/CVE-2025-61731.patch
Normal file
@@ -0,0 +1,70 @@
|
||||
From ab266ccbc19789c52dcb1dc6e8e71d2f4fd545ff Mon Sep 17 00:00:00 2001
|
||||
From: Neal Patel <nealpatel@google.com>
|
||||
Date: Thu, 4 Dec 2025 12:30:39 -0500
|
||||
Subject: [PATCH] [release-branch.go1.24] cmd/go/internal/work: sanitize flags
|
||||
before invoking 'pkg-config'
|
||||
|
||||
The addition of CgoPkgConfig allowed execution with flags not
|
||||
matching the safelist. In order to prevent potential arbitrary
|
||||
code execution at build time, ensure that flags are validated
|
||||
prior to invoking the 'pkg-config' binary.
|
||||
|
||||
Thank you to RyotaK (https://ryotak.net) of GMO Flatt Security Inc.
|
||||
for reporting this issue.
|
||||
|
||||
Fixes CVE-2025-61731
|
||||
Fixes #77100
|
||||
|
||||
CVE: CVE-2025-61731
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/00b7309387a1]
|
||||
|
||||
Change-Id: Ic51b41f1f7e697ab98c9c32c6fae35f217f7f364
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3240
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3344
|
||||
Reviewed-by: Neal Patel <nealpatel@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/736701
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
TryBot-Bypass: Michael Pratt <mpratt@google.com>
|
||||
Reviewed-by: Junyang Shao <shaojunyang@google.com>
|
||||
(cherry picked from commit 00b7309387a171bcba37382e7ed96b473df04917)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/cmd/go/internal/work/exec.go | 8 ++++++++
|
||||
src/cmd/go/internal/work/security.go | 1 +
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
|
||||
index c8f297cbe9..815942a703 100644
|
||||
--- a/src/cmd/go/internal/work/exec.go
|
||||
+++ b/src/cmd/go/internal/work/exec.go
|
||||
@@ -1684,6 +1684,14 @@ func (b *Builder) getPkgConfigFlags(a *Action) (cflags, ldflags []string, err er
|
||||
return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Running 'pkg-config' can cause execution of
|
||||
+ // arbitrary code using flags that are not in
|
||||
+ // the safelist.
|
||||
+ if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", pcflags); err != nil {
|
||||
+ return nil, nil, err
|
||||
+ }
|
||||
+
|
||||
var out []byte
|
||||
out, err = sh.runOut(p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
|
||||
if err != nil {
|
||||
diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go
|
||||
index 568eecd325..79724ed04a 100644
|
||||
--- a/src/cmd/go/internal/work/security.go
|
||||
+++ b/src/cmd/go/internal/work/security.go
|
||||
@@ -122,6 +122,7 @@ var validCompilerFlags = []*lazyregexp.Regexp{
|
||||
re(`-pedantic(-errors)?`),
|
||||
re(`-pipe`),
|
||||
re(`-pthread`),
|
||||
+ re(`--static`),
|
||||
re(`-?-std=([^@\-].*)`),
|
||||
re(`-?-stdlib=([^@\-].*)`),
|
||||
re(`--sysroot=([^@\-].*)`),
|
||||
--
|
||||
2.35.6
|
||||
53
meta/recipes-devtools/go/go/CVE-2025-61732.patch
Normal file
53
meta/recipes-devtools/go/go/CVE-2025-61732.patch
Normal file
@@ -0,0 +1,53 @@
|
||||
From fe8c665f1608126e7b644ab07bb0698ad1c0b4b6 Mon Sep 17 00:00:00 2001
|
||||
From: Neal Patel <nealpatel@google.com>
|
||||
Date: Tue, 6 Jan 2026 16:09:19 -0500
|
||||
Subject: [PATCH] [release-branch.go1.24] cmd/go: remove user-content from doc
|
||||
strings in cgo ASTs.
|
||||
|
||||
Thank you to RyotaK (https://ryotak.net) of GMO Flatt Security Inc. for reporting this issue.
|
||||
|
||||
Updates #76697
|
||||
Fixes #77128
|
||||
Fixes CVE-2025-61732
|
||||
|
||||
CVE: CVE-2025-61732
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/14d0bb39c1c4]
|
||||
|
||||
Change-Id: Ie2a96b79a813e362cbf8e6cb0e3c2d0c022bcb29
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/740001
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-by: Roland Shoemaker <roland@golang.org>
|
||||
(cherry picked from commit 14d0bb39c1c4093bd02740d14b1a2ca720ced97c)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/cmd/cgo/ast.go | 11 +++--------
|
||||
1 file changed, 3 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
|
||||
index 3cbbeafdca..eb373bdefa 100644
|
||||
--- a/src/cmd/cgo/ast.go
|
||||
+++ b/src/cmd/cgo/ast.go
|
||||
@@ -301,17 +301,12 @@ func (f *File) saveExport(x interface{}, context astContext) {
|
||||
error_(c.Pos(), "export comment has wrong name %q, want %q", name, n.Name.Name)
|
||||
}
|
||||
|
||||
- doc := ""
|
||||
- for _, c1 := range n.Doc.List {
|
||||
- if c1 != c {
|
||||
- doc += c1.Text + "\n"
|
||||
- }
|
||||
- }
|
||||
-
|
||||
f.ExpFunc = append(f.ExpFunc, &ExpFunc{
|
||||
Func: n,
|
||||
ExpName: name,
|
||||
- Doc: doc,
|
||||
+ // Caution: Do not set the Doc field on purpose
|
||||
+ // to ensure that there are no unintended artifacts
|
||||
+ // in the binary. See https://go.dev/issue/76697.
|
||||
})
|
||||
break
|
||||
}
|
||||
--
|
||||
2.35.6
|
||||
175
meta/recipes-devtools/go/go/CVE-2025-68119-dependent.patch
Normal file
175
meta/recipes-devtools/go/go/CVE-2025-68119-dependent.patch
Normal file
@@ -0,0 +1,175 @@
|
||||
From 121b6cb231b5d904c03739495fcda69152d83f88 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Harbison <mharbison72@gmail.com>
|
||||
Date: Sat, 3 Aug 2024 00:06:30 +0000
|
||||
Subject: [PATCH] cmd/go: fix the accuracy of Mercurial vcs.* stamped data
|
||||
|
||||
There were a few Mercurial command line uses that could cause the wrong
|
||||
data to be used:
|
||||
|
||||
* The log command needs '-r.' to specify the currently checked out commit
|
||||
* HGPLAIN is needed to disable optional output on commands
|
||||
* '-S' is needed to for the 'status' command to recurse into any subrepos
|
||||
|
||||
The most likely issue to be seen here was the use of '-l1' instead of
|
||||
'-r.', which prints the most recent commit instead of the current checkout.
|
||||
Since tagging in Mercurial creates a new commit, this basically means the
|
||||
data was wrong for every tagged build.
|
||||
|
||||
This also adds an hgrc config file to the test, with config options to
|
||||
keep the time and author values fixed. It's what's used in the Mercurial
|
||||
test harness to keep the commit hashes stable, and allows the tests here to
|
||||
also match the time and the revision ID, to prevent regressing.
|
||||
|
||||
Fixes #63532
|
||||
|
||||
CVE: CVE-2025-68119
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/62452bed4801]
|
||||
|
||||
Change-Id: I5b9971ce87c83431ec77e4a002bdc33fcf393856
|
||||
GitHub-Last-Rev: 62c9db0a28fee5881d0fe49f7bbb6e1653c7ff60
|
||||
GitHub-Pull-Request: golang/go#63557
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/535377
|
||||
Reviewed-by: Bryan Mills <bcmills@google.com>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Sam Thanawalla <samthanawalla@google.com>
|
||||
Auto-Submit: Sam Thanawalla <samthanawalla@google.com>
|
||||
Reviewed-by: Michael Matloob <matloob@golang.org>
|
||||
(cherry picked from commit 62452bed480108623910feace4a5cea5448e6822)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/cmd/go/internal/vcs/vcs.go | 13 +++++--
|
||||
.../testdata/script/version_buildvcs_hg.txt | 39 ++++++++++++++++---
|
||||
2 files changed, 43 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go
|
||||
index 89d9f0e94e..60f76d77cf 100644
|
||||
--- a/src/cmd/go/internal/vcs/vcs.go
|
||||
+++ b/src/cmd/go/internal/vcs/vcs.go
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
type Cmd struct {
|
||||
Name string
|
||||
Cmd string // name of binary to invoke command
|
||||
+ Env []string // any environment values to set/override
|
||||
RootNames []rootName // filename and mode indicating the root of a checkout directory
|
||||
|
||||
CreateCmd []string // commands to download a fresh copy of a repository
|
||||
@@ -154,6 +155,10 @@ func vcsByCmd(cmd string) *Cmd {
|
||||
var vcsHg = &Cmd{
|
||||
Name: "Mercurial",
|
||||
Cmd: "hg",
|
||||
+
|
||||
+ // HGPLAIN=1 turns off additional output that a user may have enabled via
|
||||
+ // config options or certain extensions.
|
||||
+ Env: []string{"HGPLAIN=1"},
|
||||
RootNames: []rootName{
|
||||
{filename: ".hg", isDir: true},
|
||||
},
|
||||
@@ -189,12 +194,11 @@ func hgRemoteRepo(vcsHg *Cmd, rootDir string) (remoteRepo string, err error) {
|
||||
|
||||
func hgStatus(vcsHg *Cmd, rootDir string) (Status, error) {
|
||||
// Output changeset ID and seconds since epoch.
|
||||
- out, err := vcsHg.runOutputVerboseOnly(rootDir, `log -l1 -T {node}:{date|hgdate}`)
|
||||
+ out, err := vcsHg.runOutputVerboseOnly(rootDir, `log -r. -T {node}:{date|hgdate}`)
|
||||
if err != nil {
|
||||
return Status{}, err
|
||||
}
|
||||
|
||||
- // Successful execution without output indicates an empty repo (no commits).
|
||||
var rev string
|
||||
var commitTime time.Time
|
||||
if len(out) > 0 {
|
||||
@@ -209,7 +213,7 @@ func hgStatus(vcsHg *Cmd, rootDir string) (Status, error) {
|
||||
}
|
||||
|
||||
// Also look for untracked files.
|
||||
- out, err = vcsHg.runOutputVerboseOnly(rootDir, "status")
|
||||
+ out, err = vcsHg.runOutputVerboseOnly(rootDir, "status -S")
|
||||
if err != nil {
|
||||
return Status{}, err
|
||||
}
|
||||
@@ -689,6 +693,9 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([
|
||||
|
||||
cmd := exec.Command(v.Cmd, args...)
|
||||
cmd.Dir = dir
|
||||
+ if v.Env != nil {
|
||||
+ cmd.Env = append(cmd.Environ(), v.Env...)
|
||||
+ }
|
||||
if cfg.BuildX {
|
||||
fmt.Fprintf(os.Stderr, "cd %s\n", dir)
|
||||
fmt.Fprintf(os.Stderr, "%s %s\n", v.Cmd, strings.Join(args, " "))
|
||||
diff --git a/src/cmd/go/testdata/script/version_buildvcs_hg.txt b/src/cmd/go/testdata/script/version_buildvcs_hg.txt
|
||||
index fbbd886102..13904fae12 100644
|
||||
--- a/src/cmd/go/testdata/script/version_buildvcs_hg.txt
|
||||
+++ b/src/cmd/go/testdata/script/version_buildvcs_hg.txt
|
||||
@@ -6,6 +6,8 @@
|
||||
[short] skip
|
||||
env GOBIN=$WORK/gopath/bin
|
||||
env oldpath=$PATH
|
||||
+env TZ=GMT
|
||||
+env HGRCPATH=$WORK/hgrc
|
||||
cd repo/a
|
||||
|
||||
# If there's no local repository, there's no VCS info.
|
||||
@@ -29,24 +31,43 @@ cd ..
|
||||
env PATH=$oldpath
|
||||
rm .hg
|
||||
|
||||
-# If there is an empty repository in a parent directory, only "uncommitted" is tagged.
|
||||
+# An empty repository or one explicitly updated to null uses the null cset ID,
|
||||
+# and the time is hard set to 1/1/70, regardless of the current time.
|
||||
exec hg init
|
||||
cd a
|
||||
go install
|
||||
go version -m $GOBIN/a$GOEXE
|
||||
-! stdout vcs.revision
|
||||
-! stdout vcs.time
|
||||
+stdout '^\tbuild\tvcs.revision=0000000000000000000000000000000000000000$'
|
||||
+stdout '^\tbuild\tvcs.time=1970-01-01T00:00:00Z$'
|
||||
stdout '^\tbuild\tvcs.modified=true$'
|
||||
cd ..
|
||||
|
||||
# Revision and commit time are tagged for repositories with commits.
|
||||
exec hg add a README
|
||||
-exec hg commit -m 'initial commit'
|
||||
+exec hg commit -m 'initial commit' --user test-user --date '2024-07-31T01:21:27+00:00'
|
||||
cd a
|
||||
go install
|
||||
go version -m $GOBIN/a$GOEXE
|
||||
-stdout '^\tbuild\tvcs.revision='
|
||||
-stdout '^\tbuild\tvcs.time='
|
||||
+stdout '^\tbuild\tvcs.revision=71eaed52daeaafea83cb604f75b0a0336ef2c345$'
|
||||
+stdout '^\tbuild\tvcs.time=2024-07-31T01:21:27Z$'
|
||||
+stdout '^\tbuild\tvcs.modified=false$'
|
||||
+rm $GOBIN/a$GOEXE
|
||||
+
|
||||
+# Add an extra commit and then back off of it to show that the hash is
|
||||
+# from the checked out revision, not the tip revision.
|
||||
+cp ../../outside/empty.txt .
|
||||
+exec hg ci -Am 'another commit' --user test-user --date '2024-08-01T19:24:38+00:00'
|
||||
+exec hg update --clean -r '.^'
|
||||
+
|
||||
+# Modified state is not thrown off by extra status output
|
||||
+exec hg bisect -v -g .
|
||||
+exec hg bisect -v -b '.^^'
|
||||
+exec hg status
|
||||
+stdout '^.+'
|
||||
+go install
|
||||
+go version -m $GOBIN/a$GOEXE
|
||||
+stdout '^\tbuild\tvcs.revision=71eaed52daeaafea83cb604f75b0a0336ef2c345$'
|
||||
+stdout '^\tbuild\tvcs.time=2024-07-31T01:21:27Z$'
|
||||
stdout '^\tbuild\tvcs.modified=false$'
|
||||
rm $GOBIN/a$GOEXE
|
||||
|
||||
@@ -88,4 +109,10 @@ go 1.18
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
+-- $WORK/hgrc --
|
||||
+[ui]
|
||||
+# tweakdefaults is an opt-in that may print extra output in commands like
|
||||
+# status. That can be disabled by setting HGPLAIN=1.
|
||||
+tweakdefaults = 1
|
||||
+
|
||||
-- outside/empty.txt --
|
||||
--
|
||||
2.35.6
|
||||
828
meta/recipes-devtools/go/go/CVE-2025-68119.patch
Normal file
828
meta/recipes-devtools/go/go/CVE-2025-68119.patch
Normal file
@@ -0,0 +1,828 @@
|
||||
From 204e2fdacfbdb72a0b85fb526c8599128e430e94 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Wed, 10 Dec 2025 08:13:07 -0500
|
||||
Subject: [PATCH] [release-branch.go1.24] cmd/go: update VCS commands to use
|
||||
safer flag/argument syntax
|
||||
|
||||
In various situations, the toolchain invokes VCS commands. Some of these
|
||||
commands take arbitrary input, either provided by users or fetched from
|
||||
external sources. To prevent potential command injection vulnerabilities
|
||||
or misinterpretation of arguments as flags, this change updates the VCS
|
||||
commands to use various techniques to separate flags from positional
|
||||
arguments, and to directly associate flags with their values.
|
||||
|
||||
Additionally, we update the environment variable for Mercurial to use
|
||||
`HGPLAIN=+strictflags`, which is the more explicit way to disable user
|
||||
configurations (intended or otherwise) that might interfere with command
|
||||
execution.
|
||||
|
||||
We also now disallow version strings from being prefixed with '-' or
|
||||
'/', as doing so opens us up to making the same mistake again in the
|
||||
future. As far as we know there are currently ~0 public modules affected
|
||||
by this.
|
||||
|
||||
While I was working on cmd/go/internal/vcs, I also noticed that a
|
||||
significant portion of the commands being implemented were dead code.
|
||||
In order to reduce the maintenance burden and surface area for potential
|
||||
issues, I removed the dead code for unused commands.
|
||||
|
||||
We should probably follow up with a more structured change to make it
|
||||
harder to accidentally re-introduce these issues in the future, but for
|
||||
now this addresses the issue at hand.
|
||||
|
||||
Thanks to splitline (@splitline) from DEVCORE Research Team for
|
||||
reporting this issue.
|
||||
|
||||
Fixes CVE-2025-68119
|
||||
Updates #77099
|
||||
Fixes #77103
|
||||
|
||||
CVE: CVE-2025-68119
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/73fe85f0ea1b]
|
||||
|
||||
Backport Changes:
|
||||
- In file src/cmd/go/internal/modfetch/codehost/git.go, Replaced the
|
||||
function call runGIT with RUN. This changes is not present in current
|
||||
version v1.22.12 and this changes were introduced in version v1.24 by
|
||||
this commit https://github.com/golang/go/commit/8aa2eed8fb90
|
||||
|
||||
Change-Id: I9d9f4ee05b95be49fe14edf71a1b8e6c0784378e
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3260
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/736710
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
Reviewed-by: Junyang Shao <shaojunyang@google.com>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
(cherry picked from commit 94a1296a457387d1fd6eca1a9bcd44e89bdd9d55)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/739421
|
||||
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
|
||||
(cherry picked from commit 73fe85f0ea1bf2cec8e9a89bf5645de06ecaa0a6)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/cmd/go/internal/modcmd/edit.go | 10 +-
|
||||
src/cmd/go/internal/modfetch/codehost/git.go | 20 +-
|
||||
src/cmd/go/internal/modfetch/codehost/vcs.go | 20 +-
|
||||
src/cmd/go/internal/modget/query.go | 5 +-
|
||||
src/cmd/go/internal/modload/build.go | 12 +-
|
||||
src/cmd/go/internal/modload/list.go | 30 +-
|
||||
src/cmd/go/internal/toolchain/select.go | 7 +-
|
||||
src/cmd/go/internal/vcs/vcs.go | 331 +------------------
|
||||
src/cmd/go/internal/workcmd/edit.go | 5 +-
|
||||
9 files changed, 96 insertions(+), 344 deletions(-)
|
||||
|
||||
diff --git a/src/cmd/go/internal/modcmd/edit.go b/src/cmd/go/internal/modcmd/edit.go
|
||||
index db131b0881..330603fe32 100644
|
||||
--- a/src/cmd/go/internal/modcmd/edit.go
|
||||
+++ b/src/cmd/go/internal/modcmd/edit.go
|
||||
@@ -284,7 +284,10 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) {
|
||||
|
||||
// parsePathVersion parses -flag=arg expecting arg to be path@version.
|
||||
func parsePathVersion(flag, arg string) (path, version string) {
|
||||
- before, after, found := strings.Cut(arg, "@")
|
||||
+ before, after, found, err := modload.ParsePathVersion(arg)
|
||||
+ if err != nil {
|
||||
+ base.Fatalf("go: -%s=%s: %v", flag, arg, err)
|
||||
+ }
|
||||
if !found {
|
||||
base.Fatalf("go: -%s=%s: need path@version", flag, arg)
|
||||
}
|
||||
@@ -318,7 +321,10 @@ func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version
|
||||
if allowDirPath && modfile.IsDirectoryPath(arg) {
|
||||
return arg, "", nil
|
||||
}
|
||||
- before, after, found := strings.Cut(arg, "@")
|
||||
+ before, after, found, err := modload.ParsePathVersion(arg)
|
||||
+ if err != nil {
|
||||
+ return "", "", err
|
||||
+ }
|
||||
if !found {
|
||||
path = arg
|
||||
} else {
|
||||
diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go
|
||||
index 9996be7af7..45727ae3fb 100644
|
||||
--- a/src/cmd/go/internal/modfetch/codehost/git.go
|
||||
+++ b/src/cmd/go/internal/modfetch/codehost/git.go
|
||||
@@ -246,7 +246,7 @@ func (r *gitRepo) loadRefs(ctx context.Context) (map[string]string, error) {
|
||||
r.refsErr = err
|
||||
return
|
||||
}
|
||||
- out, gitErr := Run(ctx, r.dir, "git", "ls-remote", "-q", r.remote)
|
||||
+ out, gitErr := Run(ctx, r.dir, "git", "ls-remote", "-q","--end-of-options", r.remote)
|
||||
release()
|
||||
|
||||
if gitErr != nil {
|
||||
@@ -509,7 +509,7 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro
|
||||
if fromTag && !slices.Contains(info.Tags, tag) {
|
||||
// The local repo includes the commit hash we want, but it is missing
|
||||
// the corresponding tag. Add that tag and try again.
|
||||
- _, err := Run(ctx, r.dir, "git", "tag", tag, hash)
|
||||
+ _, err := Run(ctx, r.dir, "git", "tag","--end-of-options", tag, hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -554,7 +554,7 @@ func (r *gitRepo) stat(ctx context.Context, rev string) (info *RevInfo, err erro
|
||||
// an apparent Git bug introduced in Git 2.21 (commit 61c771),
|
||||
// which causes the handler for protocol version 1 to sometimes miss
|
||||
// tags that point to the requested commit (see https://go.dev/issue/56881).
|
||||
- _, err = Run(ctx, r.dir, "git", "-c", "protocol.version=2", "fetch", "-f", "--depth=1", r.remote, refspec)
|
||||
+ _, err = Run(ctx, r.dir, "git", "-c", "protocol.version=2", "fetch", "-f", "--depth=1","--end-of-options", r.remote, refspec)
|
||||
release()
|
||||
|
||||
if err == nil {
|
||||
@@ -597,12 +597,12 @@ func (r *gitRepo) fetchRefsLocked(ctx context.Context) error {
|
||||
}
|
||||
defer release()
|
||||
|
||||
- if _, err := Run(ctx, r.dir, "git", "fetch", "-f", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
|
||||
+ if _, err := Run(ctx, r.dir, "git", "fetch", "-f","--end-of-options", r.remote, "refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filepath.Join(r.dir, "shallow")); err == nil {
|
||||
- if _, err := Run(ctx, r.dir, "git", "fetch", "--unshallow", "-f", r.remote); err != nil {
|
||||
+ if _, err := Run(ctx, r.dir, "git", "fetch", "--unshallow", "-f", "--end-of-options",r.remote); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -615,7 +615,7 @@ func (r *gitRepo) fetchRefsLocked(ctx context.Context) error {
|
||||
// statLocal returns a new RevInfo describing rev in the local git repository.
|
||||
// It uses version as info.Version.
|
||||
func (r *gitRepo) statLocal(ctx context.Context, version, rev string) (*RevInfo, error) {
|
||||
- out, err := Run(ctx, r.dir, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", rev, "--")
|
||||
+ out, err := Run(ctx, r.dir, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D","--end-of-options", rev, "--")
|
||||
if err != nil {
|
||||
// Return info with Origin.RepoSum if possible to allow caching of negative lookup.
|
||||
var info *RevInfo
|
||||
@@ -705,7 +705,7 @@ func (r *gitRepo) ReadFile(ctx context.Context, rev, file string, maxSize int64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
- out, err := Run(ctx, r.dir, "git", "cat-file", "blob", info.Name+":"+file)
|
||||
+ out, err := Run(ctx, r.dir, "git", "cat-file","--end-of-options", "blob", info.Name+":"+file)
|
||||
if err != nil {
|
||||
return nil, fs.ErrNotExist
|
||||
}
|
||||
@@ -723,7 +723,7 @@ func (r *gitRepo) RecentTag(ctx context.Context, rev, prefix string, allowed fun
|
||||
// result is definitive.
|
||||
describe := func() (definitive bool) {
|
||||
var out []byte
|
||||
- out, err = Run(ctx, r.dir, "git", "for-each-ref", "--format", "%(refname)", "refs/tags", "--merged", rev)
|
||||
+ out, err = Run(ctx, r.dir, "git", "for-each-ref", "--format=%(refname)", "--merged="+rev)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
@@ -865,7 +865,7 @@ func (r *gitRepo) ReadZip(ctx context.Context, rev, subdir string, maxSize int64
|
||||
// TODO: Use maxSize or drop it.
|
||||
args := []string{}
|
||||
if subdir != "" {
|
||||
- args = append(args, "--", subdir)
|
||||
+ args = append(args, subdir)
|
||||
}
|
||||
info, err := r.Stat(ctx, rev) // download rev into local git repo
|
||||
if err != nil {
|
||||
@@ -887,7 +887,7 @@ func (r *gitRepo) ReadZip(ctx context.Context, rev, subdir string, maxSize int64
|
||||
// text file line endings. Setting -c core.autocrlf=input means only
|
||||
// translate files on the way into the repo, not on the way out (archive).
|
||||
// The -c core.eol=lf should be unnecessary but set it anyway.
|
||||
- archive, err := Run(ctx, r.dir, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", info.Name, args)
|
||||
+ archive, err := Run(ctx, r.dir, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", "--end-of-options", info.Name, args)
|
||||
if err != nil {
|
||||
if bytes.Contains(err.(*RunError).Stderr, []byte("did not match any files")) {
|
||||
return nil, fs.ErrNotExist
|
||||
diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go
|
||||
index 5bd100556b..425f61269f 100644
|
||||
--- a/src/cmd/go/internal/modfetch/codehost/vcs.go
|
||||
+++ b/src/cmd/go/internal/modfetch/codehost/vcs.go
|
||||
@@ -162,20 +162,20 @@ var vcsCmds = map[string]*vcsCmd{
|
||||
branchRE: re(`(?m)^[^\n]+$`),
|
||||
badLocalRevRE: re(`(?m)^(tip)$`),
|
||||
statLocal: func(rev, remote string) []string {
|
||||
- return []string{"hg", "log", "-l1", "-r", rev, "--template", "{node} {date|hgdate} {tags}"}
|
||||
+ return []string{"hg", "log", "-l1", fmt.Sprintf("--rev=%s", rev), "--template", "{node} {date|hgdate} {tags}"}
|
||||
},
|
||||
parseStat: hgParseStat,
|
||||
fetch: []string{"hg", "pull", "-f"},
|
||||
latest: "tip",
|
||||
readFile: func(rev, file, remote string) []string {
|
||||
- return []string{"hg", "cat", "-r", rev, file}
|
||||
+ return []string{"hg", "cat", fmt.Sprintf("--rev=%s", rev), "--", file}
|
||||
},
|
||||
readZip: func(rev, subdir, remote, target string) []string {
|
||||
pattern := []string{}
|
||||
if subdir != "" {
|
||||
- pattern = []string{"-I", subdir + "/**"}
|
||||
+ pattern = []string{fmt.Sprintf("--include=%s", subdir+"/**")}
|
||||
}
|
||||
- return str.StringList("hg", "archive", "-t", "zip", "--no-decode", "-r", rev, "--prefix=prefix/", pattern, "--", target)
|
||||
+ return str.StringList("hg", "archive", "-t", "zip", "--no-decode", fmt.Sprintf("--rev=%s", rev), "--prefix=prefix/", pattern, "--", target)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -215,19 +215,19 @@ var vcsCmds = map[string]*vcsCmd{
|
||||
tagRE: re(`(?m)^\S+`),
|
||||
badLocalRevRE: re(`^revno:-`),
|
||||
statLocal: func(rev, remote string) []string {
|
||||
- return []string{"bzr", "log", "-l1", "--long", "--show-ids", "-r", rev}
|
||||
+ return []string{"bzr", "log", "-l1", "--long", "--show-ids", fmt.Sprintf("--revision=%s", rev)}
|
||||
},
|
||||
parseStat: bzrParseStat,
|
||||
latest: "revno:-1",
|
||||
readFile: func(rev, file, remote string) []string {
|
||||
- return []string{"bzr", "cat", "-r", rev, file}
|
||||
+ return []string{"bzr", "cat", fmt.Sprintf("--revision=%s", rev), "--", file}
|
||||
},
|
||||
readZip: func(rev, subdir, remote, target string) []string {
|
||||
extra := []string{}
|
||||
if subdir != "" {
|
||||
extra = []string{"./" + subdir}
|
||||
}
|
||||
- return str.StringList("bzr", "export", "--format=zip", "-r", rev, "--root=prefix/", "--", target, extra)
|
||||
+ return str.StringList("bzr", "export", "--format=zip", fmt.Sprintf("--revision=%s", rev), "--root=prefix/", "--", target, extra)
|
||||
},
|
||||
},
|
||||
|
||||
@@ -242,17 +242,17 @@ var vcsCmds = map[string]*vcsCmd{
|
||||
},
|
||||
tagRE: re(`XXXTODO`),
|
||||
statLocal: func(rev, remote string) []string {
|
||||
- return []string{"fossil", "info", "-R", ".fossil", rev}
|
||||
+ return []string{"fossil", "info", "-R", ".fossil", "--", rev}
|
||||
},
|
||||
parseStat: fossilParseStat,
|
||||
latest: "trunk",
|
||||
readFile: func(rev, file, remote string) []string {
|
||||
- return []string{"fossil", "cat", "-R", ".fossil", "-r", rev, file}
|
||||
+ return []string{"fossil", "cat", "-R", ".fossil", fmt.Sprintf("-r=%s", rev), "--", file}
|
||||
},
|
||||
readZip: func(rev, subdir, remote, target string) []string {
|
||||
extra := []string{}
|
||||
if subdir != "" && !strings.ContainsAny(subdir, "*?[],") {
|
||||
- extra = []string{"--include", subdir}
|
||||
+ extra = []string{fmt.Sprintf("--include=%s", subdir)}
|
||||
}
|
||||
// Note that vcsRepo.ReadZip below rewrites this command
|
||||
// to run in a different directory, to work around a fossil bug.
|
||||
diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go
|
||||
index 498ba6c2ff..0d33a52677 100644
|
||||
--- a/src/cmd/go/internal/modget/query.go
|
||||
+++ b/src/cmd/go/internal/modget/query.go
|
||||
@@ -139,7 +139,10 @@ func errSet(err error) pathSet { return pathSet{err: err} }
|
||||
// newQuery returns a new query parsed from the raw argument,
|
||||
// which must be either path or path@version.
|
||||
func newQuery(raw string) (*query, error) {
|
||||
- pattern, rawVers, found := strings.Cut(raw, "@")
|
||||
+ pattern, rawVers, found, err := modload.ParsePathVersion(raw)
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
if found && (strings.Contains(rawVers, "@") || rawVers == "") {
|
||||
return nil, fmt.Errorf("invalid module version syntax %q", raw)
|
||||
}
|
||||
diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go
|
||||
index 5cf1487c3e..08acf3aa2b 100644
|
||||
--- a/src/cmd/go/internal/modload/build.go
|
||||
+++ b/src/cmd/go/internal/modload/build.go
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
- "strings"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/cfg"
|
||||
@@ -88,7 +87,16 @@ func ModuleInfo(ctx context.Context, path string) *modinfo.ModulePublic {
|
||||
return nil
|
||||
}
|
||||
|
||||
- if path, vers, found := strings.Cut(path, "@"); found {
|
||||
+ path, vers, found, err := ParsePathVersion(path)
|
||||
+ if err != nil {
|
||||
+ return &modinfo.ModulePublic{
|
||||
+ Path: path,
|
||||
+ Error: &modinfo.ModuleError{
|
||||
+ Err: err.Error(),
|
||||
+ },
|
||||
+ }
|
||||
+ }
|
||||
+ if found {
|
||||
m := module.Version{Path: path, Version: vers}
|
||||
return moduleInfo(ctx, nil, m, 0, nil)
|
||||
}
|
||||
diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go
|
||||
index ef93c25121..e9efb1918e 100644
|
||||
--- a/src/cmd/go/internal/modload/list.go
|
||||
+++ b/src/cmd/go/internal/modload/list.go
|
||||
@@ -149,7 +149,11 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
|
||||
}
|
||||
continue
|
||||
}
|
||||
- if path, vers, found := strings.Cut(arg, "@"); found {
|
||||
+ path, vers, found, err := ParsePathVersion(arg)
|
||||
+ if err != nil {
|
||||
+ base.Fatalf("go: %v", err)
|
||||
+ }
|
||||
+ if found {
|
||||
if vers == "upgrade" || vers == "patch" {
|
||||
if _, ok := rs.rootSelected(path); !ok || rs.pruning == unpruned {
|
||||
needFullGraph = true
|
||||
@@ -175,7 +179,11 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List
|
||||
|
||||
matchedModule := map[module.Version]bool{}
|
||||
for _, arg := range args {
|
||||
- if path, vers, found := strings.Cut(arg, "@"); found {
|
||||
+ path, vers, found, err := ParsePathVersion(arg)
|
||||
+ if err != nil {
|
||||
+ base.Fatalf("go: %v", err)
|
||||
+ }
|
||||
+ if found {
|
||||
var current string
|
||||
if mg == nil {
|
||||
current, _ = rs.rootSelected(path)
|
||||
@@ -308,3 +316,21 @@ func modinfoError(path, vers string, err error) *modinfo.ModuleError {
|
||||
|
||||
return &modinfo.ModuleError{Err: err.Error()}
|
||||
}
|
||||
+
|
||||
+// ParsePathVersion parses arg expecting arg to be path@version. If there is no
|
||||
+// '@' in arg, found is false, vers is "", and path is arg. This mirrors the
|
||||
+// typical usage of strings.Cut. ParsePathVersion is meant to be a general
|
||||
+// replacement for strings.Cut in module version parsing. If the version is
|
||||
+// invalid, an error is returned. The version is considered invalid if it is
|
||||
+// prefixed with '-' or '/', which can cause security problems when constructing
|
||||
+// commands to execute that use the version.
|
||||
+func ParsePathVersion(arg string) (path, vers string, found bool, err error) {
|
||||
+ path, vers, found = strings.Cut(arg, "@")
|
||||
+ if !found {
|
||||
+ return arg, "", false, nil
|
||||
+ }
|
||||
+ if len(vers) > 0 && (vers[0] == '-' || vers[0] == '/') {
|
||||
+ return "", "", false, fmt.Errorf("invalid module version %q", vers)
|
||||
+ }
|
||||
+ return path, vers, true, nil
|
||||
+}
|
||||
diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go
|
||||
index 14a8d3c21d..838ebae6a7 100644
|
||||
--- a/src/cmd/go/internal/toolchain/select.go
|
||||
+++ b/src/cmd/go/internal/toolchain/select.go
|
||||
@@ -614,7 +614,10 @@ func goInstallVersion() bool {
|
||||
if !strings.Contains(pkgArg, "@") || build.IsLocalImport(pkgArg) || filepath.IsAbs(pkgArg) {
|
||||
return false
|
||||
}
|
||||
- path, version, _ := strings.Cut(pkgArg, "@")
|
||||
+ path, version, _, err := modload.ParsePathVersion(pkgArg)
|
||||
+ if err != nil {
|
||||
+ base.Fatalf("go: %v", err)
|
||||
+ }
|
||||
if path == "" || version == "" || gover.IsToolchain(path) {
|
||||
return false
|
||||
}
|
||||
@@ -650,7 +653,7 @@ func goInstallVersion() bool {
|
||||
allowed = nil
|
||||
}
|
||||
noneSelected := func(path string) (version string) { return "none" }
|
||||
- _, err := modload.QueryPackages(ctx, path, version, noneSelected, allowed)
|
||||
+ _, err = modload.QueryPackages(ctx, path, version, noneSelected, allowed)
|
||||
if errors.Is(err, gover.ErrTooNew) {
|
||||
// Run early switch, same one go install or go run would eventually do,
|
||||
// if it understood all the command-line flags.
|
||||
diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go
|
||||
index 60f76d77cf..55bf25ff62 100644
|
||||
--- a/src/cmd/go/internal/vcs/vcs.go
|
||||
+++ b/src/cmd/go/internal/vcs/vcs.go
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
- "regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -40,20 +39,10 @@ type Cmd struct {
|
||||
Env []string // any environment values to set/override
|
||||
RootNames []rootName // filename and mode indicating the root of a checkout directory
|
||||
|
||||
- CreateCmd []string // commands to download a fresh copy of a repository
|
||||
- DownloadCmd []string // commands to download updates into an existing repository
|
||||
-
|
||||
- TagCmd []tagCmd // commands to list tags
|
||||
- TagLookupCmd []tagCmd // commands to lookup tags before running tagSyncCmd
|
||||
- TagSyncCmd []string // commands to sync to specific tag
|
||||
- TagSyncDefault []string // commands to sync to default tag
|
||||
-
|
||||
Scheme []string
|
||||
PingCmd string
|
||||
|
||||
- RemoteRepo func(v *Cmd, rootDir string) (remoteRepo string, err error)
|
||||
- ResolveRepo func(v *Cmd, rootDir, remoteRepo string) (realRepo string, err error)
|
||||
- Status func(v *Cmd, rootDir string) (Status, error)
|
||||
+ Status func(v *Cmd, rootDir string) (Status, error)
|
||||
}
|
||||
|
||||
// Status is the current state of a local repository.
|
||||
@@ -156,40 +145,16 @@ var vcsHg = &Cmd{
|
||||
Name: "Mercurial",
|
||||
Cmd: "hg",
|
||||
|
||||
- // HGPLAIN=1 turns off additional output that a user may have enabled via
|
||||
- // config options or certain extensions.
|
||||
- Env: []string{"HGPLAIN=1"},
|
||||
+ // HGPLAIN=+strictflags turns off additional output that a user may have
|
||||
+ // enabled via config options or certain extensions.
|
||||
+ Env: []string{"HGPLAIN=+strictflags"},
|
||||
RootNames: []rootName{
|
||||
{filename: ".hg", isDir: true},
|
||||
},
|
||||
|
||||
- CreateCmd: []string{"clone -U -- {repo} {dir}"},
|
||||
- DownloadCmd: []string{"pull"},
|
||||
-
|
||||
- // We allow both tag and branch names as 'tags'
|
||||
- // for selecting a version. This lets people have
|
||||
- // a go.release.r60 branch and a go1 branch
|
||||
- // and make changes in both, without constantly
|
||||
- // editing .hgtags.
|
||||
- TagCmd: []tagCmd{
|
||||
- {"tags", `^(\S+)`},
|
||||
- {"branches", `^(\S+)`},
|
||||
- },
|
||||
- TagSyncCmd: []string{"update -r {tag}"},
|
||||
- TagSyncDefault: []string{"update default"},
|
||||
-
|
||||
- Scheme: []string{"https", "http", "ssh"},
|
||||
- PingCmd: "identify -- {scheme}://{repo}",
|
||||
- RemoteRepo: hgRemoteRepo,
|
||||
- Status: hgStatus,
|
||||
-}
|
||||
-
|
||||
-func hgRemoteRepo(vcsHg *Cmd, rootDir string) (remoteRepo string, err error) {
|
||||
- out, err := vcsHg.runOutput(rootDir, "paths default")
|
||||
- if err != nil {
|
||||
- return "", err
|
||||
- }
|
||||
- return strings.TrimSpace(string(out)), nil
|
||||
+ Scheme: []string{"https", "http", "ssh"},
|
||||
+ PingCmd: "identify -- {scheme}://{repo}",
|
||||
+ Status: hgStatus,
|
||||
}
|
||||
|
||||
func hgStatus(vcsHg *Cmd, rootDir string) (Status, error) {
|
||||
@@ -252,25 +217,6 @@ var vcsGit = &Cmd{
|
||||
{filename: ".git", isDir: true},
|
||||
},
|
||||
|
||||
- CreateCmd: []string{"clone -- {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"},
|
||||
- DownloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},
|
||||
-
|
||||
- TagCmd: []tagCmd{
|
||||
- // tags/xxx matches a git tag named xxx
|
||||
- // origin/xxx matches a git branch named xxx on the default remote repository
|
||||
- {"show-ref", `(?:tags|origin)/(\S+)$`},
|
||||
- },
|
||||
- TagLookupCmd: []tagCmd{
|
||||
- {"show-ref tags/{tag} origin/{tag}", `((?:tags|origin)/\S+)$`},
|
||||
- },
|
||||
- TagSyncCmd: []string{"checkout {tag}", "submodule update --init --recursive"},
|
||||
- // both createCmd and downloadCmd update the working dir.
|
||||
- // No need to do more here. We used to 'checkout master'
|
||||
- // but that doesn't work if the default branch is not named master.
|
||||
- // DO NOT add 'checkout master' here.
|
||||
- // See golang.org/issue/9032.
|
||||
- TagSyncDefault: []string{"submodule update --init --recursive"},
|
||||
-
|
||||
Scheme: []string{"git", "https", "http", "git+ssh", "ssh"},
|
||||
|
||||
// Leave out the '--' separator in the ls-remote command: git 2.7.4 does not
|
||||
@@ -279,54 +225,7 @@ var vcsGit = &Cmd{
|
||||
// See golang.org/issue/33836.
|
||||
PingCmd: "ls-remote {scheme}://{repo}",
|
||||
|
||||
- RemoteRepo: gitRemoteRepo,
|
||||
- Status: gitStatus,
|
||||
-}
|
||||
-
|
||||
-// scpSyntaxRe matches the SCP-like addresses used by Git to access
|
||||
-// repositories by SSH.
|
||||
-var scpSyntaxRe = lazyregexp.New(`^(\w+)@([\w.-]+):(.*)$`)
|
||||
-
|
||||
-func gitRemoteRepo(vcsGit *Cmd, rootDir string) (remoteRepo string, err error) {
|
||||
- const cmd = "config remote.origin.url"
|
||||
- outb, err := vcsGit.run1(rootDir, cmd, nil, false)
|
||||
- if err != nil {
|
||||
- // if it doesn't output any message, it means the config argument is correct,
|
||||
- // but the config value itself doesn't exist
|
||||
- if outb != nil && len(outb) == 0 {
|
||||
- return "", errors.New("remote origin not found")
|
||||
- }
|
||||
- return "", err
|
||||
- }
|
||||
- out := strings.TrimSpace(string(outb))
|
||||
-
|
||||
- var repoURL *urlpkg.URL
|
||||
- if m := scpSyntaxRe.FindStringSubmatch(out); m != nil {
|
||||
- // Match SCP-like syntax and convert it to a URL.
|
||||
- // Eg, "git@github.com:user/repo" becomes
|
||||
- // "ssh://git@github.com/user/repo".
|
||||
- repoURL = &urlpkg.URL{
|
||||
- Scheme: "ssh",
|
||||
- User: urlpkg.User(m[1]),
|
||||
- Host: m[2],
|
||||
- Path: m[3],
|
||||
- }
|
||||
- } else {
|
||||
- repoURL, err = urlpkg.Parse(out)
|
||||
- if err != nil {
|
||||
- return "", err
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Iterate over insecure schemes too, because this function simply
|
||||
- // reports the state of the repo. If we can't see insecure schemes then
|
||||
- // we can't report the actual repo URL.
|
||||
- for _, s := range vcsGit.Scheme {
|
||||
- if repoURL.Scheme == s {
|
||||
- return repoURL.String(), nil
|
||||
- }
|
||||
- }
|
||||
- return "", errors.New("unable to parse output of git " + cmd)
|
||||
+ Status: gitStatus,
|
||||
}
|
||||
|
||||
func gitStatus(vcsGit *Cmd, rootDir string) (Status, error) {
|
||||
@@ -366,62 +265,9 @@ var vcsBzr = &Cmd{
|
||||
{filename: ".bzr", isDir: true},
|
||||
},
|
||||
|
||||
- CreateCmd: []string{"branch -- {repo} {dir}"},
|
||||
-
|
||||
- // Without --overwrite bzr will not pull tags that changed.
|
||||
- // Replace by --overwrite-tags after http://pad.lv/681792 goes in.
|
||||
- DownloadCmd: []string{"pull --overwrite"},
|
||||
-
|
||||
- TagCmd: []tagCmd{{"tags", `^(\S+)`}},
|
||||
- TagSyncCmd: []string{"update -r {tag}"},
|
||||
- TagSyncDefault: []string{"update -r revno:-1"},
|
||||
-
|
||||
- Scheme: []string{"https", "http", "bzr", "bzr+ssh"},
|
||||
- PingCmd: "info -- {scheme}://{repo}",
|
||||
- RemoteRepo: bzrRemoteRepo,
|
||||
- ResolveRepo: bzrResolveRepo,
|
||||
- Status: bzrStatus,
|
||||
-}
|
||||
-
|
||||
-func bzrRemoteRepo(vcsBzr *Cmd, rootDir string) (remoteRepo string, err error) {
|
||||
- outb, err := vcsBzr.runOutput(rootDir, "config parent_location")
|
||||
- if err != nil {
|
||||
- return "", err
|
||||
- }
|
||||
- return strings.TrimSpace(string(outb)), nil
|
||||
-}
|
||||
-
|
||||
-func bzrResolveRepo(vcsBzr *Cmd, rootDir, remoteRepo string) (realRepo string, err error) {
|
||||
- outb, err := vcsBzr.runOutput(rootDir, "info "+remoteRepo)
|
||||
- if err != nil {
|
||||
- return "", err
|
||||
- }
|
||||
- out := string(outb)
|
||||
-
|
||||
- // Expect:
|
||||
- // ...
|
||||
- // (branch root|repository branch): <URL>
|
||||
- // ...
|
||||
-
|
||||
- found := false
|
||||
- for _, prefix := range []string{"\n branch root: ", "\n repository branch: "} {
|
||||
- i := strings.Index(out, prefix)
|
||||
- if i >= 0 {
|
||||
- out = out[i+len(prefix):]
|
||||
- found = true
|
||||
- break
|
||||
- }
|
||||
- }
|
||||
- if !found {
|
||||
- return "", fmt.Errorf("unable to parse output of bzr info")
|
||||
- }
|
||||
-
|
||||
- i := strings.Index(out, "\n")
|
||||
- if i < 0 {
|
||||
- return "", fmt.Errorf("unable to parse output of bzr info")
|
||||
- }
|
||||
- out = out[:i]
|
||||
- return strings.TrimSpace(out), nil
|
||||
+ Scheme: []string{"https", "http", "bzr", "bzr+ssh"},
|
||||
+ PingCmd: "info -- {scheme}://{repo}",
|
||||
+ Status: bzrStatus,
|
||||
}
|
||||
|
||||
func bzrStatus(vcsBzr *Cmd, rootDir string) (Status, error) {
|
||||
@@ -489,45 +335,11 @@ var vcsSvn = &Cmd{
|
||||
{filename: ".svn", isDir: true},
|
||||
},
|
||||
|
||||
- CreateCmd: []string{"checkout -- {repo} {dir}"},
|
||||
- DownloadCmd: []string{"update"},
|
||||
-
|
||||
// There is no tag command in subversion.
|
||||
// The branch information is all in the path names.
|
||||
|
||||
- Scheme: []string{"https", "http", "svn", "svn+ssh"},
|
||||
- PingCmd: "info -- {scheme}://{repo}",
|
||||
- RemoteRepo: svnRemoteRepo,
|
||||
-}
|
||||
-
|
||||
-func svnRemoteRepo(vcsSvn *Cmd, rootDir string) (remoteRepo string, err error) {
|
||||
- outb, err := vcsSvn.runOutput(rootDir, "info")
|
||||
- if err != nil {
|
||||
- return "", err
|
||||
- }
|
||||
- out := string(outb)
|
||||
-
|
||||
- // Expect:
|
||||
- //
|
||||
- // ...
|
||||
- // URL: <URL>
|
||||
- // ...
|
||||
- //
|
||||
- // Note that we're not using the Repository Root line,
|
||||
- // because svn allows checking out subtrees.
|
||||
- // The URL will be the URL of the subtree (what we used with 'svn co')
|
||||
- // while the Repository Root may be a much higher parent.
|
||||
- i := strings.Index(out, "\nURL: ")
|
||||
- if i < 0 {
|
||||
- return "", fmt.Errorf("unable to parse output of svn info")
|
||||
- }
|
||||
- out = out[i+len("\nURL: "):]
|
||||
- i = strings.Index(out, "\n")
|
||||
- if i < 0 {
|
||||
- return "", fmt.Errorf("unable to parse output of svn info")
|
||||
- }
|
||||
- out = out[:i]
|
||||
- return strings.TrimSpace(out), nil
|
||||
+ Scheme: []string{"https", "http", "svn", "svn+ssh"},
|
||||
+ PingCmd: "info -- {scheme}://{repo}",
|
||||
}
|
||||
|
||||
// fossilRepoName is the name go get associates with a fossil repository. In the
|
||||
@@ -543,24 +355,8 @@ var vcsFossil = &Cmd{
|
||||
{filename: "_FOSSIL_", isDir: false},
|
||||
},
|
||||
|
||||
- CreateCmd: []string{"-go-internal-mkdir {dir} clone -- {repo} " + filepath.Join("{dir}", fossilRepoName), "-go-internal-cd {dir} open .fossil"},
|
||||
- DownloadCmd: []string{"up"},
|
||||
-
|
||||
- TagCmd: []tagCmd{{"tag ls", `(.*)`}},
|
||||
- TagSyncCmd: []string{"up tag:{tag}"},
|
||||
- TagSyncDefault: []string{"up trunk"},
|
||||
-
|
||||
- Scheme: []string{"https", "http"},
|
||||
- RemoteRepo: fossilRemoteRepo,
|
||||
- Status: fossilStatus,
|
||||
-}
|
||||
-
|
||||
-func fossilRemoteRepo(vcsFossil *Cmd, rootDir string) (remoteRepo string, err error) {
|
||||
- out, err := vcsFossil.runOutput(rootDir, "remote-url")
|
||||
- if err != nil {
|
||||
- return "", err
|
||||
- }
|
||||
- return strings.TrimSpace(string(out)), nil
|
||||
+ Scheme: []string{"https", "http"},
|
||||
+ Status: fossilStatus,
|
||||
}
|
||||
|
||||
var errFossilInfo = errors.New("unable to parse output of fossil info")
|
||||
@@ -661,7 +457,7 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([
|
||||
args[i] = expand(m, arg)
|
||||
}
|
||||
|
||||
- if len(args) >= 2 && args[0] == "-go-internal-mkdir" {
|
||||
+ if len(args) >= 2 && args[0] == "--go-internal-mkdir" {
|
||||
var err error
|
||||
if filepath.IsAbs(args[1]) {
|
||||
err = os.Mkdir(args[1], fs.ModePerm)
|
||||
@@ -674,7 +470,7 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([
|
||||
args = args[2:]
|
||||
}
|
||||
|
||||
- if len(args) >= 2 && args[0] == "-go-internal-cd" {
|
||||
+ if len(args) >= 2 && args[0] == "--go-internal-cd" {
|
||||
if filepath.IsAbs(args[1]) {
|
||||
dir = args[1]
|
||||
} else {
|
||||
@@ -735,99 +531,6 @@ func (v *Cmd) Ping(scheme, repo string) error {
|
||||
return v.runVerboseOnly(dir, v.PingCmd, "scheme", scheme, "repo", repo)
|
||||
}
|
||||
|
||||
-// Create creates a new copy of repo in dir.
|
||||
-// The parent of dir must exist; dir must not.
|
||||
-func (v *Cmd) Create(dir, repo string) error {
|
||||
- release, err := base.AcquireNet()
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- defer release()
|
||||
-
|
||||
- for _, cmd := range v.CreateCmd {
|
||||
- if err := v.run(filepath.Dir(dir), cmd, "dir", dir, "repo", repo); err != nil {
|
||||
- return err
|
||||
- }
|
||||
- }
|
||||
- return nil
|
||||
-}
|
||||
-
|
||||
-// Download downloads any new changes for the repo in dir.
|
||||
-func (v *Cmd) Download(dir string) error {
|
||||
- release, err := base.AcquireNet()
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- defer release()
|
||||
-
|
||||
- for _, cmd := range v.DownloadCmd {
|
||||
- if err := v.run(dir, cmd); err != nil {
|
||||
- return err
|
||||
- }
|
||||
- }
|
||||
- return nil
|
||||
-}
|
||||
-
|
||||
-// Tags returns the list of available tags for the repo in dir.
|
||||
-func (v *Cmd) Tags(dir string) ([]string, error) {
|
||||
- var tags []string
|
||||
- for _, tc := range v.TagCmd {
|
||||
- out, err := v.runOutput(dir, tc.cmd)
|
||||
- if err != nil {
|
||||
- return nil, err
|
||||
- }
|
||||
- re := regexp.MustCompile(`(?m-s)` + tc.pattern)
|
||||
- for _, m := range re.FindAllStringSubmatch(string(out), -1) {
|
||||
- tags = append(tags, m[1])
|
||||
- }
|
||||
- }
|
||||
- return tags, nil
|
||||
-}
|
||||
-
|
||||
-// TagSync syncs the repo in dir to the named tag,
|
||||
-// which either is a tag returned by tags or is v.tagDefault.
|
||||
-func (v *Cmd) TagSync(dir, tag string) error {
|
||||
- if v.TagSyncCmd == nil {
|
||||
- return nil
|
||||
- }
|
||||
- if tag != "" {
|
||||
- for _, tc := range v.TagLookupCmd {
|
||||
- out, err := v.runOutput(dir, tc.cmd, "tag", tag)
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- re := regexp.MustCompile(`(?m-s)` + tc.pattern)
|
||||
- m := re.FindStringSubmatch(string(out))
|
||||
- if len(m) > 1 {
|
||||
- tag = m[1]
|
||||
- break
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- release, err := base.AcquireNet()
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- defer release()
|
||||
-
|
||||
- if tag == "" && v.TagSyncDefault != nil {
|
||||
- for _, cmd := range v.TagSyncDefault {
|
||||
- if err := v.run(dir, cmd); err != nil {
|
||||
- return err
|
||||
- }
|
||||
- }
|
||||
- return nil
|
||||
- }
|
||||
-
|
||||
- for _, cmd := range v.TagSyncCmd {
|
||||
- if err := v.run(dir, cmd, "tag", tag); err != nil {
|
||||
- return err
|
||||
- }
|
||||
- }
|
||||
- return nil
|
||||
-}
|
||||
-
|
||||
// A vcsPath describes how to convert an import path into a
|
||||
// version control system and repository name.
|
||||
type vcsPath struct {
|
||||
diff --git a/src/cmd/go/internal/workcmd/edit.go b/src/cmd/go/internal/workcmd/edit.go
|
||||
index 8d975b0b3d..c1252cc95e 100644
|
||||
--- a/src/cmd/go/internal/workcmd/edit.go
|
||||
+++ b/src/cmd/go/internal/workcmd/edit.go
|
||||
@@ -242,7 +242,10 @@ func allowedVersionArg(arg string) bool {
|
||||
// parsePathVersionOptional parses path[@version], using adj to
|
||||
// describe any errors.
|
||||
func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version string, err error) {
|
||||
- before, after, found := strings.Cut(arg, "@")
|
||||
+ before, after, found, err := modload.ParsePathVersion(arg)
|
||||
+ if err != nil {
|
||||
+ return "", "", err
|
||||
+ }
|
||||
if !found {
|
||||
path = arg
|
||||
} else {
|
||||
--
|
||||
2.35.6
|
||||
253
meta/recipes-devtools/go/go/CVE-2025-68121_p1.patch
Normal file
253
meta/recipes-devtools/go/go/CVE-2025-68121_p1.patch
Normal file
@@ -0,0 +1,253 @@
|
||||
From 529caf01aff2314585688c0f92f009d0ad0914be Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <roland@golang.org>
|
||||
Date: Mon, 26 Jan 2026 10:55:32 -0800
|
||||
Subject: [PATCH 1/2] [release-branch.go1.24] crypto/tls: add verifiedChains
|
||||
expiration checking during resumption
|
||||
|
||||
When resuming a session, check that the verifiedChains contain at least
|
||||
one chain that is still valid at the time of resumption. If not, trigger
|
||||
a new handshake.
|
||||
|
||||
Updates #77113
|
||||
Updates #77355
|
||||
Updates CVE-2025-68121
|
||||
|
||||
CVE: CVE-2025-68121
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/5f07b226f9aa]
|
||||
|
||||
Change-Id: I14f585c43da17802513cbdd5b10c552d7a38b34e
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/739321
|
||||
Reviewed-by: Coia Prant <coiaprant@gmail.com>
|
||||
Reviewed-by: Filippo Valsorda <filippo@golang.org>
|
||||
Auto-Submit: Roland Shoemaker <roland@golang.org>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/740061
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-by: Nicholas Husin <nsh@golang.org>
|
||||
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
(cherry picked from commit 5f07b226f9aa185aca4b88a9ae58456d7800fc06)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/crypto/tls/common.go | 13 +++
|
||||
src/crypto/tls/handshake_client.go | 10 +-
|
||||
src/crypto/tls/handshake_server.go | 2 +-
|
||||
src/crypto/tls/handshake_server_test.go | 122 +++++++++++++++++++++++
|
||||
src/crypto/tls/handshake_server_tls13.go | 2 +-
|
||||
5 files changed, 144 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
|
||||
index 849e8b0a20..738c7e100b 100644
|
||||
--- a/src/crypto/tls/common.go
|
||||
+++ b/src/crypto/tls/common.go
|
||||
@@ -1555,3 +1555,16 @@ func (e *CertificateVerificationError) Error() string {
|
||||
func (e *CertificateVerificationError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
+
|
||||
+// anyUnexpiredChain reports if at least one of verifiedChains is still
|
||||
+// unexpired. If verifiedChains is empty, it returns false.
|
||||
+func anyUnexpiredChain(verifiedChains [][]*x509.Certificate, now time.Time) bool {
|
||||
+ for _, chain := range verifiedChains {
|
||||
+ if len(chain) != 0 && !slices.ContainsFunc(chain, func(cert *x509.Certificate) bool {
|
||||
+ return now.Before(cert.NotBefore) || now.After(cert.NotAfter) // cert is expired
|
||||
+ }) {
|
||||
+ return true
|
||||
+ }
|
||||
+ }
|
||||
+ return false
|
||||
+}
|
||||
diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
|
||||
index 08a2d47974..c2ff9e1959 100644
|
||||
--- a/src/crypto/tls/handshake_client.go
|
||||
+++ b/src/crypto/tls/handshake_client.go
|
||||
@@ -322,9 +322,6 @@ func (c *Conn) loadSession(hello *clientHelloMsg) (
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
|
||||
- // Check that the cached server certificate is not expired, and that it's
|
||||
- // valid for the ServerName. This should be ensured by the cache key, but
|
||||
- // protect the application from a faulty ClientSessionCache implementation.
|
||||
if c.config.time().After(session.peerCertificates[0].NotAfter) {
|
||||
// Expired certificate, delete the entry.
|
||||
c.config.ClientSessionCache.Put(cacheKey, nil)
|
||||
@@ -336,6 +333,13 @@ func (c *Conn) loadSession(hello *clientHelloMsg) (
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
if err := session.peerCertificates[0].VerifyHostname(c.config.ServerName); err != nil {
|
||||
+ // This should be ensured by the cache key, but protect the
|
||||
+ // application from a faulty ClientSessionCache implementation.
|
||||
+ return nil, nil, nil, nil
|
||||
+ }
|
||||
+ if !anyUnexpiredChain(session.verifiedChains, c.config.time()) {
|
||||
+ // No valid chains, delete the entry.
|
||||
+ c.config.ClientSessionCache.Put(cacheKey, nil)
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
}
|
||||
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
|
||||
index 17b6891783..608b2535f1 100644
|
||||
--- a/src/crypto/tls/handshake_server.go
|
||||
+++ b/src/crypto/tls/handshake_server.go
|
||||
@@ -483,7 +483,7 @@ func (hs *serverHandshakeState) checkForResumption() error {
|
||||
return nil
|
||||
}
|
||||
if sessionHasClientCerts && c.config.ClientAuth >= VerifyClientCertIfGiven &&
|
||||
- len(sessionState.verifiedChains) == 0 {
|
||||
+ !anyUnexpiredChain(sessionState.verifiedChains, c.config.time()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go
|
||||
index 0f10a3e7a6..9eff106ecf 100644
|
||||
--- a/src/crypto/tls/handshake_server_test.go
|
||||
+++ b/src/crypto/tls/handshake_server_test.go
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
+ "crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -2049,3 +2050,124 @@ func TestHandshakeContextHierarchy(t *testing.T) {
|
||||
t.Errorf("Unexpected client error: %v", err)
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestHandshakeChainExpiryResumption(t *testing.T) {
|
||||
+ t.Run("TLS1.2", func(t *testing.T) {
|
||||
+ testHandshakeChainExpiryResumption(t, VersionTLS12)
|
||||
+ })
|
||||
+ t.Run("TLS1.3", func(t *testing.T) {
|
||||
+ testHandshakeChainExpiryResumption(t, VersionTLS13)
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
+func testHandshakeChainExpiryResumption(t *testing.T, version uint16) {
|
||||
+ now := time.Now()
|
||||
+
|
||||
+ createChain := func(leafNotAfter, rootNotAfter time.Time) (leafDER, expiredLeafDER []byte, root *x509.Certificate) {
|
||||
+ tmpl := &x509.Certificate{
|
||||
+ Subject: pkix.Name{CommonName: "root"},
|
||||
+ NotBefore: rootNotAfter.Add(-time.Hour * 24),
|
||||
+ NotAfter: rootNotAfter,
|
||||
+ IsCA: true,
|
||||
+ BasicConstraintsValid: true,
|
||||
+ }
|
||||
+ rootDER, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+ root, err = x509.ParseCertificate(rootDER)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("ParseCertificate: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ tmpl = &x509.Certificate{
|
||||
+ Subject: pkix.Name{},
|
||||
+ DNSNames: []string{"expired-resume.example.com"},
|
||||
+ NotBefore: leafNotAfter.Add(-time.Hour * 24),
|
||||
+ NotAfter: leafNotAfter,
|
||||
+ KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
+ }
|
||||
+ leafCertDER, err := x509.CreateCertificate(rand.Reader, tmpl, root, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+ tmpl.NotBefore, tmpl.NotAfter = leafNotAfter.Add(-time.Hour*24*365), leafNotAfter.Add(-time.Hour*24*364)
|
||||
+ expiredLeafDERCertDER, err := x509.CreateCertificate(rand.Reader, tmpl, root, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ return leafCertDER, expiredLeafDERCertDER, root
|
||||
+ }
|
||||
+ testExpiration := func(name string, leafNotAfter, rootNotAfter time.Time) {
|
||||
+ t.Run(name, func(t *testing.T) {
|
||||
+ initialLeafDER, expiredLeafDER, initialRoot := createChain(leafNotAfter, rootNotAfter)
|
||||
+
|
||||
+ serverConfig := testConfig.Clone()
|
||||
+ serverConfig.MaxVersion = version
|
||||
+ serverConfig.Certificates = []Certificate{{
|
||||
+ Certificate: [][]byte{initialLeafDER, expiredLeafDER},
|
||||
+ PrivateKey: testECDSAPrivateKey,
|
||||
+ }}
|
||||
+ serverConfig.ClientCAs = x509.NewCertPool()
|
||||
+ serverConfig.ClientCAs.AddCert(initialRoot)
|
||||
+ serverConfig.ClientAuth = RequireAndVerifyClientCert
|
||||
+ serverConfig.Time = func() time.Time {
|
||||
+ return now
|
||||
+ }
|
||||
+ serverConfig.InsecureSkipVerify = false
|
||||
+ serverConfig.ServerName = "expired-resume.example.com"
|
||||
+
|
||||
+ clientConfig := testConfig.Clone()
|
||||
+ clientConfig.MaxVersion = version
|
||||
+ clientConfig.Certificates = []Certificate{{
|
||||
+ Certificate: [][]byte{initialLeafDER, expiredLeafDER},
|
||||
+ PrivateKey: testECDSAPrivateKey,
|
||||
+ }}
|
||||
+ clientConfig.RootCAs = x509.NewCertPool()
|
||||
+ clientConfig.RootCAs.AddCert(initialRoot)
|
||||
+ clientConfig.ServerName = "expired-resume.example.com"
|
||||
+ clientConfig.ClientSessionCache = NewLRUClientSessionCache(32)
|
||||
+ clientConfig.InsecureSkipVerify = false
|
||||
+ clientConfig.ServerName = "expired-resume.example.com"
|
||||
+ clientConfig.Time = func() time.Time {
|
||||
+ return now
|
||||
+ }
|
||||
+
|
||||
+ testResume := func(t *testing.T, sc, cc *Config, expectResume bool) {
|
||||
+ t.Helper()
|
||||
+ ss, cs, err := testHandshake(t, cc, sc)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("handshake: %v", err)
|
||||
+ }
|
||||
+ if cs.DidResume != expectResume {
|
||||
+ t.Fatalf("DidResume = %v; want %v", cs.DidResume, expectResume)
|
||||
+ }
|
||||
+ if ss.DidResume != expectResume {
|
||||
+ t.Fatalf("DidResume = %v; want %v", cs.DidResume, expectResume)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ testResume(t, serverConfig, clientConfig, false)
|
||||
+ testResume(t, serverConfig, clientConfig, true)
|
||||
+
|
||||
+ expiredNow := time.Unix(0, min(leafNotAfter.UnixNano(), rootNotAfter.UnixNano())).Add(time.Minute)
|
||||
+
|
||||
+ freshLeafDER, expiredLeafDER, freshRoot := createChain(expiredNow.Add(time.Hour), expiredNow.Add(time.Hour))
|
||||
+ clientConfig.Certificates = []Certificate{{
|
||||
+ Certificate: [][]byte{freshLeafDER, expiredLeafDER},
|
||||
+ PrivateKey: testECDSAPrivateKey,
|
||||
+ }}
|
||||
+ serverConfig.Time = func() time.Time {
|
||||
+ return expiredNow
|
||||
+ }
|
||||
+ serverConfig.ClientCAs = x509.NewCertPool()
|
||||
+ serverConfig.ClientCAs.AddCert(freshRoot)
|
||||
+
|
||||
+ testResume(t, serverConfig, clientConfig, false)
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ testExpiration("LeafExpiresBeforeRoot", now.Add(2*time.Hour), now.Add(3*time.Hour))
|
||||
+ testExpiration("LeafExpiresAfterRoot", now.Add(2*time.Hour), now.Add(time.Hour))
|
||||
+}
|
||||
diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go
|
||||
index 5aa69e9640..a48a296721 100644
|
||||
--- a/src/crypto/tls/handshake_server_tls13.go
|
||||
+++ b/src/crypto/tls/handshake_server_tls13.go
|
||||
@@ -346,7 +346,7 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error {
|
||||
continue
|
||||
}
|
||||
if sessionHasClientCerts && c.config.ClientAuth >= VerifyClientCertIfGiven &&
|
||||
- len(sessionState.verifiedChains) == 0 {
|
||||
+ !anyUnexpiredChain(sessionState.verifiedChains, c.config.time()) {
|
||||
continue
|
||||
}
|
||||
|
||||
--
|
||||
2.35.6
|
||||
385
meta/recipes-devtools/go/go/CVE-2025-68121_p2.patch
Normal file
385
meta/recipes-devtools/go/go/CVE-2025-68121_p2.patch
Normal file
@@ -0,0 +1,385 @@
|
||||
From c22ca724688b18d51b4bbf97ec42914a7b2642c5 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <roland@golang.org>
|
||||
Date: Mon, 26 Jan 2026 11:18:45 -0800
|
||||
Subject: [PATCH] [release-branch.go1.24] crypto/tls: check verifiedChains
|
||||
roots when resuming sessions
|
||||
|
||||
When resuming TLS sessions, on the server and client verify that the
|
||||
chains stored in the session state (verifiedChains) are still acceptable
|
||||
with regards to the Config by checking for the inclusion of the root in
|
||||
either ClientCAs (server) or RootCAs (client). This prevents resuming
|
||||
a session with a certificate chain that would be rejected during a full
|
||||
handshake due to an untrusted root.
|
||||
|
||||
Updates #77113
|
||||
Updates #77355
|
||||
Updates CVE-2025-68121
|
||||
|
||||
CVE: CVE-2025-68121
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/cb75daf3b291]
|
||||
|
||||
Backport Changes:
|
||||
- In src/crypto/tls/common.go, the upstream fix introduces the use of
|
||||
slices.ContainsFunc(). To align with that change, the slices library
|
||||
needs to be imported in our local common.go file as well. Since this
|
||||
package is not available in our current Go version (v1.22), we are
|
||||
adding it manually to resolve the compilation issue.
|
||||
- The slices library was originally introduced in Go v1.23 as part of
|
||||
the this commit:https://github.com/golang/go/commit/0b57881571a7
|
||||
|
||||
Change-Id: I11fe00909ef1961c24ecf80bf5b97f7b1121d359
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/737700
|
||||
Auto-Submit: Roland Shoemaker <roland@golang.org>
|
||||
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Coia Prant <coiaprant@gmail.com>
|
||||
Reviewed-by: Filippo Valsorda <filippo@golang.org>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/740062
|
||||
Reviewed-by: Damien Neil <dneil@google.com>
|
||||
Reviewed-by: Nicholas Husin <nsh@golang.org>
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
|
||||
(cherry picked from commit cb75daf3b29129620fa4a35ee2d3903e908aeb1c)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/crypto/tls/common.go | 26 ++-
|
||||
src/crypto/tls/handshake_client.go | 7 +-
|
||||
src/crypto/tls/handshake_server.go | 7 +-
|
||||
src/crypto/tls/handshake_server_test.go | 214 +++++++++++++++++++++++
|
||||
src/crypto/tls/handshake_server_tls13.go | 8 +-
|
||||
5 files changed, 254 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
|
||||
index 738c7e100b..299d6f32cb 100644
|
||||
--- a/src/crypto/tls/common.go
|
||||
+++ b/src/crypto/tls/common.go
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"internal/godebug"
|
||||
"io"
|
||||
"net"
|
||||
+ "slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -1556,13 +1557,28 @@ func (e *CertificateVerificationError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
-// anyUnexpiredChain reports if at least one of verifiedChains is still
|
||||
-// unexpired. If verifiedChains is empty, it returns false.
|
||||
-func anyUnexpiredChain(verifiedChains [][]*x509.Certificate, now time.Time) bool {
|
||||
+// anyValidVerifiedChain reports if at least one of the chains in verifiedChains
|
||||
+// is valid, as indicated by none of the certificates being expired and the root
|
||||
+// being in opts.Roots (or in the system root pool if opts.Roots is nil). If
|
||||
+// verifiedChains is empty, it returns false.
|
||||
+func anyValidVerifiedChain(verifiedChains [][]*x509.Certificate, opts x509.VerifyOptions) bool {
|
||||
for _, chain := range verifiedChains {
|
||||
- if len(chain) != 0 && !slices.ContainsFunc(chain, func(cert *x509.Certificate) bool {
|
||||
- return now.Before(cert.NotBefore) || now.After(cert.NotAfter) // cert is expired
|
||||
+ if len(chain) == 0 {
|
||||
+ continue
|
||||
+ }
|
||||
+ if slices.ContainsFunc(chain, func(cert *x509.Certificate) bool {
|
||||
+ return opts.CurrentTime.Before(cert.NotBefore) || opts.CurrentTime.After(cert.NotAfter)
|
||||
}) {
|
||||
+ continue
|
||||
+ }
|
||||
+ // Since we already validated the chain, we only care that it is
|
||||
+ // rooted in a CA in CAs, or in the system pool. On platforms where
|
||||
+ // we control chain validation (e.g. not Windows or macOS) this is a
|
||||
+ // simple lookup in the CertPool internal hash map. On other
|
||||
+ // platforms, this may be more expensive, depending on how they
|
||||
+ // implement verification of just root certificates.
|
||||
+ root := chain[len(chain)-1]
|
||||
+ if _, err := root.Verify(opts); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
|
||||
index c2ff9e1959..c8746b1023 100644
|
||||
--- a/src/crypto/tls/handshake_client.go
|
||||
+++ b/src/crypto/tls/handshake_client.go
|
||||
@@ -337,7 +337,12 @@ func (c *Conn) loadSession(hello *clientHelloMsg) (
|
||||
// application from a faulty ClientSessionCache implementation.
|
||||
return nil, nil, nil, nil
|
||||
}
|
||||
- if !anyUnexpiredChain(session.verifiedChains, c.config.time()) {
|
||||
+ opts := x509.VerifyOptions{
|
||||
+ CurrentTime: c.config.time(),
|
||||
+ Roots: c.config.RootCAs,
|
||||
+ KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
+ }
|
||||
+ if !anyValidVerifiedChain(session.verifiedChains, opts) {
|
||||
// No valid chains, delete the entry.
|
||||
c.config.ClientSessionCache.Put(cacheKey, nil)
|
||||
return nil, nil, nil, nil
|
||||
diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go
|
||||
index 608b2535f1..4e3f5e19fb 100644
|
||||
--- a/src/crypto/tls/handshake_server.go
|
||||
+++ b/src/crypto/tls/handshake_server.go
|
||||
@@ -482,8 +482,13 @@ func (hs *serverHandshakeState) checkForResumption() error {
|
||||
if sessionHasClientCerts && c.config.time().After(sessionState.peerCertificates[0].NotAfter) {
|
||||
return nil
|
||||
}
|
||||
+ opts := x509.VerifyOptions{
|
||||
+ CurrentTime: c.config.time(),
|
||||
+ Roots: c.config.ClientCAs,
|
||||
+ KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
+ }
|
||||
if sessionHasClientCerts && c.config.ClientAuth >= VerifyClientCertIfGiven &&
|
||||
- !anyUnexpiredChain(sessionState.verifiedChains, c.config.time()) {
|
||||
+ !anyValidVerifiedChain(sessionState.verifiedChains, opts) {
|
||||
return nil
|
||||
}
|
||||
|
||||
diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go
|
||||
index 9eff106ecf..c44ad51804 100644
|
||||
--- a/src/crypto/tls/handshake_server_test.go
|
||||
+++ b/src/crypto/tls/handshake_server_test.go
|
||||
@@ -2171,3 +2171,217 @@ func testHandshakeChainExpiryResumption(t *testing.T, version uint16) {
|
||||
testExpiration("LeafExpiresBeforeRoot", now.Add(2*time.Hour), now.Add(3*time.Hour))
|
||||
testExpiration("LeafExpiresAfterRoot", now.Add(2*time.Hour), now.Add(time.Hour))
|
||||
}
|
||||
+
|
||||
+func TestHandshakeGetConfigForClientDifferentClientCAs(t *testing.T) {
|
||||
+ t.Run("TLS1.2", func(t *testing.T) {
|
||||
+ testHandshakeGetConfigForClientDifferentClientCAs(t, VersionTLS12)
|
||||
+ })
|
||||
+ t.Run("TLS1.3", func(t *testing.T) {
|
||||
+ testHandshakeGetConfigForClientDifferentClientCAs(t, VersionTLS13)
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
+func testHandshakeGetConfigForClientDifferentClientCAs(t *testing.T, version uint16) {
|
||||
+ now := time.Now()
|
||||
+ tmpl := &x509.Certificate{
|
||||
+ Subject: pkix.Name{CommonName: "root"},
|
||||
+ NotBefore: now.Add(-time.Hour * 24),
|
||||
+ NotAfter: now.Add(time.Hour * 24),
|
||||
+ IsCA: true,
|
||||
+ BasicConstraintsValid: true,
|
||||
+ }
|
||||
+ rootDER, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+ rootA, err := x509.ParseCertificate(rootDER)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("ParseCertificate: %v", err)
|
||||
+ }
|
||||
+ rootDER, err = x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+ rootB, err := x509.ParseCertificate(rootDER)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("ParseCertificate: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ tmpl = &x509.Certificate{
|
||||
+ Subject: pkix.Name{},
|
||||
+ DNSNames: []string{"example.com"},
|
||||
+ NotBefore: now.Add(-time.Hour * 24),
|
||||
+ NotAfter: now.Add(time.Hour * 24),
|
||||
+ KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
+ }
|
||||
+ certDER, err := x509.CreateCertificate(rand.Reader, tmpl, rootA, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ serverConfig := testConfig.Clone()
|
||||
+ serverConfig.MaxVersion = version
|
||||
+ serverConfig.Certificates = []Certificate{{
|
||||
+ Certificate: [][]byte{certDER},
|
||||
+ PrivateKey: testECDSAPrivateKey,
|
||||
+ }}
|
||||
+ serverConfig.Time = func() time.Time {
|
||||
+ return now
|
||||
+ }
|
||||
+ serverConfig.ClientCAs = x509.NewCertPool()
|
||||
+ serverConfig.ClientCAs.AddCert(rootA)
|
||||
+ serverConfig.ClientAuth = RequireAndVerifyClientCert
|
||||
+ switchConfig := false
|
||||
+ serverConfig.GetConfigForClient = func(clientHello *ClientHelloInfo) (*Config, error) {
|
||||
+ if !switchConfig {
|
||||
+ return nil, nil
|
||||
+ }
|
||||
+ cfg := serverConfig.Clone()
|
||||
+ cfg.ClientCAs = x509.NewCertPool()
|
||||
+ cfg.ClientCAs.AddCert(rootB)
|
||||
+ return cfg, nil
|
||||
+ }
|
||||
+ serverConfig.InsecureSkipVerify = false
|
||||
+ serverConfig.ServerName = "example.com"
|
||||
+
|
||||
+ clientConfig := testConfig.Clone()
|
||||
+ clientConfig.MaxVersion = version
|
||||
+ clientConfig.Certificates = []Certificate{{
|
||||
+ Certificate: [][]byte{certDER},
|
||||
+ PrivateKey: testECDSAPrivateKey,
|
||||
+ }}
|
||||
+ clientConfig.ClientSessionCache = NewLRUClientSessionCache(32)
|
||||
+ clientConfig.RootCAs = x509.NewCertPool()
|
||||
+ clientConfig.RootCAs.AddCert(rootA)
|
||||
+ clientConfig.Time = func() time.Time {
|
||||
+ return now
|
||||
+ }
|
||||
+ clientConfig.InsecureSkipVerify = false
|
||||
+ clientConfig.ServerName = "example.com"
|
||||
+
|
||||
+ testResume := func(t *testing.T, sc, cc *Config, expectResume bool) {
|
||||
+ t.Helper()
|
||||
+ ss, cs, err := testHandshake(t, cc, sc)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("handshake: %v", err)
|
||||
+ }
|
||||
+ if cs.DidResume != expectResume {
|
||||
+ t.Fatalf("DidResume = %v; want %v", cs.DidResume, expectResume)
|
||||
+ }
|
||||
+ if ss.DidResume != expectResume {
|
||||
+ t.Fatalf("DidResume = %v; want %v", cs.DidResume, expectResume)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ testResume(t, serverConfig, clientConfig, false)
|
||||
+ testResume(t, serverConfig, clientConfig, true)
|
||||
+
|
||||
+ // Cause GetConfigForClient to return a config cloned from the base config,
|
||||
+ // but with a different ClientCAs pool. This should cause resumption to fail.
|
||||
+ switchConfig = true
|
||||
+
|
||||
+ testResume(t, serverConfig, clientConfig, false)
|
||||
+ testResume(t, serverConfig, clientConfig, true)
|
||||
+}
|
||||
+
|
||||
+func TestHandshakeChangeRootCAsResumption(t *testing.T) {
|
||||
+ t.Run("TLS1.2", func(t *testing.T) {
|
||||
+ testHandshakeChangeRootCAsResumption(t, VersionTLS12)
|
||||
+ })
|
||||
+ t.Run("TLS1.3", func(t *testing.T) {
|
||||
+ testHandshakeChangeRootCAsResumption(t, VersionTLS13)
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
+func testHandshakeChangeRootCAsResumption(t *testing.T, version uint16) {
|
||||
+ now := time.Now()
|
||||
+ tmpl := &x509.Certificate{
|
||||
+ Subject: pkix.Name{CommonName: "root"},
|
||||
+ NotBefore: now.Add(-time.Hour * 24),
|
||||
+ NotAfter: now.Add(time.Hour * 24),
|
||||
+ IsCA: true,
|
||||
+ BasicConstraintsValid: true,
|
||||
+ }
|
||||
+ rootDER, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+ rootA, err := x509.ParseCertificate(rootDER)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("ParseCertificate: %v", err)
|
||||
+ }
|
||||
+ rootDER, err = x509.CreateCertificate(rand.Reader, tmpl, tmpl, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+ rootB, err := x509.ParseCertificate(rootDER)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("ParseCertificate: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ tmpl = &x509.Certificate{
|
||||
+ Subject: pkix.Name{},
|
||||
+ DNSNames: []string{"example.com"},
|
||||
+ NotBefore: now.Add(-time.Hour * 24),
|
||||
+ NotAfter: now.Add(time.Hour * 24),
|
||||
+ KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
+ }
|
||||
+ certDER, err := x509.CreateCertificate(rand.Reader, tmpl, rootA, &testECDSAPrivateKey.PublicKey, testECDSAPrivateKey)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("CreateCertificate: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ serverConfig := testConfig.Clone()
|
||||
+ serverConfig.MaxVersion = version
|
||||
+ serverConfig.Certificates = []Certificate{{
|
||||
+ Certificate: [][]byte{certDER},
|
||||
+ PrivateKey: testECDSAPrivateKey,
|
||||
+ }}
|
||||
+ serverConfig.Time = func() time.Time {
|
||||
+ return now
|
||||
+ }
|
||||
+ serverConfig.ClientCAs = x509.NewCertPool()
|
||||
+ serverConfig.ClientCAs.AddCert(rootA)
|
||||
+ serverConfig.ClientAuth = RequireAndVerifyClientCert
|
||||
+ serverConfig.InsecureSkipVerify = false
|
||||
+ serverConfig.ServerName = "example.com"
|
||||
+
|
||||
+ clientConfig := testConfig.Clone()
|
||||
+ clientConfig.MaxVersion = version
|
||||
+ clientConfig.Certificates = []Certificate{{
|
||||
+ Certificate: [][]byte{certDER},
|
||||
+ PrivateKey: testECDSAPrivateKey,
|
||||
+ }}
|
||||
+ clientConfig.ClientSessionCache = NewLRUClientSessionCache(32)
|
||||
+ clientConfig.RootCAs = x509.NewCertPool()
|
||||
+ clientConfig.RootCAs.AddCert(rootA)
|
||||
+ clientConfig.Time = func() time.Time {
|
||||
+ return now
|
||||
+ }
|
||||
+ clientConfig.InsecureSkipVerify = false
|
||||
+ clientConfig.ServerName = "example.com"
|
||||
+
|
||||
+ testResume := func(t *testing.T, sc, cc *Config, expectResume bool) {
|
||||
+ t.Helper()
|
||||
+ ss, cs, err := testHandshake(t, cc, sc)
|
||||
+ if err != nil {
|
||||
+ t.Fatalf("handshake: %v", err)
|
||||
+ }
|
||||
+ if cs.DidResume != expectResume {
|
||||
+ t.Fatalf("DidResume = %v; want %v", cs.DidResume, expectResume)
|
||||
+ }
|
||||
+ if ss.DidResume != expectResume {
|
||||
+ t.Fatalf("DidResume = %v; want %v", cs.DidResume, expectResume)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ testResume(t, serverConfig, clientConfig, false)
|
||||
+ testResume(t, serverConfig, clientConfig, true)
|
||||
+
|
||||
+ clientConfig = clientConfig.Clone()
|
||||
+ clientConfig.RootCAs = x509.NewCertPool()
|
||||
+ clientConfig.RootCAs.AddCert(rootB)
|
||||
+
|
||||
+ testResume(t, serverConfig, clientConfig, false)
|
||||
+ testResume(t, serverConfig, clientConfig, true)
|
||||
+}
|
||||
diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go
|
||||
index a48a296721..1ecee3a867 100644
|
||||
--- a/src/crypto/tls/handshake_server_tls13.go
|
||||
+++ b/src/crypto/tls/handshake_server_tls13.go
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"crypto/hmac"
|
||||
"crypto/rsa"
|
||||
"encoding/binary"
|
||||
+ "crypto/x509"
|
||||
"errors"
|
||||
"hash"
|
||||
"io"
|
||||
@@ -345,8 +346,13 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error {
|
||||
if sessionHasClientCerts && c.config.time().After(sessionState.peerCertificates[0].NotAfter) {
|
||||
continue
|
||||
}
|
||||
+ opts := x509.VerifyOptions{
|
||||
+ CurrentTime: c.config.time(),
|
||||
+ Roots: c.config.ClientCAs,
|
||||
+ KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
|
||||
+ }
|
||||
if sessionHasClientCerts && c.config.ClientAuth >= VerifyClientCertIfGiven &&
|
||||
- !anyUnexpiredChain(sessionState.verifiedChains, c.config.time()) {
|
||||
+ !anyValidVerifiedChain(sessionState.verifiedChains, opts) {
|
||||
continue
|
||||
}
|
||||
|
||||
--
|
||||
2.35.6
|
||||
82
meta/recipes-devtools/go/go/CVE-2025-68121_p3.patch
Normal file
82
meta/recipes-devtools/go/go/CVE-2025-68121_p3.patch
Normal file
@@ -0,0 +1,82 @@
|
||||
From f38ac662b21e333b77951848a7e0549e4f69799e Mon Sep 17 00:00:00 2001
|
||||
From: Filippo Valsorda <filippo@golang.org>
|
||||
Date: Thu, 29 Jan 2026 11:32:25 +0100
|
||||
Subject: [PATCH] [release-branch.go1.24] crypto/tls: document resumption
|
||||
behavior across Configs
|
||||
|
||||
Updates #77113
|
||||
Updates #77217
|
||||
Updates CVE-2025-68121
|
||||
|
||||
CVE: CVE-2025-68121
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/6a501314718b]
|
||||
|
||||
Change-Id: Ia47904a9ed001275aad0243a6a0ce57e6a6a6964
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/740240
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Reviewed-by: Roland Shoemaker <roland@golang.org>
|
||||
Reviewed-by: Michael Pratt <mpratt@google.com>
|
||||
Auto-Submit: Filippo Valsorda <filippo@golang.org>
|
||||
(cherry picked from commit 1c9abbdc8e9032cd613bd147c78b166ebacc8a2e)
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/741180
|
||||
Auto-Submit: Michael Pratt <mpratt@google.com>
|
||||
(cherry picked from commit 6a501314718b6d69bad1723b3065ca6067b560ea)
|
||||
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
|
||||
---
|
||||
src/crypto/tls/common.go | 26 +++++++++++++++++++-------
|
||||
1 file changed, 19 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
|
||||
index 299d6f32cb..348bdf0866 100644
|
||||
--- a/src/crypto/tls/common.go
|
||||
+++ b/src/crypto/tls/common.go
|
||||
@@ -595,10 +595,13 @@ type Config struct {
|
||||
// If GetConfigForClient is nil, the Config passed to Server() will be
|
||||
// used for all connections.
|
||||
//
|
||||
- // If SessionTicketKey was explicitly set on the returned Config, or if
|
||||
- // SetSessionTicketKeys was called on the returned Config, those keys will
|
||||
+ // If SessionTicketKey is explicitly set on the returned Config, or if
|
||||
+ // SetSessionTicketKeys is called on the returned Config, those keys will
|
||||
// be used. Otherwise, the original Config keys will be used (and possibly
|
||||
- // rotated if they are automatically managed).
|
||||
+ // rotated if they are automatically managed). WARNING: this allows session
|
||||
+ // resumtion of connections originally established with the parent (or a
|
||||
+ // sibling) Config, which may bypass the [Config.VerifyPeerCertificate]
|
||||
+ // value of the returned Config.
|
||||
GetConfigForClient func(*ClientHelloInfo) (*Config, error)
|
||||
|
||||
// VerifyPeerCertificate, if not nil, is called after normal
|
||||
@@ -616,8 +619,10 @@ type Config struct {
|
||||
// rawCerts may be empty on the server if ClientAuth is RequestClientCert or
|
||||
// VerifyClientCertIfGiven.
|
||||
//
|
||||
- // This callback is not invoked on resumed connections, as certificates are
|
||||
- // not re-verified on resumption.
|
||||
+ // This callback is not invoked on resumed connections. WARNING: this
|
||||
+ // includes connections resumed across Configs returned by [Config.Clone] or
|
||||
+ // [Config.GetConfigForClient] and their parents. If that is not intended,
|
||||
+ // use [Config.VerifyConnection] instead, or set [Config.SessionTicketsDisabled].
|
||||
//
|
||||
// verifiedChains and its contents should not be modified.
|
||||
VerifyPeerCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
|
||||
@@ -825,8 +830,15 @@ func (c *Config) ticketKeyFromBytes(b [32]byte) (key ticketKey) {
|
||||
// ticket, and the lifetime we set for all tickets we send.
|
||||
const maxSessionTicketLifetime = 7 * 24 * time.Hour
|
||||
|
||||
-// Clone returns a shallow clone of c or nil if c is nil. It is safe to clone a [Config] that is
|
||||
-// being used concurrently by a TLS client or server.
|
||||
+// Clone returns a shallow clone of c or nil if c is nil. It is safe to clone a
|
||||
+// [Config] that is being used concurrently by a TLS client or server.
|
||||
+//
|
||||
+// The returned Config can share session ticket keys with the original Config,
|
||||
+// which means connections could be resumed across the two Configs. WARNING:
|
||||
+// [Config.VerifyPeerCertificate] does not get called on resumed connections,
|
||||
+// including connections that were originally established on the parent Config.
|
||||
+// If that is not intended, use [Config.VerifyConnection] instead, or set
|
||||
+// [Config.SessionTicketsDisabled].
|
||||
func (c *Config) Clone() *Config {
|
||||
if c == nil {
|
||||
return nil
|
||||
--
|
||||
2.35.6
|
||||
@@ -12,7 +12,7 @@ SRC_URI:append:class-nativesdk = " \
|
||||
file://older-glibc-symbols.patch"
|
||||
SRC_URI[prebuilt.sha256sum] = "ed9f456856e9d86359f169f46a70ad7be4190d6040282b84c8d97b99072485aa"
|
||||
|
||||
SRCREV = "9ab513512d8b5180a430ae4fa738cb531154cdef"
|
||||
SRCREV = "43cbd8fb4914328094ccdb4bb827d74b1bac2046"
|
||||
S = "${WORKDIR}/git"
|
||||
PV = "1.9.3+git"
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
From a5c5702112a9ccbf6abbbaac6078982f5f84bb2e Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Stone <daniels@collabora.com>
|
||||
Date: Thu, 23 Nov 2023 16:44:10 +0000
|
||||
Subject: [PATCH] touch-calibrator: Regularise surface/view mapping
|
||||
|
||||
Upstream-Status: Backport [https://gitlab.freedesktop.org/wayland/weston/-/commit/a5c5702112a9ccbf6abbbaac6078982f5f84bb2e]
|
||||
|
||||
Manually mark the surface as mapped exactly once - in the committed
|
||||
handler where we have our content, and assert that it's correct when we
|
||||
want to use the surface by instantiating a view.
|
||||
|
||||
The view handling can be made much more simple by simply using the new
|
||||
view helpers.
|
||||
|
||||
Signed-off-by: Daniel Stone <daniels@collabora.com>
|
||||
Signed-off-by: Ming Liu <liu.ming50@gmail.com>
|
||||
---
|
||||
libweston/touch-calibration.c | 22 ++++++++++++----------
|
||||
1 file changed, 12 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/libweston/touch-calibration.c b/libweston/touch-calibration.c
|
||||
index 45689ddd..f4c9366a 100644
|
||||
--- a/libweston/touch-calibration.c
|
||||
+++ b/libweston/touch-calibration.c
|
||||
@@ -189,6 +189,7 @@ map_calibrator(struct weston_touch_calibrator *calibrator)
|
||||
assert(calibrator->output);
|
||||
assert(calibrator->surface);
|
||||
assert(calibrator->surface->resource);
|
||||
+ assert(weston_surface_is_mapped(calibrator->surface));
|
||||
|
||||
calibrator->view = weston_view_create(calibrator->surface);
|
||||
if (!calibrator->view) {
|
||||
@@ -196,17 +197,9 @@ map_calibrator(struct weston_touch_calibrator *calibrator)
|
||||
return;
|
||||
}
|
||||
|
||||
- weston_layer_entry_insert(&c->calibrator_layer.view_list,
|
||||
- &calibrator->view->layer_link);
|
||||
-
|
||||
weston_view_set_position(calibrator->view, calibrator->output->pos);
|
||||
- calibrator->view->output = calibrator->surface->output;
|
||||
- calibrator->view->is_mapped = true;
|
||||
-
|
||||
- calibrator->surface->output = calibrator->output;
|
||||
- weston_surface_map(calibrator->surface);
|
||||
-
|
||||
- weston_output_schedule_repaint(calibrator->output);
|
||||
+ weston_view_move_to_layer(calibrator->view,
|
||||
+ &c->calibrator_layer.view_list);
|
||||
|
||||
device->ops->get_calibration(device, &device->saved_calibration);
|
||||
device->ops->set_calibration(device, &identity);
|
||||
@@ -260,6 +253,13 @@ touch_calibrator_surface_committed(struct wl_listener *listener, void *data)
|
||||
wl_list_remove(&calibrator->surface_commit_listener.link);
|
||||
wl_list_init(&calibrator->surface_commit_listener.link);
|
||||
|
||||
+ if (!weston_surface_has_content(surface)) {
|
||||
+ wl_resource_post_error(calibrator->resource,
|
||||
+ WESTON_TOUCH_CALIBRATOR_ERROR_BAD_SIZE,
|
||||
+ "calibrator surface size has no content");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (surface->width != calibrator->output->width ||
|
||||
surface->height != calibrator->output->height) {
|
||||
wl_resource_post_error(calibrator->resource,
|
||||
@@ -268,6 +268,8 @@ touch_calibrator_surface_committed(struct wl_listener *listener, void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
+ weston_surface_map(surface);
|
||||
+
|
||||
weston_compositor_set_touch_mode_calib(calibrator->compositor);
|
||||
/* results in call to touch_calibrator_mode_changed() */
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@@ -9,6 +9,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=d79ee9e66bb0f95d3386a7acae780b70 \
|
||||
SRC_URI = "https://gitlab.freedesktop.org/wayland/weston/-/releases/${PV}/downloads/${BPN}-${PV}.tar.xz \
|
||||
file://0001-libweston-tools-Include-libgen.h-for-basename-signat.patch \
|
||||
file://0001-vnc-Allow-neatvnc-in-version-0.8.0.patch \
|
||||
file://0001-touch-calibrator-Regularise-surface-view-mapping.patch \
|
||||
file://weston.png \
|
||||
file://weston.desktop \
|
||||
file://xwayland.weston-start \
|
||||
|
||||
@@ -14,13 +14,13 @@ python () {
|
||||
raise bb.parse.SkipRecipe("Set PREFERRED_PROVIDER_virtual/kernel to linux-yocto-rt to enable it")
|
||||
}
|
||||
|
||||
SRCREV_machine ?= "30009325411827c48a376212ef00a5637f67b914"
|
||||
SRCREV_meta ?= "50530c858c90f124629dadce78f696b590747ea5"
|
||||
SRCREV_machine ?= "5a49ab75e554557c1d3665b22233c4de9a2c2a75"
|
||||
SRCREV_meta ?= "17375dce1754d0783fb3fb9e684691951f9ff357"
|
||||
|
||||
SRC_URI = "git://git.yoctoproject.org/linux-yocto.git;branch=${KBRANCH};name=machine;protocol=https \
|
||||
git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-6.6;destsuffix=${KMETA};protocol=https"
|
||||
|
||||
LINUX_VERSION ?= "6.6.111"
|
||||
LINUX_VERSION ?= "6.6.123"
|
||||
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ require recipes-kernel/linux/linux-yocto.inc
|
||||
# CVE exclusions
|
||||
include recipes-kernel/linux/cve-exclusion_6.6.inc
|
||||
|
||||
LINUX_VERSION ?= "6.6.111"
|
||||
LINUX_VERSION ?= "6.6.123"
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
|
||||
|
||||
DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}"
|
||||
@@ -17,8 +17,8 @@ DEPENDS += "openssl-native util-linux-native"
|
||||
KMETA = "kernel-meta"
|
||||
KCONF_BSP_AUDIT_LEVEL = "2"
|
||||
|
||||
SRCREV_machine ?= "529f5ce5c38c39bc1fe4022f499ee718bff0cb8b"
|
||||
SRCREV_meta ?= "50530c858c90f124629dadce78f696b590747ea5"
|
||||
SRCREV_machine ?= "18a3ba79eed015d2cbd1f5af2c1417d12b369698"
|
||||
SRCREV_meta ?= "17375dce1754d0783fb3fb9e684691951f9ff357"
|
||||
|
||||
PV = "${LINUX_VERSION}+git"
|
||||
|
||||
|
||||
@@ -18,25 +18,25 @@ KBRANCH:qemux86-64 ?= "v6.6/standard/base"
|
||||
KBRANCH:qemuloongarch64 ?= "v6.6/standard/base"
|
||||
KBRANCH:qemumips64 ?= "v6.6/standard/mti-malta64"
|
||||
|
||||
SRCREV_machine:qemuarm ?= "f864fe79b2b8052e10bbe3ae443941ccefa5a951"
|
||||
SRCREV_machine:qemuarm64 ?= "cdd229fbaaa25d5d9eb055477af8c2b82238763b"
|
||||
SRCREV_machine:qemuloongarch64 ?= "2a17dc587afe4e133deef4d8c9ec98724aee785b"
|
||||
SRCREV_machine:qemumips ?= "2f5bef5596eeb6ac65023cfeb1a6402efcdc965f"
|
||||
SRCREV_machine:qemuppc ?= "be45c09ed7f4b5a09f95cd90484ef083c8552344"
|
||||
SRCREV_machine:qemuriscv64 ?= "2a17dc587afe4e133deef4d8c9ec98724aee785b"
|
||||
SRCREV_machine:qemuriscv32 ?= "2a17dc587afe4e133deef4d8c9ec98724aee785b"
|
||||
SRCREV_machine:qemux86 ?= "2a17dc587afe4e133deef4d8c9ec98724aee785b"
|
||||
SRCREV_machine:qemux86-64 ?= "2a17dc587afe4e133deef4d8c9ec98724aee785b"
|
||||
SRCREV_machine:qemumips64 ?= "130d3c48ab3b914907b88ff240463b4e5718d526"
|
||||
SRCREV_machine ?= "2a17dc587afe4e133deef4d8c9ec98724aee785b"
|
||||
SRCREV_meta ?= "50530c858c90f124629dadce78f696b590747ea5"
|
||||
SRCREV_machine:qemuarm ?= "b562777a433f835ae245e08c27df6b47e3ae2505"
|
||||
SRCREV_machine:qemuarm64 ?= "2df2455c7199cb8db4ea0118f908f952ff73eb97"
|
||||
SRCREV_machine:qemuloongarch64 ?= "af240d7d57ebf66e87bc2dff34855e630a97ead1"
|
||||
SRCREV_machine:qemumips ?= "6b9c16676cd4c8494ca7cdff355cb1cfe4d8fb3a"
|
||||
SRCREV_machine:qemuppc ?= "bf3f6c731ea41e519389b24104458870475dce20"
|
||||
SRCREV_machine:qemuriscv64 ?= "af240d7d57ebf66e87bc2dff34855e630a97ead1"
|
||||
SRCREV_machine:qemuriscv32 ?= "af240d7d57ebf66e87bc2dff34855e630a97ead1"
|
||||
SRCREV_machine:qemux86 ?= "af240d7d57ebf66e87bc2dff34855e630a97ead1"
|
||||
SRCREV_machine:qemux86-64 ?= "af240d7d57ebf66e87bc2dff34855e630a97ead1"
|
||||
SRCREV_machine:qemumips64 ?= "9fb8ff244fe5c5d6aa08457cfb9bbe4a3ef47366"
|
||||
SRCREV_machine ?= "af240d7d57ebf66e87bc2dff34855e630a97ead1"
|
||||
SRCREV_meta ?= "17375dce1754d0783fb3fb9e684691951f9ff357"
|
||||
|
||||
# set your preferred provider of linux-yocto to 'linux-yocto-upstream', and you'll
|
||||
# get the <version>/base branch, which is pure upstream -stable, and the same
|
||||
# meta SRCREV as the linux-yocto-standard builds. Select your version using the
|
||||
# normal PREFERRED_VERSION settings.
|
||||
BBCLASSEXTEND = "devupstream:target"
|
||||
SRCREV_machine:class-devupstream ?= "655054d2c3c184875f95646abd828b5dfc027d5e"
|
||||
SRCREV_machine:class-devupstream ?= "c56aaf1a85ae918dd521fb2869028cf533d2755a"
|
||||
PN:class-devupstream = "linux-yocto-upstream"
|
||||
KBRANCH:class-devupstream = "v6.6/base"
|
||||
|
||||
@@ -44,7 +44,7 @@ SRC_URI = "git://git.yoctoproject.org/linux-yocto.git;name=machine;branch=${KBRA
|
||||
git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-6.6;destsuffix=${KMETA};protocol=https"
|
||||
|
||||
LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
|
||||
LINUX_VERSION ?= "6.6.111"
|
||||
LINUX_VERSION ?= "6.6.123"
|
||||
|
||||
PV = "${LINUX_VERSION}+git"
|
||||
|
||||
|
||||
34
meta/recipes-multimedia/alsa/alsa-lib/CVE-2026-25068.patch
Normal file
34
meta/recipes-multimedia/alsa/alsa-lib/CVE-2026-25068.patch
Normal file
@@ -0,0 +1,34 @@
|
||||
From 5f7fe33002d2d98d84f72e381ec2cccc0d5d3d40 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Kysela <perex@perex.cz>
|
||||
Date: Thu, 29 Jan 2026 16:51:09 +0100
|
||||
Subject: [PATCH] topology: decoder - add boundary check for channel mixer
|
||||
count
|
||||
|
||||
Malicious binary topology file may cause heap corruption.
|
||||
|
||||
CVE: CVE-2026-25068
|
||||
|
||||
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
|
||||
|
||||
Upstream-Status: Backport [https://github.com/alsa-project/alsa-lib/commit/5f7fe33002d2d98d84f72e381ec2cccc0d5d3d40]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
src/topology/ctl.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/src/topology/ctl.c b/src/topology/ctl.c
|
||||
index a0c24518..322c461c 100644
|
||||
--- a/src/topology/ctl.c
|
||||
+++ b/src/topology/ctl.c
|
||||
@@ -1247,6 +1247,11 @@ int tplg_decode_control_mixer1(snd_tplg_t *tplg,
|
||||
if (mc->num_channels > 0) {
|
||||
map = tplg_calloc(heap, sizeof(*map));
|
||||
map->num_channels = mc->num_channels;
|
||||
+ if (map->num_channels > SND_TPLG_MAX_CHAN ||
|
||||
+ map->num_channels > SND_SOC_TPLG_MAX_CHAN) {
|
||||
+ SNDERR("mixer: unexpected channel count %d", map->num_channels);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
for (i = 0; i < map->num_channels; i++) {
|
||||
map->channel[i].reg = mc->channel[i].reg;
|
||||
map->channel[i].shift = mc->channel[i].shift;
|
||||
@@ -11,6 +11,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=a916467b91076e631dd8edb7424769c7 \
|
||||
|
||||
SRC_URI = "https://www.alsa-project.org/files/pub/lib/${BP}.tar.bz2 \
|
||||
file://0001-topology-correct-version-script-path.patch \
|
||||
file://CVE-2026-25068.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "9f3f2f69b995f9ad37359072fbc69a3a88bfba081fc83e9be30e14662795bb4d"
|
||||
|
||||
|
||||
@@ -48,9 +48,10 @@ CVE_STATUS[CVE-2023-39018] = "cpe-incorrect: This issue belongs to ffmpeg-cli-wr
|
||||
CVE_STATUS[CVE-2025-1373] = "fixed-version: Vulnerable code not present in any release"
|
||||
|
||||
CVE_STATUS_GROUPS += "CVE_STATUS_FIXED_61x"
|
||||
CVE_STATUS_FIXED_61x = "CVE-2023-49502 CVE-2023-50007 CVE-2023-50008 CVE-2023-50009 CVE-2023-50010 CVE-2024-31578 CVE-2024-31582 CVE-2024-31585"
|
||||
CVE_STATUS_FIXED_61x = "CVE-2023-49502 CVE-2023-50007 CVE-2023-50008 CVE-2023-50009 CVE-2023-50010 CVE-2024-31578 CVE-2024-31582 CVE-2024-31585 CVE-2025-1594"
|
||||
CVE_STATUS_FIXED_61x[status] = "cpe-incorrect:these CVEs are fixed in 6.1.x"
|
||||
|
||||
CVE_STATUS[CVE-2025-25468] = "cpe-incorrect:vulnerability was introduced in v8.0"
|
||||
CVE_STATUS[CVE-2025-25469] = "cpe-incorrect: Current version (6.1.4) is not impacted."
|
||||
|
||||
# Build fails when thumb is enabled: https://bugzilla.yoctoproject.org/show_bug.cgi?id=7717
|
||||
|
||||
61
meta/recipes-multimedia/libpng/files/CVE-2026-25646.patch
Normal file
61
meta/recipes-multimedia/libpng/files/CVE-2026-25646.patch
Normal file
@@ -0,0 +1,61 @@
|
||||
From 01d03b8453eb30ade759cd45c707e5a1c7277d88 Mon Sep 17 00:00:00 2001
|
||||
From: Cosmin Truta <ctruta@gmail.com>
|
||||
Date: Fri, 6 Feb 2026 19:11:54 +0200
|
||||
Subject: [PATCH] Fix a heap buffer overflow in `png_set_quantize`
|
||||
|
||||
The color distance hash table stored the current palette indices, but
|
||||
the color-pruning loop assumed the original indices. When colors were
|
||||
eliminated and indices changed, the stored indices became stale. This
|
||||
caused the loop bound `max_d` to grow past the 769-element hash array.
|
||||
|
||||
The fix consists in storing the original indices via `palette_to_index`
|
||||
to match the pruning loop's expectations.
|
||||
|
||||
Reported-by: Joshua Inscoe <pwnalone@users.noreply.github.com>
|
||||
Co-authored-by: Joshua Inscoe <pwnalone@users.noreply.github.com>
|
||||
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
|
||||
|
||||
CVE: CVE-2026-25646
|
||||
Upstream-Status: Backport [https://github.com/pnggroup/libpng/commit/01d03b8453eb30ade759cd45c707e5a1c7277d88]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
AUTHORS | 1 +
|
||||
pngrtran.c | 6 +++---
|
||||
2 files changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index b9c0fffcf..4094f4a57 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -15,6 +15,7 @@ Authors, for copyright and licensing purposes.
|
||||
* Guy Eric Schalnat
|
||||
* James Yu
|
||||
* John Bowler
|
||||
+ * Joshua Inscoe
|
||||
* Kevin Bracey
|
||||
* Magnus Holmgren
|
||||
* Mandar Sahastrabuddhe
|
||||
diff --git a/pngrtran.c b/pngrtran.c
|
||||
index fe8f9d32c..1fce9af12 100644
|
||||
--- a/pngrtran.c
|
||||
+++ b/pngrtran.c
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
/* pngrtran.c - transforms the data in a row for PNG readers
|
||||
*
|
||||
- * Copyright (c) 2018-2024 Cosmin Truta
|
||||
+ * Copyright (c) 2018-2026 Cosmin Truta
|
||||
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
|
||||
* Copyright (c) 1996-1997 Andreas Dilger
|
||||
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||
@@ -647,8 +647,8 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
|
||||
break;
|
||||
|
||||
t->next = hash[d];
|
||||
- t->left = (png_byte)i;
|
||||
- t->right = (png_byte)j;
|
||||
+ t->left = png_ptr->palette_to_index[i];
|
||||
+ t->right = png_ptr->palette_to_index[j];
|
||||
hash[d] = t;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ SRC_URI = "${SOURCEFORGE_MIRROR}/project/${BPN}/${BPN}${LIBV}/${PV}/${BP}.tar.xz
|
||||
file://CVE-2025-66293-02.patch \
|
||||
file://CVE-2026-22695.patch \
|
||||
file://CVE-2026-22801.patch \
|
||||
file://CVE-2026-25646.patch \
|
||||
"
|
||||
|
||||
SRC_URI[sha256sum] = "c919dbc11f4c03b05aba3f8884d8eb7adfe3572ad228af972bb60057bdb48450"
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From d9a35ea0d5c64c19dd635ae578e0028df8f66d6a Mon Sep 17 00:00:00 2001
|
||||
From: Sisyphus-wang <43361974+Sisyphus-wang@users.noreply.github.com>
|
||||
Date: Fri, 11 Jul 2025 15:14:48 +0800
|
||||
Subject: [PATCH] Update mpeg_l3_encode.c
|
||||
|
||||
fix memoryLeak bug
|
||||
|
||||
CVE: CVE-2025-56226
|
||||
Upstream-Status: Backport [https://github.com/libsndfile/libsndfile/commit/d9a35ea0d5c64c19dd635ae578e0028df8f66d6a]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
src/mpeg_l3_encode.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/mpeg_l3_encode.c b/src/mpeg_l3_encode.c
|
||||
index 97324f79..04b1d501 100644
|
||||
--- a/src/mpeg_l3_encode.c
|
||||
+++ b/src/mpeg_l3_encode.c
|
||||
@@ -87,7 +87,8 @@ mpeg_l3_encoder_init (SF_PRIVATE *psf, int info_tag)
|
||||
if (! (pmpeg->lamef = lame_init ()))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
- pmpeg->compression = -1.0 ; /* Unset */
|
||||
+ psf->codec_close = mpeg_l3_encoder_close ; /* Set psf->codec_close early*/
|
||||
+ pmpeg->compression = -1.0 ; /* Unset */
|
||||
|
||||
lame_set_in_samplerate (pmpeg->lamef, psf->sf.samplerate) ;
|
||||
lame_set_num_channels (pmpeg->lamef, psf->sf.channels) ;
|
||||
@@ -115,7 +116,6 @@ mpeg_l3_encoder_init (SF_PRIVATE *psf, int info_tag)
|
||||
}
|
||||
|
||||
psf->sf.seekable = 0 ;
|
||||
- psf->codec_close = mpeg_l3_encoder_close ;
|
||||
psf->byterate = mpeg_l3_encoder_byterate ;
|
||||
psf->datalength = 0 ;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
From 68f6c16fe1407eff4cdde158566694c3ed666c2f Mon Sep 17 00:00:00 2001
|
||||
From: Sisyphus-wang <43361974+Sisyphus-wang@users.noreply.github.com>
|
||||
Date: Fri, 11 Jul 2025 15:26:24 +0800
|
||||
Subject: [PATCH] Update sndfile-convert.c
|
||||
|
||||
fix memoryLeak in sndfile-conver.c
|
||||
|
||||
CVE: CVE-2025-56226
|
||||
Upstream-Status: Backport [https://github.com/libsndfile/libsndfile/commit/68f6c16fe1407eff4cdde158566694c3ed666c2f]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
programs/sndfile-convert.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/programs/sndfile-convert.c b/programs/sndfile-convert.c
|
||||
index 95f59d3c..a9f0cfac 100644
|
||||
--- a/programs/sndfile-convert.c
|
||||
+++ b/programs/sndfile-convert.c
|
||||
@@ -301,6 +301,7 @@ main (int argc, char * argv [])
|
||||
|
||||
if ((sfinfo.format = sfe_file_type_of_ext (outfilename, sfinfo.format)) == 0)
|
||||
{ printf ("Error : Not able to determine output file type for %s.\n", outfilename) ;
|
||||
+ sf_close (infile) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
@@ -344,6 +345,7 @@ main (int argc, char * argv [])
|
||||
/* Open the output file. */
|
||||
if ((outfile = sf_open (outfilename, SFM_WRITE, &sfinfo)) == NULL)
|
||||
{ printf ("Not able to open output file %s : %s\n", outfilename, sf_strerror (NULL)) ;
|
||||
+ sf_close (infile) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
@@ -360,6 +362,8 @@ main (int argc, char * argv [])
|
||||
|| (infileminor == SF_FORMAT_MPEG_LAYER_III) || (outfileminor == SF_FORMAT_MPEG_LAYER_III))
|
||||
{ if (sfe_copy_data_fp (outfile, infile, sfinfo.channels, normalize) != 0)
|
||||
{ printf ("Error : Not able to decode input file %s.\n", infilename) ;
|
||||
+ sf_close (infile) ;
|
||||
+ sf_close (outfile) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
}
|
||||
@@ -11,6 +11,8 @@ SRC_URI = "${GITHUB_BASE_URI}/download/${PV}/libsndfile-${PV}.tar.xz \
|
||||
file://noopus.patch \
|
||||
file://cve-2022-33065.patch \
|
||||
file://CVE-2024-50612.patch \
|
||||
file://CVE-2025-56226-01.patch \
|
||||
file://CVE-2025-56226-02.patch \
|
||||
"
|
||||
GITHUB_BASE_URI = "https://github.com/libsndfile/libsndfile/releases/"
|
||||
|
||||
|
||||
@@ -21,3 +21,5 @@ CVE_PRODUCT = "theora"
|
||||
inherit autotools pkgconfig
|
||||
|
||||
EXTRA_OECONF = "--disable-examples"
|
||||
|
||||
CVE_STATUS[CVE-2024-56431] = "fixed-version:branch 1.1 is not affected, vulnerable code is not present yet"
|
||||
|
||||
108
meta/recipes-support/gnupg/gnupg/CVE-2025-68973.patch
Normal file
108
meta/recipes-support/gnupg/gnupg/CVE-2025-68973.patch
Normal file
@@ -0,0 +1,108 @@
|
||||
From 4ecc5122f20e10c17172ed72f4fa46c784b5fb48 Mon Sep 17 00:00:00 2001
|
||||
From: Werner Koch <wk@gnupg.org>
|
||||
Date: Thu, 23 Oct 2025 11:36:04 +0200
|
||||
Subject: [PATCH] gpg: Fix possible memory corruption in the armor parser.
|
||||
|
||||
* g10/armor.c (armor_filter): Fix faulty double increment.
|
||||
|
||||
* common/iobuf.c (underflow_target): Assert that the filter
|
||||
implementations behave well.
|
||||
--
|
||||
|
||||
This fixes a bug in a code path which can only be reached with special
|
||||
crafted input data and would then error out at an upper layer due to
|
||||
corrupt input (every second byte in the buffer is unitialized
|
||||
garbage). No fuzzing has yet hit this case and we don't have a test
|
||||
case for this code path. However memory corruption can never be
|
||||
tolerated as it always has the protential for remode code execution.
|
||||
|
||||
Reported-by: 8b79fe4dd0581c1cd000e1fbecba9f39e16a396a
|
||||
Fixes-commit: c27c7416d5148865a513e007fb6f0a34993a6073
|
||||
which fixed
|
||||
Fixes-commit: 7d0efec7cf5ae110c99511abc32587ff0c45b14f
|
||||
Backported-from-master: 115d138ba599328005c5321c0ef9f00355838ca9
|
||||
|
||||
The bug was introduced on 1999-01-07 by me:
|
||||
* armor.c: Rewrote large parts.
|
||||
which I fixed on 1999-03-02 but missed to fix the other case:
|
||||
* armor.c (armor_filter): Fixed armor bypassing.
|
||||
|
||||
Below is base64+gzipped test data which can be used with valgrind to
|
||||
show access to uninitalized memory in write(2) in the unpatched code.
|
||||
|
||||
--8<---------------cut here---------------start------------->8---
|
||||
H4sICIDd+WgCA3h4AO3QMQ6CQBCG0djOKbY3G05gscYFSRAJt/AExp6Di0cQG0ze
|
||||
a//MV0zOq3Pt+jFN3ZTKfLvP9ZLafqifJUe8juOjeZbVtSkbRPmRgICAgICAgICA
|
||||
gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
|
||||
gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
|
||||
gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
|
||||
gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
|
||||
gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
|
||||
gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA
|
||||
gICAgICAgICAgICAgICAgICAgICAgICAgMCXF6dYDgAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7E14AAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwZ94aieId3+8EAA==
|
||||
--8<---------------cut here---------------end--------------->8---
|
||||
|
||||
CVE: CVE-2025-68973
|
||||
Upstream-Status: Backport [https://github.com/gpg/gnupg/commit/4ecc5122f20e10c17172ed72f4fa46c784b5fb48]
|
||||
Signed-off-by: Peter Marko <peter.marko@siemens.com>
|
||||
---
|
||||
common/iobuf.c | 8 +++++++-
|
||||
g10/armor.c | 4 ++--
|
||||
2 files changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/common/iobuf.c b/common/iobuf.c
|
||||
index 748e6935d..2497713c1 100644
|
||||
--- a/common/iobuf.c
|
||||
+++ b/common/iobuf.c
|
||||
@@ -2043,6 +2043,8 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
|
||||
rc = 0;
|
||||
else
|
||||
{
|
||||
+ size_t tmplen;
|
||||
+
|
||||
/* If no buffered data and drain buffer has been setup, and drain
|
||||
* buffer is largish, read data directly to drain buffer. */
|
||||
if (a->d.len == 0
|
||||
@@ -2055,8 +2057,10 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
|
||||
log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes, to external drain)\n",
|
||||
a->no, a->subno, (ulong)len);
|
||||
|
||||
- rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
|
||||
+ tmplen = len; /* Used to check for bugs in the filter. */
|
||||
+ rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
|
||||
a->e_d.buf, &len);
|
||||
+ log_assert (len <= tmplen);
|
||||
a->e_d.used = len;
|
||||
len = 0;
|
||||
}
|
||||
@@ -2066,8 +2070,10 @@ underflow_target (iobuf_t a, int clear_pending_eof, size_t target)
|
||||
log_debug ("iobuf-%d.%d: underflow: A->FILTER (%lu bytes)\n",
|
||||
a->no, a->subno, (ulong)len);
|
||||
|
||||
+ tmplen = len; /* Used to check for bugs in the filter. */
|
||||
rc = a->filter (a->filter_ov, IOBUFCTRL_UNDERFLOW, a->chain,
|
||||
&a->d.buf[a->d.len], &len);
|
||||
+ log_assert (len <= tmplen);
|
||||
}
|
||||
}
|
||||
a->d.len += len;
|
||||
diff --git a/g10/armor.c b/g10/armor.c
|
||||
index 81af15339..f8cfa86db 100644
|
||||
--- a/g10/armor.c
|
||||
+++ b/g10/armor.c
|
||||
@@ -1302,8 +1302,8 @@ armor_filter( void *opaque, int control,
|
||||
n = 0;
|
||||
if( afx->buffer_len ) {
|
||||
/* Copy the data from AFX->BUFFER to BUF. */
|
||||
- for(; n < size && afx->buffer_pos < afx->buffer_len; n++ )
|
||||
- buf[n++] = afx->buffer[afx->buffer_pos++];
|
||||
+ for(; n < size && afx->buffer_pos < afx->buffer_len;)
|
||||
+ buf[n++] = afx->buffer[afx->buffer_pos++];
|
||||
if( afx->buffer_pos >= afx->buffer_len )
|
||||
afx->buffer_len = 0;
|
||||
}
|
||||
@@ -18,6 +18,7 @@ SRC_URI = "${GNUPG_MIRROR}/${BPN}/${BPN}-${PV}.tar.bz2 \
|
||||
file://0002-use-pkgconfig-instead-of-npth-config.patch \
|
||||
file://0004-autogen.sh-fix-find-version-for-beta-checking.patch \
|
||||
file://0001-Woverride-init-is-not-needed-with-gcc-9.patch \
|
||||
file://CVE-2025-68973.patch \
|
||||
"
|
||||
SRC_URI:append:class-native = " file://0001-configure.ac-use-a-custom-value-for-the-location-of-.patch \
|
||||
file://relocate.patch"
|
||||
|
||||
@@ -21,3 +21,5 @@ ALTERNATIVE_LINK_NAME[xxd] = "${bindir}/xxd"
|
||||
# in many places for _FORTIFY_SOURCE=2. Security flags become part of CC.
|
||||
#
|
||||
lcl_maybe_fortify = "${@oe.utils.conditional('DEBUG_BUILD','1','','-D_FORTIFY_SOURCE=1',d)}"
|
||||
|
||||
CVE_STATUS[CVE-2025-66476] = "not-applicable-platform: Issue only applies on Windows"
|
||||
|
||||
@@ -57,8 +57,8 @@ logger = scriptutils.logger_create(PROGNAME, stream=sys.stdout)
|
||||
|
||||
DEFAULT_INSTALL_DIR = os.path.join(os.path.split(scripts_path)[0],'buildtools')
|
||||
DEFAULT_BASE_URL = 'https://downloads.yoctoproject.org/releases/yocto'
|
||||
DEFAULT_RELEASE = 'yocto-5.0.14'
|
||||
DEFAULT_INSTALLER_VERSION = '5.0.14'
|
||||
DEFAULT_RELEASE = 'yocto-5.0.15'
|
||||
DEFAULT_INSTALLER_VERSION = '5.0.15'
|
||||
DEFAULT_BUILDDATE = '202110XX'
|
||||
|
||||
# Python version sanity check
|
||||
|
||||
@@ -220,6 +220,34 @@ def wic_list(args, scripts_path):
|
||||
|
||||
return False
|
||||
|
||||
_DEBUGFS_VERSION = None
|
||||
|
||||
def debugfs_version_check(debugfs_path, min_ver=(1, 46, 5)):
|
||||
global _DEBUGFS_VERSION
|
||||
|
||||
if _DEBUGFS_VERSION is None:
|
||||
out = ""
|
||||
for flag in ("-V", "-v"):
|
||||
try:
|
||||
out = exec_cmd(f"{debugfs_path} {flag}")
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
import re
|
||||
m = re.search(r"(\d+)\.(\d+)\.(\d+)", out or "")
|
||||
_DEBUGFS_VERSION = tuple(map(int, m.groups())) if m else None
|
||||
|
||||
ver = _DEBUGFS_VERSION
|
||||
|
||||
if ver is not None and ver < min_ver:
|
||||
raise WicError(
|
||||
"Sorry, debugfs 1.46.5 or later is required for this script. "
|
||||
"Older versions of debugfs can make directory copies into ext* partitions "
|
||||
"via scripted debugfs (-f) unreliable or broken. Detected version: %s"
|
||||
% (".".join(map(str, ver)) if ver else "unknown")
|
||||
)
|
||||
|
||||
|
||||
class Disk:
|
||||
def __init__(self, imagepath, native_sysroot, fstypes=('fat', 'ext')):
|
||||
@@ -327,29 +355,65 @@ class Disk:
|
||||
path))
|
||||
|
||||
def copy(self, src, dest):
|
||||
"""Copy partition image into wic image."""
|
||||
pnum = dest.part if isinstance(src, str) else src.part
|
||||
"""Copy files or directories to/from the vfat or ext* partition."""
|
||||
pnum = dest.part if isinstance(src, str) else src.part
|
||||
partimg = self._get_part_image(pnum)
|
||||
|
||||
if self.partitions[pnum].fstype.startswith('ext'):
|
||||
if isinstance(src, str):
|
||||
cmd = "printf 'cd {}\nwrite {} {}\n' | {} -w {}".\
|
||||
format(os.path.dirname(dest.path), src, os.path.basename(src),
|
||||
self.debugfs, self._get_part_image(pnum))
|
||||
else: # copy from wic
|
||||
# run both dump and rdump to support both files and directory
|
||||
if isinstance(src, str): # host to image case
|
||||
if os.path.isdir(src):
|
||||
debugfs_version_check(self.debugfs)
|
||||
base = os.path.abspath(src)
|
||||
base_parent = os.path.dirname(base)
|
||||
cmds = []
|
||||
made = set()
|
||||
|
||||
for root, dirs, files in os.walk(base):
|
||||
for fname in files:
|
||||
host_file = os.path.join(root, fname)
|
||||
rel = os.path.relpath(host_file, base_parent)
|
||||
dest_file = os.path.join(dest.path, rel)
|
||||
dest_dir = os.path.dirname(dest_file)
|
||||
|
||||
# create dir structure (mkdir -p)
|
||||
parts = dest_dir.strip('/').split('/')
|
||||
cur = ''
|
||||
for p in parts:
|
||||
cur = cur + '/' + p
|
||||
if cur not in made:
|
||||
cmds.append(f'mkdir "{cur}"')
|
||||
made.add(cur)
|
||||
|
||||
cmds.append(f'write "{host_file}" "{dest_file}"')
|
||||
|
||||
# write script to a temp file
|
||||
with tempfile.NamedTemporaryFile(mode='w', delete=False,
|
||||
prefix='wic-debugfs-') as tf:
|
||||
for line in cmds:
|
||||
tf.write(line + '\n')
|
||||
scriptname = tf.name
|
||||
|
||||
cmd = f"{self.debugfs} -w -f {scriptname} {partimg}"
|
||||
|
||||
else: # single file
|
||||
cmd = "printf 'cd {}\nwrite {} {}\n' | {} -w {}".\
|
||||
format(os.path.dirname(dest.path), src,
|
||||
os.path.basename(src), self.debugfs, partimg)
|
||||
|
||||
else: # image to host case
|
||||
cmd = "printf 'cd {}\ndump /{} {}\nrdump /{} {}\n' | {} {}".\
|
||||
format(os.path.dirname(src.path), src.path,
|
||||
dest, src.path, dest, self.debugfs,
|
||||
self._get_part_image(pnum))
|
||||
dest, src.path, dest, self.debugfs, partimg)
|
||||
|
||||
else: # fat
|
||||
if isinstance(src, str):
|
||||
cmd = "{} -i {} -snop {} ::{}".format(self.mcopy,
|
||||
self._get_part_image(pnum),
|
||||
src, dest.path)
|
||||
partimg,
|
||||
src, dest.path)
|
||||
else:
|
||||
cmd = "{} -i {} -snop ::{} {}".format(self.mcopy,
|
||||
self._get_part_image(pnum),
|
||||
src.path, dest)
|
||||
partimg,
|
||||
src.path, dest)
|
||||
|
||||
exec_cmd(cmd, as_shell=True)
|
||||
self._put_part_image(pnum)
|
||||
|
||||
Reference in New Issue
Block a user