From aed00a2bdb8fadcc47b62717af772faeaab3a151 Mon Sep 17 00:00:00 2001 From: Timo Beckers Date: Mon, 2 May 2022 17:25:05 +0200 Subject: [PATCH] prog: recognize ENOTSUPP in testRun() Not all program types support PROG_TEST_RUN on all kernel versions. Previously, when testing a program type that didn't have a test runner implemented, the following error would be returned: Error when running: can't test program: can't run test: errno 524 Since this isn't overly descriptive, make it clear to the caller that the kernel supports test runs, just not for the particular program type. Also fixes haveProgTestRun on kernels between 4.12 (where PROG_TEST_RUN was introduced) and 4.16 (where sk_filter test runner was added). Signed-off-by: Timo Beckers --- prog.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/prog.go b/prog.go index 353123512..cf4189f3a 100644 --- a/prog.go +++ b/prog.go @@ -590,6 +590,7 @@ func (p *Program) Benchmark(in []byte, repeat int, reset func()) (uint32, time.D var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() error { prog, err := NewProgram(&ProgramSpec{ + // SocketFilter does not require privileges on newer kernels. Type: SocketFilter, Instructions: asm.Instructions{ asm.LoadImm(asm.R0, 0, asm.DWord), @@ -612,15 +613,23 @@ var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() e } err = sys.ProgRun(&attr) - if errors.Is(err, unix.EINVAL) { + switch { + case errors.Is(err, unix.EINVAL): // Check for EINVAL specifically, rather than err != nil since we // otherwise misdetect due to insufficient permissions. return internal.ErrNotSupported - } - if errors.Is(err, unix.EINTR) { + + case errors.Is(err, unix.EINTR): // We know that PROG_TEST_RUN is supported if we get EINTR. return nil + + case errors.Is(err, unix.ENOTSUPP): + // The first PROG_TEST_RUN patches shipped in 4.12 didn't include + // a test runner for SocketFilter. ENOTSUPP means PROG_TEST_RUN is + // supported, but not for the program type used in the probe. + return nil } + return err }) @@ -670,6 +679,10 @@ func (p *Program) testRun(in []byte, repeat int, reset func()) (uint32, []byte, continue } + if errors.Is(err, unix.ENOTSUPP) { + return 0, nil, 0, fmt.Errorf("kernel doesn't support testing program type %s: %w", p.Type(), ErrNotSupported) + } + return 0, nil, 0, fmt.Errorf("can't run test: %w", err) }