mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
debug/elf: prevent offset overflow
When applying relocations, a malformed ELF file can provide an offset
that, when added to the relocation size, overflows. This wrapped-around
value could then incorrectly pass the bounds check, leading to a panic
when the slice is accessed with the original large offset.
This change eliminates the manual bounds and overflow checks
and writes a relocation to slice by calling putUint.
The putUint helper function centralizes the logic for validating slice
access, correctly handling both out-of-bounds and integer overflow conditions.
This simplifies the relocation code and improves robustness when parsing
malformed ELF files.
Fixes #75516
Change-Id: I00d806bf5501a9bf70200585ba4fd0475d7b2ddc
GitHub-Last-Rev: 49144311d3
GitHub-Pull-Request: golang/go#75522
Reviewed-on: https://go-review.googlesource.com/c/go/+/705075
Reviewed-by: Florian Lehner <lehner.florian86@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Commit-Queue: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
34e67623a8
commit
5500cbf0e4
1 changed files with 57 additions and 103 deletions
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"internal/saferio"
|
"internal/saferio"
|
||||||
"internal/zstd"
|
"internal/zstd"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
@ -830,17 +831,9 @@ func (f *File) applyRelocationsAMD64(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_X86_64_64:
|
case R_X86_64_64:
|
||||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 8, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val64 := sym.Value + uint64(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
|
|
||||||
case R_X86_64_32:
|
case R_X86_64_32:
|
||||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 4, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -872,12 +865,7 @@ func (f *File) applyRelocations386(dst []byte, rels []byte) error {
|
||||||
sym := &symbols[symNo-1]
|
sym := &symbols[symNo-1]
|
||||||
|
|
||||||
if t == R_386_32 {
|
if t == R_386_32 {
|
||||||
if rel.Off+4 >= uint32(len(dst)) {
|
putUint(f.ByteOrder, dst, uint64(rel.Off), 4, sym.Value, 0, true)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
|
|
||||||
val += uint32(sym.Value)
|
|
||||||
f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -910,12 +898,7 @@ func (f *File) applyRelocationsARM(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_ARM_ABS32:
|
case R_ARM_ABS32:
|
||||||
if rel.Off+4 >= uint32(len(dst)) {
|
putUint(f.ByteOrder, dst, uint64(rel.Off), 4, sym.Value, 0, true)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
|
|
||||||
val += uint32(sym.Value)
|
|
||||||
f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -955,17 +938,9 @@ func (f *File) applyRelocationsARM64(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_AARCH64_ABS64:
|
case R_AARCH64_ABS64:
|
||||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 8, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val64 := sym.Value + uint64(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
|
|
||||||
case R_AARCH64_ABS32:
|
case R_AARCH64_ABS32:
|
||||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 4, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1001,11 +976,7 @@ func (f *File) applyRelocationsPPC(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_PPC_ADDR32:
|
case R_PPC_ADDR32:
|
||||||
if rela.Off+4 >= uint32(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, uint64(rela.Off), 4, sym.Value, 0, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1041,17 +1012,9 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_PPC64_ADDR64:
|
case R_PPC64_ADDR64:
|
||||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 8, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val64 := sym.Value + uint64(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
|
|
||||||
case R_PPC64_ADDR32:
|
case R_PPC64_ADDR32:
|
||||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 4, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1084,12 +1047,7 @@ func (f *File) applyRelocationsMIPS(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_MIPS_32:
|
case R_MIPS_32:
|
||||||
if rel.Off+4 >= uint32(len(dst)) {
|
putUint(f.ByteOrder, dst, uint64(rel.Off), 4, sym.Value, 0, true)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val := f.ByteOrder.Uint32(dst[rel.Off : rel.Off+4])
|
|
||||||
val += uint32(sym.Value)
|
|
||||||
f.ByteOrder.PutUint32(dst[rel.Off:rel.Off+4], val)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1132,17 +1090,9 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_MIPS_64:
|
case R_MIPS_64:
|
||||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 8, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val64 := sym.Value + uint64(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
|
|
||||||
case R_MIPS_32:
|
case R_MIPS_32:
|
||||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 4, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1180,17 +1130,9 @@ func (f *File) applyRelocationsLOONG64(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_LARCH_64:
|
case R_LARCH_64:
|
||||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 8, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val64 := sym.Value + uint64(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
|
|
||||||
case R_LARCH_32:
|
case R_LARCH_32:
|
||||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 4, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1226,17 +1168,9 @@ func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_RISCV_64:
|
case R_RISCV_64:
|
||||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 8, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val64 := sym.Value + uint64(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
|
|
||||||
case R_RISCV_32:
|
case R_RISCV_32:
|
||||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 4, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1272,17 +1206,9 @@ func (f *File) applyRelocationss390x(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_390_64:
|
case R_390_64:
|
||||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 8, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val64 := sym.Value + uint64(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
|
|
||||||
case R_390_32:
|
case R_390_32:
|
||||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 4, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1318,17 +1244,10 @@ func (f *File) applyRelocationsSPARC64(dst []byte, rels []byte) error {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case R_SPARC_64, R_SPARC_UA64:
|
case R_SPARC_64, R_SPARC_UA64:
|
||||||
if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 8, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val64 := sym.Value + uint64(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val64)
|
|
||||||
case R_SPARC_32, R_SPARC_UA32:
|
case R_SPARC_32, R_SPARC_UA32:
|
||||||
if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
|
putUint(f.ByteOrder, dst, rela.Off, 4, sym.Value, rela.Addend, false)
|
||||||
continue
|
|
||||||
}
|
|
||||||
val32 := uint32(sym.Value) + uint32(rela.Addend)
|
|
||||||
f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val32)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1903,3 +1822,38 @@ type nobitsSectionReader struct{}
|
||||||
func (*nobitsSectionReader) ReadAt(p []byte, off int64) (n int, err error) {
|
func (*nobitsSectionReader) ReadAt(p []byte, off int64) (n int, err error) {
|
||||||
return 0, errors.New("unexpected read from SHT_NOBITS section")
|
return 0, errors.New("unexpected read from SHT_NOBITS section")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// putUint writes a relocation to slice
|
||||||
|
// at offset start of length length (4 or 8 bytes),
|
||||||
|
// adding sym+addend to the existing value if readUint is true,
|
||||||
|
// or just writing sym+addend if readUint is false.
|
||||||
|
// If the write would extend beyond the end of slice, putUint does nothing.
|
||||||
|
// If the addend is negative, putUint does nothing.
|
||||||
|
// If the addition would overflow, putUint does nothing.
|
||||||
|
func putUint(byteOrder binary.ByteOrder, slice []byte, start, length, sym uint64, addend int64, readUint bool) {
|
||||||
|
if start+length > uint64(len(slice)) || math.MaxUint64-start < length {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if addend < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s := slice[start : start+length]
|
||||||
|
|
||||||
|
switch length {
|
||||||
|
case 4:
|
||||||
|
ae := uint32(addend)
|
||||||
|
if readUint {
|
||||||
|
ae += byteOrder.Uint32(s)
|
||||||
|
}
|
||||||
|
byteOrder.PutUint32(s, uint32(sym)+ae)
|
||||||
|
case 8:
|
||||||
|
ae := uint64(addend)
|
||||||
|
if readUint {
|
||||||
|
ae += byteOrder.Uint64(s)
|
||||||
|
}
|
||||||
|
byteOrder.PutUint64(s, sym+ae)
|
||||||
|
default:
|
||||||
|
panic("can't happen")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue