From fd18f3ba5031079102ca4dc4cf425c2b496408ba Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 10 Apr 2020 14:07:13 -0700 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Dmitry Vyukov --- src/cmd/link/internal/ld/elf.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index e15f94d5e0..fbf91fd51f 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -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) -- 2.48.1