From cbd720f60b6353c29d7bae66a7892841065ee0fc Mon Sep 17 00:00:00 2001 From: Lorenz Bauer Date: Tue, 26 Jul 2022 10:46:42 +0000 Subject: [PATCH] link: run TestKprobeOffset on arm64 TestKprobeOffset used to hardcode specific offsets to test against, which meant we had to make it amd64 specific. It turns out that even on a single arch the offsets aren't stable due to changes in the compiler. Hence the test was changed to brute force a valid offset, but we forgot to run it on all arches. Trying to execute the test on Linux 5.13 on arm64 triggers EINVAL instead of the expected EILSEQ however. This is because arm64 returns EINVAL when trying to use an offset that is not a multiple of four. Relying on EILSEQ is therefore not portable, and probably shouldn't be encouraged. Drop the check for EILSEQ from TestKprobeOffset and execute it on all arches. --- internal/unix/types_linux.go | 1 + internal/unix/types_other.go | 1 + link/kprobe.go | 7 ++++--- link/kprobe_amd64_test.go | 32 -------------------------------- link/kprobe_test.go | 17 +++++++++++++++++ 5 files changed, 23 insertions(+), 35 deletions(-) delete mode 100644 link/kprobe_amd64_test.go diff --git a/internal/unix/types_linux.go b/internal/unix/types_linux.go index 0b43d5724..8a030da28 100644 --- a/internal/unix/types_linux.go +++ b/internal/unix/types_linux.go @@ -24,6 +24,7 @@ const ( E2BIG = linux.E2BIG EFAULT = linux.EFAULT EACCES = linux.EACCES + EILSEQ = linux.EILSEQ BPF_F_NO_PREALLOC = linux.BPF_F_NO_PREALLOC BPF_F_NUMA_NODE = linux.BPF_F_NUMA_NODE diff --git a/internal/unix/types_other.go b/internal/unix/types_other.go index 2fc2d2de1..b1318f607 100644 --- a/internal/unix/types_other.go +++ b/internal/unix/types_other.go @@ -25,6 +25,7 @@ const ( E2BIG = syscall.Errno(0) EFAULT = syscall.EFAULT EACCES = syscall.Errno(0) + EILSEQ = syscall.Errno(0) BPF_F_NO_PREALLOC = 0 BPF_F_NUMA_NODE = 0 diff --git a/link/kprobe.go b/link/kprobe.go index 7d93e4f3f..10fcf8ee0 100644 --- a/link/kprobe.go +++ b/link/kprobe.go @@ -307,9 +307,10 @@ func pmuProbe(typ probeType, args probeArgs) (*perfEvent, error) { if errors.Is(err, os.ErrNotExist) { return nil, fmt.Errorf("symbol '%s+%#x' not found: %w", args.symbol, args.offset, os.ErrNotExist) } - // Since commit ab105a4fb894, -EILSEQ is returned when a kprobe sym+offset is resolved - // to an invalid insn boundary. - if errors.Is(err, syscall.EILSEQ) { + // Since commit ab105a4fb894, EILSEQ is returned when a kprobe sym+offset is resolved + // to an invalid insn boundary. The exact conditions that trigger this error are + // arch specific however. + if errors.Is(err, unix.EILSEQ) { return nil, fmt.Errorf("symbol '%s+%#x' not found (bad insn boundary): %w", args.symbol, args.offset, os.ErrNotExist) } // Since at least commit cb9a19fe4aa51, ENOTSUPP is returned diff --git a/link/kprobe_amd64_test.go b/link/kprobe_amd64_test.go deleted file mode 100644 index 7bcad454e..000000000 --- a/link/kprobe_amd64_test.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build amd64 -// +build amd64 - -package link - -import ( - "errors" - "os" - "testing" - - "github.com/cilium/ebpf" -) - -func TestKprobeOffset(t *testing.T) { - prog := mustLoadProgram(t, ebpf.Kprobe, 0, "") - - for i := uint64(2); i < 10; i++ { - k, err := Kprobe("inet6_release", prog, &KprobeOptions{Offset: i}) - if err != nil { - continue - } - k.Close() - - _, err = Kprobe("inet6_release", prog, &KprobeOptions{Offset: i - 1}) - if !errors.Is(err, os.ErrNotExist) { - t.Fatalf("expected 'os.ErrNotExist', got: '%v'", err) - } - return - } - - t.Fatal("no valid offsets found") -} diff --git a/link/kprobe_test.go b/link/kprobe_test.go index 9d2dd1636..ba39c990d 100644 --- a/link/kprobe_test.go +++ b/link/kprobe_test.go @@ -53,6 +53,23 @@ func TestKprobe(t *testing.T) { testLink(t, k, prog) } +func TestKprobeOffset(t *testing.T) { + prog := mustLoadProgram(t, ebpf.Kprobe, 0, "") + + // The layout of a function is compiler and arch dependent, so we try to + // find a valid attach target in the first few bytes of the function. + for i := uint64(1); i < 16; i++ { + k, err := Kprobe("inet6_release", prog, &KprobeOptions{Offset: i}) + if err != nil { + continue + } + k.Close() + return + } + + t.Fatal("Can't attach with non-zero offset") +} + func TestKretprobe(t *testing.T) { prog := mustLoadProgram(t, ebpf.Kprobe, 0, "")