]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/link: don't unmap output file at error exit
authorCherry Mui <cherryyz@google.com>
Thu, 11 Nov 2021 21:51:08 +0000 (16:51 -0500)
committerCherry Mui <cherryyz@google.com>
Fri, 12 Nov 2021 14:55:44 +0000 (14:55 +0000)
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>
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/outbuf.go
src/cmd/link/internal/ld/sym.go

index 91665b2ebb41944672525edaff7ed162fd0ad4f5..9e13db7b718783597d8a42644ef6e5c3fc8441a8 100644 (file)
@@ -1103,7 +1103,6 @@ func hostlinksetup(ctxt *Link) {
                *flagTmpdir = dir
                ownTmpDir = true
                AtExit(func() {
-                       ctxt.Out.Close()
                        os.RemoveAll(*flagTmpdir)
                })
        }
index 9d5e8854fea65418c75c30717f865f80cfbd03bc..1d21dce9c5a27e0f33e31f02a8df6f44e3e8fa78 100644 (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
index 72639962e2ffa6b76a5a40a1219f61c183ef9a3a..d51a59ef467372ec0d23bd8307c0b3dfc7f614ba 100644 (file)
@@ -60,7 +60,7 @@ func linknew(arch *sys.Arch) *Link {
 
        AtExit(func() {
                if nerrors > 0 {
-                       ctxt.Out.Close()
+                       ctxt.Out.ErrorClose()
                        mayberemoveoutfile()
                }
        })