Commit 34c480af authored by David Crawshaw's avatar David Crawshaw

runtime: resolve type offsets using source module

The runtime.typeEquals function is used during typelinksinit to
determine the canonical set of *_type values to use throughout the
runtime. As such, it is run against non-canonical *_type values, that
is, types from modules that are duplicates of a type from another
module that was loaded earlier in the program life.

These non-canonical *_type values sometimes contain pointers. These
pointers are pointing to position-independent data, and so they are set
by ld.so using dynamic relocations when the module is loaded. As such,
the pointer can point to the equivalent memory from a previous module.

This means if typesEqual follows a pointer inside a *_type, it can end
up at a piece of memory from another module. If it reads a typeOff or
nameOff from that memory and attempts to resolve it against the
non-canonical *_type from the later module, it will end up with a
reference to junk memory.

Instead, resolve against the pointer the offset was read from, so the
data is valid.

Fixes #17709.
Should no longer matter after #17724 is resolved in a later Go.

Change-Id: Ie88b151a3407d82ac030a97b5b6a19fc781901cb
Reviewed-on: https://go-review.googlesource.com/32513
Run-TryBot: David Crawshaw <crawshaw@golang.org>
Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 3f1ed245
......@@ -199,11 +199,11 @@ func (t *_type) nameOff(off nameOff) name {
return resolveNameOff(unsafe.Pointer(t), off)
}
func (t *_type) typeOff(off typeOff) *_type {
func resolveTypeOff(ptrInModule unsafe.Pointer, off typeOff) *_type {
if off == 0 {
return nil
}
base := uintptr(unsafe.Pointer(t))
base := uintptr(ptrInModule)
var md *moduledata
for next := &firstmoduledata; next != nil; next = next.next {
if base >= next.types && base < next.etypes {
......@@ -235,6 +235,10 @@ func (t *_type) typeOff(off typeOff) *_type {
return (*_type)(unsafe.Pointer(res))
}
func (t *_type) typeOff(off typeOff) *_type {
return resolveTypeOff(unsafe.Pointer(t), off)
}
func (t *_type) textOff(off textOff) unsafe.Pointer {
base := uintptr(unsafe.Pointer(t))
var md *moduledata
......@@ -596,15 +600,19 @@ func typesEqual(t, v *_type) bool {
for i := range it.mhdr {
tm := &it.mhdr[i]
vm := &iv.mhdr[i]
tname := it.typ.nameOff(tm.name)
vname := iv.typ.nameOff(vm.name)
// Note the mhdr array can be relocated from
// another module. See #17724.
tname := resolveNameOff(unsafe.Pointer(tm), tm.name)
vname := resolveNameOff(unsafe.Pointer(vm), vm.name)
if tname.name() != vname.name() {
return false
}
if tname.pkgPath() != vname.pkgPath() {
return false
}
if !typesEqual(it.typ.typeOff(tm.ityp), iv.typ.typeOff(vm.ityp)) {
tityp := resolveTypeOff(unsafe.Pointer(tm), tm.ityp)
vityp := resolveTypeOff(unsafe.Pointer(vm), vm.ityp)
if !typesEqual(tityp, vityp) {
return false
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment