From 1e0c614526a50c3a376016132a9b8dbf6af19887 Mon Sep 17 00:00:00 2001 From: Timo Beckers Date: Fri, 6 May 2022 10:32:18 +0200 Subject: [PATCH] prog: friendly error w/ sentinel if kernel doesn't support bpf2bpf 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 --- internal/btf/core_reloc_test.go | 3 +-- linker_test.go | 6 ++---- prog.go | 7 +++++++ prog_test.go | 1 + 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/internal/btf/core_reloc_test.go b/internal/btf/core_reloc_test.go index b254efc49..c150c395a 100644 --- a/internal/btf/core_reloc_test.go +++ b/internal/btf/core_reloc_test.go @@ -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 { @@ -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) } diff --git a/linker_test.go b/linker_test.go index 283a842d8..51bdf8d5e 100644 --- a/linker_test.go +++ b/linker_test.go @@ -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) } @@ -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 } @@ -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) } diff --git a/prog.go b/prog.go index b72c0f591..33d0fa26d 100644 --- a/prog.go +++ b/prog.go @@ -361,6 +361,13 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, handles *hand } } + if errors.Is(logErr, unix.EINVAL) || errors.Is(logErr, unix.EPERM) && + len(spec.Instructions.FunctionReferences()) > 0 { + if err := haveBPFToBPFCalls(); err != nil { + return nil, fmt.Errorf("load program: %w (program contains bpf2bpf calls)", err) + } + } + 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. diff --git a/prog_test.go b/prog_test.go index 52e2400a0..147c38a5c 100644 --- a/prog_test.go +++ b/prog_test.go @@ -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) }