1
0
mirror of https://github.com/golang/go synced 2024-11-18 08:14:41 -07:00

cmd/link: turn ASLR off for netbsd+race

The race detector can't handle ASLR (adddress space layout randomization).
On some platforms it can re-exec the binary with ASLR off. But not NetBSD.
For NetBSD we have to introduce a special ELF header note that tells
the kernel not to use ASLR.

This works fine for internal linking. For external linking it also works,
but "readelf -n" shows multiple notes in the resulting binary. Maybe the
last one wins? Not sure, but it appears to work.

Change-Id: I5fe6dd861e42a8293f64d0dacb166631ea670fcc
Reviewed-on: https://go-review.googlesource.com/c/go/+/227864
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
This commit is contained in:
Keith Randall 2020-04-10 14:07:13 -07:00
parent df15eaedd0
commit fd18f3ba50

View File

@ -883,6 +883,25 @@ func elfwritenetbsdsig(out *OutBuf) int {
return int(sh.size)
}
// The race detector can't handle ASLR (address space layout randomization).
// ASLR is on by default for NetBSD, so we turn the ASLR off eplicitly
// using a magic elf Note when building race binaries.
func elfnetbsdpax(sh *ElfShdr, startva uint64, resoff uint64) int {
n := int(Rnd(4, 4) + Rnd(4, 4))
return elfnote(sh, startva, resoff, n)
}
func elfwritenetbsdpax(out *OutBuf) int {
sh := elfwritenotehdr(out, ".note.netbsd.pax", 4 /* length of PaX\x00 */, 4 /* length of flags */, 0x03 /* PaX type */)
if sh == nil {
return 0
}
out.Write([]byte("PaX\x00"))
out.Write32(0x20) // 0x20 = Force disable ASLR
return int(sh.size)
}
// OpenBSD Signature
const (
ELF_NOTE_OPENBSD_NAMESZ = 8
@ -1484,6 +1503,9 @@ func (ctxt *Link) doelf() {
}
if ctxt.IsNetbsd() {
shstrtab.Addstring(".note.netbsd.ident")
if *flagRace {
shstrtab.Addstring(".note.netbsd.pax")
}
}
if ctxt.IsOpenbsd() {
shstrtab.Addstring(".note.openbsd.ident")
@ -1821,6 +1843,14 @@ func Asmbelf(ctxt *Link, symo int64) {
var pph *ElfPhdr
var pnote *ElfPhdr
if *flagRace && ctxt.IsNetbsd() {
sh := elfshname(".note.netbsd.pax")
resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff)))
pnote = newElfPhdr()
pnote.type_ = PT_NOTE
pnote.flags = PF_R
phsh(pnote, sh)
}
if ctxt.LinkMode == LinkExternal {
/* skip program headers */
eh.phoff = 0
@ -2298,6 +2328,9 @@ elfobj:
a += int64(elfwritegobuildid(ctxt.Out))
}
}
if *flagRace && ctxt.IsNetbsd() {
a += int64(elfwritenetbsdpax(ctxt.Out))
}
if a > elfreserve {
Errorf(nil, "ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext)