Skip to content

Commit 125ee42

Browse files
committed
btf: use line info to annotate poisoned CO-RE relocations
Add a line info when poisoning an instruction to make the action explicit in the verifier log. Given a program like: ; return bpf_core_enum_value(enum nonexist_enum, NON_EXIST); 0: LdImmDW dst: r0 imm: 1 2: Exit The verifier output now is: 0: R1=ctx(off=0,imm=0) R10=fp0 ; instruction poisoned by CO-RE 0: (18) r10 = 0xbad2310 frame pointer is read only Signed-off-by: Lorenz Bauer <[email protected]>
1 parent 81e49c1 commit 125ee42

2 files changed

Lines changed: 55 additions & 0 deletions

File tree

btf/core.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,18 @@ func (f *COREFixup) Apply(ins *asm.Instruction) error {
5454
// Replace all single size instruction with a invalid call instruction.
5555
*ins = asm.BuiltinFunc(COREBadRelocationSentinel).Call()
5656
}
57+
58+
// Add context to the kernel verifier output.
59+
if source := ins.Source(); source != nil {
60+
*ins = ins.WithSource(&Line{
61+
line: fmt.Sprintf("instruction poisoned by CO-RE: %s", source),
62+
})
63+
} else {
64+
*ins = ins.WithSource(&Line{
65+
line: "instruction poisoned by CO-RE",
66+
})
67+
}
68+
5769
return nil
5870
}
5971

btf/core_reloc_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
package btf_test
22

33
import (
4+
"bytes"
45
"io"
56
"os"
7+
"slices"
68
"strings"
79
"testing"
810

911
"github.com/cilium/ebpf"
1012
"github.com/cilium/ebpf/btf"
1113
"github.com/cilium/ebpf/internal"
1214
"github.com/cilium/ebpf/internal/testutils"
15+
16+
"github.com/go-quicktest/qt"
1317
)
1418

1519
func TestCORERelocationLoad(t *testing.T) {
@@ -121,3 +125,42 @@ func TestLD64IMMReloc(t *testing.T) {
121125
}
122126
defer coll.Close()
123127
}
128+
129+
func TestCOREPoisonLineInfo(t *testing.T) {
130+
testutils.SkipOnOldKernel(t, "5.0", "program ext_infos")
131+
132+
spec, err := ebpf.LoadCollectionSpec(testutils.NativeFile(t, "../testdata/errors-%s.elf"))
133+
qt.Assert(t, qt.IsNil(err))
134+
135+
var b btf.Builder
136+
raw, err := b.Marshal(nil, nil)
137+
qt.Assert(t, qt.IsNil(err))
138+
empty, err := btf.LoadSpecFromReader(bytes.NewReader(raw))
139+
qt.Assert(t, qt.IsNil(err))
140+
141+
for _, test := range []struct {
142+
name string
143+
}{
144+
{"poisoned_single"},
145+
{"poisoned_double"},
146+
} {
147+
progSpec := spec.Programs[test.name]
148+
qt.Assert(t, qt.IsNotNil(progSpec))
149+
150+
t.Run(test.name, func(t *testing.T) {
151+
t.Log(progSpec.Instructions)
152+
_, err := ebpf.NewProgramWithOptions(progSpec, ebpf.ProgramOptions{
153+
KernelTypes: empty,
154+
})
155+
testutils.SkipIfNotSupported(t, err)
156+
157+
var ve *ebpf.VerifierError
158+
qt.Assert(t, qt.ErrorAs(err, &ve))
159+
found := slices.ContainsFunc(ve.Log, func(line string) bool {
160+
return strings.HasPrefix(line, "; instruction poisoned by CO-RE")
161+
})
162+
qt.Assert(t, qt.IsTrue(found))
163+
t.Logf("%-5v", ve)
164+
})
165+
}
166+
}

0 commit comments

Comments
 (0)