From 585cbd50fdbadad200d553e1bbe7ea12d2529554 Mon Sep 17 00:00:00 2001 From: aymericdd Date: Tue, 12 Sep 2023 16:28:43 +0200 Subject: [PATCH 1/3] feat: GetMapsByName Allow a user to get a list of maps by name. --- libbpfgo.go | 28 ++++++++++++++++++ selftest/map-get-maps-by-name/Makefile | 1 + selftest/map-get-maps-by-name/go.mod | 7 +++++ selftest/map-get-maps-by-name/go.sum | 4 +++ selftest/map-get-maps-by-name/main.bpf.c | 20 +++++++++++++ selftest/map-get-maps-by-name/main.go | 36 ++++++++++++++++++++++++ selftest/map-get-maps-by-name/run.sh | 1 + 7 files changed, 97 insertions(+) create mode 120000 selftest/map-get-maps-by-name/Makefile create mode 100644 selftest/map-get-maps-by-name/go.mod create mode 100644 selftest/map-get-maps-by-name/go.sum create mode 100644 selftest/map-get-maps-by-name/main.bpf.c create mode 100644 selftest/map-get-maps-by-name/main.go create mode 120000 selftest/map-get-maps-by-name/run.sh diff --git a/libbpfgo.go b/libbpfgo.go index 01cdfb96..beffa54d 100644 --- a/libbpfgo.go +++ b/libbpfgo.go @@ -393,6 +393,34 @@ func (m *Module) InitGlobalVariable(name string, value interface{}) error { return err } +// GetMapsByName retrieves BPF maps with the specified name. +func GetMapsByName(name string) []*BPFMapLow { + bpfMaps := []*BPFMapLow{} + + startId := C.uint(0) + nextId := C.uint(0) + + for { + err := C.bpf_map_get_next_id(startId, &nextId) + if err != 0 { + return bpfMaps + } + + startId = nextId + 1 + + bpfMapLow, errMap := GetMapByID(uint32(nextId)) + if errMap != nil { + return bpfMaps + } + + if bpfMapLow.Name() != name { + continue + } + + bpfMaps = append(bpfMaps, bpfMapLow) + } +} + func (m *Module) GetMap(mapName string) (*BPFMap, error) { cs := C.CString(mapName) bpfMapC, errno := C.bpf_object__find_map_by_name(m.obj, cs) diff --git a/selftest/map-get-maps-by-name/Makefile b/selftest/map-get-maps-by-name/Makefile new file mode 120000 index 00000000..d981720c --- /dev/null +++ b/selftest/map-get-maps-by-name/Makefile @@ -0,0 +1 @@ +../common/Makefile \ No newline at end of file diff --git a/selftest/map-get-maps-by-name/go.mod b/selftest/map-get-maps-by-name/go.mod new file mode 100644 index 00000000..1fd0933d --- /dev/null +++ b/selftest/map-get-maps-by-name/go.mod @@ -0,0 +1,7 @@ +module github.com/aquasecurity/libbpfgo/selftest/map-update + +go 1.18 + +require github.com/aquasecurity/libbpfgo v0.4.7-libbpf-1.2.0-b2e29a1 + +replace github.com/aquasecurity/libbpfgo => ../../ diff --git a/selftest/map-get-maps-by-name/go.sum b/selftest/map-get-maps-by-name/go.sum new file mode 100644 index 00000000..c60af667 --- /dev/null +++ b/selftest/map-get-maps-by-name/go.sum @@ -0,0 +1,4 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/selftest/map-get-maps-by-name/main.bpf.c b/selftest/map-get-maps-by-name/main.bpf.c new file mode 100644 index 00000000..b095e26a --- /dev/null +++ b/selftest/map-get-maps-by-name/main.bpf.c @@ -0,0 +1,20 @@ +//+build ignore + +#include + +#include + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __uint(key_size, sizeof(u32)); + __uint(value_size, sizeof(u32)); +} test SEC(".maps"); + +SEC("kprobe/sys_execve") +int kprobe__sys_execve(struct pt_regs *ctx) +{ + return 0; +} + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; \ No newline at end of file diff --git a/selftest/map-get-maps-by-name/main.go b/selftest/map-get-maps-by-name/main.go new file mode 100644 index 00000000..afd90bae --- /dev/null +++ b/selftest/map-get-maps-by-name/main.go @@ -0,0 +1,36 @@ +package main + +import "C" + +import ( + "fmt" + "os" + "unsafe" + + bpf "github.com/aquasecurity/libbpfgo" +) + +func main() { + bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + defer bpfModule.Close() + + bpfModule.BPFLoadObject() + + testMaps := bpf.GetMapsByName("test") + if len(testMaps) == 0 { + fmt.Fprintln(os.Stderr, fmt.Errorf("no maps found")) + os.Exit(-1) + } + + testMap := testMaps[0] + key1 := uint32(0) + value1 := uint32(55) + if err := testMap.Update(unsafe.Pointer(&key1), unsafe.Pointer(&value1)); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } +} diff --git a/selftest/map-get-maps-by-name/run.sh b/selftest/map-get-maps-by-name/run.sh new file mode 120000 index 00000000..aee911b2 --- /dev/null +++ b/selftest/map-get-maps-by-name/run.sh @@ -0,0 +1 @@ +../common/run.sh \ No newline at end of file From 6c53f03969d384af37db3f2c66b66d924f3f01d5 Mon Sep 17 00:00:00 2001 From: aymericdd Date: Wed, 13 Sep 2023 16:35:42 +0200 Subject: [PATCH 2/3] feat: GetMapsIdsByName Allow a user to get a list of maps Ids filtered by map name. --- libbpfgo.go | 17 +++++++++++------ selftest/map-get-maps-by-name/main.go | 19 ++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/libbpfgo.go b/libbpfgo.go index beffa54d..9e0c3e39 100644 --- a/libbpfgo.go +++ b/libbpfgo.go @@ -393,9 +393,10 @@ func (m *Module) InitGlobalVariable(name string, value interface{}) error { return err } -// GetMapsByName retrieves BPF maps with the specified name. -func GetMapsByName(name string) []*BPFMapLow { - bpfMaps := []*BPFMapLow{} +// GetMapsIdsByName searches for maps with a given name. +// It returns a slice of unsigned 32-bit integers representing the IDs of matching maps. +func GetMapsIdsByName(name string) []uint32 { + bpfMapsIds := []uint32{} startId := C.uint(0) nextId := C.uint(0) @@ -403,21 +404,25 @@ func GetMapsByName(name string) []*BPFMapLow { for { err := C.bpf_map_get_next_id(startId, &nextId) if err != 0 { - return bpfMaps + return bpfMapsIds } startId = nextId + 1 bpfMapLow, errMap := GetMapByID(uint32(nextId)) if errMap != nil { - return bpfMaps + return bpfMapsIds + } + + if err := syscall.Close(bpfMapLow.FileDescriptor()); err != nil { + return bpfMapsIds } if bpfMapLow.Name() != name { continue } - bpfMaps = append(bpfMaps, bpfMapLow) + bpfMapsIds = append(bpfMapsIds, bpfMapLow.info.ID) } } diff --git a/selftest/map-get-maps-by-name/main.go b/selftest/map-get-maps-by-name/main.go index afd90bae..9308d1ab 100644 --- a/selftest/map-get-maps-by-name/main.go +++ b/selftest/map-get-maps-by-name/main.go @@ -10,6 +10,8 @@ import ( bpf "github.com/aquasecurity/libbpfgo" ) +const BPFMapName = "test" + func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { @@ -20,16 +22,23 @@ func main() { bpfModule.BPFLoadObject() - testMaps := bpf.GetMapsByName("test") - if len(testMaps) == 0 { - fmt.Fprintln(os.Stderr, fmt.Errorf("no maps found")) + mapsIdS := bpf.GetMapsIdsByName(BPFMapName) + if len(mapsIdS) == 0 { + fmt.Fprintln(os.Stderr, fmt.Errorf("no maps found for the %s map", BPFMapName)) + os.Exit(-1) + } + + bpfMapId := mapsIdS[0] + + bpfMap, err := bpf.GetMapByID(bpfMapId) + if err != nil { + fmt.Fprintln(os.Stderr, fmt.Errorf("the %s map with %d id not found: %w", BPFMapName, bpfMapId, err)) os.Exit(-1) } - testMap := testMaps[0] key1 := uint32(0) value1 := uint32(55) - if err := testMap.Update(unsafe.Pointer(&key1), unsafe.Pointer(&value1)); err != nil { + if err := bpfMap.Update(unsafe.Pointer(&key1), unsafe.Pointer(&value1)); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(-1) } From d42a1116d303766c5a85be8cc27e4351fd11272f Mon Sep 17 00:00:00 2001 From: aymericdd Date: Thu, 14 Sep 2023 10:44:16 +0200 Subject: [PATCH 3/3] lint --- selftest/map-get-maps-by-name/main.bpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selftest/map-get-maps-by-name/main.bpf.c b/selftest/map-get-maps-by-name/main.bpf.c index b095e26a..84f2dd52 100644 --- a/selftest/map-get-maps-by-name/main.bpf.c +++ b/selftest/map-get-maps-by-name/main.bpf.c @@ -17,4 +17,4 @@ int kprobe__sys_execve(struct pt_regs *ctx) return 0; } -char LICENSE[] SEC("license") = "Dual BSD/GPL"; \ No newline at end of file +char LICENSE[] SEC("license") = "Dual BSD/GPL";