Skip to content

Commit a79ea27

Browse files
rolandshoemakercherrymui
authored andcommitted
[release-branch.go1.21] cmd/go: disallow -lto_library in LDFLAGS
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 #67121 Fixes CVE-2024-24787 Change-Id: I77ac8585efbdbdfd5f39c39ed623b9408a0f9eaf Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1380 Reviewed-by: Russ Cox <[email protected]> Reviewed-by: Damien Neil <[email protected]> (cherry picked from commit 9a79141fbbca1105e5c786f15e38741ca7843290) Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1401 Reviewed-by: Tatiana Bradley <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/583795 Reviewed-by: David Chase <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 78d89b2 commit a79ea27

File tree

2 files changed

+32
-4
lines changed

2 files changed

+32
-4
lines changed

src/cmd/go/internal/work/security.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ var validCompilerFlagsWithNextArg = []string{
141141
"-x",
142142
}
143143

144+
var invalidLinkerFlags = []*lazyregexp.Regexp{
145+
// On macOS this means the linker loads and executes the next argument.
146+
// Have to exclude separately because -lfoo is allowed in general.
147+
re(`-lto_library`),
148+
}
149+
144150
var validLinkerFlags = []*lazyregexp.Regexp{
145151
re(`-F([^@\-].*)`),
146152
re(`-l([^@\-].*)`),
@@ -231,12 +237,12 @@ var validLinkerFlagsWithNextArg = []string{
231237

232238
func checkCompilerFlags(name, source string, list []string) error {
233239
checkOverrides := true
234-
return checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides)
240+
return checkFlags(name, source, list, nil, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides)
235241
}
236242

237243
func checkLinkerFlags(name, source string, list []string) error {
238244
checkOverrides := true
239-
return checkFlags(name, source, list, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides)
245+
return checkFlags(name, source, list, invalidLinkerFlags, validLinkerFlags, validLinkerFlagsWithNextArg, checkOverrides)
240246
}
241247

242248
// checkCompilerFlagsForInternalLink returns an error if 'list'
@@ -245,7 +251,7 @@ func checkLinkerFlags(name, source string, list []string) error {
245251
// external linker).
246252
func checkCompilerFlagsForInternalLink(name, source string, list []string) error {
247253
checkOverrides := false
248-
if err := checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides); err != nil {
254+
if err := checkFlags(name, source, list, nil, validCompilerFlags, validCompilerFlagsWithNextArg, checkOverrides); err != nil {
249255
return err
250256
}
251257
// Currently the only flag on the allow list that causes problems
@@ -258,7 +264,7 @@ func checkCompilerFlagsForInternalLink(name, source string, list []string) error
258264
return nil
259265
}
260266

261-
func checkFlags(name, source string, list []string, valid []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error {
267+
func checkFlags(name, source string, list []string, invalid, valid []*lazyregexp.Regexp, validNext []string, checkOverrides bool) error {
262268
// Let users override rules with $CGO_CFLAGS_ALLOW, $CGO_CFLAGS_DISALLOW, etc.
263269
var (
264270
allow *regexp.Regexp
@@ -290,6 +296,11 @@ Args:
290296
if allow != nil && allow.FindString(arg) == arg {
291297
continue Args
292298
}
299+
for _, re := range invalid {
300+
if re.FindString(arg) == arg { // must be complete match
301+
goto Bad
302+
}
303+
}
293304
for _, re := range valid {
294305
if re.FindString(arg) == arg { // must be complete match
295306
continue Args
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[!GOOS:darwin] skip
2+
[!cgo] skip
3+
4+
! go build
5+
stderr 'invalid flag in #cgo LDFLAGS: -lto_library'
6+
7+
-- go.mod --
8+
module ldflag
9+
10+
-- main.go --
11+
package main
12+
13+
// #cgo CFLAGS: -flto
14+
// #cgo LDFLAGS: -lto_library bad.dylib
15+
import "C"
16+
17+
func main() {}

0 commit comments

Comments
 (0)