cmd/link: don't unmap output file at error exit

When the link exits on error it currently calls Out.Close, which
will munmap the output buffer and close the file. This may be
called in concurrent phase where other goroutines may be writing
to the output buffer. The munmap can race with the write, causing
it to write to unmapped memory and crash. This CL changes it to
just close the file without unmapping. We're exiting on error
anyway so no need to unmap.

Fixes #47816.

Change-Id: I0e89aca991bdada3d017b7d5c8efc29e46308c03
Reviewed-on: https://go-review.googlesource.com/c/go/+/363357
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cherry Mui 2021-11-11 16:51:08 -05:00
parent 7bed3c7975
commit e9f0381a80
3 changed files with 15 additions and 2 deletions

View File

@ -1103,7 +1103,6 @@ func hostlinksetup(ctxt *Link) {
*flagTmpdir = dir
ownTmpDir = true
AtExit(func() {
ctxt.Out.Close()
os.RemoveAll(*flagTmpdir)
})
}

View File

@ -131,6 +131,20 @@ func (out *OutBuf) Close() error {
return nil
}
// ErrorClose closes the output file (if any).
// It is supposed to be called only at exit on error, so it doesn't do
// any clean up or buffer flushing, just closes the file.
func (out *OutBuf) ErrorClose() {
if out.isView {
panic(viewCloseError)
}
if out.f == nil {
return
}
out.f.Close() // best effort, ignore error
out.f = nil
}
// isMmapped returns true if the OutBuf is mmaped.
func (out *OutBuf) isMmapped() bool {
return len(out.buf) != 0

View File

@ -60,7 +60,7 @@ func linknew(arch *sys.Arch) *Link {
AtExit(func() {
if nerrors > 0 {
ctxt.Out.Close()
ctxt.Out.ErrorClose()
mayberemoveoutfile()
}
})