Skip to content

Commit ba42120

Browse files
zx2c4gopherbot
authored andcommitted
runtime: properly compute whether PC is inside vDSO pages
The old calculation just looked whether PC was within a page of a vDSO symbol. This doesn't work because the vDSO .text might span two whole pages, with trampolines and such redirecting PC around between them. This manifests itself with the new vDSO getrandom() function, where on PowerPC, the trampoline is quite far away from the actual C function it jumps into. The effect is that the signal handler doesn't know it's interrupting a vDSO call and forgets to restore g to R30, resulting in a crash. Fix this by storing the start and end of the LOAD section from the program headers. We could be more specific and parse out the .text section, but PT_LOAD is good enough and appears to work well. Change-Id: I3cf16955177eedb51e28b3b1a0191b32c3327a42 Reviewed-on: https://go-review.googlesource.com/c/go/+/616015 Auto-Submit: Jason Donenfeld <[email protected]> Reviewed-by: Michael Pratt <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 4aa5aa6 commit ba42120

File tree

1 file changed

+5
-7
lines changed

1 file changed

+5
-7
lines changed

src/runtime/vdso_linux.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ type vdsoInfo struct {
9797
verdef *elfVerdef
9898
}
9999

100+
var vdsoLoadStart, vdsoLoadEnd uintptr
101+
100102
// see vdso_linux_*.go for vdsoSymbolKeys[] and vdso*Sym vars
101103

102104
func vdsoInitFromSysinfoEhdr(info *vdsoInfo, hdr *elfEhdr) {
@@ -116,6 +118,8 @@ func vdsoInitFromSysinfoEhdr(info *vdsoInfo, hdr *elfEhdr) {
116118
if !foundVaddr {
117119
foundVaddr = true
118120
info.loadOffset = info.loadAddr + uintptr(pt.p_offset-pt.p_vaddr)
121+
vdsoLoadStart = info.loadOffset
122+
vdsoLoadEnd = info.loadOffset + uintptr(pt.p_memsz)
119123
}
120124

121125
case _PT_DYNAMIC:
@@ -285,11 +289,5 @@ func vdsoauxv(tag, val uintptr) {
285289
//
286290
//go:nosplit
287291
func inVDSOPage(pc uintptr) bool {
288-
for _, k := range vdsoSymbolKeys {
289-
if *k.ptr != 0 {
290-
page := *k.ptr &^ (physPageSize - 1)
291-
return pc >= page && pc < page+physPageSize
292-
}
293-
}
294-
return false
292+
return pc >= vdsoLoadStart && pc < vdsoLoadEnd
295293
}

0 commit comments

Comments
 (0)