Skip to content

Commit

Permalink
cmd/go: disallow -lto_library in LDFLAGS
Browse files Browse the repository at this point in the history
The darwin linker allows setting the LTO library with the -lto_library
flag. This wasn't caught by our "safe linker flags" check because it
was covered by the -lx flag used for linking libraries. This change
adds a specific check for excluded flags which otherwise satisfy our
existing checks.

Loading a mallicious LTO library would allow an attacker to cause the
linker to execute abritrary code when "go build" was called.

Thanks to Juho Forsén of Mattermost for reporting this issue.

Fixes #67119
Fixes CVE-2024-24787

Change-Id: I77ac8585efbdbdfd5f39c39ed623b9408a0f9eaf
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1380
Reviewed-by: Russ Cox <rsc@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/583815
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
rolandshoemaker authored and cherrymui committed May 7, 2024
1 parent 38ee0c7 commit 348b238
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 4 deletions.
19 changes: 15 additions & 4 deletions src/cmd/go/internal/work/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ var validCompilerFlagsWithNextArg = []string{
"-x",
}

var invalidLinkerFlags = []*lazyregexp.Regexp{
// On macOS this means the linker loads and executes the next argument.
// Have to exclude separately because -lfoo is allowed in general.
re(`-lto_library`),
}

var validLinkerFlags = []*lazyregexp.Regexp{
re(`-F([^@\-].*)`),
re(`-l([^@\-].*)`),
Expand Down Expand Up @@ -234,12 +240,12 @@ var validLinkerFlagsWithNextArg = []string{

func checkCompilerFlags(name, source string, list []string) error {
checkOverrides := true
return checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides)
return checkFlags(name, source, list, nil, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides)
}

func checkLinkerFlags(name, source string, list []string) error {
checkOverrides := true
return checkFlags(name, source, list, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides)
return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides)
}

// checkCompilerFlagsForInternalLink returns an error if 'list'
Expand All @@ -248,7 +254,7 @@ func checkLinkerFlags(name, source string, list []string) error {
// external linker).
func checkCompilerFlagsForInternalLink(name, source string, list []string) error {
checkOverrides := false
if err := checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides); err != nil {
if err := checkFlags(name, source, list, nil, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides); err != nil {
return err
}
// Currently the only flag on the allow list that causes problems
Expand All @@ -261,7 +267,7 @@ func checkCompilerFlagsForInternalLink(name, source string, list []string) error
return nil
}

func checkFlags(name, source string, list []string, valid []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error {
func checkFlags(name, source string, list []string, invalid, valid []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error {
// Let users override rules with $CGO_CFLAGS_ALLOW, $CGO_CFLAGS_DISALLOW, etc.
var (
allow *regexp.Regexp
Expand Down Expand Up @@ -293,6 +299,11 @@ Args:
if allow != nil && allow.FindString(arg) == arg {
continue Args
}
for _, re := range invalid {
if re.FindString(arg) == arg { // must be complete match
goto Bad
}
}
for _, re := range valid {
if re.FindString(arg) == arg { // must be complete match
continue Args
Expand Down
17 changes: 17 additions & 0 deletions src/cmd/go/testdata/script/darwin_lto_library_ldflag.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[!GOOS:darwin] skip
[!cgo] skip

! go build
stderr 'invalid flag in #cgo LDFLAGS: -lto_library'

-- go.mod --
module ldflag

-- main.go --
package main

// #cgo CFLAGS: -flto
// #cgo LDFLAGS: -lto_library bad.dylib
import "C"

func main() {}

0 comments on commit 348b238

Please sign in to comment.