Skip to content

Commit

Permalink
btf: Take instruction size into account when handling poison relocation
Browse files Browse the repository at this point in the history
A CO-RE relocation might be poisoned, in such cases we write a "bogus"
instruction to the relocation target. This can still result in working
code if that instruction turns out to be in a dead code branch due to
other CO-RE logic.

Currently this bogus instructions is always a function call to a
non-existing function. This is a problem when the original instruction
is a dword load immediate, which takes 2 instructions worth of space.
When we replace this with a function call, we shrink the instruction
stream which throws off offsets and instruction metadata.

So this commit makes makes the CO-RE logic check if we are dealing with
a dword load immediate, and if so, we replace it with a dword imm load
of 0xbad2310 to R10, which is illigal and will trip the verifier if
evaluated.

Signed-off-by: Dylan Reimerink <[email protected]>
  • Loading branch information
dylandreimerink committed Feb 20, 2024
1 parent ff37506 commit 933e7a3
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 8 deletions.
9 changes: 7 additions & 2 deletions btf/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"math"
"reflect"
"slices"
"strconv"
"strings"

Expand Down Expand Up @@ -39,11 +40,15 @@ func (f *COREFixup) String() string {
return fmt.Sprintf("%s=%d->%d", f.kind, f.local, f.target)
}

func (f *COREFixup) Apply(ins *asm.Instruction) error {
func (f *COREFixup) Apply(i int, insns *asm.Instructions) error {
ins := &(*insns)[i]
if f.poison {
const badRelo = 0xbad2310

*ins = asm.BuiltinFunc(badRelo).Call()
if ins.OpCode.IsDWordLoad() {
*insns = slices.Insert(*insns, i+1, asm.BuiltinFunc(badRelo).Call())
}
(*insns)[i] = asm.BuiltinFunc(badRelo).Call()
return nil
}

Expand Down
12 changes: 7 additions & 5 deletions linker.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ func hasFunctionReferences(insns asm.Instructions) bool {
//
// Passing a nil target will relocate against the running kernel. insns are
// modified in place.
func applyRelocations(insns asm.Instructions, target *btf.Spec, bo binary.ByteOrder, b *btf.Builder) error {
func applyRelocations(insns *asm.Instructions, target *btf.Spec, bo binary.ByteOrder, b *btf.Builder) error {
var relos []*btf.CORERelocation
var reloInsns []*asm.Instruction
var indicies []int
iter := insns.Iterate()
for iter.Next() {
if relo := btf.CORERelocationMetadata(iter.Ins); relo != nil {
relos = append(relos, relo)
reloInsns = append(reloInsns, iter.Ins)
indicies = append(indicies, iter.Index)
}
}

Expand All @@ -143,8 +143,10 @@ func applyRelocations(insns asm.Instructions, target *btf.Spec, bo binary.ByteOr
return err
}

for i, fixup := range fixups {
if err := fixup.Apply(reloInsns[i]); err != nil {
// A fixup might grow the instruction stream below itself, so we need to apply them in
// reverse order to not invalidate the indicies.
for i := len(fixups) - 1; i >= 0; i-- {
if err := fixups[i].Apply(indicies[i], insns); err != nil {
return fmt.Errorf("fixup for %s: %w", relos[i], err)
}
}
Expand Down
2 changes: 1 addition & 1 deletion prog.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
copy(insns, spec.Instructions)

var b btf.Builder
if err := applyRelocations(insns, opts.KernelTypes, spec.ByteOrder, &b); err != nil {
if err := applyRelocations(&insns, opts.KernelTypes, spec.ByteOrder, &b); err != nil {
return nil, fmt.Errorf("apply CO-RE relocations: %w", err)
}

Expand Down

0 comments on commit 933e7a3

Please sign in to comment.