On Wed May 13, 2026 at 7:28 AM CEST, Hitendra Prajapati via
lists.openembedded.org wrote:
> Pick patch from [1] & [2] also mentioned at Debian report in [3] & [4]
>
> [1]
> https://github.com/golang/go/commit/4c79c4223e42b4727d1600e71ad6983cfb21f534
> [2]
> https://github.com/golang/go/commit/02f574a8303560a4a79a42834f3092ce7c9a57cc
> [3] https://security-tracker.debian.org/tracker/CVE-2026-32282
> [4] https://security-tracker.debian.org/tracker/CVE-2026-32283
>
> Signed-off-by: Hitendra Prajapati <[email protected]>
> ---
> meta/recipes-devtools/go/go-1.22.12.inc | 2 +
> .../go/go/CVE-2026-32282.patch | 240 ++++++++++++++++++
> .../go/go/CVE-2026-32283.patch | 178 +++++++++++++
> 3 files changed, 420 insertions(+)
> create mode 100644 meta/recipes-devtools/go/go/CVE-2026-32282.patch
> create mode 100644 meta/recipes-devtools/go/go/CVE-2026-32283.patch
>
> diff --git a/meta/recipes-devtools/go/go-1.22.12.inc
> b/meta/recipes-devtools/go/go-1.22.12.inc
> index 5753243f0e..7e61a51362 100644
> --- a/meta/recipes-devtools/go/go-1.22.12.inc
> +++ b/meta/recipes-devtools/go/go-1.22.12.inc
> @@ -45,6 +45,8 @@ SRC_URI += "\
> file://CVE-2026-27143.patch \
> file://CVE-2026-27144.patch \
> file://CVE-2026-32280.patch \
> + file://CVE-2026-32282.patch \
> + file://CVE-2026-32283.patch \
> "
> SRC_URI[main.sha256sum] =
> "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
>
> diff --git a/meta/recipes-devtools/go/go/CVE-2026-32282.patch
> b/meta/recipes-devtools/go/go/CVE-2026-32282.patch
> new file mode 100644
> index 0000000000..b0633b092c
> --- /dev/null
> +++ b/meta/recipes-devtools/go/go/CVE-2026-32282.patch
> @@ -0,0 +1,240 @@
> +From 4c79c4223e42b4727d1600e71ad6983cfb21f534 Mon Sep 17 00:00:00 2001
> +From: Damien Neil <[email protected]>
> +Date: Mon, 23 Mar 2026 10:34:50 -0700
> +Subject: [PATCH] [release-branch.go1.25] internal/syscall/unix: properly
> + support AT_SYMLINK_NOFOLLOW on Linux
> +
> +On Linux, the fchmodat syscall silently ignores the AT_SYMLINK_NOFOLLOW flag.
> +
> +Change the Linux Fchmodat function to use the fstatat2 syscall
> +(added in Linux 6.6) when available.
> +
> +When fstatat2 is not available, use the same workaround as
> +GNU libc and musl, which is to open the target file
> +with O_PATH and then chmod it via /proc/self/fd.
> +
> +This change fixes an os.Root escape, where Root.Chmod could follow
> +a symlink and act on a file outside of the root. Root.Chmod checks
> +to see if its target is a symlink before calling fchmodat, so this
> +escape requires the target to be replaced with a symlink in between
> +the initial check and the fchmodat.
> +
> +Thanks to Uuganbayar Lkhamsuren (https://github.com/uug4na)
> +for reporting this issue.
> +
> +Fixes CVE-2026-32282
> +Fixes #78293
> +
> +Change-Id: Ie487be1a853b341a77b42ae0c59301d46a6a6964
> +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3900
> +Reviewed-by: Damien Neil <[email protected]>
> +Reviewed-by: Neal Patel <[email protected]>
> +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3982
> +Commit-Queue: Damien Neil <[email protected]>
> +Reviewed-on: https://go-review.googlesource.com/c/go/+/763550
> +Reviewed-by: David Chase <[email protected]>
> +Auto-Submit: Gopher Robot <[email protected]>
> +TryBot-Bypass: Gopher Robot <[email protected]>
> +Reviewed-by: Junyang Shao <[email protected]>
> +
> +
> +CVE: CVE-2026-32282
> +Upstream-Status: Backport
> [https://github.com/golang/go/commit/4c79c4223e42b4727d1600e71ad6983cfb21f534]
> +Signed-off-by: Hitendra Prajapati <[email protected]>
> +---
> + src/cmd/dist/buildtool.go | 1 +
> + src/internal/syscall/unix/at_sysnum_linux.go | 2 +
> + src/internal/syscall/unix/fchmodat_linux.go | 51 ++++++++++++++++
> + src/internal/syscall/unix/fchmodat_other.go | 29 +++++++++
> + src/internal/syscall/unix/fchmodat_test.go | 62 ++++++++++++++++++++
> + 5 files changed, 145 insertions(+)
> + create mode 100644 src/internal/syscall/unix/fchmodat_linux.go
> + create mode 100644 src/internal/syscall/unix/fchmodat_other.go
> + create mode 100644 src/internal/syscall/unix/fchmodat_test.go
> +
> +diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
> +index 3232896..9cc7075 100644
> +--- a/src/cmd/dist/buildtool.go
> ++++ b/src/cmd/dist/buildtool.go
> +@@ -74,6 +74,7 @@ var bootstrapDirs = []string{
> + "internal/goroot",
> + "internal/gover",
> + "internal/goversion",
> ++ "internal/itoa",
> + // internal/lazyregexp is provided by Go 1.17, which permits it to
> + // be imported by other packages in this list, but is not provided
> + // by the Go 1.17 version of gccgo. It's on this list only to
> +diff --git a/src/internal/syscall/unix/at_sysnum_linux.go
> b/src/internal/syscall/unix/at_sysnum_linux.go
> +index 7c3b15c..12ee1d4 100644
> +--- a/src/internal/syscall/unix/at_sysnum_linux.go
> ++++ b/src/internal/syscall/unix/at_sysnum_linux.go
> +@@ -16,4 +16,6 @@ const (
> + AT_SYMLINK_NOFOLLOW = 0x100
> +
> + UTIME_OMIT = 0x3ffffffe
> ++
> ++ O_PATH = 0x200000
> + )
> +diff --git a/src/internal/syscall/unix/fchmodat_linux.go
> b/src/internal/syscall/unix/fchmodat_linux.go
> +new file mode 100644
> +index 0000000..a9fa42b
> +--- /dev/null
> ++++ b/src/internal/syscall/unix/fchmodat_linux.go
> +@@ -0,0 +1,51 @@
> ++// Copyright 2026 The Go Authors. All rights reserved.
> ++// Use of this source code is governed by a BSD-style
> ++// license that can be found in the LICENSE file.
> ++
> ++//go:build linux
> ++
> ++package unix
> ++
> ++import (
> ++ "internal/itoa"
> ++ "syscall"
> ++)
> ++
> ++func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
Hello,
Upstream patch *moves* the function but this path only add the new one.
I find that surprising... Can you check that this is correct?
Thanks!
> ++ // On Linux, the fchmodat syscall silently ignores the
> AT_SYMLINK_NOFOLLOW flag.
> ++ // We need to use fchmodat2 instead.
> ++ // syscall.Fchmodat handles this.
> ++ if err := syscall.Fchmodat(dirfd, path, mode, flags); err !=
> syscall.EOPNOTSUPP {
> ++ return err
> ++ }
> ++
> ++ // This kernel doesn't appear to support fchmodat2 (added in Linux 6.6).
> ++ // We can't fall back to Fchmod, because it requires write permissions
> on the file.
> ++ // Instead, use the same workaround as GNU libc and musl, which is to
> open the file
> ++ // and then fchmodat the FD in /proc/self/fd.
> ++ // See: https://lwn.net/Articles/939217/
> ++ fd, err := Openat(dirfd, path,
> O_PATH|syscall.O_NOFOLLOW|syscall.O_CLOEXEC, 0)
> ++ if err != nil {
> ++ return err
> ++ }
> ++ defer syscall.Close(fd)
> ++ procPath := "/proc/self/fd/" + itoa.Itoa(fd)
> ++
> ++ // Check to see if this file is a symlink.
> ++ // (We passed O_NOFOLLOW above, but O_PATH|O_NOFOLLOW will open a
> symlink.)
> ++ var st syscall.Stat_t
> ++ if err := syscall.Stat(procPath, &st); err != nil {
> ++ if err == syscall.ENOENT {
> ++ // /proc has probably not been mounted. Give up.
> ++ return syscall.EOPNOTSUPP
> ++ }
> ++ return err
> ++ }
> ++ if st.Mode&syscall.S_IFMT == syscall.S_IFLNK {
> ++ // fchmodat on the proc FD for a symlink apparently gives
> inconsistent
> ++ // results, so just refuse to try.
> ++ return syscall.EOPNOTSUPP
> ++ }
> ++
> ++ return syscall.Fchmodat(AT_FDCWD, procPath, mode,
> flags&^AT_SYMLINK_NOFOLLOW)
> ++}
> +diff --git a/src/internal/syscall/unix/fchmodat_other.go
> b/src/internal/syscall/unix/fchmodat_other.go
> +new file mode 100644
> +index 0000000..76f478c
> +--- /dev/null
> ++++ b/src/internal/syscall/unix/fchmodat_other.go
> +@@ -0,0 +1,29 @@
> ++// Copyright 2026 The Go Authors. All rights reserved.
> ++// Use of this source code is governed by a BSD-style
> ++// license that can be found in the LICENSE file.
> ++
> ++//go:build dragonfly || freebsd || netbsd || (openbsd && mips64)
> ++
> ++package unix
> ++
> ++import (
> ++ "syscall"
> ++ "unsafe"
> ++)
> ++
> ++func Fchmodat(dirfd int, path string, mode uint32, flags int) error {
> ++ p, err := syscall.BytePtrFromString(path)
> ++ if err != nil {
> ++ return err
> ++ }
> ++ _, _, errno := syscall.Syscall6(fchmodatTrap,
> ++ uintptr(dirfd),
> ++ uintptr(unsafe.Pointer(p)),
> ++ uintptr(mode),
> ++ uintptr(flags),
> ++ 0, 0)
> ++ if errno != 0 {
> ++ return errno
> ++ }
> ++ return nil
> ++}
> +diff --git a/src/internal/syscall/unix/fchmodat_test.go
> b/src/internal/syscall/unix/fchmodat_test.go
> +new file mode 100644
> +index 0000000..49a0985
> +--- /dev/null
> ++++ b/src/internal/syscall/unix/fchmodat_test.go
> +@@ -0,0 +1,62 @@
> ++// Copyright 2026 The Go Authors. All rights reserved.
> ++// Use of this source code is governed by a BSD-style
> ++// license that can be found in the LICENSE file.
> ++
> ++//go:build unix || wasip1
> ++
> ++package unix_test
> ++
> ++import (
> ++ "internal/syscall/unix"
> ++ "os"
> ++ "runtime"
> ++ "testing"
> ++)
> ++
> ++// TestFchmodAtSymlinkNofollow verifies that Fchmodat honors the
> AT_SYMLINK_NOFOLLOW flag.
> ++func TestFchmodatSymlinkNofollow(t *testing.T) {
> ++ if runtime.GOOS == "wasip1" {
> ++ t.Skip("wasip1 doesn't support chmod")
> ++ }
> ++
> ++ dir := t.TempDir()
> ++ filename := dir + "/file"
> ++ linkname := dir + "/symlink"
> ++ if err := os.WriteFile(filename, nil, 0o100); err != nil {
> ++ t.Fatal(err)
> ++ }
> ++ if err := os.Symlink(filename, linkname); err != nil {
> ++ t.Fatal(err)
> ++ }
> ++
> ++ parent, err := os.Open(dir)
> ++ if err != nil {
> ++ t.Fatal(err)
> ++ }
> ++ defer parent.Close()
> ++
> ++ lstatMode := func(path string) os.FileMode {
> ++ st, err := os.Lstat(path)
> ++ if err != nil {
> ++ t.Fatal(err)
> ++ }
> ++ return st.Mode()
> ++ }
> ++
> ++ // Fchmodat with no flags follows symlinks.
> ++ const mode1 = 0o200
> ++ if err := unix.Fchmodat(int(parent.Fd()), "symlink", mode1, 0); err !=
> nil {
> ++ t.Fatal(err)
> ++ }
> ++ if got, want := lstatMode(filename), os.FileMode(mode1); got != want {
> ++ t.Errorf("after Fchmodat(parent, symlink, %v, 0); mode = %v,
> want %v", mode1, got, want)
> ++ }
> ++
> ++ // Fchmodat with AT_SYMLINK_NOFOLLOW does not follow symlinks.
> ++ // The Fchmodat call may fail or chmod the symlink itself, depending on
> the kernel version.
> ++ const mode2 = 0o400
> ++ unix.Fchmodat(int(parent.Fd()), "symlink", mode2,
> unix.AT_SYMLINK_NOFOLLOW)
> ++ if got, want := lstatMode(filename), os.FileMode(mode1); got != want {
> ++ t.Errorf("after Fchmodat(parent, symlink, %v,
> AT_SYMLINK_NOFOLLOW); mode = %v, want %v", mode1, got, want)
> ++ }
> ++}
> +--
> +2.50.1
> +
> diff --git a/meta/recipes-devtools/go/go/CVE-2026-32283.patch
> b/meta/recipes-devtools/go/go/CVE-2026-32283.patch
> new file mode 100644
> index 0000000000..bae4b7b605
> --- /dev/null
> +++ b/meta/recipes-devtools/go/go/CVE-2026-32283.patch
> @@ -0,0 +1,178 @@
> +From 02f574a8303560a4a79a42834f3092ce7c9a57cc Mon Sep 17 00:00:00 2001
> +From: Roland Shoemaker <[email protected]>
> +Date: Mon, 23 Mar 2026 11:54:41 -0700
> +Subject: [PATCH] [release-branch.go1.25] crypto/tls: prevent deadlock when
> + client sends multiple key update messages
> +
> +When we made setReadTrafficSecret send an alert when there are pending
> +handshake messages, we introduced a deadlock when the client sends
> +multiple key update messages that request a response, as handleKeyUpdate
> +will lock the mutex, and defer the unlocking until the end of the
> +function, but setReadTrafficSecret called sendAlert in the failure case,
> +which also tries to lock the mutex.
> +
> +Add an argument to setReadTrafficSecret which lets the caller indicate
> +if the mutex is already locked, and if so, call sendAlertLocked instead
> +of sendAlert.
> +
> +Thanks to Jakub Ciolek for reporting this issue.
> +
> +Fixes #78334
> +Fixes CVE-2026-32283
> +
> +Change-Id: Id8e56974233c910e0d66ba96eafbd2ea57832610
> +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3881
> +Reviewed-by: Damien Neil <[email protected]>
> +Reviewed-by: Nicholas Husin <[email protected]>
> +Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3988
> +Reviewed-on: https://go-review.googlesource.com/c/go/+/763555
> +Auto-Submit: Gopher Robot <[email protected]>
> +Reviewed-by: David Chase <[email protected]>
> +TryBot-Bypass: Gopher Robot <[email protected]>
> +Reviewed-by: Junyang Shao <[email protected]>
> +
> +CVE: CVE-2026-32283
> +Upstream-Status: Backport
> [https://github.com/golang/go/commit/02f574a8303560a4a79a42834f3092ce7c9a57cc]
> +Signed-off-by: Hitendra Prajapati <[email protected]>
> +---
> + src/crypto/tls/conn.go | 10 +++--
> + src/crypto/tls/handshake_client_tls13.go | 4 +-
> + src/crypto/tls/handshake_server_tls13.go | 4 +-
> + src/crypto/tls/handshake_test.go | 48 ++++++++++++++++++++++++
> + 4 files changed, 59 insertions(+), 7 deletions(-)
> +
> +diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go
> +index 08609ce..770d456 100644
> +--- a/src/crypto/tls/conn.go
> ++++ b/src/crypto/tls/conn.go
> +@@ -1345,7 +1345,7 @@ func (c *Conn) handleKeyUpdate(keyUpdate
> *keyUpdateMsg) error {
> + }
> +
> + newSecret := cipherSuite.nextTrafficSecret(c.in.trafficSecret)
> +- if err := c.setReadTrafficSecret(cipherSuite,
> QUICEncryptionLevelInitial, newSecret); err != nil {
> ++ if err := c.setReadTrafficSecret(cipherSuite,
> QUICEncryptionLevelInitial, newSecret, keyUpdate.updateRequested); err != nil
> {
> + return err
> + }
> +
> +@@ -1675,12 +1675,16 @@ func (c *Conn) VerifyHostname(host string) error {
> + // 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 {
> ++func (c *Conn) setReadTrafficSecret(suite *cipherSuiteTLS13, level
> QUICEncryptionLevel, secret []byte, locked bool) 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)
> ++ if locked {
> ++ c.sendAlertLocked(alertUnexpectedMessage)
> ++ } else {
> ++ c.sendAlert(alertUnexpectedMessage)
> ++ }
> + return errors.New("tls: handshake buffer not empty before
> setting read traffic secret")
> + }
> + c.in.setTrafficSecret(suite, level, secret)
> +diff --git a/src/crypto/tls/handshake_client_tls13.go
> b/src/crypto/tls/handshake_client_tls13.go
> +index 68ff92b..2d58b21 100644
> +--- a/src/crypto/tls/handshake_client_tls13.go
> ++++ b/src/crypto/tls/handshake_client_tls13.go
> +@@ -396,7 +396,7 @@ func (hs *clientHandshakeStateTLS13)
> establishHandshakeKeys() error {
> + c.setWriteTrafficSecret(hs.suite, QUICEncryptionLevelHandshake,
> clientSecret)
> + serverSecret := hs.suite.deriveSecret(handshakeSecret,
> + serverHandshakeTrafficLabel, hs.transcript)
> +- if err := c.setReadTrafficSecret(hs.suite,
> QUICEncryptionLevelHandshake, serverSecret); err != nil {
> ++ if err := c.setReadTrafficSecret(hs.suite,
> QUICEncryptionLevelHandshake, serverSecret, false); err != nil {
> + return err
> + }
> +
> +@@ -607,7 +607,7 @@ func (hs *clientHandshakeStateTLS13)
> readServerFinished() error {
> + clientApplicationTrafficLabel, hs.transcript)
> + serverSecret := hs.suite.deriveSecret(hs.masterSecret,
> + serverApplicationTrafficLabel, hs.transcript)
> +- if err := c.setReadTrafficSecret(hs.suite,
> QUICEncryptionLevelApplication, serverSecret); err != nil {
> ++ if err := c.setReadTrafficSecret(hs.suite,
> QUICEncryptionLevelApplication, serverSecret, false); err != nil {
> + return err
> + }
> +
> +diff --git a/src/crypto/tls/handshake_server_tls13.go
> b/src/crypto/tls/handshake_server_tls13.go
> +index 1ecee3a..f73b536 100644
> +--- a/src/crypto/tls/handshake_server_tls13.go
> ++++ b/src/crypto/tls/handshake_server_tls13.go
> +@@ -636,7 +636,7 @@ func (hs *serverHandshakeStateTLS13)
> sendServerParameters() error {
> + 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 {
> ++ if err := c.setReadTrafficSecret(hs.suite,
> QUICEncryptionLevelHandshake, clientSecret, false); err != nil {
> + return err
> + }
> +
> +@@ -1005,7 +1005,7 @@ func (hs *serverHandshakeStateTLS13)
> readClientFinished() error {
> + return errors.New("tls: invalid client finished hash")
> + }
> +
> +- if err := c.setReadTrafficSecret(hs.suite,
> QUICEncryptionLevelApplication, hs.trafficSecret); err != nil {
> ++ if err := c.setReadTrafficSecret(hs.suite,
> QUICEncryptionLevelApplication, hs.trafficSecret, false); err != nil {
> + return err
> + }
> +
> +diff --git a/src/crypto/tls/handshake_test.go
> b/src/crypto/tls/handshake_test.go
> +index 4991a0e..a95d751 100644
> +--- a/src/crypto/tls/handshake_test.go
> ++++ b/src/crypto/tls/handshake_test.go
> +@@ -673,3 +673,51 @@ func concatHandshakeMessages(msgs ...handshakeMessage)
> ([]byte, error) {
> + outBuf = append(outBuf, marshalled...)
> + return outBuf, nil
> + }
> ++
> ++func TestMultipleKeyUpdate(t *testing.T) {
> ++ for _, requestUpdate := range []bool{true, false} {
> ++ t.Run(fmt.Sprintf("requestUpdate=%t", requestUpdate), func(t
> *testing.T) {
> ++
> ++ c, s := localPipe(t)
> ++ cfg := testConfig.Clone()
> ++ cfg.MinVersion = VersionTLS13
> ++ cfg.MaxVersion = VersionTLS13
> ++ client := Client(c, testConfig)
> ++ server := Server(s, testConfig)
> ++
> ++ clientHandshakeDone := make(chan struct{})
> ++ go func() {
> ++ if err := client.Handshake(); err != nil {
> ++ }
> ++ close(clientHandshakeDone)
> ++ io.Copy(io.Discard, server)
> ++ }()
> ++
> ++ if err := server.Handshake(); err != nil {
> ++ t.Fatalf("server handshake failed: %v\n", err)
> ++ }
> ++ <-clientHandshakeDone
> ++
> ++ c.SetReadDeadline(time.Now().Add(1 * time.Second))
> ++ s.SetReadDeadline(time.Now().Add(1 * time.Second))
> ++
> ++ kuMsg, err := (&keyUpdateMsg{updateRequested:
> requestUpdate}).marshal()
> ++ if err != nil {
> ++ t.Fatalf("failed to marshal key update message:
> %v", err)
> ++ }
> ++
> ++ client.out.Lock()
> ++ if _, err :=
> client.writeRecordLocked(recordTypeHandshake, append(kuMsg, kuMsg...)); err
> != nil {
> ++ t.Fatalf("failed to write key update messages:
> %v", err)
> ++ }
> ++ client.out.Unlock()
> ++
> ++ _, err = io.Copy(io.Discard, client)
> ++ if err == nil {
> ++ t.Fatal("expected multiple key update messages
> to cause an error, got nil")
> ++ } else if !strings.HasSuffix(err.Error(), "tls:
> unexpected message") {
> ++ t.Fatalf("unexpected error: %v", err)
> ++ }
> ++ })
> ++ }
> ++}
> +--
> +2.50.1
> +
--
Yoann Congal
Smile ECS
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#238057):
https://lists.openembedded.org/g/openembedded-core/message/238057
Mute This Topic: https://lists.openembedded.org/mt/119293084/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-