From 8bd332d2cf575e957aaac1e7a5de28c2422d6ad9 Mon Sep 17 00:00:00 2001 From: shun159 Date: Thu, 21 Sep 2023 15:26:28 +0900 Subject: [PATCH] elfparser: Add method to load BPF from an io.ReaderAt - Introduce the `LoadBpfFromReader` method in the `bpfSDKClient`. - This method enables loading ELF files directly from an io.ReaderAt. Signed-off-by: shun159 --- Makefile | 5 ++++- pkg/elfparser/elf.go | 26 ++++++++++++++++++-------- pkg/elfparser/elf_test.go | 16 ++++++++++++++++ pkg/elfparser/test-data/test.bpf.c | 9 +++++++++ pkg/elfparser/test-data/test.bpf.elf | Bin 0 -> 3856 bytes 5 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 pkg/elfparser/test-data/test.bpf.c create mode 100644 pkg/elfparser/test-data/test.bpf.elf diff --git a/Makefile b/Makefile index eb2b0c7..2f13b79 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ export GOPROXY = direct CURDIR := $(abspath .) TESTDATADIR := $(CURDIR)/test-data +ELFPARSERDIR := $(CURDIR)/pkg/elfparser BPFTOOL := bpftool CLANG := clang LOGFILE_PATH ?= stdout @@ -48,7 +49,8 @@ TARGETS := \ $(TESTDATADIR)/recoverydata \ $(TESTDATADIR)/test-kprobe \ $(TESTDATADIR)/xdp \ - $(TESTDATADIR)/ring_buffer + $(TESTDATADIR)/ring_buffer \ + $(ELFPARSERDIR)/test-data/test %.bpf.elf: %.bpf.c $(CLANG) $(CLANG_INCLUDE) $(BPF_CFLAGS) -c $< -o $@ @@ -74,3 +76,4 @@ unit-test: ## Run unit tests clean: -@rm -f $(TESTDATADIR)/vmlinux.h -@rm -f $(TESTDATADIR)/*.elf + -@rm -f $(ELFPARSERDIR)/test-data/*.elf diff --git a/pkg/elfparser/elf.go b/pkg/elfparser/elf.go index c919315..7edd7db 100644 --- a/pkg/elfparser/elf.go +++ b/pkg/elfparser/elf.go @@ -50,6 +50,7 @@ var sdkCache = cache.Get() type BpfSDKClient interface { IncreaseRlimit() error LoadBpfFile(path, customizedPinPath string) (map[string]BpfData, map[string]ebpf_maps.BpfMap, error) + LoadBpfFromReader(r io.ReaderAt, customizedPinPath string) (map[string]BpfData, map[string]ebpf_maps.BpfMap, error) RecoverGlobalMaps() (map[string]ebpf_maps.BpfMap, error) RecoverAllBpfProgramsAndMaps() (map[string]BpfData, error) } @@ -122,26 +123,35 @@ func newElfLoader(elfFile *elf.File, bpfmapapi ebpf_maps.BpfMapAPIs, bpfprogapi return elfloader } -func (b *bpfSDKClient) LoadBpfFile(path, customizedPinPath string) (map[string]BpfData, map[string]ebpf_maps.BpfMap, error) { - bpfFile, err := os.Open(path) +// LoadBpfFromReader loads ELF file from io.ReaderAt and parses an ELF file into BPF objects +func (b *bpfSDKClient) LoadBpfFromReader(r io.ReaderAt, customizedPinPath string) ( + map[string]BpfData, + map[string]ebpf_maps.BpfMap, + error, +) { + elfFile, err := elf.NewFile(r) if err != nil { - log.Infof("LoadBpfFile failed to open") return nil, nil, err } - defer bpfFile.Close() - elfFile, err := elf.NewFile(bpfFile) + elfLoader := newElfLoader(elfFile, b.mapApi, b.progApi, customizedPinPath) + bpfLoadedProg, bpfLoadedMaps, err := elfLoader.doLoadELF() if err != nil { return nil, nil, err } - elfLoader := newElfLoader(elfFile, b.mapApi, b.progApi, customizedPinPath) + return bpfLoadedProg, bpfLoadedMaps, nil +} - bpfLoadedProg, bpfLoadedMaps, err := elfLoader.doLoadELF() +func (b *bpfSDKClient) LoadBpfFile(path, customizedPinPath string) (map[string]BpfData, map[string]ebpf_maps.BpfMap, error) { + bpfFile, err := os.Open(path) if err != nil { + log.Infof("LoadBpfFile failed to open") return nil, nil, err } - return bpfLoadedProg, bpfLoadedMaps, nil + defer bpfFile.Close() + + return b.LoadBpfFromReader(bpfFile, customizedPinPath) } func (e *elfLoader) loadMap(parsedMapData []ebpf_maps.CreateEBPFMapInput) (map[string]ebpf_maps.BpfMap, error) { diff --git a/pkg/elfparser/elf_test.go b/pkg/elfparser/elf_test.go index 056feb6..f539594 100644 --- a/pkg/elfparser/elf_test.go +++ b/pkg/elfparser/elf_test.go @@ -15,7 +15,9 @@ package elfparser import ( + "bytes" "debug/elf" + _ "embed" "errors" "os" "sort" @@ -668,3 +670,17 @@ func TestProgType(t *testing.T) { }) } } + +//go:embed test-data/test.bpf.elf +var elfBytes []byte + +func TestLoadBpfFromEmbeddedElf(t *testing.T) { + if os.Getuid() != 0 { + t.Skip("Test requires root privileges.") + } + + bpfSDKclient := New() + r := bytes.NewReader(elfBytes) + _, _, err := bpfSDKclient.LoadBpfFromReader(r, "") + assert.NoError(t, err) +} diff --git a/pkg/elfparser/test-data/test.bpf.c b/pkg/elfparser/test-data/test.bpf.c new file mode 100644 index 0000000..f049b83 --- /dev/null +++ b/pkg/elfparser/test-data/test.bpf.c @@ -0,0 +1,9 @@ +#include + +#include +#include + +SEC("kprobe") +int test_kprobe(struct pt_regs *ctx) { return 0; } + +char _license[] SEC("license") = "GPL"; diff --git a/pkg/elfparser/test-data/test.bpf.elf b/pkg/elfparser/test-data/test.bpf.elf new file mode 100644 index 0000000000000000000000000000000000000000..94fed33207c200b480462fa355e84c0a42505242 GIT binary patch literal 3856 zcmb_fONbm*6us5eJ>4^%m`p~=gcwuCjE>?|Pl861Xfly}7|3FXStMCl_NRJgNKbd$ zRWnKa;130H;efah!9*7#=teiXQc(zkAPFu+a1mUIu3Wir5znc5x2LA2A_l#1`@Z{o z=hb`nzN&uy$nm2&%Mv9^{*)C>ts)x-SH@G(a7soI`I#}lW#qA$<6;e4V`C!)d#ty4 z&$>vJOf9mWEG!)ltQtPAFN|AG${8|rxA1; zxB*@UzYTsD{3-Yg@YmqW;Cidto^_V|UNGNjJG=I{lkOg=%ykz0N-($B-u2+#O1D+L zQ0a92cC*zvSE-&0Cj45rIT19@PRw>H-Ltb5zt!wkdx77pgnkfCG^$}W8o7vb>o+r< zc&+)m-wu4K&sBTkd52D%ICR>3eEQ50@8s#3Bc3OO@XmI7otiK6?NI9BdFh5;&z}wC zRyu+oQ|q6ro-fbC;d6m_Y~W@=OnqW5X#va)?c@*$C*W^1|$r&vk;;- zvN7IJxFdI%hS%Qz?do0Y{2edmf4O$~)up3v!e*t7G8iQ@ezY(?WTB`m>n09GZqQ6O z(?S2HA$h2#H@VhK`W)80{Bb?YX~$)~#%1@fp4BcpI?dHKYPJlmHAZ$^vl(OyJ8mu6 zf}1vj?C1(y?f4k#ro{TSE?$CtIO@m&h{aVvWoqdqh_0H0G_DIt2#A<&&_5?}e$78jx^94atzdj!;m%Fa}L7mJxAn{r0 z*L>>qPk~9QC)dwAP1mpU?TDgdeBN(&r}W(^{a8x(jIQ$ymBnrNwZ&PlTC4T^C2>Rl zd?;?uZ@G`1JnHt9I0$!`*J(BbKMXVvCLOls+rAg+OgGau8t|{^^X+Cw+*WI8!K=a* z%+Id8v=U*QDw)>oRTunKmv*8HU0{aQnz+G*g-Dv!n`iwm;u|FMtkbmH9Q@BIhu*hp z=8K3n)^d`jl1gICI!MwdQ2r@j>rHdC9#wzY>NC48-sr`8BHTqq+=U!u+FD6z{q8@p=!tX=&Jid_l5nDo|97?G{#9P2};MZ-?H$p z82n2nm-yU!-G9a33mfN5<8%zr_wXf2@l~FJQ^(1;N7=w2y&qz2Z7k0zYyDmGmFAd4 zuAlc)di_7bmW6-H;4i0~>3aGB`C0hO24DAy`20Rh z7XGD-=Vz~`@h`%bh5xVt8ef5qMw+kYcQDAp|0)BY??%nneR%`6Ec_=8{!