Message ID | 20251006105247.611808-1-archana.polampalli@windriver.com |
---|---|
State | Under Review |
Delegated to: | Steve Sakoman |
Headers | show |
Series | [scarthgap,1/1] go: fix CVE-2025-47906 | expand |
This patch doesn't apply: Applying: go: fix CVE-2025-47906 error: sha1 information is lacking or useless (meta/recipes-devtools/go/go-1.22.12.inc). error: could not build fake ancestor Patch failed at 0001 go: fix CVE-2025-47906 It appears that you aren't at the current scarthgap HEAD. Could you please rebase and resend? Thanks, Steve On Mon, Oct 6, 2025 at 3:52 AM Polampalli, Archana via lists.openembedded.org <archana.polampalli=windriver.com@lists.openembedded.org> wrote: > > From: Archana Polampalli <archana.polampalli@windriver.com> > > If the PATH environment variable contains paths which are executables > (rather than just directories), passing certain strings to LookPath > ("", ".", and ".."), can result in the binaries listed in the PATH > being unexpectedly returned. > > Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> > --- > meta/recipes-devtools/go/go-1.22.12.inc | 1 + > .../go/go/CVE-2025-47906.patch | 183 ++++++++++++++++++ > 2 files changed, 184 insertions(+) > create mode 100644 meta/recipes-devtools/go/go/CVE-2025-47906.patch > > diff --git a/meta/recipes-devtools/go/go-1.22.12.inc b/meta/recipes-devtools/go/go-1.22.12.inc > index 4de087170c..af4ec39f56 100644 > --- a/meta/recipes-devtools/go/go-1.22.12.inc > +++ b/meta/recipes-devtools/go/go-1.22.12.inc > @@ -18,5 +18,6 @@ SRC_URI += "\ > file://CVE-2025-22871.patch \ > file://CVE-2025-4673.patch \ > file://CVE-2025-4674.patch \ > + file://CVE-2025-47906.patch \ > " > SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71" > diff --git a/meta/recipes-devtools/go/go/CVE-2025-47906.patch b/meta/recipes-devtools/go/go/CVE-2025-47906.patch > new file mode 100644 > index 0000000000..88895f496d > --- /dev/null > +++ b/meta/recipes-devtools/go/go/CVE-2025-47906.patch > @@ -0,0 +1,183 @@ > +From 8fa31a2d7d9e60c50a3a94080c097b6e65773f4b Mon Sep 17 00:00:00 2001 > +From: =?UTF-8?q?Olivier=20Mengu=C3=A9?= <olivier.mengue@gmail.com> > +Date: Mon, 30 Jun 2025 16:58:59 +0200 > +Subject: [PATCH] [release-branch.go1.23] os/exec: fix incorrect expansion of > + "", "." and ".." in LookPath Fix incorrect expansion of "" and "." when $PATH > + contains an executable file or, on Windows, a parent directory of a %PATH% > + element contains an file with the same name as the %PATH% element but with > + one of the %PATHEXT% extension (ex: C:\utils\bin is in PATH, and > + C:\utils\bin.exe exists). > + > +Fix incorrect expansion of ".." when $PATH contains an element which is > +an the concatenation of the path to an executable file (or on Windows > +a path that can be expanded to an executable by appending a %PATHEXT% > +extension), a path separator and a name. > + > +"", "." and ".." are now rejected early with ErrNotFound. > + > +Fixes CVE-2025-47906 > +Fixes #74803 > + > +Change-Id: Ie50cc0a660fce8fbdc952a7f2e05c36062dcb50e > +Reviewed-on: https://go-review.googlesource.com/c/go/+/685755 > +LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> > +Auto-Submit: Damien Neil <dneil@google.com> > +Reviewed-by: Roland Shoemaker <roland@golang.org> > +Reviewed-by: Damien Neil <dneil@google.com> > +(cherry picked from commit e0b07dc) > +Reviewed-on: https://go-review.googlesource.com/c/go/+/691855 > +Reviewed-by: Michael Knyszek <mknyszek@google.com> > + > +CVE: CVE-2025-47906 > + > +Upstream-Status: Backport [https://github.com/golang/go/commit/8fa31a2d7d9e60c50a3a94080c097b6e65773f4b] > + > +Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> > +--- > + src/os/exec/dot_test.go | 56 +++++++++++++++++++++++++++++++++++++++ > + src/os/exec/exec.go | 10 +++++++ > + src/os/exec/lp_plan9.go | 4 +++ > + src/os/exec/lp_unix.go | 4 +++ > + src/os/exec/lp_windows.go | 7 +++++ > + 5 files changed, 81 insertions(+) > + > +diff --git a/src/os/exec/dot_test.go b/src/os/exec/dot_test.go > +index ed4bad2..86e9cbb 100644 > +--- a/src/os/exec/dot_test.go > ++++ b/src/os/exec/dot_test.go > +@@ -178,4 +178,60 @@ func TestLookPath(t *testing.T) { > + } > + } > + }) > ++ > ++ checker := func(test string) func(t *testing.T) { > ++ return func(t *testing.T) { > ++ t.Helper() > ++ t.Logf("PATH=%s", os.Getenv("PATH")) > ++ p, err := LookPath(test) > ++ if err == nil { > ++ t.Errorf("%q: error expected, got nil", test) > ++ } > ++ if p != "" { > ++ t.Errorf("%q: path returned should be \"\". Got %q", test, p) > ++ } > ++ } > ++ } > ++ > ++ // Reference behavior for the next test > ++ t.Run(pathVar+"=$OTHER2", func(t *testing.T) { > ++ t.Run("empty", checker("")) > ++ t.Run("dot", checker(".")) > ++ t.Run("dotdot1", checker("abc/..")) > ++ t.Run("dotdot2", checker("..")) > ++ }) > ++ > ++ // Test the behavior when PATH contains an executable file which is not a directory > ++ t.Run(pathVar+"=exe", func(t *testing.T) { > ++ // Inject an executable file (not a directory) in PATH. > ++ // Use our own binary os.Args[0]. > ++ testenv.MustHaveExec(t) > ++ exe, err := os.Executable() > ++ if err != nil { > ++ t.Fatal(err) > ++ } > ++ > ++ t.Setenv(pathVar, exe) > ++ t.Run("empty", checker("")) > ++ t.Run("dot", checker(".")) > ++ t.Run("dotdot1", checker("abc/..")) > ++ t.Run("dotdot2", checker("..")) > ++ }) > ++ > ++ // Test the behavior when PATH contains an executable file which is not a directory > ++ t.Run(pathVar+"=exe/xx", func(t *testing.T) { > ++ // Inject an executable file (not a directory) in PATH. > ++ // Use our own binary os.Args[0]. > ++ testenv.MustHaveExec(t) > ++ exe, err := os.Executable() > ++ if err != nil { > ++ t.Fatal(err) > ++ } > ++ > ++ t.Setenv(pathVar, filepath.Join(exe, "xx")) > ++ t.Run("empty", checker("")) > ++ t.Run("dot", checker(".")) > ++ t.Run("dotdot1", checker("abc/..")) > ++ t.Run("dotdot2", checker("..")) > ++ }) > + } > +diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go > +index b8ef5a0..2c7f510 100644 > +--- a/src/os/exec/exec.go > ++++ b/src/os/exec/exec.go > +@@ -1310,3 +1310,13 @@ func addCriticalEnv(env []string) []string { > + // Code should use errors.Is(err, ErrDot), not err == ErrDot, > + // to test whether a returned error err is due to this condition. > + var ErrDot = errors.New("cannot run executable found relative to current directory") > ++ > ++// validateLookPath excludes paths that can't be valid > ++// executable names. See issue #74466 and CVE-2025-47906. > ++func validateLookPath(s string) error { > ++ switch s { > ++ case "", ".", "..": > ++ return ErrNotFound > ++ } > ++ return nil > ++} > +diff --git a/src/os/exec/lp_plan9.go b/src/os/exec/lp_plan9.go > +index dffdbac..39f3d33 100644 > +--- a/src/os/exec/lp_plan9.go > ++++ b/src/os/exec/lp_plan9.go > +@@ -36,6 +36,10 @@ func findExecutable(file string) error { > + // As of Go 1.19, LookPath will instead return that path along with an error satisfying > + // errors.Is(err, ErrDot). See the package documentation for more details. > + func LookPath(file string) (string, error) { > ++ if err := validateLookPath(file); err != nil { > ++ return "", &Error{file, err} > ++ } > ++ > + // skip the path lookup for these prefixes > + skip := []string{"/", "#", "./", "../"} > + > +diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go > +index 3787132..2543525 100644 > +--- a/src/os/exec/lp_unix.go > ++++ b/src/os/exec/lp_unix.go > +@@ -54,6 +54,10 @@ func LookPath(file string) (string, error) { > + // (only bypass the path if file begins with / or ./ or ../) > + // but that would not match all the Unix shells. > + > ++ if err := validateLookPath(file); err != nil { > ++ return "", &Error{file, err} > ++ } > ++ > + if strings.Contains(file, "/") { > + err := findExecutable(file) > + if err == nil { > +diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go > +index 698a97c..e0b74e3 100644 > +--- a/src/os/exec/lp_windows.go > ++++ b/src/os/exec/lp_windows.go > +@@ -68,6 +68,9 @@ func findExecutable(file string, exts []string) (string, error) { > + // As of Go 1.19, LookPath will instead return that path along with an error satisfying > + // errors.Is(err, ErrDot). See the package documentation for more details. > + func LookPath(file string) (string, error) { > ++ if err := validateLookPath(file); err != nil { > ++ return "", &Error{file, err} > ++ } > + return lookPath(file, pathExt()) > + } > + > +@@ -81,6 +84,10 @@ func LookPath(file string) (string, error) { > + // "C:\foo\example.com" would be returned as-is even if the > + // program is actually "C:\foo\example.com.exe". > + func lookExtensions(path, dir string) (string, error) { > ++ if err := validateLookPath(path); err != nil { > ++ return "", &Error{path, err} > ++ } > ++ > + if filepath.Base(path) == path { > + path = "." + string(filepath.Separator) + path > + } > +-- > +2.40.0 > -- > 2.40.0 > > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#224476): https://lists.openembedded.org/g/openembedded-core/message/224476 > Mute This Topic: https://lists.openembedded.org/mt/115614883/3620601 > Group Owner: openembedded-core+owner@lists.openembedded.org > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com] > -=-=-=-=-=-=-=-=-=-=-=- >
diff --git a/meta/recipes-devtools/go/go-1.22.12.inc b/meta/recipes-devtools/go/go-1.22.12.inc index 4de087170c..af4ec39f56 100644 --- a/meta/recipes-devtools/go/go-1.22.12.inc +++ b/meta/recipes-devtools/go/go-1.22.12.inc @@ -18,5 +18,6 @@ SRC_URI += "\ file://CVE-2025-22871.patch \ file://CVE-2025-4673.patch \ file://CVE-2025-4674.patch \ + file://CVE-2025-47906.patch \ " SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71" diff --git a/meta/recipes-devtools/go/go/CVE-2025-47906.patch b/meta/recipes-devtools/go/go/CVE-2025-47906.patch new file mode 100644 index 0000000000..88895f496d --- /dev/null +++ b/meta/recipes-devtools/go/go/CVE-2025-47906.patch @@ -0,0 +1,183 @@ +From 8fa31a2d7d9e60c50a3a94080c097b6e65773f4b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Olivier=20Mengu=C3=A9?= <olivier.mengue@gmail.com> +Date: Mon, 30 Jun 2025 16:58:59 +0200 +Subject: [PATCH] [release-branch.go1.23] os/exec: fix incorrect expansion of + "", "." and ".." in LookPath Fix incorrect expansion of "" and "." when $PATH + contains an executable file or, on Windows, a parent directory of a %PATH% + element contains an file with the same name as the %PATH% element but with + one of the %PATHEXT% extension (ex: C:\utils\bin is in PATH, and + C:\utils\bin.exe exists). + +Fix incorrect expansion of ".." when $PATH contains an element which is +an the concatenation of the path to an executable file (or on Windows +a path that can be expanded to an executable by appending a %PATHEXT% +extension), a path separator and a name. + +"", "." and ".." are now rejected early with ErrNotFound. + +Fixes CVE-2025-47906 +Fixes #74803 + +Change-Id: Ie50cc0a660fce8fbdc952a7f2e05c36062dcb50e +Reviewed-on: https://go-review.googlesource.com/c/go/+/685755 +LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> +Auto-Submit: Damien Neil <dneil@google.com> +Reviewed-by: Roland Shoemaker <roland@golang.org> +Reviewed-by: Damien Neil <dneil@google.com> +(cherry picked from commit e0b07dc) +Reviewed-on: https://go-review.googlesource.com/c/go/+/691855 +Reviewed-by: Michael Knyszek <mknyszek@google.com> + +CVE: CVE-2025-47906 + +Upstream-Status: Backport [https://github.com/golang/go/commit/8fa31a2d7d9e60c50a3a94080c097b6e65773f4b] + +Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> +--- + src/os/exec/dot_test.go | 56 +++++++++++++++++++++++++++++++++++++++ + src/os/exec/exec.go | 10 +++++++ + src/os/exec/lp_plan9.go | 4 +++ + src/os/exec/lp_unix.go | 4 +++ + src/os/exec/lp_windows.go | 7 +++++ + 5 files changed, 81 insertions(+) + +diff --git a/src/os/exec/dot_test.go b/src/os/exec/dot_test.go +index ed4bad2..86e9cbb 100644 +--- a/src/os/exec/dot_test.go ++++ b/src/os/exec/dot_test.go +@@ -178,4 +178,60 @@ func TestLookPath(t *testing.T) { + } + } + }) ++ ++ checker := func(test string) func(t *testing.T) { ++ return func(t *testing.T) { ++ t.Helper() ++ t.Logf("PATH=%s", os.Getenv("PATH")) ++ p, err := LookPath(test) ++ if err == nil { ++ t.Errorf("%q: error expected, got nil", test) ++ } ++ if p != "" { ++ t.Errorf("%q: path returned should be \"\". Got %q", test, p) ++ } ++ } ++ } ++ ++ // Reference behavior for the next test ++ t.Run(pathVar+"=$OTHER2", func(t *testing.T) { ++ t.Run("empty", checker("")) ++ t.Run("dot", checker(".")) ++ t.Run("dotdot1", checker("abc/..")) ++ t.Run("dotdot2", checker("..")) ++ }) ++ ++ // Test the behavior when PATH contains an executable file which is not a directory ++ t.Run(pathVar+"=exe", func(t *testing.T) { ++ // Inject an executable file (not a directory) in PATH. ++ // Use our own binary os.Args[0]. ++ testenv.MustHaveExec(t) ++ exe, err := os.Executable() ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ t.Setenv(pathVar, exe) ++ t.Run("empty", checker("")) ++ t.Run("dot", checker(".")) ++ t.Run("dotdot1", checker("abc/..")) ++ t.Run("dotdot2", checker("..")) ++ }) ++ ++ // Test the behavior when PATH contains an executable file which is not a directory ++ t.Run(pathVar+"=exe/xx", func(t *testing.T) { ++ // Inject an executable file (not a directory) in PATH. ++ // Use our own binary os.Args[0]. ++ testenv.MustHaveExec(t) ++ exe, err := os.Executable() ++ if err != nil { ++ t.Fatal(err) ++ } ++ ++ t.Setenv(pathVar, filepath.Join(exe, "xx")) ++ t.Run("empty", checker("")) ++ t.Run("dot", checker(".")) ++ t.Run("dotdot1", checker("abc/..")) ++ t.Run("dotdot2", checker("..")) ++ }) + } +diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go +index b8ef5a0..2c7f510 100644 +--- a/src/os/exec/exec.go ++++ b/src/os/exec/exec.go +@@ -1310,3 +1310,13 @@ func addCriticalEnv(env []string) []string { + // Code should use errors.Is(err, ErrDot), not err == ErrDot, + // to test whether a returned error err is due to this condition. + var ErrDot = errors.New("cannot run executable found relative to current directory") ++ ++// validateLookPath excludes paths that can't be valid ++// executable names. See issue #74466 and CVE-2025-47906. ++func validateLookPath(s string) error { ++ switch s { ++ case "", ".", "..": ++ return ErrNotFound ++ } ++ return nil ++} +diff --git a/src/os/exec/lp_plan9.go b/src/os/exec/lp_plan9.go +index dffdbac..39f3d33 100644 +--- a/src/os/exec/lp_plan9.go ++++ b/src/os/exec/lp_plan9.go +@@ -36,6 +36,10 @@ func findExecutable(file string) error { + // As of Go 1.19, LookPath will instead return that path along with an error satisfying + // errors.Is(err, ErrDot). See the package documentation for more details. + func LookPath(file string) (string, error) { ++ if err := validateLookPath(file); err != nil { ++ return "", &Error{file, err} ++ } ++ + // skip the path lookup for these prefixes + skip := []string{"/", "#", "./", "../"} + +diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go +index 3787132..2543525 100644 +--- a/src/os/exec/lp_unix.go ++++ b/src/os/exec/lp_unix.go +@@ -54,6 +54,10 @@ func LookPath(file string) (string, error) { + // (only bypass the path if file begins with / or ./ or ../) + // but that would not match all the Unix shells. + ++ if err := validateLookPath(file); err != nil { ++ return "", &Error{file, err} ++ } ++ + if strings.Contains(file, "/") { + err := findExecutable(file) + if err == nil { +diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go +index 698a97c..e0b74e3 100644 +--- a/src/os/exec/lp_windows.go ++++ b/src/os/exec/lp_windows.go +@@ -68,6 +68,9 @@ func findExecutable(file string, exts []string) (string, error) { + // As of Go 1.19, LookPath will instead return that path along with an error satisfying + // errors.Is(err, ErrDot). See the package documentation for more details. + func LookPath(file string) (string, error) { ++ if err := validateLookPath(file); err != nil { ++ return "", &Error{file, err} ++ } + return lookPath(file, pathExt()) + } + +@@ -81,6 +84,10 @@ func LookPath(file string) (string, error) { + // "C:\foo\example.com" would be returned as-is even if the + // program is actually "C:\foo\example.com.exe". + func lookExtensions(path, dir string) (string, error) { ++ if err := validateLookPath(path); err != nil { ++ return "", &Error{path, err} ++ } ++ + if filepath.Base(path) == path { + path = "." + string(filepath.Separator) + path + } +-- +2.40.0