Skip to content

Commit

Permalink
prog: friendly error w/ sentinel if kernel doesn't support bpf2bpf
Browse files Browse the repository at this point in the history
If a program has function references, return ErrNotSupported if program
creation fails and we know the kernel doesn't support bpf2bpf calls, or if the
user is unprivileged.

Signed-off-by: Timo Beckers <timo@isovalent.com>
  • Loading branch information
ti-mo committed May 9, 2022
1 parent b83e121 commit 030ac0e
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 6 deletions.
3 changes: 1 addition & 2 deletions internal/btf/core_reloc_test.go
Expand Up @@ -90,8 +90,6 @@ func TestCORERelocationRead(t *testing.T) {
}
defer tgt.Close()

testutils.SkipOnOldKernel(t, "4.16", "bpf2bpf calls")

for _, progSpec := range spec.Programs {
t.Run(progSpec.Name, func(t *testing.T) {
if _, err := tgt.Seek(0, io.SeekStart); err != nil {
Expand All @@ -101,6 +99,7 @@ func TestCORERelocationRead(t *testing.T) {
prog, err := ebpf.NewProgramWithOptions(progSpec, ebpf.ProgramOptions{
TargetBTF: tgt,
})
testutils.SkipIfNotSupported(t, err)
if err != nil {
t.Fatal("Load program:", err)
}
Expand Down
11 changes: 11 additions & 0 deletions linker.go
Expand Up @@ -110,6 +110,17 @@ func findReferences(progs map[string]*ProgramSpec) error {
return nil
}

// hasReferences returns true if insns contains one or more bpf2bpf
// function references.
func hasReferences(insns asm.Instructions) bool {
for _, i := range insns {
if i.IsFunctionReference() {
return true
}
}
return false
}

// applyRelocations collects and applies any CO-RE relocations in insns.
//
// Passing a nil target will relocate against the running kernel. insns are
Expand Down
6 changes: 2 additions & 4 deletions linker_test.go
Expand Up @@ -42,9 +42,8 @@ func TestFindReferences(t *testing.T) {
t.Fatal(err)
}

testutils.SkipOnOldKernel(t, "4.16", "bpf2bpf calls")

prog, err := NewProgram(progs["entrypoint"])
testutils.SkipIfNotSupported(t, err)
if err != nil {
t.Fatal(err)
}
Expand All @@ -66,8 +65,6 @@ func TestForwardFunctionDeclaration(t *testing.T) {
t.Fatal(err)
}

testutils.SkipOnOldKernel(t, "4.16", "bpf2bpf calls")

if coll.ByteOrder != internal.NativeEndian {
return
}
Expand All @@ -91,6 +88,7 @@ func TestForwardFunctionDeclaration(t *testing.T) {
spec.BTF = nil

prog, err := NewProgram(spec)
testutils.SkipIfNotSupported(t, err)
if err != nil {
t.Fatal(err)
}
Expand Down
6 changes: 6 additions & 0 deletions prog.go
Expand Up @@ -361,6 +361,12 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand
}
}

if (errors.Is(err, unix.EINVAL) || errors.Is(err, unix.EPERM)) && hasReferences(spec.Instructions) {
if err := haveBPFToBPFCalls(); err != nil {
return nil, fmt.Errorf("load program: %w", internal.ErrorWithLog(err, logBuf, logErr))
}
}

if errors.Is(logErr, unix.EPERM) && len(logBuf) > 0 && logBuf[0] == 0 {
// EPERM due to RLIMIT_MEMLOCK happens before the verifier, so we can
// check that the log is empty to reduce false positives.
Expand Down
1 change: 1 addition & 0 deletions prog_test.go
Expand Up @@ -374,6 +374,7 @@ func TestProgramWithUnsatisfiedMap(t *testing.T) {
progSpec.ByteOrder = nil

_, err = NewProgram(progSpec)
testutils.SkipIfNotSupported(t, err)
if !errors.Is(err, asm.ErrUnsatisfiedMapReference) {
t.Fatal("Expected an error wrapping asm.ErrUnsatisfiedMapReference, got", err)
}
Expand Down

0 comments on commit 030ac0e

Please sign in to comment.