From ed5ed9154a47db876fb31d65ff8c16d1d0db687c Mon Sep 17 00:00:00 2001 From: Timo Beckers Date: Fri, 4 Mar 2022 17:54:23 +0100 Subject: [PATCH] btf: add CO-RE read test that fails unless relocations were correctly applied The linker rework in 9d739bd caused a piece of code that appended CORERelos to the entrypoint instruction stream to be forgotten. The existing CO-RE tests were all written in a way where the BPF programs would return 0 (success) if no CO-RE relocations were applied at all. This caused CO-RE relocations against functions (subprogs) that were only included by a bpf2bpf call to be skipped. This patch adds a broken test program that returns non-zero if left unaltered, and requires CO-RE relocation against another BTF blob to return 0. Additionally, the checks are performed from a non-inlined subprogram to ensure CO-RE relocations against subprogs work. Signed-off-by: Timo Beckers --- Makefile | 4 +- internal/btf/core_reloc_test.go | 59 ++++++++++++++++++- internal/btf/testdata/relocs_read-eb.elf | Bin 0 -> 1944 bytes internal/btf/testdata/relocs_read-el.elf | Bin 0 -> 1944 bytes internal/btf/testdata/relocs_read.c | 37 ++++++++++++ internal/btf/testdata/relocs_read_tgt-eb.elf | Bin 0 -> 1272 bytes internal/btf/testdata/relocs_read_tgt-el.elf | Bin 0 -> 1272 bytes internal/btf/testdata/relocs_read_tgt.c | 16 +++++ 8 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 internal/btf/testdata/relocs_read-eb.elf create mode 100644 internal/btf/testdata/relocs_read-el.elf create mode 100644 internal/btf/testdata/relocs_read.c create mode 100644 internal/btf/testdata/relocs_read_tgt-eb.elf create mode 100644 internal/btf/testdata/relocs_read_tgt-el.elf create mode 100644 internal/btf/testdata/relocs_read_tgt.c diff --git a/Makefile b/Makefile index 76a448caa..2384847a6 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,9 @@ TARGETS := \ testdata/map_spin_lock \ testdata/subprog_reloc \ testdata/fwd_decl \ - internal/btf/testdata/relocs + internal/btf/testdata/relocs \ + internal/btf/testdata/relocs_read \ + internal/btf/testdata/relocs_read_tgt .PHONY: all clean container-all container-shell generate diff --git a/internal/btf/core_reloc_test.go b/internal/btf/core_reloc_test.go index f4cf2bafe..dc6b91d64 100644 --- a/internal/btf/core_reloc_test.go +++ b/internal/btf/core_reloc_test.go @@ -1,17 +1,19 @@ package btf_test import ( + "fmt" "io" "os" "strings" "testing" "github.com/cilium/ebpf" + "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/testutils" ) func TestCoreRelocationLoad(t *testing.T) { - testutils.Files(t, testutils.Glob(t, "testdata/*-el.elf"), func(t *testing.T, file string) { + testutils.Files(t, testutils.Glob(t, "testdata/relocs-*.elf"), func(t *testing.T, file string) { fh, err := os.Open(file) if err != nil { t.Fatal(err) @@ -23,6 +25,10 @@ func TestCoreRelocationLoad(t *testing.T) { t.Fatal(err) } + if spec.ByteOrder != internal.NativeEndian { + return + } + for _, progSpec := range spec.Programs { t.Run(progSpec.Name, func(t *testing.T) { if _, err := fh.Seek(0, io.SeekStart); err != nil { @@ -60,3 +66,54 @@ func TestCoreRelocationLoad(t *testing.T) { } }) } + +func TestCoreRelocationRead(t *testing.T) { + testutils.Files(t, testutils.Glob(t, "testdata/relocs_read-*.elf"), func(t *testing.T, file string) { + fh, err := os.Open(file) + if err != nil { + t.Fatal(err) + } + defer fh.Close() + + spec, err := ebpf.LoadCollectionSpecFromReader(fh) + if err != nil { + t.Fatal(err) + } + + if spec.ByteOrder != internal.NativeEndian { + return + } + + tgt, err := os.Open(fmt.Sprintf("testdata/relocs_read_tgt-%s.elf", internal.ClangEndian)) + if err != nil { + t.Fatal(err) + } + defer tgt.Close() + + for _, progSpec := range spec.Programs { + t.Run(progSpec.Name, func(t *testing.T) { + if _, err := tgt.Seek(0, io.SeekStart); err != nil { + t.Fatal(err) + } + + prog, err := ebpf.NewProgramWithOptions(progSpec, ebpf.ProgramOptions{ + TargetBTF: tgt, + }) + if err != nil { + t.Fatal("Load program:", err) + } + defer prog.Close() + + ret, _, err := prog.Test(make([]byte, 14)) + testutils.SkipIfNotSupported(t, err) + if err != nil { + t.Fatal("Error when running:", err) + } + + if ret != 0 { + t.Error("Assertion failed on line", ret) + } + }) + } + }) +} diff --git a/internal/btf/testdata/relocs_read-eb.elf b/internal/btf/testdata/relocs_read-eb.elf new file mode 100644 index 0000000000000000000000000000000000000000..70cf0e456c92acf080c8641cae71c163248de526 GIT binary patch literal 1944 zcmbtUJ8u&~5FR_u!y!oF6&?*&fMiQxJ3>N&5XlN6LLxzgYfryy}hjjjy*V*)I2pR19WA1h{vM% zXTf6+Ifdm#5|-!iqHa&)A1~uplfFbE(5T-@KgvNQ56!6$DqyyN`$v**q`O;4IOIKK z3`$vp(jJ1Yt9;fWHfw)WwFacsi6rbcRs#RNR3h(DB$Xa<%OuUxi}ZK;Z-vb8S7FbcXZeAa^RTa)mF z(hx`7MJJHj^>Hb-7Oax%2cGS?t`~+S@G4H(nw+$1WwES-!i_jQUPghMJP|e(O6a>w zUW9t+An+ormG&_qYS%691muF!x0rXKm!RAw9)Q|7>4W{rz=N=PcgUelIRU*Ua)UPW ziCvNU5zHlppNY(k!LAvYH>$4i8~vTGo)FihkHRhI32Cf*(s&**lh5@`yph418T=}P-(~PFu(|%%4F0vBpJQL~`XlH?S6ycPDBJDTW!q^sgRq4sipLZ=4a{rH@r-<#nVPEES5W@Hh5b<} z@jovy%t1kT<^Memzc#wO+>RNph*Kfj%|89PAwz9}capZ{pRj?Sl_f0e`XeMv~def?h?H_Vq&65a=}PUyn=#6yJc^0kqgHy?7l+@8Y#4= zvGybW0d|x^VWcs!u&}h&#=^vo^EYqjv6mML<0Nx4zxjIe=DoM~>`ryQ$8pGzLw_hk z#!57GD$^@kty``Tx+l47+C5!BfigWMZYrT9 z3RXjfdgvey71lcLV}^L@F3$vXN%$S)A@~ZIr#1>Uqsl@5+=ct0;~;em>r7|BH(0rq z<}(h!!xf@DB;)7c$wi`a7w!YD2!0EBZi(oDUv?$D+j-%N`x1E21ygUx8VsO?$&nAnXN zg2LVM=`gX*r-NZ@V$7$M_LKRSv^T?MJ(Is<`FAb++QRQGeAtC~{cjfj-G#Z|Ub#|c z{Souf@S=)yi}OYO>Hy^a%4If>vf12R^Za@}P8xWkcudN#L2j*SiF~Tg&6T}tvg-c} zZj(9v+GTYrqMA7x&wx=x@;B|Id^5i>E8fn(C;3(w?TcYk=4kvDq+vL08^>OkD>h*{ zEl9T!o83mvOlg4+8MK=U{DY)-%k*!)8&!+E^Z}!jMYhK6X8#{khPRjo!`Cp_k q=kr~%^RL2|t9BxY9q=*jb1=x>uZ?FABTMOc^K&5i_l-fMo&Ohv*{$UO literal 0 HcmV?d00001 diff --git a/internal/btf/testdata/relocs_read.c b/internal/btf/testdata/relocs_read.c new file mode 100644 index 000000000..c58b37296 --- /dev/null +++ b/internal/btf/testdata/relocs_read.c @@ -0,0 +1,37 @@ +#include "../../../testdata/common.h" + +#define core_access __builtin_preserve_access_index + +// Struct with the members declared in the wrong order. Accesses need +// a successful CO-RE relocation against the type in relocs_read_tgt.c +// for the test below to pass. +struct s { + char b; + char a; +}; + +// Perform a read from a subprog to ensure CO-RE relocations +// occurring there are tracked and executed in the final linked program. +__attribute__((noinline)) int read_subprog() { + struct s foo = { + .a = 0, + .b = 1, + }; + + if (core_access(foo.a) == 0) + return __LINE__; + + if (core_access(foo.b) == 1) + return __LINE__; + + return 0; +} + +__section("socket") int reads() { + int ret = subprog(); + if (ret) + return ret; + + return 0; +} + diff --git a/internal/btf/testdata/relocs_read_tgt-eb.elf b/internal/btf/testdata/relocs_read_tgt-eb.elf new file mode 100644 index 0000000000000000000000000000000000000000..b0effd5f86f2c6f01c7945a480f91c5fda96e4c2 GIT binary patch literal 1272 zcmb_b!Dz>Kkb?&c-c-Hns_N>lp3g7#cH%gaMk4tQJ8(2BFyc$g2JYLD z)$>hj%i3L$#bR-Fnk;#JztOhV>5|HKr!Rh5_lBcyp^2~Lclg0(K;#-(flk10-d^@b z_he-m!?+Jz11K7x-2sftXPu55PK*?@s+vn?$|ECL51vv_)VMb??|P=JO`(kH>2f^H z>!B`HF*FAz%bA(j%(R;v%epSjOiz-0s>`9u^Rlkfv^IK{o22d@pJb}LCABCSN&a4G z=|AlQkHsB2L1UB$4%^VLfJXqEz6H3x{;lA9rnLDUF_MqUs^$Ew|#FuqRIaQV)$W7 literal 0 HcmV?d00001 diff --git a/internal/btf/testdata/relocs_read_tgt-el.elf b/internal/btf/testdata/relocs_read_tgt-el.elf new file mode 100644 index 0000000000000000000000000000000000000000..34c056daa2d61f6431b0d9cda2310558c1fbf2fd GIT binary patch literal 1272 zcmbtS&ubGw6n>l3{y+;=JQOc(ZyS(Jyopr^f<>VR4<0-S>14CkLN<|^i8R#GdiUy0 z5dVsL^AGY|^kn?L-8V_xi-Hfny!U-G-(=ptIeWan*N7qs5y=l(u%L?kY%J<-S$1Vz zR^{85N?(KN*K9Vs(0y*F(%nvV+C@d>qvp@wBiYvaB{K0|InpMNshkq6ppHSWRN6J_ zBLI6=xbF?XHHHOPuLB-Hl-+?xay0TXm=wiSQlB4tN!w6zJ2Jy|-@j`6-1&j=rfu`# zICDLln?cVX`ZS|6E}cm$K9LQZ`-vUJ+1TbilV!PcN#eYnWIlGSlhf3+cEyR2zGSbB zmCpSRa97xLT;56KCNl8=cm~`7cm+v*)k*WgOV-yyBhyc*$N))wk}Ip(@XOQGVYzxX>?=d-BCmWoewf&Ebm_up216L~}H<@7@R2P$&De7eEU nC&@^F@T5yYf4-{!;j)Oj-s>%B&HdRJ=^U8HrTXWB7Ipt`?#5xk literal 0 HcmV?d00001 diff --git a/internal/btf/testdata/relocs_read_tgt.c b/internal/btf/testdata/relocs_read_tgt.c new file mode 100644 index 000000000..38bb4b156 --- /dev/null +++ b/internal/btf/testdata/relocs_read_tgt.c @@ -0,0 +1,16 @@ +/* + This file exists to emit ELFs with specific BTF types to use as target BTF + in tests. It can be made redundant when btf.Spec can be handcrafted and + passed as a CO-RE target in the future. +*/ + +#define core_access __builtin_preserve_access_index + +struct s { + char a; + char b; +}; + +int dummy() { + return core_access((struct s){}.a); +}