diff --git a/.github/actions/build-dependencies/action.yaml b/.github/actions/build-dependencies/action.yaml index e3fff2b7..b4ccf421 100644 --- a/.github/actions/build-dependencies/action.yaml +++ b/.github/actions/build-dependencies/action.yaml @@ -21,6 +21,8 @@ runs: sudo apt-get install --yes llvm-14 clang-14 clang-format-14 sudo apt-get install --yes libelf-dev libzstd-dev zlib1g-dev sudo apt-get install --yes virtme-ng + sudo apt-get install --yes gcc-multilib + sudo apt-get install --yes systemtap-sdt-dev for tool in "clang" "clang-format" "llc" "llvm-strip" do sudo rm -f /usr/bin/$tool diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 2505b83e..d3a7bd7c 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -31,7 +31,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install dependencies run: | diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 0bb85c6f..51e46dc5 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-24.04 steps: - name: Checkout Code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install Dependencies uses: ./.github/actions/build-dependencies - name: Lint @@ -60,7 +60,7 @@ jobs: go-version: [ '1.18', '1.19', '1.20', '1.21', '1.22', '1.23', 'stable' ] steps: - name: Checkout Code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install Dependencies uses: ./.github/actions/build-dependencies with: @@ -76,7 +76,7 @@ jobs: go-version: [ '1.18', '1.19', '1.20', '1.21', '1.22', '1.23', 'stable' ] steps: - name: Checkout Code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install Dependencies uses: ./.github/actions/build-dependencies with: @@ -92,7 +92,7 @@ jobs: go-version: [ '1.18', '1.19', '1.20', '1.21', '1.22', '1.23', 'stable' ] steps: - name: Checkout Code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Install Dependencies uses: ./.github/actions/build-dependencies with: diff --git a/.gitignore b/.gitignore index e2e03e39..cf0eb6b6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ selftest/*/*.o selftest/*/*.skel.h selftest/*/*-static selftest/*/*-dynamic -selftest/uprobe/ctest -selftest/uprobe/gotest +selftest/*/ctest +selftest/*/gotest testing/tracee .vagrant* diff --git a/Makefile b/Makefile index e7c3e78a..7e4d2a10 100644 --- a/Makefile +++ b/Makefile @@ -171,13 +171,15 @@ selftest-clean: helpers-test-run: helpers-test-static-run helpers-test-static-run: libbpfgo-static - CC=$(CLANG) \ + cd $(HELPERS) && \ + CC=$(CLANG) \ CGO_CFLAGS=$(CGO_CFLAGS_STATIC) \ CGO_LDFLAGS=$(CGO_LDFLAGS_STATIC) \ - sudo -E env PATH=$(PATH) $(GO) test -v $(HELPERS)/... + sudo -E env PATH=$(PATH) $(GO) test -v ./... helpers-test-dynamic-run: libbpfgo-dynamic - sudo $(GO) test -v $(HELPERS)/... + cd $(HELPERS) && \ + sudo $(GO) test -v ./... # vagrant diff --git a/go.mod b/go.mod index 058c6523..fff49290 100644 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/aquasecurity/libbpfgo go 1.21 require ( - github.com/stretchr/testify v1.10.0 - kernel.org/pub/linux/libs/security/libcap/cap v1.2.75 + github.com/stretchr/testify v1.11.1 + kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - kernel.org/pub/linux/libs/security/libcap/psx v1.2.76-rc1 // indirect + kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 // indirect ) diff --git a/go.sum b/go.sum index 036e4c30..aaf7ad69 100644 --- a/go.sum +++ b/go.sum @@ -2,14 +2,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -kernel.org/pub/linux/libs/security/libcap/cap v1.2.75 h1:f78VOelVeTl82xITLNCvtOQ6yHbrsL2X8lSs2kJ6laE= -kernel.org/pub/linux/libs/security/libcap/cap v1.2.75/go.mod h1:/0v7MsGCcYOmU5VrtrvcjgqCar2mdCr/STymAGfd57A= -kernel.org/pub/linux/libs/security/libcap/psx v1.2.75/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= -kernel.org/pub/linux/libs/security/libcap/psx v1.2.76-rc1 h1:Tq5hYNtVgkIUTv+5BtOZjC5JB4s8TutijJE5vBaoW84= -kernel.org/pub/linux/libs/security/libcap/psx v1.2.76-rc1/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/go.work b/go.work deleted file mode 100644 index edc7b36d..00000000 --- a/go.work +++ /dev/null @@ -1,6 +0,0 @@ -go 1.21 - -use ( - . - ./helpers -) diff --git a/go.work.sum b/go.work.sum deleted file mode 100644 index a06bcbbf..00000000 --- a/go.work.sum +++ /dev/null @@ -1 +0,0 @@ -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= diff --git a/libbpf b/libbpf index 09b9e831..b4fa3e39 160000 --- a/libbpf +++ b/libbpf @@ -1 +1 @@ -Subproject commit 09b9e83102eb8ab9e540d36b4559c55f3bcdb95d +Subproject commit b4fa3e39a77fd65574fb5f899486795fc3d89bd9 diff --git a/libbpfgo.c b/libbpfgo.c index 654dea44..0eca30ad 100644 --- a/libbpfgo.c +++ b/libbpfgo.c @@ -43,9 +43,25 @@ void cgo_libbpf_set_print_fn() libbpf_set_print(libbpf_print_fn); } +struct user_ring_buffer *cgo_init_user_ring_buf(int map_fd) +{ + struct user_ring_buffer *rb; + + rb = user_ring_buffer__new(map_fd, NULL); + if (!rb) { + int saved_errno = errno; + fprintf(stderr, "Failed to initialize user ring buffer: %s\n", strerror(errno)); + errno = saved_errno; + + return NULL; + } + + return rb; +} + struct ring_buffer *cgo_init_ring_buf(int map_fd, uintptr_t ctx) { - struct ring_buffer *rb = NULL; + struct ring_buffer *rb; rb = ring_buffer__new(map_fd, ringbufferCallback, (void *) ctx, NULL); if (!rb) { @@ -131,6 +147,27 @@ int cgo_bpf_prog_detach_cgroup_legacy(int prog_fd, // eBPF program file descri return syscall(__NR_bpf, BPF_PROG_DETACH, &attr, sizeof(attr)); } +struct bpf_link *cgo_bpf_program__attach_uprobe_multi( + struct bpf_program *prog, + pid_t pid, + const char *binary_path, + const char *func_pattern, + const unsigned long *offsets, // bpf_uprobe_multi_opts.offsets + const __u64 *cookies, // bpf_uprobe_multi_opts.cookies + size_t cnt, // bpf_uprobe_multi_opts.cnt + bool retprobe // bpf_uprobe_multi_opts.retprobe +) +{ + struct bpf_uprobe_multi_opts opts = {}; + opts.sz = sizeof(opts); + opts.offsets = offsets; + opts.cookies = cookies; + opts.cnt = cnt; + opts.retprobe = retprobe; + + return bpf_program__attach_uprobe_multi(prog, pid, binary_path, func_pattern, &opts); +} + // // struct handlers // @@ -567,4 +604,4 @@ struct bpf_xdp_attach_opts *cgo_bpf_xdp_attach_opts_new(__u32 fd) void cgo_bpf_xdp_attach_opts_free(struct bpf_xdp_attach_opts *opts) { free(opts); -} \ No newline at end of file +} diff --git a/libbpfgo.go b/libbpfgo.go index f6dabf2d..98fa5768 100644 --- a/libbpfgo.go +++ b/libbpfgo.go @@ -80,7 +80,7 @@ func SetStrictMode(mode LibbpfStrictMode) { func BPFProgramTypeIsSupported(progType BPFProgType) (bool, error) { supportedC := C.libbpf_probe_bpf_prog_type(C.enum_bpf_prog_type(int(progType)), nil) - if supportedC < 1 { + if supportedC < 0 { return false, syscall.Errno(-supportedC) } @@ -89,7 +89,7 @@ func BPFProgramTypeIsSupported(progType BPFProgType) (bool, error) { func BPFMapTypeIsSupported(mapType MapType) (bool, error) { supportedC := C.libbpf_probe_bpf_map_type(C.enum_bpf_map_type(int(mapType)), nil) - if supportedC < 1 { + if supportedC < 0 { return false, syscall.Errno(-supportedC) } diff --git a/libbpfgo.h b/libbpfgo.h index 27e960cd..9c3235ba 100644 --- a/libbpfgo.h +++ b/libbpfgo.h @@ -22,6 +22,7 @@ void cgo_libbpf_set_print_fn(); struct ring_buffer *cgo_init_ring_buf(int map_fd, uintptr_t ctx); +struct user_ring_buffer *cgo_init_user_ring_buf(int map_fd); int cgo_add_ring_buf(struct ring_buffer *rb, int map_fd, uintptr_t ctx); struct perf_buffer *cgo_init_perf_buf(int map_fd, int page_cnt, uintptr_t ctx); @@ -30,6 +31,15 @@ void cgo_bpf_map__initial_value(struct bpf_map *map, void *value); int cgo_bpf_prog_attach_cgroup_legacy(int prog_fd, int target_fd, int type); int cgo_bpf_prog_detach_cgroup_legacy(int prog_fd, int target_fd, int type); +struct bpf_link *cgo_bpf_program__attach_uprobe_multi(struct bpf_program *prog, + pid_t pid, + const char *binary_path, + const char *func_pattern, + const unsigned long *offsets, + const __u64 *cookies, + size_t count, + bool retprobe); + // // struct handlers // diff --git a/link.go b/link.go index db0f3829..85f9ba94 100644 --- a/link.go +++ b/link.go @@ -34,6 +34,7 @@ const ( Netns Iter StructOps + USDT ) // diff --git a/module.go b/module.go index d183affc..6967acd9 100644 --- a/module.go +++ b/module.go @@ -21,12 +21,13 @@ import ( // type Module struct { - obj *C.struct_bpf_object - links []*BPFLink - perfBufs []*PerfBuffer - ringBufs []*RingBuffer - elf *elf.File - loaded bool + obj *C.struct_bpf_object + links []*BPFLink + perfBufs []*PerfBuffer + ringBufs []*RingBuffer + userRingBufs []*UserRingBuffer + elf *elf.File + loaded bool } // @@ -187,6 +188,9 @@ func (m *Module) Close() { for _, rb := range m.ringBufs { rb.Close() } + for _, rb := range m.userRingBufs { + rb.Close() + } for _, link := range m.links { if link.link != nil { link.Destroy() @@ -327,6 +331,30 @@ func (m *Module) GetProgram(progName string) (*BPFProg, error) { }, nil } +func (m *Module) InitUserRingBuf(mapName string, eventsChan chan []byte) (*UserRingBuffer, error) { + bpfMap, err := m.GetMap(mapName) + if err != nil { + return nil, err + } + + if eventsChan == nil { + return nil, fmt.Errorf("events channel can not be nil") + } + + rbC, errno := C.cgo_init_user_ring_buf(C.int(bpfMap.FileDescriptor())) + if rbC == nil { + return nil, fmt.Errorf("failed to initialize user ring buffer: %w", errno) + } + + ringBuf := &UserRingBuffer{ + rb: rbC, + bpfMap: bpfMap, + w: eventsChan, + } + m.userRingBufs = append(m.userRingBufs, ringBuf) + return ringBuf, nil +} + func (m *Module) InitRingBuf(mapName string, eventsChan chan []byte) (*RingBuffer, error) { bpfMap, err := m.GetMap(mapName) if err != nil { diff --git a/prog.go b/prog.go index 13434e63..f8f9b3c8 100644 --- a/prog.go +++ b/prog.go @@ -607,7 +607,7 @@ func (p *BPFProg) AttachIter(opts IterOpts) (*BPFLink, error) { // AttachUprobe attaches the BPFProgram to entry of the symbol in the library or binary at 'path' // which can be relative or absolute. A pid can be provided to attach to, or -1 can be specified // to attach to all processes -func (p *BPFProg) AttachUprobe(pid int, path string, offset uint32) (*BPFLink, error) { +func (p *BPFProg) AttachUprobe(pid int, path string, offset uint64) (*BPFLink, error) { absPath, err := filepath.Abs(path) if err != nil { return nil, err @@ -619,7 +619,7 @@ func (p *BPFProg) AttachUprobe(pid int, path string, offset uint32) (*BPFLink, e // AttachURetprobe attaches the BPFProgram to exit of the symbol in the library or binary at 'path' // which can be relative or absolute. A pid can be provided to attach to, or -1 can be specified // to attach to all processes -func (p *BPFProg) AttachURetprobe(pid int, path string, offset uint32) (*BPFLink, error) { +func (p *BPFProg) AttachURetprobe(pid int, path string, offset uint64) (*BPFLink, error) { absPath, err := filepath.Abs(path) if err != nil { return nil, err @@ -628,7 +628,35 @@ func (p *BPFProg) AttachURetprobe(pid int, path string, offset uint32) (*BPFLink return doAttachUprobe(p, true, pid, absPath, offset) } -func doAttachUprobe(prog *BPFProg, isUretprobe bool, pid int, path string, offset uint32) (*BPFLink, error) { +// AttachUprobeMulti attaches the BPFProgram to entry of the symbol in the library or binary at 'path' +// which can be relative or absolute, using the uprobe_multi link, allowing to specify multiple offsets. +// A pid can be provided to attach to, or -1 can be specified to attach to all processes. +// func_pattern argument to libbpf bpf_program__attach_uprobe_multi() which accepts a regular expression +// to specify functions to attach BPF program to, is currently not supported. +func (p *BPFProg) AttachUprobeMulti(pid int, path string, offsets, cookies []uint64) (*BPFLink, error) { + absPath, err := filepath.Abs(path) + if err != nil { + return nil, err + } + + return doAttachUprobeMulti(p, false, pid, absPath, offsets, cookies) +} + +// AttachURetprobeMulti attaches the BPFProgram to exit of the symbol in the library or binary at 'path' +// which can be relative or absolute, using the uprobe_multi link, allowing to specify multiple offsets. +// A pid can be provided to attach to, or -1 can be specified to attach to all processes. +// func_pattern argument to libbpf bpf_program__attach_uprobe_multi() which accepts a regular expression +// to specify functions to attach BPF program to, is currently not supported. +func (p *BPFProg) AttachURetprobeMulti(pid int, path string, offsets, cookies []uint64) (*BPFLink, error) { + absPath, err := filepath.Abs(path) + if err != nil { + return nil, err + } + + return doAttachUprobeMulti(p, true, pid, absPath, offsets, cookies) +} + +func doAttachUprobe(prog *BPFProg, isUretprobe bool, pid int, path string, offset uint64) (*BPFLink, error) { pathC := C.CString(path) defer C.free(unsafe.Pointer(pathC)) @@ -658,6 +686,48 @@ func doAttachUprobe(prog *BPFProg, isUretprobe bool, pid int, path string, offse return bpfLink, nil } +func doAttachUprobeMulti(prog *BPFProg, isUretprobe bool, pid int, path string, offsets, cookies []uint64) (*BPFLink, error) { + pathC := C.CString(path) + defer C.free(unsafe.Pointer(pathC)) + + var offsetsC *C.ulong + if len(offsets) > 0 { + offsetsC = (*C.ulong)(unsafe.Pointer(&offsets[0])) + } + var cookiesC *C.__u64 + if len(cookies) > 0 { + cookiesC = (*C.__u64)(unsafe.Pointer(&cookies[0])) + } + + linkC, errno := C.cgo_bpf_program__attach_uprobe_multi( + prog.prog, + C.int(pid), + pathC, + nil, + offsetsC, + cookiesC, + C.size_t(len(offsets)), + C.bool(isUretprobe), + ) + if linkC == nil { + return nil, fmt.Errorf("failed to attach u(ret)probe multi to program %s:%v with pid %d: %w ", path, offsets, pid, errno) + } + + upType := Uprobe + if isUretprobe { + upType = Uretprobe + } + + bpfLink := &BPFLink{ + link: linkC, + prog: prog, + linkType: upType, + eventName: fmt.Sprintf("%s:%d:%v", path, pid, offsets), + } + + return bpfLink, nil +} + // AttachGenericFD attaches the BPFProgram to a targetFd at the specified attachType hook. func (p *BPFProg) AttachGenericFD(targetFd int, attachType BPFAttachType, flags AttachFlag) error { retC := C.bpf_prog_attach( @@ -687,6 +757,39 @@ func (p *BPFProg) DetachGenericFD(targetFd int, attachType BPFAttachType) error return nil } +// AttachUSDT attaches the BPFProgram to the USDT static marker in the library or binary at 'binaryPath' +// which can be relative or absolute. A pid can be provided to attach to, or -1 can be specified +// to attach to all processes. +func (p *BPFProg) AttachUSDT(pid int, binaryPath string, provider string, name string) (*BPFLink, error) { + binaryPathC := C.CString(binaryPath) + defer C.free(unsafe.Pointer(binaryPathC)) + providerC := C.CString(provider) + defer C.free(unsafe.Pointer(providerC)) + nameC := C.CString(name) + defer C.free(unsafe.Pointer(nameC)) + + linkC, errno := C.bpf_program__attach_usdt( + p.prog, + C.int(pid), + binaryPathC, + providerC, + nameC, + nil, + ) + if linkC == nil { + return nil, fmt.Errorf("failed to attach USDT probe to marker %s:%s in program %s with pid %d: %w", provider, name, binaryPath, pid, errno) + } + + bpfLink := &BPFLink{ + link: linkC, + prog: p, + linkType: USDT, + eventName: fmt.Sprintf("%s:%d:%s:%s", binaryPath, pid, provider, name), + } + + return bpfLink, nil +} + // // BPF_PROG_TEST_RUN // diff --git a/selftest/attachgenericfd/go.mod b/selftest/attachgenericfd/go.mod index 2bef5812..e8b6d67e 100644 --- a/selftest/attachgenericfd/go.mod +++ b/selftest/attachgenericfd/go.mod @@ -4,6 +4,11 @@ go 1.21 require github.com/aquasecurity/libbpfgo v0.0.0 -require golang.org/x/sys v0.9.0 +require ( + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 + golang.org/x/sys v0.25.0 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/attachgenericfd/go.sum b/selftest/attachgenericfd/go.sum index d6a01bbd..06771930 100644 --- a/selftest/attachgenericfd/go.sum +++ b/selftest/attachgenericfd/go.sum @@ -2,9 +2,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/attachgenericfd/main.go b/selftest/attachgenericfd/main.go index 103caf7d..cfa2acd8 100644 --- a/selftest/attachgenericfd/main.go +++ b/selftest/attachgenericfd/main.go @@ -4,34 +4,33 @@ import "C" import ( "bytes" + "errors" "fmt" "net" - "os" "time" "unsafe" - bpf "github.com/aquasecurity/libbpfgo" "golang.org/x/sys/unix" + + bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } serverFD, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, unix.IPPROTO_IP) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer unix.Close(serverFD) @@ -40,19 +39,16 @@ func main() { Addr: [4]byte{127, 0, 0, 1}, } if err := unix.Bind(serverFD, serverAddr); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if err := unix.Listen(serverFD, 100); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } sockMapRx, err := bpfModule.GetMap("sock_map_rx") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } prog1, err := bpfModule.GetProgram("bpf_prog_parser") @@ -60,8 +56,7 @@ func main() { bpf.BPFAttachTypeSKSKBStreamParser, bpf.BPFFNone) defer func() { if err := prog1.DetachGenericFD(sockMapRx.FileDescriptor(), bpf.BPFAttachTypeSKSKBStreamParser); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } }() @@ -70,8 +65,7 @@ func main() { bpf.BPFAttachTypeSKSKBStreamVerdict, bpf.BPFFNone) defer func() { if err := prog2.DetachGenericFD(sockMapRx.FileDescriptor(), bpf.BPFAttachTypeSKSKBStreamVerdict); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } }() @@ -80,14 +74,12 @@ func main() { go func() { acceptedFD, _, err := unix.Accept(serverFD) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } key := int(0) val := int(acceptedFD) if err = sockMapRx.UpdateValueFlags(unsafe.Pointer(&key), unsafe.Pointer(&val), bpf.MapFlagUpdateAny); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } mapUpdateChan <- struct{}{} @@ -95,8 +87,7 @@ func main() { c, err := net.Dial("tcp", "127.0.0.1:22345") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer c.Close() @@ -105,24 +96,20 @@ func main() { case <-mapUpdateChan: // continue with write/read case <-time.After(15 * time.Second): // Same of the selftest - fmt.Fprintln(os.Stderr, "bpf map timeout") - os.Exit(-1) + common.Error(errors.New("bpf map timeout")) } input := []byte("foobar") if _, err = c.Write(input); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } output := make([]byte, 6) if _, err = c.Read(output); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if !bytes.Equal(output, input) { - fmt.Fprintln(os.Stderr, "data mismatch") - os.Exit(-1) + common.Error(fmt.Errorf("data mismatch: expected %q, got %q", input, output)) } } diff --git a/selftest/cgroup-legacy/go.mod b/selftest/cgroup-legacy/go.mod index 72a57bd7..22922d69 100644 --- a/selftest/cgroup-legacy/go.mod +++ b/selftest/cgroup-legacy/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/cgroup-legacy go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/cgroup-legacy/go.sum b/selftest/cgroup-legacy/go.sum index 5496456e..964bd12d 100644 --- a/selftest/cgroup-legacy/go.sum +++ b/selftest/cgroup-legacy/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/cgroup-legacy/main.go b/selftest/cgroup-legacy/main.go index ef2c6c89..fd67c52d 100644 --- a/selftest/cgroup-legacy/main.go +++ b/selftest/cgroup-legacy/main.go @@ -5,45 +5,43 @@ import "C" import ( "context" "encoding/binary" - "fmt" - "io/ioutil" + "errors" "log" - "os" "os/exec" "os/signal" - "regexp" - "runtime" "syscall" "time" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -var reCgroup2Mount = regexp.MustCompile(`(?m)^cgroup2\s(/\S+)\scgroup2\s`) - func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - Error(err) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - Error(err) + common.Error(err) } prog, err := bpfModule.GetProgram("cgroup__skb_ingress") if err != nil { - Error(err) + common.Error(err) } - cgroupRootDir := getCgroupV2RootDir() + cgroupRootDir, err := common.GetCgroupV2RootDir() + if err != nil { + common.Error(err) + } // link, err := prog.AttachCgroup(cgroupRootDir) link, err := prog.AttachCgroupLegacy(cgroupRootDir, bpf.BPFAttachTypeCgroupInetIngress) if err != nil { - Error(err) + common.Error(err) } eventsChannel := make(chan []byte, 1) @@ -54,7 +52,7 @@ func main() { "perfbuffer", eventsChannel, lostChannel, 1, ) if err != nil { - Error(err) + common.Error(err) } // signal handling @@ -69,7 +67,7 @@ func main() { go func() { _, err := exec.Command("ping", "127.0.0.1", "-c 5", "-w 10").Output() if err != nil { - Error(err) + common.Error(err) } time.Sleep(time.Second) stop() @@ -85,7 +83,7 @@ LOOP: value := int(binary.LittleEndian.Uint32(raw)) if value == 20220823 { - fmt.Println("Received correct event.") + log.Println("Received correct event") numberOfEventsReceived++ if numberOfEventsReceived >= 5 { testPassed = true @@ -99,32 +97,10 @@ LOOP: err = link.Destroy() if err != nil { - Error(err) + common.Error(err) } if !testPassed { - Error(fmt.Errorf("unable to get all packets")) + common.Error(errors.New("unable to get all packets")) } - - os.Exit(0) -} - -func getCgroupV2RootDir() string { - data, err := ioutil.ReadFile("/proc/mounts") - if err != nil { - fmt.Fprintf(os.Stderr, "read /proc/mounts failed: %+v\n", err) - os.Exit(-1) - } - items := reCgroup2Mount.FindStringSubmatch(string(data)) - if len(items) < 2 { - fmt.Fprintln(os.Stderr, "cgroupv2 is not mounted") - os.Exit(-1) - } - return items[1] -} - -func Error(err error) { - _, fn, line, _ := runtime.Caller(1) - log.Printf("ERROR: %s:%d %v\n", fn, line, err) - os.Exit(1) } diff --git a/selftest/cgroup/go.mod b/selftest/cgroup/go.mod index 72a57bd7..3963081e 100644 --- a/selftest/cgroup/go.mod +++ b/selftest/cgroup/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/cgroup go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/cgroup/go.sum b/selftest/cgroup/go.sum index 5496456e..964bd12d 100644 --- a/selftest/cgroup/go.sum +++ b/selftest/cgroup/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/cgroup/main.go b/selftest/cgroup/main.go index f5e8da6d..8597bdbe 100644 --- a/selftest/cgroup/main.go +++ b/selftest/cgroup/main.go @@ -4,52 +4,47 @@ import "C" import ( "encoding/binary" + "errors" "fmt" - "io/ioutil" - "os" "os/exec" - "regexp" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -var reCgroup2Mount = regexp.MustCompile(`(?m)^cgroup2\s(/\S+)\scgroup2\s`) - func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } prog, err := bpfModule.GetProgram("cgroup__sock") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } - cgroupRootDir := getCgroupV2RootDir() + cgroupRootDir, err := common.GetCgroupV2RootDir() + if err != nil { + common.Error(err) + } link, err := prog.AttachCgroup(cgroupRootDir) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if link.GetFd() == 0 { - os.Exit(-1) + common.Error(errors.New("failed to attach cgroup")) } eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } rb.Poll(300) @@ -58,8 +53,7 @@ func main() { for i := 0; i < 10; i++ { _, err := exec.Command("ping", "localhost", "-c 1", "-w 1").Output() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } } }() @@ -68,8 +62,7 @@ recvLoop: for { b := <-eventsChannel if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %s", b)) } numberOfEventsReceived++ if numberOfEventsReceived > 5 { @@ -80,17 +73,3 @@ recvLoop: rb.Stop() rb.Close() } - -func getCgroupV2RootDir() string { - data, err := ioutil.ReadFile("/proc/mounts") - if err != nil { - fmt.Fprintf(os.Stderr, "read /proc/mounts failed: %+v\n", err) - os.Exit(-1) - } - items := reCgroup2Mount.FindStringSubmatch(string(data)) - if len(items) < 2 { - fmt.Fprintln(os.Stderr, "cgroupv2 is not mounted") - os.Exit(-1) - } - return items[1] -} diff --git a/selftest/common/common.go b/selftest/common/common.go new file mode 100644 index 00000000..cfb26e52 --- /dev/null +++ b/selftest/common/common.go @@ -0,0 +1,151 @@ +package common + +import ( + "debug/elf" + "encoding/binary" + "errors" + "fmt" + "log" + "os" + "regexp" + "runtime" + "unsafe" + + bpf "github.com/aquasecurity/libbpfgo" +) + +// ResizeMap resizes a BPF map to the specified size. +func ResizeMap(module *bpf.Module, name string, size uint32) error { + m, err := module.GetMap(name) + if err != nil { + return err + } + + if err = m.SetMaxEntries(size); err != nil { + return err + } + + if actual := m.MaxEntries(); actual != size { + return fmt.Errorf("map resize failed, expected %v, actual %v", size, actual) + } + + return nil +} + +// KSymArch returns the kernel symbol architecture. +func KSymArch() string { + switch runtime.GOARCH { + case "amd64": + return "x64" + case "arm64": + return "arm64" + default: + panic("unsupported architecture") + } +} + +// ByteOrder returns the byte order of the system. +func ByteOrder() binary.ByteOrder { + var i int32 = 0x01020304 + u := unsafe.Pointer(&i) + pb := (*byte)(u) + b := *pb + if b == 0x04 { + return binary.LittleEndian + } + + return binary.BigEndian +} + +var reCgroup2Mount = regexp.MustCompile(`(?m)^cgroup2\s(/\S+)\scgroup2\s`) + +// GetCgroupV2RootDir returns the root directory of the cgroupv2 filesystem. +func GetCgroupV2RootDir() (string, error) { + data, err := os.ReadFile("/proc/mounts") + if err != nil { + return "", fmt.Errorf("read /proc/mounts failed: %+v", err) + } + + items := reCgroup2Mount.FindStringSubmatch(string(data)) + if len(items) < 2 { + return "", errors.New("cgroupv2 is not mounted") + } + + return items[1], nil +} + +// SymbolToOffset attempts to resolve a 'symbol' name in the binary found at +// 'path' to an offset. The offset can be used for attaching a u(ret)probe +func SymbolToOffset(path, symbol string) (uint64, error) { + f, err := elf.Open(path) + if err != nil { + return 0, fmt.Errorf("could not open elf file to resolve symbol offset: %w", err) + } + defer f.Close() + + regularSymbols, regularSymbolsErr := f.Symbols() + dynamicSymbols, dynamicSymbolsErr := f.DynamicSymbols() + + // Only if we failed getting both regular and dynamic symbols - then we abort. + if regularSymbolsErr != nil && dynamicSymbolsErr != nil { + return 0, fmt.Errorf("could not open regular or dynamic symbol sections to resolve symbol offset: %w %s", regularSymbolsErr, dynamicSymbolsErr) + } + + // Concatenating into a single list. + // The list can have duplications, but we will find the first occurrence which is sufficient. + syms := append(regularSymbols, dynamicSymbols...) + + sectionsToSearchForSymbol := []*elf.Section{} + + for i := range f.Sections { + if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR { + sectionsToSearchForSymbol = append(sectionsToSearchForSymbol, f.Sections[i]) + } + } + + var executableSection *elf.Section + + for j := range syms { + if syms[j].Name == symbol { + // Find what section the symbol is in by checking the executable section's + // addr space. + for m := range sectionsToSearchForSymbol { + if syms[j].Value > sectionsToSearchForSymbol[m].Addr && + syms[j].Value < sectionsToSearchForSymbol[m].Addr+sectionsToSearchForSymbol[m].Size { + executableSection = sectionsToSearchForSymbol[m] + } + } + + if executableSection == nil { + return 0, errors.New("could not find symbol in executable sections of binary") + } + + return syms[j].Value - executableSection.Addr + executableSection.Offset, nil + } + } + + return 0, fmt.Errorf("symbol %s not found in %s", symbol, path) +} + +// Ordered constraint for comparable types +type Ordered interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string +} + +// Min returns the minimum of two values. +func Min[T Ordered](a, b T) T { + if a < b { + return a + } + + return b +} + +// Error logs the error and exits the program. +func Error(err error) { + _, fn, line, _ := runtime.Caller(1) + log.Fatalf("ERROR: %s:%d %v\n", fn, line, err) +} diff --git a/selftest/common/go.mod b/selftest/common/go.mod new file mode 100644 index 00000000..82c38b99 --- /dev/null +++ b/selftest/common/go.mod @@ -0,0 +1,9 @@ +module github.com/aquasecurity/libbpfgo/selftest/common + +go 1.21 + +require github.com/aquasecurity/libbpfgo v0.0.0 + +replace github.com/aquasecurity/libbpfgo => ../.. + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/common/go.sum b/selftest/common/go.sum new file mode 100644 index 00000000..964bd12d --- /dev/null +++ b/selftest/common/go.sum @@ -0,0 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/common/run-6.1.sh b/selftest/common/run-6.1.sh new file mode 100755 index 00000000..2845bd81 --- /dev/null +++ b/selftest/common/run-6.1.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# SETTINGS + +TEST=$(dirname $0)/$1 # execute +TIMEOUT=10 # seconds + +# COMMON + +COMMON="$(dirname $0)/../common/common.sh" +[[ -f $COMMON ]] && { . $COMMON; } || { error "no common"; exit 1; } + +# MAIN + +kern_version ge 6.1 + +check_build +check_ppid +test_exec +test_finish + +exit 0 diff --git a/selftest/common/vmlinux.h b/selftest/common/vmlinux.h index c10daf07..8f4fa7a1 100644 --- a/selftest/common/vmlinux.h +++ b/selftest/common/vmlinux.h @@ -866,6 +866,94 @@ struct icmp6hdr { } icmp6_dataun; }; +#if defined(__TARGET_ARCH_x86) + +struct fred_cs { + u64 cs : 16; + u64 sl : 2; + u64 wfe : 1; +}; + +struct fred_ss { + u64 ss : 16; + u64 sti : 1; + u64 swevent : 1; + u64 nmi : 1; + int : 13; + u64 vector : 8; + short : 8; + u64 type : 4; + char : 4; + u64 enclave : 1; + u64 lm : 1; + u64 nested : 1; + char : 1; + u64 insnlen : 4; +}; + +struct pt_regs { + long unsigned int r15; + long unsigned int r14; + long unsigned int r13; + long unsigned int r12; + long unsigned int bp; + long unsigned int bx; + long unsigned int r11; + long unsigned int r10; + long unsigned int r9; + long unsigned int r8; + long unsigned int ax; + long unsigned int cx; + long unsigned int dx; + long unsigned int si; + long unsigned int di; + long unsigned int orig_ax; + long unsigned int ip; + union { + u16 cs; + u64 csx; + struct fred_cs fred_cs; + }; + long unsigned int flags; + long unsigned int sp; + union { + u16 ss; + u64 ssx; + struct fred_ss fred_ss; + }; +}; + +#elif defined(__TARGET_ARCH_arm64) + +struct user_pt_regs { + __u64 regs[31]; + __u64 sp; + __u64 pc; + __u64 pstate; +}; + +struct pt_regs { + union { + struct user_pt_regs user_regs; + struct { + u64 regs[31]; + u64 sp; + u64 pc; + u64 pstate; + }; + }; + u64 orig_x0; + s32 syscallno; + u32 unused2; + u64 orig_addr_limit; + u64 pmr_save; + u64 stackframe[2]; + u64 lockdep_hardirqs; + u64 exit_rcu; +}; + +#endif + #pragma clang attribute pop #endif diff --git a/selftest/create-map/go.mod b/selftest/create-map/go.mod index 8493bf67..5732795e 100644 --- a/selftest/create-map/go.mod +++ b/selftest/create-map/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-pin-info +module github.com/aquasecurity/libbpfgo/selftest/create-map go 1.21 replace github.com/aquasecurity/libbpfgo => ../../ -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/create-map/go.sum b/selftest/create-map/go.sum index 5496456e..964bd12d 100644 --- a/selftest/create-map/go.sum +++ b/selftest/create-map/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/create-map/main.go b/selftest/create-map/main.go index e0c15ed2..78f33c83 100644 --- a/selftest/create-map/main.go +++ b/selftest/create-map/main.go @@ -3,12 +3,10 @@ package main import "C" import ( - "fmt" - "log" - "os" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) // CreateMap uses `bpf_map_create()`, a 'low-level' API in libbpf @@ -31,8 +29,7 @@ import ( func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() @@ -40,7 +37,7 @@ func main() { m, err := bpf.CreateMap(bpf.MapTypeHash, "foobar", 4, 4, 420, nil) if err != nil { - log.Fatal(err) + common.Error(err) } key1 := uint32(1) @@ -49,6 +46,6 @@ func main() { value1Unsafe := unsafe.Pointer(&value1) err = m.Update(key1Unsafe, value1Unsafe) if err != nil { - log.Fatal(err) + common.Error(err) } } diff --git a/selftest/error-handling/go.mod b/selftest/error-handling/go.mod index e4b855d8..88c85302 100644 --- a/selftest/error-handling/go.mod +++ b/selftest/error-handling/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/error-handling go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/error-handling/go.sum b/selftest/error-handling/go.sum index 5496456e..964bd12d 100644 --- a/selftest/error-handling/go.sum +++ b/selftest/error-handling/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/error-handling/main.go b/selftest/error-handling/main.go index e9f75167..9085d86a 100644 --- a/selftest/error-handling/main.go +++ b/selftest/error-handling/main.go @@ -4,19 +4,18 @@ import "C" import ( "errors" - "os" "syscall" "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() @@ -25,34 +24,28 @@ func main() { // non-existant program _, err = bpfModule.GetProgram("NewYorkYankeesRule") if err == nil { - fmt.Fprintln(os.Stderr, "undetected error, non-existant program") - os.Exit(-1) + common.Error(errors.New("undetected error, non-existant program")) } if !errors.Is(err, syscall.ENOENT) { - fmt.Fprintf(os.Stderr, "unexpected wrapped error received, expected ENOENT\n") - os.Exit(-1) + common.Error(fmt.Errorf("unexpected wrapped error received, expected ENOENT: %w", err)) } // non-existant map _, err = bpfModule.GetMap("Ih8BostonRedSox") if err == nil { - fmt.Fprintln(os.Stderr, "undetected error, non-existant map") - os.Exit(-1) + common.Error(errors.New("undetected error, non-existant map")) } if !errors.Is(err, syscall.ENOENT) { - fmt.Fprintf(os.Stderr, "unexpected wrapped error received, expected ENOENT\n") - os.Exit(-1) + common.Error(fmt.Errorf("unexpected wrapped error received, expected ENOENT: %w", err)) } // invalid tc hook tchook := bpfModule.TcHookInit() err = tchook.Create() if err == nil { - fmt.Fprintln(os.Stderr, "undetected error, invalid tchook create arguments") - os.Exit(-1) + common.Error(errors.New("undetected error, invalid tchook create arguments")) } if !errors.Is(err, syscall.EINVAL) { - fmt.Fprintf(os.Stderr, "unexpected wrapped error received, expected EINVAL\n") - os.Exit(-1) + common.Error(fmt.Errorf("unexpected wrapped error received, expected EINVAL: %w", err)) } } diff --git a/selftest/getbtffdbyid/go.mod b/selftest/getbtffdbyid/go.mod index e4b855d8..f09c5c7d 100644 --- a/selftest/getbtffdbyid/go.mod +++ b/selftest/getbtffdbyid/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/getbtffdbyid go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/getbtffdbyid/go.sum b/selftest/getbtffdbyid/go.sum index 5496456e..964bd12d 100644 --- a/selftest/getbtffdbyid/go.sum +++ b/selftest/getbtffdbyid/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/getbtffdbyid/main.go b/selftest/getbtffdbyid/main.go index e5ed9b9e..96f9ffae 100644 --- a/selftest/getbtffdbyid/main.go +++ b/selftest/getbtffdbyid/main.go @@ -3,41 +3,41 @@ package main import "C" import ( - "log" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } // Use the "inner_array_proto" map BTF ID to create a new map with the same // BTF type. innerArrayProto, err := bpfModule.GetMap("inner_array_proto") if err != nil { - log.Fatal(err) + common.Error(err) } optsProto, err := bpf.GetMapInfoByFD(innerArrayProto.FileDescriptor()) if err != nil { - log.Fatal(err) + common.Error(err) } // The "inner_array_proto" map is a BTF map, so its ID can be used to create // a new map with the same BTF type. btfFD, err := bpf.GetBTFFDByID(optsProto.BTFID) if err != nil { - log.Fatal(err) + common.Error(err) } createOpts := &bpf.BPFMapCreateOpts{ @@ -45,7 +45,7 @@ func main() { } innerArray, err := bpf.CreateMap(bpf.MapTypeArray, "inner_array", 4, 4, 1, createOpts) if err != nil { - log.Fatal(err) + common.Error(err) } // Save an element in the "inner_array" map. @@ -55,6 +55,6 @@ func main() { valueUnsafe := unsafe.Pointer(&value) err = innerArray.Update(keyUnsafe, valueUnsafe) if err != nil { - log.Fatal(err) + common.Error(err) } } diff --git a/selftest/global-variable/go.mod b/selftest/global-variable/go.mod index 9ea64497..cce383df 100644 --- a/selftest/global-variable/go.mod +++ b/selftest/global-variable/go.mod @@ -2,6 +2,11 @@ module github.com/aquasecurity/libbpfgo/selftest/global-variable go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/global-variable/go.sum b/selftest/global-variable/go.sum index 5496456e..964bd12d 100644 --- a/selftest/global-variable/go.sum +++ b/selftest/global-variable/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/global-variable/main.go b/selftest/global-variable/main.go index 25c00010..06ebc29b 100644 --- a/selftest/global-variable/main.go +++ b/selftest/global-variable/main.go @@ -4,20 +4,14 @@ import ( "bytes" "encoding/binary" "fmt" - "os" "reflect" - "runtime" "syscall" "time" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -func exitWithErr(err error) { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) -} - type Event struct { Sum uint64 A [6]byte @@ -31,7 +25,7 @@ type Config struct { func initGlobalVariables(bpfModule *bpf.Module, variables map[string]interface{}) { for name, value := range variables { if err := bpfModule.InitGlobalVariable(name, value); err != nil { - exitWithErr(err) + common.Error(err) } } } @@ -39,7 +33,7 @@ func initGlobalVariables(bpfModule *bpf.Module, variables map[string]interface{} func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - exitWithErr(err) + common.Error(err) } defer bpfModule.Close() @@ -54,22 +48,22 @@ func main() { }) if err := bpfModule.BPFLoadObject(); err != nil { - exitWithErr(err) + common.Error(err) } prog, err := bpfModule.GetProgram("kprobe__sys_mmap") if err != nil { - exitWithErr(err) + common.Error(err) } - funcName := fmt.Sprintf("__%s_sys_mmap", ksymArch()) + funcName := fmt.Sprintf("__%s_sys_mmap", common.KSymArch()) if _, err := prog.AttachKprobe(funcName); err != nil { - exitWithErr(err) + common.Error(err) } eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - exitWithErr(err) + common.Error(err) } rb.Poll(300) @@ -83,7 +77,7 @@ func main() { var event Event err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &event) if err != nil { - exitWithErr(err) + common.Error(err) } expect := Event{ @@ -91,21 +85,9 @@ func main() { A: [6]byte{'a', 'b'}, } if !reflect.DeepEqual(event, expect) { - fmt.Fprintf(os.Stderr, "want %v but got %v\n", expect, event) - os.Exit(1) + common.Error(fmt.Errorf("want %v but got %v", expect, event)) } rb.Stop() rb.Close() } - -func ksymArch() string { - switch runtime.GOARCH { - case "amd64": - return "x64" - case "arm64": - return "arm64" - default: - panic("unsupported architecture") - } -} diff --git a/selftest/iter/go.mod b/selftest/iter/go.mod index 8fad274e..b5b71f36 100644 --- a/selftest/iter/go.mod +++ b/selftest/iter/go.mod @@ -2,6 +2,11 @@ module github.com/aquasecurity/libbpfgo/selftest/iter go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/iter/go.sum b/selftest/iter/go.sum index 5496456e..964bd12d 100644 --- a/selftest/iter/go.sum +++ b/selftest/iter/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/iter/main.bpf.c b/selftest/iter/main.bpf.c index a677b214..dd205818 100644 --- a/selftest/iter/main.bpf.c +++ b/selftest/iter/main.bpf.c @@ -4,6 +4,8 @@ #include +const char sleep_comm[] = "sleep"; + SEC("iter/task") int iter__task(struct bpf_iter__task *ctx) { @@ -12,7 +14,14 @@ int iter__task(struct bpf_iter__task *ctx) if (task == NULL) return 0; - BPF_SEQ_PRINTF(seq, "%d\t%d\t%s\n", task->parent->pid, task->pid, task->comm); + // disregard all but "sleep" + const int sleep_comm_size = sizeof(sleep_comm); + for (int i = 0; i < sleep_comm_size; i++) { + if (task->comm[i] != sleep_comm[i]) + return 0; + } + + BPF_SEQ_PRINTF(seq, "%d\t%s\n", task->pid, task->comm); return 0; } diff --git a/selftest/iter/main.go b/selftest/iter/main.go index e95501e2..544ba1e8 100644 --- a/selftest/iter/main.go +++ b/selftest/iter/main.go @@ -5,89 +5,105 @@ import "C" import ( "bufio" "fmt" + "log" "os" "os/exec" "strconv" "strings" - "syscall" + "time" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -func exitWithErr(err error) { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) -} - func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - exitWithErr(err) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - exitWithErr(err) + common.Error(err) } prog, err := bpfModule.GetProgram("iter__task") if err != nil { - exitWithErr(err) + common.Error(err) } link, err := prog.AttachIter(bpf.IterOpts{}) if err != nil { - exitWithErr(err) + common.Error(err) } - reader, err := link.Reader() - if err != nil { - exitWithErr(err) - } - defer reader.Close() + // Give the iterator a moment to be fully set up before starting processes + log.Printf("Sleeping 1 second to ensure iterator is ready...") + time.Sleep(1 * time.Second) totalExecs := 10 - thisPid := syscall.Getpid() pids := make(map[int]*os.Process, 0) + + // Start processes with predictable running time to ensure they're captured + log.Printf("Starting %d sleep processes...", totalExecs) for i := 0; i < totalExecs; i++ { - cmd := exec.Command("ping", "-w", "10", "0.0.0.0") + cmd := exec.Command("sleep", "10") err := cmd.Start() if err != nil { - exitWithErr(err) + common.Error(err) } pids[cmd.Process.Pid] = cmd.Process + log.Printf("Started sleep process with PID %d", cmd.Process.Pid) + } + defer func() { + // Clean up any remaining processes + for _, proc := range pids { + _ = proc.Kill() + } + }() + + // Give processes time to start and be registered + log.Printf("Sleeping for 5 seconds to allow processes to register...") + time.Sleep(5 * time.Second) + + reader, err := link.Reader() + if err != nil { + common.Error(err) } + defer reader.Close() numberOfMatches := 0 scanner := bufio.NewScanner(reader) + log.Println("Reading iterator output:") for scanner.Scan() { - fields := strings.Split(scanner.Text(), "\t") - if len(fields) != 3 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") + line := scanner.Text() + fields := strings.Split(line, "\t") + if len(fields) != 2 { + common.Error(fmt.Errorf("invalid data retrieved: %s", line)) } - if fields[2] == "ping" { - ppid, err := strconv.Atoi(fields[0]) - if err != nil { - exitWithErr(err) - } - pid, err := strconv.Atoi(fields[1]) + + log.Printf("[iter] %s", line) + if fields[1] == "sleep" { + pid, err := strconv.Atoi(fields[0]) if err != nil { - exitWithErr(err) + common.Error(err) } if proc, found := pids[pid]; found { - if ppid == thisPid { - numberOfMatches++ - proc.Kill() - } + numberOfMatches++ + log.Printf("Matched sleep process: pid=%d", pid) + _ = proc.Kill() // Kill the sleep process } } if numberOfMatches == totalExecs { break } } + if numberOfMatches != totalExecs { err := fmt.Errorf("expect numberOfMatches == %d but got %d", totalExecs, numberOfMatches) - exitWithErr(err) + common.Error(err) + } else { + log.Printf("All %d sleep processes matched successfully", totalExecs) } } diff --git a/selftest/iterators/go.mod b/selftest/iterators/go.mod index d77f98e7..fd241f6f 100644 --- a/selftest/iterators/go.mod +++ b/selftest/iterators/go.mod @@ -2,6 +2,11 @@ module github.com/aquasecurity/libbpfgo/selftest/iterators go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/iterators/go.sum b/selftest/iterators/go.sum index 5496456e..964bd12d 100644 --- a/selftest/iterators/go.sum +++ b/selftest/iterators/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/iterators/main.go b/selftest/iterators/main.go index 1771707b..636c1c15 100644 --- a/selftest/iterators/main.go +++ b/selftest/iterators/main.go @@ -3,12 +3,11 @@ package main import "C" import ( - "encoding/binary" "fmt" - "os" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) const ( @@ -22,16 +21,14 @@ var one = 1 func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() bpfModule.BPFLoadObject() numbers, err := bpfModule.GetMap("numbers") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } testMap := map[uint32]uint32{} @@ -42,49 +39,32 @@ func main() { value := unsafe.Pointer(&one) err = numbers.Update(index, value) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } } iterator := numbers.Iterator() for iterator.Next() { keyBytes := iterator.Key() - key := determineHostByteOrder().Uint32(keyBytes) + key := common.ByteOrder().Uint32(keyBytes) val, ok := testMap[key] if !ok { - fmt.Fprintln(os.Stderr, "Unknown key was found: %d", val) - os.Exit(-1) + common.Error(fmt.Errorf("unknown key was found: %d", key)) } if val != 1 { - fmt.Fprintln(os.Stderr, "Corrupted value: %d", val) - os.Exit(-1) + common.Error(fmt.Errorf("corrupted value: %d", val)) } testMap[key] = checked } if iterator.Err() != nil { - fmt.Fprintf(os.Stderr, "iterator error: %v\n", iterator.Err()) - os.Exit(-1) + common.Error(fmt.Errorf("iterator error: %v", iterator.Err())) } // make sure it got everything for k, v := range testMap { if v != 2 { - fmt.Fprintln(os.Stderr, "Key was not found: ", k) - os.Exit(-1) + common.Error(fmt.Errorf("key was not found: %d", k)) } } } - -func determineHostByteOrder() binary.ByteOrder { - var i int32 = 0x01020304 - u := unsafe.Pointer(&i) - pb := (*byte)(u) - b := *pb - if b == 0x04 { - return binary.LittleEndian - } - - return binary.BigEndian -} diff --git a/selftest/log-callbacks/go.mod b/selftest/log-callbacks/go.mod index 7ba42200..41740de4 100644 --- a/selftest/log-callbacks/go.mod +++ b/selftest/log-callbacks/go.mod @@ -2,6 +2,11 @@ module github.com/aquasecurity/libbpfgo/selftest/log-callbacks go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/log-callbacks/go.sum b/selftest/log-callbacks/go.sum index 5496456e..964bd12d 100644 --- a/selftest/log-callbacks/go.sum +++ b/selftest/log-callbacks/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/log-callbacks/main.go b/selftest/log-callbacks/main.go index dea52868..221aa4f9 100644 --- a/selftest/log-callbacks/main.go +++ b/selftest/log-callbacks/main.go @@ -3,12 +3,12 @@ package main import "C" import ( - "os" "strings" "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) var logOutput []string @@ -34,15 +34,12 @@ func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } bpfModule.Close() if len(logOutput) != 1 { - fmt.Fprintln(os.Stderr, fmt.Sprintf("Log output should contain only one output matching the string: %s", filterMatch)) - fmt.Fprintln(os.Stderr, fmt.Sprintf("Log output: %v", logOutput)) - os.Exit(-1) + common.Error(fmt.Errorf("log output should contain only one output matching the string %s: %v", filterMatch, logOutput)) } // clean logOutput @@ -62,14 +59,11 @@ func main() { bpfModule, err = bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } bpfModule.Close() if len(logOutput) != 0 { - fmt.Fprintln(os.Stderr, "Log output should be empty") - fmt.Fprintln(os.Stderr, fmt.Sprintf("Log output: %v", logOutput)) - os.Exit(-1) + common.Error(fmt.Errorf("log output should be empty: %v", logOutput)) } } diff --git a/selftest/map-autocreate/go.mod b/selftest/map-autocreate/go.mod index e4b855d8..26c2ec13 100644 --- a/selftest/map-autocreate/go.mod +++ b/selftest/map-autocreate/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-autocreate go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-autocreate/go.sum b/selftest/map-autocreate/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-autocreate/go.sum +++ b/selftest/map-autocreate/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-autocreate/main.go b/selftest/map-autocreate/main.go index f863a0af..ddae4c3a 100644 --- a/selftest/map-autocreate/main.go +++ b/selftest/map-autocreate/main.go @@ -3,56 +3,57 @@ package main import "C" import ( - "log" + "errors" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModuleWithAutocreate, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModuleWithAutocreate.Close() testerMapWithAutocreate, err := bpfModuleWithAutocreate.GetMap("tester") if err != nil { - log.Fatal(err) + common.Error(err) } isAutocreate := testerMapWithAutocreate.Autocreate() if !isAutocreate { - log.Fatal("Autocreate is false") + common.Error(errors.New("autocreate is false")) } err = bpfModuleWithAutocreate.BPFLoadObject() if err == nil { - log.Fatal("Was able to load with a bad type of map") + common.Error(errors.New("was able to load with a bad type of map")) } bpfModuleWithoutAutocreate, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModuleWithoutAutocreate.Close() testerMapWithoutAutocreate, err := bpfModuleWithoutAutocreate.GetMap("tester") if err != nil { - log.Fatal(err) + common.Error(err) } err = testerMapWithoutAutocreate.SetAutocreate(false) if err != nil { - log.Fatal(err) + common.Error(err) } isAutocreate = testerMapWithoutAutocreate.Autocreate() if isAutocreate { - log.Fatal("Autocreate is true") + common.Error(errors.New("autocreate is true, expected false")) } err = bpfModuleWithoutAutocreate.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } } diff --git a/selftest/map-batch/go.mod b/selftest/map-batch/go.mod index e4b855d8..882783fb 100644 --- a/selftest/map-batch/go.mod +++ b/selftest/map-batch/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-batch go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-batch/go.sum b/selftest/map-batch/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-batch/go.sum +++ b/selftest/map-batch/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-batch/main.go b/selftest/map-batch/main.go index 32e576d2..60bb9758 100644 --- a/selftest/map-batch/main.go +++ b/selftest/map-batch/main.go @@ -4,19 +4,19 @@ import "C" import ( "errors" + "fmt" "log" "syscall" "unsafe" - "encoding/binary" - bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatalf("Failed to load BPF module: %v", err) + common.Error(fmt.Errorf("failed to load BPF module: %v", err)) } defer bpfModule.Close() @@ -24,7 +24,7 @@ func main() { testerMap, err := bpfModule.GetMap("tester") if err != nil { - log.Fatalf("Failed to get map: %v", err) + common.Error(fmt.Errorf("failed to get map: %v", err)) } // @@ -41,18 +41,18 @@ func main() { uint32(len(keys)), ) if err != nil { - log.Fatal(err) + common.Error(err) } if count != uint32(len(keys)) { - log.Fatalf("Failed to batch update all elements: %d/%d", count, len(keys)) + common.Error(fmt.Errorf("failed to batch update all elements: %d/%d", count, len(keys))) } val, err := testerMap.GetValue(unsafe.Pointer(&keys[0])) if err != nil { - log.Fatal(err) + common.Error(err) } - if endian().Uint32(val) != values[0] { - log.Fatalf("testerMap.GetValue returned %v, expected %v", val, values[0]) + if common.ByteOrder().Uint32(val) != values[0] { + common.Error(fmt.Errorf("testerMap.GetValue returned %v, expected %v", val, values[0])) } // Test batch update. @@ -66,10 +66,10 @@ func main() { uint32(len(keysGreater)), ) if err != nil { - log.Fatal(err) + common.Error(err) } if count == uint32(len(keysGreater)) { - log.Fatalf("count %d should be less than len(keysGreater) %d", count, len(keysGreater)) + common.Error(fmt.Errorf("count %d should be less than len(keysGreater) %d", count, len(keysGreater))) } // @@ -89,16 +89,16 @@ func main() { uint32(stepSize), ) if err != nil { - log.Fatalf("Failed to batch lookup: %v", err) + common.Error(fmt.Errorf("failed to batch lookup: %v", err)) } startKeyPtr = unsafe.Pointer(&nextKey) for i, val := range vals { - actual := endian().Uint32(val) + actual := common.ByteOrder().Uint32(val) expected := batchKeys[i] + 1 if actual != expected { - log.Fatalf("testerMap.GetValueBatch returned %v, expected %v", actual, expected) + common.Error(fmt.Errorf("testerMap.GetValueBatch returned %v, expected %v", actual, expected)) } } } @@ -115,10 +115,10 @@ func main() { uint32(len(notAllAvailableKeys)), ) if err != nil { - log.Fatal(err) + common.Error(err) } if count != expectedCount { - log.Fatalf("Failed to partial batch lookup elements: %d/%d", count, len(keys)) + common.Error(fmt.Errorf("failed to partial batch lookup elements: %d/%d", count, expectedCount)) } // Test batch lookup passing a count that is greater than the number of @@ -133,7 +133,7 @@ func main() { uint32(greaterCount), ) if err != nil { - log.Fatal(err) + common.Error(err) } // @@ -169,16 +169,16 @@ func main() { step++ continue } - log.Fatal(err) + common.Error(err) } log.Printf("testerMap.GetValueAndDeleteBatch deleted element(s): %d", count) totalKeysToDelete -= count for i, val := range vals { - actual := endian().Uint32(val) + actual := common.ByteOrder().Uint32(val) expected := deleteKeys[i] + 1 if actual != expected { - log.Fatalf("testerMap.GetValueAndDeleteBatch returned %v, expected %v", actual, expected) + common.Error(fmt.Errorf("testerMap.GetValueAndDeleteBatch returned %v, expected %v", actual, expected)) } } } @@ -198,7 +198,7 @@ func main() { uint32(len(keys)), ) if err != nil { - log.Fatal(err) + common.Error(err) } // map is full again. @@ -210,16 +210,16 @@ func main() { uint32(len(keys)+10), ) if err != nil { - log.Fatal(err) + common.Error(err) } if count != uint32(len(keys)) { - log.Fatalf("testerMap.DeleteKeyBatch failed: count=%d", count) + common.Error(fmt.Errorf("testerMap.DeleteKeyBatch failed: count=%d", count)) } // Ensure value is no longer there. v, _ := testerMap.GetValue(unsafe.Pointer(&keys[0])) if len(v) != 0 { - log.Fatalf("testerMap.GetValue was expected to fail, but succeeded") + common.Error(errors.New("testerMap.GetValue was expected to fail, but succeeded")) } // map is empty again. @@ -231,7 +231,7 @@ func main() { uint32(len(keys)), ) if err != nil { - log.Fatal(err) + common.Error(err) } // Test batch delete. @@ -242,10 +242,10 @@ func main() { uint32(fewer), ) if err != nil { - log.Fatal(err) + common.Error(err) } if count != uint32(fewer) { - log.Fatalf("testerMap.DeleteKeyBatch failed: count=%d", count) + common.Error(fmt.Errorf("testerMap.DeleteKeyBatch failed: count=%d", count)) } // map contains only 1 key-value pair. @@ -257,7 +257,7 @@ func main() { uint32(len(keys)), ) if err != nil { - log.Fatal(err) + common.Error(err) } // @@ -271,7 +271,7 @@ func main() { uint32(len(keys)), ) if err != nil { - log.Fatal(err) + common.Error(err) } // Test GetNextKey. @@ -282,14 +282,14 @@ func main() { err := testerMap.GetNextKey(keyPtr, keyPtr) if err != nil { if !errors.Is(err, syscall.ENOENT) { - log.Fatalf("testerMap.GetNextKey failed: err=%v", err) + common.Error(fmt.Errorf("testerMap.GetNextKey failed: err=%v", err)) } break } keyCnt++ } if keyCnt != len(keys) { - log.Fatalf("testerMap.GetNextKey failed: count=%d", keyCnt) + common.Error(fmt.Errorf("testerMap.GetNextKey failed: count=%d", keyCnt)) } // @@ -300,11 +300,11 @@ func main() { for i, key := range keys { val, err := testerMap.GetValueAndDeleteKey(unsafe.Pointer(&key)) if err != nil { - log.Fatalf("testerMap.GetValueAndDelete failed: err=%v", err) + common.Error(fmt.Errorf("testerMap.GetValueAndDelete failed: err=%v", err)) } - if endian().Uint32(val) != values[i] { - log.Fatalf("testerMpa.GetValueAndDetele failed: val=%d", endian().Uint32(val)) + if common.ByteOrder().Uint32(val) != values[i] { + common.Error(fmt.Errorf("testerMap.GetValueAndDelete failed: val=%d", common.ByteOrder().Uint32(val))) } } @@ -312,18 +312,6 @@ func main() { key = 0 err = testerMap.GetNextKey(keyPtr, keyPtr) if !errors.Is(err, syscall.ENOENT) { - log.Fatalf("testerMap.GetValueAndDeleteKey failed: err=%v", err) + common.Error(fmt.Errorf("testerMap.GetValueAndDeleteKey failed: err=%v", err)) } } - -func endian() binary.ByteOrder { - var i int32 = 0x01020304 - u := unsafe.Pointer(&i) - pb := (*byte)(u) - b := *pb - if b == 0x04 { - return binary.LittleEndian - } - - return binary.BigEndian -} diff --git a/selftest/map-getbyid/go.mod b/selftest/map-getbyid/go.mod index e4b855d8..44ab0fb9 100644 --- a/selftest/map-getbyid/go.mod +++ b/selftest/map-getbyid/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-getbyid go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-getbyid/go.sum b/selftest/map-getbyid/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-getbyid/go.sum +++ b/selftest/map-getbyid/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-getbyid/main.go b/selftest/map-getbyid/main.go index 9a283b85..467307ff 100644 --- a/selftest/map-getbyid/main.go +++ b/selftest/map-getbyid/main.go @@ -3,17 +3,18 @@ package main import "C" import ( - "encoding/binary" - "log" + "errors" + "fmt" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() @@ -21,35 +22,35 @@ func main() { testerMap, err := bpfModule.GetMap("tester") if err != nil { - log.Fatal(err) + common.Error(err) } // Get info about the "tester" map infoTester, err := bpf.GetMapInfoByFD(testerMap.FileDescriptor()) if err != nil { - log.Fatal(err) + common.Error(err) } // Get a new BPFMapLow object pointing to the "tester" map testerMapLow, err := bpf.GetMapByID(infoTester.ID) if err != nil { - log.Fatal(err) + common.Error(err) } if testerMapLow.Name() != testerMap.Name() { - log.Fatal("Names do not match") + common.Error(errors.New("names do not match")) } if testerMapLow.Type() != testerMap.Type() { - log.Fatal("Types do not match") + common.Error(errors.New("types do not match")) } if testerMapLow.MaxEntries() != testerMap.MaxEntries() { - log.Fatal("Max entries do not match") + common.Error(errors.New("max entries do not match")) } if testerMapLow.KeySize() != testerMap.KeySize() { - log.Fatal("Key sizes do not match") + common.Error(errors.New("key sizes do not match")) } if testerMapLow.ValueSize() != testerMap.ValueSize() { - log.Fatal("Value sizes do not match") + common.Error(errors.New("value sizes do not match")) } // Save a value in the "tester" map using the original BPFMap object @@ -59,27 +60,16 @@ func main() { value1Unsafe := unsafe.Pointer(&value1) err = testerMap.Update(key1Unsafe, value1Unsafe) if err != nil { - log.Fatal(err) + common.Error(err) } // Get the value from the "tester" map using the new BPFMapLow object v, err := testerMapLow.GetValue(key1Unsafe) if err != nil { - log.Fatal(err) + common.Error(err) } - if endian().Uint32(v) != value1 { - log.Fatal("Value mismatch") + gotValue := common.ByteOrder().Uint32(v) + if gotValue != value1 { + common.Error(fmt.Errorf("value mismatch: %d != %d", gotValue, value1)) } } - -func endian() binary.ByteOrder { - var i int32 = 0x01020304 - u := unsafe.Pointer(&i) - pb := (*byte)(u) - b := *pb - if b == 0x04 { - return binary.LittleEndian - } - - return binary.BigEndian -} diff --git a/selftest/map-getfdbyid/go.mod b/selftest/map-getfdbyid/go.mod index e4b855d8..40ec02c2 100644 --- a/selftest/map-getfdbyid/go.mod +++ b/selftest/map-getfdbyid/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-getfdbyid go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-getfdbyid/go.sum b/selftest/map-getfdbyid/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-getfdbyid/go.sum +++ b/selftest/map-getfdbyid/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-getfdbyid/main.go b/selftest/map-getfdbyid/main.go index 13401b20..b01225a5 100644 --- a/selftest/map-getfdbyid/main.go +++ b/selftest/map-getfdbyid/main.go @@ -3,15 +3,17 @@ package main import "C" import ( - "log" + "errors" + "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() @@ -19,70 +21,70 @@ func main() { testerMap, err := bpfModule.GetMap("tester") if err != nil { - log.Fatal(err) + common.Error(err) } // Get info about the "tester" map infoTester, err := bpf.GetMapInfoByFD(testerMap.FileDescriptor()) if err != nil { - log.Fatal(err) + common.Error(err) } // Get a new FD pointing to the "tester" map newFD, err := bpf.GetMapFDByID(infoTester.ID) if err != nil { - log.Fatal(err) + common.Error(err) } if newFD == testerMap.FileDescriptor() { - log.Fatal("New FD should be different from the old one") + common.Error(errors.New("new FD should be different from the old one")) } // Get info about the "tester" map again, this time using the new FD infoNewFD, err := bpf.GetMapInfoByFD(newFD) if err != nil { - log.Fatal(err) + common.Error(err) } if infoTester.Type != infoNewFD.Type { - log.Fatal("Types do not match") + common.Error(fmt.Errorf("types do not match: %s != %s", infoTester.Type, infoNewFD.Type)) } if infoTester.ID != infoNewFD.ID { - log.Fatal("IDs do not match") + common.Error(fmt.Errorf("IDs do not match: %d != %d", infoTester.ID, infoNewFD.ID)) } if infoTester.KeySize != infoNewFD.KeySize { - log.Fatal("Key sizes do not match") + common.Error(fmt.Errorf("key sizes do not match: %d != %d", infoTester.KeySize, infoNewFD.KeySize)) } if infoTester.ValueSize != infoNewFD.ValueSize { - log.Fatal("Value sizes do not match") + common.Error(fmt.Errorf("value sizes do not match: %d != %d", infoTester.ValueSize, infoNewFD.ValueSize)) } if infoTester.MaxEntries != infoNewFD.MaxEntries { - log.Fatal("Max entries do not match") + common.Error(fmt.Errorf("max entries do not match: %d != %d", infoTester.MaxEntries, infoNewFD.MaxEntries)) } if infoTester.MapFlags != infoNewFD.MapFlags { - log.Fatal("Map flags do not match") + common.Error(fmt.Errorf("map flags do not match: %d != %d", infoTester.MapFlags, infoNewFD.MapFlags)) } if infoTester.Name != infoNewFD.Name { - log.Fatal("Names do not match") + common.Error(fmt.Errorf("names do not match: %s != %s", infoTester.Name, infoNewFD.Name)) } if infoTester.IfIndex != infoNewFD.IfIndex { - log.Fatal("Ifindexes do not match") + common.Error(fmt.Errorf("ifindexes do not match: %d != %d", infoTester.IfIndex, infoNewFD.IfIndex)) } if infoTester.NetnsDev != infoNewFD.NetnsDev { - log.Fatal("Netns do not match") + common.Error(fmt.Errorf("netns dev do not match: %d != %d", infoTester.NetnsDev, infoNewFD.NetnsDev)) } if infoTester.NetnsIno != infoNewFD.NetnsIno { - log.Fatal("Netns inodes do not match") + common.Error(fmt.Errorf("netns inodes do not match: %d != %d", infoTester.NetnsIno, infoNewFD.NetnsIno)) } if infoTester.BTFID != infoNewFD.BTFID { - log.Fatal("BTF IDs do not match") + common.Error(fmt.Errorf("BTF IDs do not match: %d != %d", infoTester.BTFID, infoNewFD.BTFID)) } if infoTester.BTFKeyTypeID != infoNewFD.BTFKeyTypeID { - log.Fatal("BTF key type IDs do not match") + common.Error(fmt.Errorf("BTF key type IDs do not match: %d != %d", infoTester.BTFKeyTypeID, infoNewFD.BTFKeyTypeID)) } if infoTester.BTFValueTypeID != infoNewFD.BTFValueTypeID { - log.Fatal("BTF value type IDs do not match") + common.Error(fmt.Errorf("BTF value type IDs do not match: %d != %d", infoTester.BTFValueTypeID, infoNewFD.BTFValueTypeID)) } if infoTester.MapExtra != infoNewFD.MapExtra { - log.Fatal("Map extras do not match") + common.Error(fmt.Errorf("map extras do not match: %v != %v", infoTester.MapExtra, infoNewFD.MapExtra)) } } diff --git a/selftest/map-getmapsbyname/go.mod b/selftest/map-getmapsbyname/go.mod index e4b855d8..7320fe77 100644 --- a/selftest/map-getmapsbyname/go.mod +++ b/selftest/map-getmapsbyname/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-getmapsbyname go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-getmapsbyname/go.sum b/selftest/map-getmapsbyname/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-getmapsbyname/go.sum +++ b/selftest/map-getmapsbyname/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-getmapsbyname/main.go b/selftest/map-getmapsbyname/main.go index d9cd8e8d..f911ef6b 100644 --- a/selftest/map-getmapsbyname/main.go +++ b/selftest/map-getmapsbyname/main.go @@ -3,11 +3,12 @@ package main import "C" import ( - "log" + "fmt" "syscall" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) const ( @@ -24,7 +25,7 @@ const ( func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() @@ -33,25 +34,25 @@ func main() { startId := uint32(0) notFoundMapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToNotFind, &startId) if len(notFoundMapsIDs) != 0 { - log.Fatalf("the %s map should not be found, but it was found with ids: %v", BPFMapNameToNotFind, notFoundMapsIDs) + common.Error(fmt.Errorf("the %s map should not be found, but it was found with ids: %v", BPFMapNameToNotFind, notFoundMapsIDs)) } startId = 0 bpfHashMapsIDs, err := bpf.GetMapsIDsByName(BPFHashMapNameToFind, &startId) if err != nil { - log.Fatal(err) + common.Error(err) } if len(bpfHashMapsIDs) == 0 { - log.Fatalf("the %s map should be found", BPFHashMapNameToFind) + common.Error(fmt.Errorf("the %s map should be found", BPFHashMapNameToFind)) } startId = 0 mapsIDs, err := bpf.GetMapsIDsByName(BPFMapNameToFind, &startId) if err != nil { - log.Fatal(err) + common.Error(err) } if len(mapsIDs) == 0 { - log.Fatalf("the %s map was not found", BPFMapNameToFind) + common.Error(fmt.Errorf("the %s map was not found", BPFMapNameToFind)) } // try to identify the map by its properties @@ -59,7 +60,7 @@ func main() { for _, id := range mapsIDs { bpfMap, err := bpf.GetMapByID(id) if err != nil { - log.Fatalf("the %s map with %d id was not found: %v", BPFMapNameToFind, id, err) + common.Error(fmt.Errorf("the %s map with %d id was not found: %v", BPFMapNameToFind, id, err)) } if bpfMap.Type() == BPFMapTypeToFind && @@ -70,13 +71,13 @@ func main() { similarMaps = append(similarMaps, bpfMap) } else { if err := syscall.Close(bpfMap.FileDescriptor()); err != nil { - log.Fatalf("failed to close the file descriptor of the %s map with %d id: %v", BPFMapNameToFind, id, err) + common.Error(fmt.Errorf("failed to close the file descriptor of the %s map with %d id: %v", BPFMapNameToFind, id, err)) } } } if len(similarMaps) == 0 { - log.Fatalf("no %s maps with the same properties found", BPFMapNameToFind) + common.Error(fmt.Errorf("no %s maps with the same properties found", BPFMapNameToFind)) } if len(similarMaps) > 1 { // This is a conundrum for the user, as they cannot decide which map to use @@ -91,6 +92,6 @@ func main() { key1 := uint32(0) value1 := uint32(55) if err := bpfMap.Update(unsafe.Pointer(&key1), unsafe.Pointer(&value1)); err != nil { - log.Fatal(err) + common.Error(err) } } diff --git a/selftest/map-innerinfo/go.mod b/selftest/map-innerinfo/go.mod index e4b855d8..1e915a5d 100644 --- a/selftest/map-innerinfo/go.mod +++ b/selftest/map-innerinfo/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-innerinfo go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-innerinfo/go.sum b/selftest/map-innerinfo/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-innerinfo/go.sum +++ b/selftest/map-innerinfo/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-innerinfo/main.go b/selftest/map-innerinfo/main.go index bd69a64a..ffc10c45 100644 --- a/selftest/map-innerinfo/main.go +++ b/selftest/map-innerinfo/main.go @@ -3,63 +3,65 @@ package main import "C" import ( - "log" + "errors" + "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() outerHash, err := bpfModule.GetMap("outer_hash") if err != nil { - log.Fatal(err) + common.Error(err) } // Retrieve an inner map prototype information from the outer map. innerInfo, err := outerHash.InnerMapInfo() if err != nil { - log.Fatal(err) + common.Error(err) } if innerInfo.Name != "outer_hash.inner" { - log.Fatal("inner prototype name should be 'outer_hash.inner'") + common.Error(fmt.Errorf("inner prototype name should be 'outer_hash.inner': %s", innerInfo.Name)) } if innerInfo.Type != bpf.MapTypeArray { - log.Fatal("inner prototype type should be MapTypeArray") + common.Error(fmt.Errorf("inner prototype type should be MapTypeArray: %s", innerInfo.Type)) } if innerInfo.MaxEntries != 1 { - log.Fatal("inner prototype max entries should be 1") + common.Error(fmt.Errorf("inner prototype max entries should be 1: %d", innerInfo.MaxEntries)) } if innerInfo.KeySize != 4 { - log.Fatal("inner prototype key size should be 4") + common.Error(fmt.Errorf("inner prototype key size should be 4: %d", innerInfo.KeySize)) } if innerInfo.ValueSize != 4 { - log.Fatal("inner prototype value size should be 4") + common.Error(fmt.Errorf("inner prototype value size should be 4: %d", innerInfo.ValueSize)) } if innerInfo.MapFlags != 0 { - log.Fatal("inner prototype map flags should be 0") + common.Error(fmt.Errorf("inner prototype map flags should be 0: %d", innerInfo.MapFlags)) } if innerInfo.IfIndex != 0 { - log.Fatal("inner prototype ifindex should be 0") + common.Error(fmt.Errorf("inner prototype ifindex should be 0: %d", innerInfo.IfIndex)) } if innerInfo.MapExtra != 0 { - log.Fatal("inner prototype map extra should be 0") + common.Error(fmt.Errorf("inner prototype map extra should be 0: %d", innerInfo.MapExtra)) } err = bpfModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } // Attempting to get inner map prototype information after the // object is loaded will fail. _, err = outerHash.InnerMapInfo() if err == nil { - log.Fatal("should fail after object is loaded") + common.Error(errors.New("should fail to get inner map info after object is loaded")) } } diff --git a/selftest/map-keysize/go.mod b/selftest/map-keysize/go.mod index e4b855d8..7c47f286 100644 --- a/selftest/map-keysize/go.mod +++ b/selftest/map-keysize/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-keysize go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-keysize/go.sum b/selftest/map-keysize/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-keysize/go.sum +++ b/selftest/map-keysize/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-keysize/main.go b/selftest/map-keysize/main.go index edbf2451..32f9c8df 100644 --- a/selftest/map-keysize/main.go +++ b/selftest/map-keysize/main.go @@ -3,36 +3,37 @@ package main import "C" import ( - "log" + "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() testerMap, err := bpfModule.GetMap("tester") if err != nil { - log.Fatal(err) + common.Error(err) } keySize := testerMap.KeySize() if keySize != 4 { - log.Fatal("keySize do not match") + common.Error(fmt.Errorf("keySize do not match, expected 4, got %d", keySize)) } err = testerMap.SetKeySize(8) if err != nil { - log.Fatal(err) + common.Error(err) } keySize = testerMap.KeySize() if keySize != 8 { - log.Fatal("keySize do not match") + common.Error(fmt.Errorf("keySize do not match, expected 8, got %d", keySize)) } bpfModule.BPFLoadObject() diff --git a/selftest/map-of-maps-outer-high-inner-high/go.mod b/selftest/map-of-maps-outer-high-inner-high/go.mod index e4b855d8..5db8fd2f 100644 --- a/selftest/map-of-maps-outer-high-inner-high/go.mod +++ b/selftest/map-of-maps-outer-high-inner-high/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-of-maps-outer-high-inner-high go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-of-maps-outer-high-inner-high/go.sum b/selftest/map-of-maps-outer-high-inner-high/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-of-maps-outer-high-inner-high/go.sum +++ b/selftest/map-of-maps-outer-high-inner-high/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-of-maps-outer-high-inner-high/main.go b/selftest/map-of-maps-outer-high-inner-high/main.go index 4431d461..7537ec38 100644 --- a/selftest/map-of-maps-outer-high-inner-high/main.go +++ b/selftest/map-of-maps-outer-high-inner-high/main.go @@ -3,17 +3,17 @@ package main import "C" import ( - "encoding/binary" - "log" + "fmt" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() @@ -21,17 +21,17 @@ func main() { // BPF object, we do not need to do anything before loading the object. err = bpfModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } outerHash, err := bpfModule.GetMap("outer_hash") if err != nil { - log.Fatal(err) + common.Error(err) } innerArray, err := bpfModule.GetMap("inner_array") if err != nil { - log.Fatal(err) + common.Error(err) } // Retrieve the "inner_array" map ID from the "outer_hash" map, @@ -40,22 +40,22 @@ func main() { key1Unsafe := unsafe.Pointer(&key1) innerMapIDBytes, err := outerHash.GetValue(key1Unsafe) if err != nil { - log.Fatal(err) + common.Error(err) } // Inner map ID retrieved from the outer map element. - innerMapID := endian().Uint32(innerMapIDBytes) + innerMapID := common.ByteOrder().Uint32(innerMapIDBytes) // Retrieve the "inner_array" map Info. - innerMapInfo, error := bpf.GetMapInfoByFD(innerArray.FileDescriptor()) - if error != nil { - log.Fatal(error) + innerMapInfo, err := bpf.GetMapInfoByFD(innerArray.FileDescriptor()) + if err != nil { + common.Error(err) } // Check if the inner map ID retrieved from the outer map matches the // inner map ID retrieved directly from the inner map. if innerMapInfo.ID != innerMapID { - log.Fatal("inner map ID does not match") + common.Error(fmt.Errorf("inner map ID does not match: expected %d, got %d", innerMapInfo.ID, innerMapID)) } // Save an element in the "inner_array" map. @@ -64,18 +64,6 @@ func main() { value1Unsafe := unsafe.Pointer(&value1) err = innerArray.Update(key1Unsafe, value1Unsafe) if err != nil { - log.Fatal(err) + common.Error(err) } } - -func endian() binary.ByteOrder { - var i int32 = 0x01020304 - u := unsafe.Pointer(&i) - pb := (*byte)(u) - b := *pb - if b == 0x04 { - return binary.LittleEndian - } - - return binary.BigEndian -} diff --git a/selftest/map-of-maps-outer-high-inner-low/go.mod b/selftest/map-of-maps-outer-high-inner-low/go.mod index e4b855d8..396feb8f 100644 --- a/selftest/map-of-maps-outer-high-inner-low/go.mod +++ b/selftest/map-of-maps-outer-high-inner-low/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-of-maps-outer-high-inner-low go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-of-maps-outer-high-inner-low/go.sum b/selftest/map-of-maps-outer-high-inner-low/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-of-maps-outer-high-inner-low/go.sum +++ b/selftest/map-of-maps-outer-high-inner-low/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-of-maps-outer-high-inner-low/main.go b/selftest/map-of-maps-outer-high-inner-low/main.go index e996dd24..5068a659 100644 --- a/selftest/map-of-maps-outer-high-inner-low/main.go +++ b/selftest/map-of-maps-outer-high-inner-low/main.go @@ -3,28 +3,28 @@ package main import "C" import ( - "encoding/binary" - "log" + "fmt" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() outerHash, err := bpfModule.GetMap("outer_hash") if err != nil { - log.Fatal(err) + common.Error(err) } innerArray, err := bpf.CreateMap(bpf.MapTypeArray, "inner_array", 4, 4, 1, nil) if err != nil { - log.Fatal(err) + common.Error(err) } // As the "outer_hash" map does not have an inner map prototype pre-allocated, @@ -33,12 +33,12 @@ func main() { // fail to load. The template map can be removed after the object is loaded. err = outerHash.SetInnerMap(innerArray.FileDescriptor()) if err != nil { - log.Fatal(err) + common.Error(err) } err = bpfModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } // Save the inner map in the "outer_hash" map, using the hash key 1917. @@ -50,7 +50,7 @@ func main() { valueUnsafe := unsafe.Pointer(&value) err = outerHash.Update(keyUnsafe, valueUnsafe) if err != nil { - log.Fatal(err) + common.Error(err) } // Retrieve the value of the previous saved element from the "outer_hash" map, @@ -59,22 +59,22 @@ func main() { keyUnsafe = unsafe.Pointer(&key) innerMapIDBytes, err := outerHash.GetValue(keyUnsafe) // "inner_array" ID if err != nil { - log.Fatal(err) + common.Error(err) } // Inner map ID retrieved from the outer map element. - innerMapID := endian().Uint32(innerMapIDBytes) + innerMapID := common.ByteOrder().Uint32(innerMapIDBytes) // Retrieve the "inner_array" map Info. - innerMapInfo, error := bpf.GetMapInfoByFD(innerArray.FileDescriptor()) - if error != nil { - log.Fatal(error) + innerMapInfo, err := bpf.GetMapInfoByFD(innerArray.FileDescriptor()) + if err != nil { + common.Error(err) } // Check if the inner map ID retrieved from the outer map matches the // inner map ID retrieved directly from the inner map. if innerMapInfo.ID != innerMapID { - log.Fatal("inner map ID does not match") + common.Error(fmt.Errorf("inner map ID does not match: %d != %d", innerMapInfo.ID, innerMapID)) } // Save an element in the "inner_array" map. @@ -82,18 +82,6 @@ func main() { value = uint32(191711) err = innerArray.Update(keyUnsafe, valueUnsafe) if err != nil { - log.Fatal(err) + common.Error(err) } } - -func endian() binary.ByteOrder { - var i int32 = 0x01020304 - u := unsafe.Pointer(&i) - pb := (*byte)(u) - b := *pb - if b == 0x04 { - return binary.LittleEndian - } - - return binary.BigEndian -} diff --git a/selftest/map-of-maps-outer-low-inner-low/go.mod b/selftest/map-of-maps-outer-low-inner-low/go.mod index e4b855d8..f76b039f 100644 --- a/selftest/map-of-maps-outer-low-inner-low/go.mod +++ b/selftest/map-of-maps-outer-low-inner-low/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-of-maps-outer-low-inner-low go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-of-maps-outer-low-inner-low/go.sum b/selftest/map-of-maps-outer-low-inner-low/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-of-maps-outer-low-inner-low/go.sum +++ b/selftest/map-of-maps-outer-low-inner-low/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-of-maps-outer-low-inner-low/main.go b/selftest/map-of-maps-outer-low-inner-low/main.go index 45de7188..baa125d1 100644 --- a/selftest/map-of-maps-outer-low-inner-low/main.go +++ b/selftest/map-of-maps-outer-low-inner-low/main.go @@ -3,28 +3,27 @@ package main import "C" import ( - "encoding/binary" - "log" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } innerArray, err := bpf.CreateMap(bpf.MapTypeArray, "inner_array", 4, 4, 1, nil) if err != nil { - log.Fatal(err) + common.Error(err) } // Create the "outer_hash" map, using the "inner_array" map as a prototype. @@ -33,7 +32,7 @@ func main() { } outerHash, err := bpf.CreateMap(bpf.MapTypeHash, "outer_hash", 4, 4, 1, &opts) if err != nil { - log.Fatal(err) + common.Error(err) } // Save the inner map in the "outer_hash" map, using the hash key 1917. @@ -45,7 +44,7 @@ func main() { value1Unsafe := unsafe.Pointer(&value1) err = outerHash.Update(key1Unsafe, value1Unsafe) if err != nil { - log.Fatal(err) + common.Error(err) } // Save an element in the "inner_array" map. @@ -54,18 +53,6 @@ func main() { value1Unsafe = unsafe.Pointer(&value1) err = innerArray.Update(key1Unsafe, value1Unsafe) if err != nil { - log.Fatal(err) + common.Error(err) } } - -func endian() binary.ByteOrder { - var i int32 = 0x01020304 - u := unsafe.Pointer(&i) - pb := (*byte)(u) - b := *pb - if b == 0x04 { - return binary.LittleEndian - } - - return binary.BigEndian -} diff --git a/selftest/map-pin-info/go.mod b/selftest/map-pin-info/go.mod index 12f3e9ca..75a5ab68 100644 --- a/selftest/map-pin-info/go.mod +++ b/selftest/map-pin-info/go.mod @@ -2,6 +2,11 @@ module github.com/aquasecurity/libbpfgo/selftest/map-pin-info go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-pin-info/go.sum b/selftest/map-pin-info/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-pin-info/go.sum +++ b/selftest/map-pin-info/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-pin-info/main.go b/selftest/map-pin-info/main.go index 417d96f6..8c2145b7 100644 --- a/selftest/map-pin-info/main.go +++ b/selftest/map-pin-info/main.go @@ -4,9 +4,9 @@ import "C" import ( "fmt" - "os" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func getSupposedPinPath(m *bpf.BPFMap) string { @@ -16,8 +16,7 @@ func getSupposedPinPath(m *bpf.BPFMap) string { func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() @@ -25,8 +24,7 @@ func main() { pinnedMap, err := bpfModule.GetMap("pinned_map") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } var supposedPinPath = getSupposedPinPath(pinnedMap) var actualPinPath string @@ -34,31 +32,22 @@ func main() { defer pinnedMap.Unpin(supposedPinPath) if !pinnedMap.IsPinned() { - fmt.Fprintf(os.Stderr, - "IsPinned() returned 'false' when map %s should be pinned\n", - pinnedMap.GetName()) - os.Exit(-1) + common.Error(fmt.Errorf("IsPinned() returned 'false' when map %s should be pinned", pinnedMap.Name())) } - actualPinPath = pinnedMap.GetPinPath() + actualPinPath = pinnedMap.PinPath() if actualPinPath != supposedPinPath { - fmt.Fprintf(os.Stderr, - "GetPinPath() returned %s when should be %s\n", - actualPinPath, supposedPinPath) - os.Exit(-1) + common.Error(fmt.Errorf("PinPath() returned %s when should be %s", + actualPinPath, supposedPinPath)) } notPinnedMap, err := bpfModule.GetMap("not_pinned_map") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if notPinnedMap.IsPinned() { - fmt.Fprintf(os.Stderr, - "IsPinned() returned 'true' when map %s should not be pinned\n", - pinnedMap.GetName()) - os.Exit(-1) + common.Error(fmt.Errorf("IsPinned() returned 'true' when map %s should not be pinned", notPinnedMap.Name())) } supposedPinPath = getSupposedPinPath(notPinnedMap) @@ -66,11 +55,9 @@ func main() { notPinnedMap.Pin(supposedPinPath) defer notPinnedMap.Unpin(supposedPinPath) - actualPinPath = notPinnedMap.GetPinPath() + actualPinPath = notPinnedMap.PinPath() if actualPinPath != supposedPinPath { - fmt.Fprintf(os.Stderr, - "GetPinPath() returned %s when should be %s\n", - actualPinPath, supposedPinPath) - os.Exit(-1) + common.Error(fmt.Errorf("PinPath() returned %s when should be %s", + actualPinPath, supposedPinPath)) } } diff --git a/selftest/map-setinner/go.mod b/selftest/map-setinner/go.mod index e4b855d8..7ddd42be 100644 --- a/selftest/map-setinner/go.mod +++ b/selftest/map-setinner/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/map-setinner go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-setinner/go.sum b/selftest/map-setinner/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-setinner/go.sum +++ b/selftest/map-setinner/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-setinner/main.go b/selftest/map-setinner/main.go index b406f6bc..b94f13a7 100644 --- a/selftest/map-setinner/main.go +++ b/selftest/map-setinner/main.go @@ -3,27 +3,28 @@ package main import "C" import ( - "log" + "errors" "syscall" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() outerHash, err := bpfModule.GetMap("outer_hash") if err != nil { - log.Fatal(err) + common.Error(err) } templateInnerMap, err := bpf.CreateMap(bpf.MapTypeHash, "template_inner_map", 4, 4, 420, nil) if err != nil { - log.Fatal(err) + common.Error(err) } // As the "outer_hash" map does not have an inner map prototype pre-allocated, @@ -32,12 +33,12 @@ func main() { // fail to load. The template map can be removed after the object is loaded. err = outerHash.SetInnerMap(templateInnerMap.FileDescriptor()) if err != nil { - log.Fatal(err) + common.Error(err) } err = bpfModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } // @@ -47,13 +48,13 @@ func main() { // Attempting to set inner map after the object is loaded will fail. err = outerHash.SetInnerMap(templateInnerMap.FileDescriptor()) if err == nil { - log.Fatal("should fail after object is loaded") + common.Error(errors.New("should fail after object is loaded")) } // If not needed anymore, remove the "template_inner_map", // freeing up resources. err = syscall.Close(templateInnerMap.FileDescriptor()) if err != nil { - log.Fatal(err) + common.Error(err) } } diff --git a/selftest/map-update/go.mod b/selftest/map-update/go.mod index e4b855d8..567d1cb0 100644 --- a/selftest/map-update/go.mod +++ b/selftest/map-update/go.mod @@ -2,6 +2,11 @@ module github.com/aquasecurity/libbpfgo/selftest/map-update go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/map-update/go.sum b/selftest/map-update/go.sum index 5496456e..964bd12d 100644 --- a/selftest/map-update/go.sum +++ b/selftest/map-update/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/map-update/main.go b/selftest/map-update/main.go index 23301b02..8c2c027d 100644 --- a/selftest/map-update/main.go +++ b/selftest/map-update/main.go @@ -3,8 +3,7 @@ package main import "C" import ( - "os" - "runtime" + "errors" "time" "unsafe" @@ -13,59 +12,37 @@ import ( "syscall" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -func resizeMap(module *bpf.Module, name string, size uint32) error { - m, err := module.GetMap("events") - if err != nil { - return err - } - - if err = m.Resize(size); err != nil { - return err - } - - if actual := m.GetMaxEntries(); actual != size { - return fmt.Errorf("map resize failed, expected %v, actual %v", size, actual) - } - - return nil -} - func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() - if err = resizeMap(bpfModule, "events", 8192); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + if err = common.ResizeMap(bpfModule, "events", 8192); err != nil { + common.Error(err) } bpfModule.BPFLoadObject() prog, err := bpfModule.GetProgram("kprobe__sys_mmap") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } testerMap, err := bpfModule.GetMap("tester") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if testerMap.Name() != "tester" { - fmt.Fprintln(os.Stderr, "wrong map") - os.Exit(-1) + common.Error(errors.New("wrong map name")) } if testerMap.Type() != bpf.MapTypeHash { - fmt.Fprintln(os.Stderr, "wrong map type") - os.Exit(-1) + common.Error(errors.New("wrong map type")) } key1 := uint32(1) @@ -80,19 +57,17 @@ func main() { value2Unsafe := unsafe.Pointer(&value2[0]) testerMap.Update(key2Unsafe, value2Unsafe) - funcName := fmt.Sprintf("__%s_sys_mmap", ksymArch()) + funcName := fmt.Sprintf("__%s_sys_mmap", common.KSymArch()) _, err = prog.AttachKprobe(funcName) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } eventsChannel := make(chan []byte) lostChannel := make(chan uint64) pb, err := bpfModule.InitPerfBuf("events", eventsChannel, lostChannel, 1) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } pb.Poll(300) @@ -105,27 +80,14 @@ func main() { ev := <-eventsChannel if binary.LittleEndian.Uint32(ev) != 50 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", ev)) } ev = <-eventsChannel if ev[0] != value2[0] || ev[1] != value2[1] || ev[2] != value2[2] { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", ev)) } pb.Stop() pb.Close() } - -func ksymArch() string { - switch runtime.GOARCH { - case "amd64": - return "x64" - case "arm64": - return "arm64" - default: - panic("unsupported architecture") - } -} diff --git a/selftest/module-attach-detach/go.mod b/selftest/module-attach-detach/go.mod index 97710baf..655f003a 100644 --- a/selftest/module-attach-detach/go.mod +++ b/selftest/module-attach-detach/go.mod @@ -2,8 +2,13 @@ module github.com/aquasecurity/libbpfgo/selftest/module-attach-detach go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ replace github.com/aquasecurity/libbpfgo/helpers => ../../helpers + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/module-attach-detach/go.sum b/selftest/module-attach-detach/go.sum index 5496456e..964bd12d 100644 --- a/selftest/module-attach-detach/go.sum +++ b/selftest/module-attach-detach/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/module-attach-detach/main.go b/selftest/module-attach-detach/main.go index c318a552..e5bb75a9 100644 --- a/selftest/module-attach-detach/main.go +++ b/selftest/module-attach-detach/main.go @@ -3,38 +3,33 @@ package main import "C" import ( - "os" - "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } // attach all programs err = bpfModule.AttachPrograms() if err != nil { - fmt.Fprintln(os.Stderr, fmt.Sprintf("attach programs failed: %s", err)) - os.Exit(-1) + common.Error(fmt.Errorf("attach programs failed: %s", err)) } // detach all programs err = bpfModule.DetachPrograms() if err != nil { - fmt.Fprintln(os.Stderr, fmt.Sprintf("detach programs failed: %s", err)) - os.Exit(-1) + common.Error(fmt.Errorf("detach programs failed: %s", err)) } } diff --git a/selftest/multiple-objects/go.mod b/selftest/multiple-objects/go.mod index d4920d84..a9a9bd83 100644 --- a/selftest/multiple-objects/go.mod +++ b/selftest/multiple-objects/go.mod @@ -1,9 +1,14 @@ -module github.com/aquasecurity/libbpfgo/selftest/tracing +module github.com/aquasecurity/libbpfgo/selftest/multiple-objects go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ replace github.com/aquasecurity/libbpfgo/helpers => ../../helpers + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/multiple-objects/go.sum b/selftest/multiple-objects/go.sum index 5496456e..964bd12d 100644 --- a/selftest/multiple-objects/go.sum +++ b/selftest/multiple-objects/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/multiple-objects/main.go b/selftest/multiple-objects/main.go index 8a8fed65..214826e2 100644 --- a/selftest/multiple-objects/main.go +++ b/selftest/multiple-objects/main.go @@ -4,82 +4,76 @@ import "C" import ( "encoding/binary" - "log" - "os" + "errors" "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { mapModule, err := bpf.NewModuleFromFile("map.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer mapModule.Close() firstModule, err := bpf.NewModuleFromFile("first.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer firstModule.Close() secondModule, err := bpf.NewModuleFromFile("second.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer secondModule.Close() err = mapModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } err = firstModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } err = secondModule.BPFLoadObject() if err != nil { - log.Fatal(err) + common.Error(err) } firstProgram, err := firstModule.GetProgram("openat_fentry") if err != nil { - log.Fatalf("couldn't get program1 %s\n", err) + common.Error(fmt.Errorf("couldn't get program1 %s", err)) } link1, err := firstProgram.AttachGeneric() if err != nil { - fmt.Println("couldn't attach prog") - os.Exit(-1) + common.Error(fmt.Errorf("couldn't attach prog1 %s", err)) } if link1.GetFd() == 0 { - os.Exit(-1) + common.Error(errors.New("link1 fd is 0")) } secondProgram, err := secondModule.GetProgram("mmap_fentry") if err != nil { - log.Fatalf("couldn't get program2 %s\n", err) + common.Error(fmt.Errorf("couldn't get program2 %s", err)) } link2, err := secondProgram.AttachGeneric() if err != nil { - fmt.Println("couldn't attach prog") - os.Exit(-1) + common.Error(fmt.Errorf("couldn't attach program2 %s", err)) } if link2.GetFd() == 0 { - os.Exit(-1) + common.Error(errors.New("link2 fd is 0")) } eventsChannel := make(chan []byte) ringBuf, err := mapModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Println("couldn't init ringbuffer") - os.Exit(-1) + common.Error(fmt.Errorf("couldn't init ringbuffer %s", err)) } ringBuf.Poll(300) gotOne, gotTwo := false, false @@ -99,7 +93,7 @@ thisloop: break thisloop } default: - log.Fatal("got invalid response from bpf") + common.Error(fmt.Errorf("got invalid event %d", binary.LittleEndian.Uint32(b))) } } } diff --git a/selftest/netns/go.mod b/selftest/netns/go.mod index 72a57bd7..48e1f100 100644 --- a/selftest/netns/go.mod +++ b/selftest/netns/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/netns go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/netns/go.sum b/selftest/netns/go.sum index 5496456e..964bd12d 100644 --- a/selftest/netns/go.sum +++ b/selftest/netns/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/netns/main.go b/selftest/netns/main.go index 24797971..9ad9474c 100644 --- a/selftest/netns/main.go +++ b/selftest/netns/main.go @@ -4,47 +4,43 @@ import "C" import ( "encoding/binary" + "errors" "fmt" "net" - "os" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } prog, err := bpfModule.GetProgram("sk_lookup__lookup") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } link, err := prog.AttachNetns("/proc/self/ns/net") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if link.GetFd() == 0 { - os.Exit(-1) + common.Error(errors.New("fd is 0")) } eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } rb.Poll(300) @@ -52,8 +48,7 @@ func main() { go func() { l, err := net.Listen("tcp", "127.0.0.1:") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } go func() { for { @@ -63,8 +58,7 @@ func main() { for i := 0; i < 10; i++ { c, err := net.Dial("tcp", l.Addr().String()) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } c.Write([]byte{0}) c.Close() @@ -75,8 +69,7 @@ recvLoop: for { b := <-eventsChannel if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid event data: %v", b)) } numberOfEventsReceived++ if numberOfEventsReceived > 5 { diff --git a/selftest/object-iterator/go.mod b/selftest/object-iterator/go.mod index 72a57bd7..b419b28c 100644 --- a/selftest/object-iterator/go.mod +++ b/selftest/object-iterator/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/object-iterator go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/object-iterator/go.sum b/selftest/object-iterator/go.sum index 5496456e..964bd12d 100644 --- a/selftest/object-iterator/go.sum +++ b/selftest/object-iterator/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/object-iterator/main.go b/selftest/object-iterator/main.go index 0f5abd37..6d58e53f 100644 --- a/selftest/object-iterator/main.go +++ b/selftest/object-iterator/main.go @@ -3,25 +3,23 @@ package main import "C" import ( - "os" - + "errors" "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } iterator := bpfModule.Iterator() @@ -40,13 +38,11 @@ func main() { } if len(expectedProgramNames) != 3 { - fmt.Fprintln(os.Stderr, "did not iterate over expected programs") - os.Exit(-1) + common.Error(errors.New("did not iterate over expected programs")) } for k, v := range expectedProgramNames { if !v { - fmt.Fprintf(os.Stderr, "did not iterate over expected program: %s", k) - os.Exit(-1) + common.Error(fmt.Errorf("did not iterate over expected program: %s", k)) } } @@ -63,13 +59,11 @@ func main() { } if len(expectedMapNames) != 2 { - fmt.Fprintln(os.Stderr, "did not iterate over expected maps") - os.Exit(-1) + common.Error(errors.New("did not iterate over expected maps")) } for k, v := range expectedMapNames { if !v { - fmt.Fprintf(os.Stderr, "did not iterate over expected map: %s", k) - os.Exit(-1) + common.Error(fmt.Errorf("did not iterate over expected map: %s", k)) } } } diff --git a/selftest/percpu/go.mod b/selftest/percpu/go.mod index 72a57bd7..db30a661 100644 --- a/selftest/percpu/go.mod +++ b/selftest/percpu/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/percu go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/percpu/go.sum b/selftest/percpu/go.sum index 5496456e..964bd12d 100644 --- a/selftest/percpu/go.sum +++ b/selftest/percpu/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/percpu/main.go b/selftest/percpu/main.go index a772dfdb..7d0c6de2 100644 --- a/selftest/percpu/main.go +++ b/selftest/percpu/main.go @@ -4,43 +4,40 @@ import "C" import ( "encoding/binary" - "fmt" - "os" + "errors" + "log" "runtime" "syscall" "time" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } prog, err := bpfModule.GetProgram("mmap_fentry") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } link, err := prog.AttachGeneric() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if link.GetFd() == 0 { - os.Exit(-1) + common.Error(errors.New("link fd is 0")) } go func() { @@ -52,8 +49,7 @@ func main() { lostEventCounterMap, err := bpfModule.GetMap("percpu_hash") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } time.Sleep(time.Second * 2) @@ -61,13 +57,12 @@ func main() { values := make([]byte, 8*runtime.NumCPU()) err = lostEventCounterMap.GetValueReadInto(unsafe.Pointer(&key), &values) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } last := 0 for i := 0; i < runtime.NumCPU(); i++ { - fmt.Printf("CPU %d: %d\n", i, binary.LittleEndian.Uint32(values[last:last+8])) + log.Printf("CPU %d: %d\n", i, binary.LittleEndian.Uint32(values[last:last+8])) last += 8 } } diff --git a/selftest/perfbuffers/go.mod b/selftest/perfbuffers/go.mod index 72a57bd7..3d2dc603 100644 --- a/selftest/perfbuffers/go.mod +++ b/selftest/perfbuffers/go.mod @@ -2,6 +2,11 @@ module github.com/aquasecurity/libbpfgo/selftest/perfbuffers go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/perfbuffers/go.sum b/selftest/perfbuffers/go.sum index 5496456e..964bd12d 100644 --- a/selftest/perfbuffers/go.sum +++ b/selftest/perfbuffers/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/perfbuffers/main.go b/selftest/perfbuffers/main.go index c01dd26a..85ba7c9e 100644 --- a/selftest/perfbuffers/main.go +++ b/selftest/perfbuffers/main.go @@ -3,8 +3,6 @@ package main import "C" import ( - "os" - "runtime" "time" "encoding/binary" @@ -12,58 +10,37 @@ import ( "syscall" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -func resizeMap(module *bpf.Module, name string, size uint32) error { - m, err := module.GetMap("events") - if err != nil { - return err - } - - if err = m.Resize(size); err != nil { - return err - } - - if actual := m.GetMaxEntries(); actual != size { - return fmt.Errorf("map resize failed, expected %v, actual %v", size, actual) - } - - return nil -} - func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() - if err = resizeMap(bpfModule, "events", 8192); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + if err = common.ResizeMap(bpfModule, "events", 8192); err != nil { + common.Error(err) } bpfModule.BPFLoadObject() prog, err := bpfModule.GetProgram("kprobe__sys_mmap") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } - funcName := fmt.Sprintf("__%s_sys_mmap", ksymArch()) + funcName := fmt.Sprintf("__%s_sys_mmap", common.KSymArch()) _, err = prog.AttachKprobe(funcName) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } eventsChannel := make(chan []byte) lostChannel := make(chan uint64) pb, err := bpfModule.InitPerfBuf("events", eventsChannel, lostChannel, 1) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } pb.Poll(300) @@ -77,8 +54,7 @@ func main() { return case b := <-eventsChannel: if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } } } @@ -101,14 +77,3 @@ func main() { pb.Close() pb.Stop() } - -func ksymArch() string { - switch runtime.GOARCH { - case "amd64": - return "x64" - case "arm64": - return "arm64" - default: - panic("unsupported architecture") - } -} diff --git a/selftest/probe-features/go.mod b/selftest/probe-features/go.mod index 12f3e9ca..617cde1b 100644 --- a/selftest/probe-features/go.mod +++ b/selftest/probe-features/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-pin-info +module github.com/aquasecurity/libbpfgo/selftest/probe-features go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/probe-features/go.sum b/selftest/probe-features/go.sum index 5496456e..964bd12d 100644 --- a/selftest/probe-features/go.sum +++ b/selftest/probe-features/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/probe-features/main.go b/selftest/probe-features/main.go index caf264b7..2daf12ac 100644 --- a/selftest/probe-features/main.go +++ b/selftest/probe-features/main.go @@ -3,44 +3,38 @@ package main import "C" import ( - "fmt" - "log" - "os" + "errors" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() kprobeProg, err := bpfModule.GetProgram("kprobe__sys_mmap") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } err = kprobeProg.SetAutoload(false) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } isSupported, err := bpf.BPFProgramTypeIsSupported(bpf.BPFProgTypeKprobe) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if isSupported { err = kprobeProg.SetAutoload(true) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } } @@ -48,27 +42,24 @@ func main() { autoLoadOrig := kprobeProg.Autoload() kprobeProg.SetAutoload((!autoLoadOrig)) if kprobeProg.Autoload() == autoLoadOrig { - fmt.Println(os.Stderr, "auto load result wrong") - os.Exit(-1) + common.Error(errors.New("auto load result not changed")) } kprobeProg.SetAutoload((autoLoadOrig)) err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } isSupported, err = bpf.BPFMapTypeIsSupported(bpf.MapTypeHash) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if isSupported { _, err = bpf.CreateMap(bpf.MapTypeHash, "foobar", 4, 4, 420, nil) if err != nil { - log.Fatal(err) + common.Error(err) } } } diff --git a/selftest/probe-ringbuf-non-supported/go.mod b/selftest/probe-ringbuf-non-supported/go.mod index 12f3e9ca..2e75c1f1 100644 --- a/selftest/probe-ringbuf-non-supported/go.mod +++ b/selftest/probe-ringbuf-non-supported/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-pin-info +module github.com/aquasecurity/libbpfgo/selftest/probe-ringbuf-non-supported go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/probe-ringbuf-non-supported/go.sum b/selftest/probe-ringbuf-non-supported/go.sum index 01361f9f..964bd12d 100644 --- a/selftest/probe-ringbuf-non-supported/go.sum +++ b/selftest/probe-ringbuf-non-supported/go.sum @@ -6,7 +6,7 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -kernel.org/pub/linux/libs/security/libcap/cap v1.2.75 h1:f78VOelVeTl82xITLNCvtOQ6yHbrsL2X8lSs2kJ6laE= -kernel.org/pub/linux/libs/security/libcap/cap v1.2.75/go.mod h1:/0v7MsGCcYOmU5VrtrvcjgqCar2mdCr/STymAGfd57A= -kernel.org/pub/linux/libs/security/libcap/psx v1.2.76-rc1 h1:Tq5hYNtVgkIUTv+5BtOZjC5JB4s8TutijJE5vBaoW84= -kernel.org/pub/linux/libs/security/libcap/psx v1.2.76-rc1/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/probe-ringbuf-non-supported/main.go b/selftest/probe-ringbuf-non-supported/main.go index 639239ab..9c29ba39 100644 --- a/selftest/probe-ringbuf-non-supported/main.go +++ b/selftest/probe-ringbuf-non-supported/main.go @@ -1,19 +1,19 @@ package main import ( - "fmt" - "os" + "errors" + "log" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { // Should not be supported before 5.8 isSupported, err := bpf.BPFMapTypeIsSupported(bpf.MapTypeRingbuf) if err == nil || isSupported { - fmt.Fprintln(os.Stderr, "Ringbuf is supported unexpectedly or no error") - os.Exit(-1) + common.Error(errors.New("ringbuf is supported unexpectedly or no error")) } - fmt.Fprintln(os.Stdout, "Ringbuf is not supported as expected") + log.Println("Ringbuf is not supported as expected") } diff --git a/selftest/probe-ringbuf/go.mod b/selftest/probe-ringbuf/go.mod index 12f3e9ca..a2b745ff 100644 --- a/selftest/probe-ringbuf/go.mod +++ b/selftest/probe-ringbuf/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-pin-info +module github.com/aquasecurity/libbpfgo/selftest/probe-ringbuf go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/probe-ringbuf/go.sum b/selftest/probe-ringbuf/go.sum index 01361f9f..964bd12d 100644 --- a/selftest/probe-ringbuf/go.sum +++ b/selftest/probe-ringbuf/go.sum @@ -6,7 +6,7 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -kernel.org/pub/linux/libs/security/libcap/cap v1.2.75 h1:f78VOelVeTl82xITLNCvtOQ6yHbrsL2X8lSs2kJ6laE= -kernel.org/pub/linux/libs/security/libcap/cap v1.2.75/go.mod h1:/0v7MsGCcYOmU5VrtrvcjgqCar2mdCr/STymAGfd57A= -kernel.org/pub/linux/libs/security/libcap/psx v1.2.76-rc1 h1:Tq5hYNtVgkIUTv+5BtOZjC5JB4s8TutijJE5vBaoW84= -kernel.org/pub/linux/libs/security/libcap/psx v1.2.76-rc1/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/probe-ringbuf/main.go b/selftest/probe-ringbuf/main.go index ea89bb34..93df3d9b 100644 --- a/selftest/probe-ringbuf/main.go +++ b/selftest/probe-ringbuf/main.go @@ -3,37 +3,31 @@ package main import "C" import ( - "fmt" - "os" - bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } // Should be supported from 5.8 onwards isSupported, err := bpf.BPFMapTypeIsSupported(bpf.MapTypeRingbuf) if err != nil || !isSupported { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } eventsChannel1 := make(chan []byte) _, err = bpfModule.InitRingBuf("events1", eventsChannel1) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } } diff --git a/selftest/prog-run/go.mod b/selftest/prog-run/go.mod index 1071f201..164e4a46 100644 --- a/selftest/prog-run/go.mod +++ b/selftest/prog-run/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/testrun +module github.com/aquasecurity/libbpfgo/selftest/prog-run go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/prog-run/go.sum b/selftest/prog-run/go.sum index 5496456e..964bd12d 100644 --- a/selftest/prog-run/go.sum +++ b/selftest/prog-run/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/prog-run/main.go b/selftest/prog-run/main.go index 32fde9c8..dfcdde3c 100644 --- a/selftest/prog-run/main.go +++ b/selftest/prog-run/main.go @@ -4,26 +4,27 @@ import "C" import ( "encoding/binary" - "log" + "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatalf("Failed to load BPF module: %v", err) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - log.Fatalf("Failed to load object: %v", err) + common.Error(err) } tcProg, err := bpfModule.GetProgram("test_tc") if err != nil || tcProg == nil { - log.Fatalf("Failed to get prog test_tc: %v", err) + common.Error(fmt.Errorf("failed to get prog test_tc: %v", err)) } dataIn := make([]byte, 16) @@ -38,15 +39,15 @@ func main() { err = tcProg.Run(&opts) if err != nil { - log.Fatalf("Failed to run prog: %v", err) + common.Error(err) } if opts.RetVal != 1 { - log.Fatalf("retVal %d should be 1", opts.RetVal) + common.Error(fmt.Errorf("retVal %d should be 1", opts.RetVal)) } if len(opts.DataOut) != 14 { - log.Fatalf("dataOut len %v should be 14", opts.DataOut) + common.Error(fmt.Errorf("dataOut len %v should be 14", opts.DataOut)) } if binary.LittleEndian.Uint32(opts.DataOut) != 0x04030201 { - log.Fatalf("dataOut 0x%x should be 0x04030201", binary.LittleEndian.Uint32(opts.DataOut)) + common.Error(fmt.Errorf("dataOut 0x%x should be 0x04030201", binary.LittleEndian.Uint32(opts.DataOut))) } } diff --git a/selftest/reuse-fd/go.mod b/selftest/reuse-fd/go.mod index e4b855d8..fb7765f8 100644 --- a/selftest/reuse-fd/go.mod +++ b/selftest/reuse-fd/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/map-update +module github.com/aquasecurity/libbpfgo/selftest/reuse-fd go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/reuse-fd/go.sum b/selftest/reuse-fd/go.sum index 5496456e..964bd12d 100644 --- a/selftest/reuse-fd/go.sum +++ b/selftest/reuse-fd/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/reuse-fd/main.go b/selftest/reuse-fd/main.go index e709b686..96f06df8 100644 --- a/selftest/reuse-fd/main.go +++ b/selftest/reuse-fd/main.go @@ -5,16 +5,17 @@ import "C" import ( "bytes" - "log" + "fmt" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - log.Fatal(err) + common.Error(err) } defer bpfModule.Close() @@ -22,12 +23,12 @@ func main() { testerMap, err := bpfModule.GetMap("tester") if err != nil { - log.Fatal(err) + common.Error(err) } testerReusedMap, err := bpfModule.GetMap("tester_reused") if err != nil { - log.Fatal(err) + common.Error(err) } // @@ -39,11 +40,11 @@ func main() { // different FD. err = testerReusedMap.ReuseFD(testerMap.FileDescriptor()) if err != nil { - log.Fatal(err) + common.Error(err) } if err != nil { - log.Fatal(err) + common.Error(err) } valueSize := C.sizeof_struct_value @@ -58,7 +59,7 @@ func main() { value1Unsafe := unsafe.Pointer(&value1[0]) err = testerMap.Update(key1Unsafe, value1Unsafe) // update "tester" if err != nil { - log.Fatal(err) + common.Error(err) } key2 := int32(42069420) @@ -71,7 +72,7 @@ func main() { value2Unsafe := unsafe.Pointer(&value2[0]) err = testerReusedMap.Update(key2Unsafe, value2Unsafe) // also update "tester" if err != nil { - log.Fatal(err) + common.Error(err) } // @@ -80,7 +81,7 @@ func main() { toReuseCreated, err := bpf.CreateMap(bpf.MapTypeArray, "toreuse", 4, 4, 420, nil) if err != nil { - log.Fatal(err) + common.Error(err) } // The current instance of "toreuse" will be closed, and toReuseCreated @@ -88,15 +89,15 @@ func main() { // different FD. err = toReuseCreated.ReuseFD(testerMap.FileDescriptor()) if err != nil { - log.Fatal(err) + common.Error(err) } val2, err := toReuseCreated.GetValue(key2Unsafe) // lookup "tester" if err != nil { - log.Fatal(err) + common.Error(err) } if !bytes.Equal(val2, value2) { - log.Fatal("wrong value") + common.Error(fmt.Errorf("expected value %s, got %s", value2, val2)) } } diff --git a/selftest/ringbuffers/go.mod b/selftest/ringbuffers/go.mod index 72a57bd7..db94e174 100644 --- a/selftest/ringbuffers/go.mod +++ b/selftest/ringbuffers/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/ringbuffers go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/ringbuffers/go.sum b/selftest/ringbuffers/go.sum index 5496456e..964bd12d 100644 --- a/selftest/ringbuffers/go.sum +++ b/selftest/ringbuffers/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/ringbuffers/main.go b/selftest/ringbuffers/main.go index 6a123955..9bd8df29 100644 --- a/selftest/ringbuffers/main.go +++ b/selftest/ringbuffers/main.go @@ -3,8 +3,6 @@ package main import "C" import ( - "os" - "runtime" "syscall" "time" @@ -12,64 +10,42 @@ import ( "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -func resizeMap(module *bpf.Module, name string, size uint32) error { - m, err := module.GetMap(name) - if err != nil { - return err - } - - if err = m.Resize(size); err != nil { - return err - } - - if actual := m.GetMaxEntries(); actual != size { - return fmt.Errorf("map resize failed, expected %v, actual %v", size, actual) - } - - return nil -} - func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() - if err = resizeMap(bpfModule, "events1", 8192); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + if err = common.ResizeMap(bpfModule, "events1", 8192); err != nil { + common.Error(err) } bpfModule.BPFLoadObject() prog, err := bpfModule.GetProgram("kprobe__sys_mmap") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } - funcName := fmt.Sprintf("__%s_sys_mmap", ksymArch()) + funcName := fmt.Sprintf("__%s_sys_mmap", common.KSymArch()) _, err = prog.AttachKprobe(funcName) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } eventsChannel1 := make(chan []byte) rb, err := bpfModule.InitRingBuf("events1", eventsChannel1) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } eventsChannel2 := make(chan []byte) ret, err := bpfModule.AddRingBuf(rb, "events2", eventsChannel2) if !ret { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } rb.Poll(300) @@ -88,8 +64,7 @@ recvLoop: select { case b := <-eventsChannel1: if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } numberOfEvent1Received++ if numberOfEvent1Received > 5 && numberOfEvent2Received > 5 { @@ -97,8 +72,7 @@ recvLoop: } case b := <-eventsChannel2: if binary.LittleEndian.Uint32(b) != 2024 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } numberOfEvent2Received++ if numberOfEvent1Received > 5 && numberOfEvent2Received > 5 { @@ -114,14 +88,3 @@ recvLoop: rb.Close() rb.Stop() } - -func ksymArch() string { - switch runtime.GOARCH { - case "amd64": - return "x64" - case "arm64": - return "arm64" - default: - panic("unsupported architecture") - } -} diff --git a/selftest/set-attach/go.mod b/selftest/set-attach/go.mod index 72a57bd7..1546b0fc 100644 --- a/selftest/set-attach/go.mod +++ b/selftest/set-attach/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/set-attach go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/set-attach/go.sum b/selftest/set-attach/go.sum index 5496456e..964bd12d 100644 --- a/selftest/set-attach/go.sum +++ b/selftest/set-attach/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/set-attach/main.go b/selftest/set-attach/main.go index 49a0b3e3..41a4b842 100644 --- a/selftest/set-attach/main.go +++ b/selftest/set-attach/main.go @@ -4,75 +4,66 @@ import "C" import ( "encoding/binary" - "os" - "runtime" + "errors" "syscall" "time" "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() prog, err := bpfModule.GetProgram("foobar") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } // eBPF program type should only be set if it differs from the desired one // commit d6e6286a12e7 ("libbpf: disassociate section handler on explicit bpf_program__set_type() call") // err = prog.SetType(bpf.BPFProgTypeTracing) // if err != nil { - // fmt.Fprintln(os.Stderr, err) - // os.Exit(-1) + // common.Error(err) // } err = prog.SetExpectedAttachType(bpf.BPFAttachTypeTraceFentry) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } - funcName := fmt.Sprintf("__%s_sys_mmap", ksymArch()) + funcName := fmt.Sprintf("__%s_sys_mmap", common.KSymArch()) err = prog.SetAttachTarget(0, funcName) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } // Test auto attach autoAttachOrig := prog.Autoattach() prog.SetAutoattach(!autoAttachOrig) if prog.Autoattach() == autoAttachOrig { - fmt.Fprintln(os.Stderr, "set auto attach failed") - os.Exit(-1) + common.Error(errors.New("set auto attach failed")) } prog.SetAutoattach(autoAttachOrig) err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } _, err = prog.AttachGeneric() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } rb.Poll(300) @@ -87,8 +78,7 @@ recvLoop: for { b := <-eventsChannel if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } numberOfEventsReceived++ if numberOfEventsReceived > 5 { @@ -98,14 +88,3 @@ recvLoop: rb.Stop() rb.Close() } - -func ksymArch() string { - switch runtime.GOARCH { - case "amd64": - return "x64" - case "arm64": - return "arm64" - default: - panic("unsupported architecture") - } -} diff --git a/selftest/spinlocks/go.mod b/selftest/spinlocks/go.mod index 72a57bd7..02cbe5dc 100644 --- a/selftest/spinlocks/go.mod +++ b/selftest/spinlocks/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/spinlocks go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/spinlocks/go.sum b/selftest/spinlocks/go.sum index 5496456e..964bd12d 100644 --- a/selftest/spinlocks/go.sum +++ b/selftest/spinlocks/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/spinlocks/main.go b/selftest/spinlocks/main.go index f3b9a20f..d658eddb 100644 --- a/selftest/spinlocks/main.go +++ b/selftest/spinlocks/main.go @@ -3,7 +3,8 @@ package main import "C" import ( - "os" + "errors" + "log" "syscall" "time" "unsafe" @@ -12,72 +13,49 @@ import ( "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -func resizeMap(module *bpf.Module, name string, size uint32) error { - m, err := module.GetMap("events") - if err != nil { - return err - } - - if err = m.Resize(size); err != nil { - return err - } - - if actual := m.GetMaxEntries(); actual != size { - return fmt.Errorf("map resize failed, expected %v, actual %v", size, actual) - } - - return nil -} - func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() - if err = resizeMap(bpfModule, "events", 8192); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + if err = common.ResizeMap(bpfModule, "events", 8192); err != nil { + common.Error(err) } err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } // bpfModule.ListProgramNames() prog, err := bpfModule.GetProgram("mmap_fentry") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } link, err := prog.AttachGeneric() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if link.GetFd() == 0 { - os.Exit(-1) + common.Error(errors.New("failed to attach program")) } eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } lostEventCounterMap, err := bpfModule.GetMap("counter_hash_map") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } var lostEventCounterKey uint32 = 1 @@ -97,8 +75,7 @@ recvLoop: for { b := <-eventsChannel if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } numberOfEventsReceived++ if numberOfEventsReceived > 5 { @@ -111,9 +88,8 @@ recvLoop: val, err := lostEventCounterMap.GetValue(unsafe.Pointer(&lostEventCounterKey)) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } - fmt.Println("lost events = ", val) + log.Printf("lost events = %d", binary.LittleEndian.Uint32(val)) } diff --git a/selftest/struct-ops/go.mod b/selftest/struct-ops/go.mod index d24b6b41..13ef99ad 100644 --- a/selftest/struct-ops/go.mod +++ b/selftest/struct-ops/go.mod @@ -2,6 +2,11 @@ module github.com/aquasecurity/libbpfgo/selftest/struct-ops go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/struct-ops/go.sum b/selftest/struct-ops/go.sum index 5496456e..964bd12d 100644 --- a/selftest/struct-ops/go.sum +++ b/selftest/struct-ops/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/struct-ops/main.go b/selftest/struct-ops/main.go index 1da9de4a..a5165eea 100644 --- a/selftest/struct-ops/main.go +++ b/selftest/struct-ops/main.go @@ -9,36 +9,24 @@ import ( "syscall" "time" - "encoding/binary" "unsafe" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) -func endian() binary.ByteOrder { - var i int32 = 0x01020304 - u := unsafe.Pointer(&i) - pb := (*byte)(u) - b := *pb - if b == 0x04 { - return binary.LittleEndian - } - - return binary.BigEndian -} - func main() { bpfModule, err := bpf.NewModuleFromFileArgs(bpf.NewModuleArgs{ BPFObjPath: "main.bpf.o", KernelLogLevel: 0, }) if err != nil { - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() if err := bpfModule.BPFLoadObject(); err != nil { - os.Exit(-1) + common.Error(err) } m := bpfModule @@ -54,13 +42,11 @@ func main() { if m.Type().String() == "BPF_MAP_TYPE_STRUCT_OPS" { var link *bpf.BPFLink if link, err = m.AttachStructOps(); err != nil { - log.Printf("error: %v", err) - os.Exit(-1) + common.Error(err) } afterFunc = func() { if err := link.Destroy(); err != nil { - log.Printf("error: %v", err) - os.Exit(-1) + common.Error(err) } } } @@ -68,8 +54,7 @@ func main() { var statsMap *bpf.BPFMap if statsMap, err = bpfModule.GetMap("stats"); err != nil { - log.Printf("error: %v", err) - os.Exit(-1) + common.Error(err) } var wg sync.WaitGroup ctx, cancel := context.WithCancel(context.Background()) @@ -94,13 +79,12 @@ func main() { wg.Wait() afterFunc() log.Println("scheduler exit") - os.Exit(0) } func getStat(m *bpf.BPFMap) []uint64 { cpuNum, err := bpf.NumPossibleCPUs() if err != nil { - log.Fatal(err) + common.Error(err) } cnts := make([][]uint64, 2) cnts[0] = make([]uint64, cpuNum) @@ -109,11 +93,11 @@ func getStat(m *bpf.BPFMap) []uint64 { for i := 0; i < 2; i++ { v, err := m.GetValue(unsafe.Pointer(&i)) if err != nil { - log.Fatal(err) + common.Error(err) } for cpu := 0; cpu < cpuNum; cpu++ { n := v[cpu*8 : cpu*8+8] - cnts[i][cpu] = endian().Uint64(n) + cnts[i][cpu] = common.ByteOrder().Uint64(n) stats[i] += cnts[i][cpu] } } diff --git a/selftest/tc/go.mod b/selftest/tc/go.mod index 72a57bd7..88291a1d 100644 --- a/selftest/tc/go.mod +++ b/selftest/tc/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/tc go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/tc/go.sum b/selftest/tc/go.sum index 5496456e..964bd12d 100644 --- a/selftest/tc/go.sum +++ b/selftest/tc/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/tc/main.go b/selftest/tc/main.go index 8304afbf..0fc1feaf 100644 --- a/selftest/tc/main.go +++ b/selftest/tc/main.go @@ -4,54 +4,51 @@ import "C" import ( "encoding/binary" - "os" + "log" "os/exec" "syscall" "fmt" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } hook := bpfModule.TcHookInit() defer func() { if err := hook.Destroy(); err != nil { - fmt.Fprintln(os.Stderr, err) + log.Printf("Failed to destroy tc hook: %v", err) } }() err = hook.SetInterfaceByName("lo") if err != nil { - fmt.Fprintln(os.Stderr, "failed to set tc hook on interface lo: %v", err) - os.Exit(-1) + common.Error(fmt.Errorf("failed to set tc hook on interface lo: %v", err)) } hook.SetAttachPoint(bpf.BPFTcEgress) err = hook.Create() if err != nil { if errno, ok := err.(syscall.Errno); ok && errno != syscall.EEXIST { - fmt.Fprintln(os.Stderr, "tc hook create: %v", err) + common.Error(fmt.Errorf("tc hook create: %v", err)) } } tcProg, err := bpfModule.GetProgram("target") if tcProg == nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } var tcOpts bpf.TcOpts // https://elixir.bootlin.com/linux/v6.8.4/source/tools/testing/selftests/bpf/prog_tests/tc_bpf.c#L26 @@ -60,8 +57,7 @@ func main() { tcOpts.Priority = 1 err = hook.Attach(&tcOpts) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } // test for query @@ -69,12 +65,10 @@ func main() { tcOpts.ProgId = 0 err = hook.Query(&tcOpts) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if tcOpts.Handle != 1 { - fmt.Fprintln(os.Stderr, "query info error, handle:%d", tcOpts.Handle) - os.Exit(-1) + common.Error(fmt.Errorf("query info error, handle: %d", tcOpts.Handle)) } // test for detach @@ -83,16 +77,14 @@ func main() { tcOpts.ProgId = 0 err = hook.Detach(&tcOpts) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } }() eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } rb.Poll(300) @@ -100,8 +92,7 @@ func main() { go func() { _, err := exec.Command("ping", "localhost", "-c 10").Output() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } }() @@ -110,8 +101,7 @@ recvLoop: for { b := <-eventsChannel if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } numberOfEventsReceived++ if numberOfEventsReceived > 5 { diff --git a/selftest/tracing-by-offset/go.mod b/selftest/tracing-by-offset/go.mod index 6abf9d51..32192b59 100644 --- a/selftest/tracing-by-offset/go.mod +++ b/selftest/tracing-by-offset/go.mod @@ -5,10 +5,13 @@ go 1.21 require ( github.com/aquasecurity/libbpfgo v0.0.0 github.com/aquasecurity/libbpfgo/helpers v0.4.5 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 ) -require golang.org/x/sys v0.18.0 // indirect +require golang.org/x/sys v0.25.0 // indirect replace github.com/aquasecurity/libbpfgo => ../../ replace github.com/aquasecurity/libbpfgo/helpers => ../../helpers + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/tracing-by-offset/go.sum b/selftest/tracing-by-offset/go.sum index 56d1d2ec..06771930 100644 --- a/selftest/tracing-by-offset/go.sum +++ b/selftest/tracing-by-offset/go.sum @@ -2,9 +2,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/tracing-by-offset/main.go b/selftest/tracing-by-offset/main.go index 33133dcb..47036213 100644 --- a/selftest/tracing-by-offset/main.go +++ b/selftest/tracing-by-offset/main.go @@ -3,8 +3,6 @@ package main import "C" import ( - "os" - "runtime" "time" "fmt" @@ -12,41 +10,37 @@ import ( bpf "github.com/aquasecurity/libbpfgo" "github.com/aquasecurity/libbpfgo/helpers" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { - funcName := fmt.Sprintf("__%s_sys_mmap", ksymArch()) + funcName := fmt.Sprintf("__%s_sys_mmap", common.KSymArch()) kst, err := helpers.NewKernelSymbolTable() if err != nil { - fmt.Fprintln(os.Stderr, "NewKernelSymbolTable() failed: %v", err) - os.Exit(-1) + common.Error(err) } funcSymbol, err := kst.GetSymbolByName(funcName) if err != nil { - fmt.Fprintln(os.Stderr, "Expected to find symbol %s, but it was not found", funcSymbol) - os.Exit(-1) + common.Error(err) } bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() bpfModule.BPFLoadObject() prog, err := bpfModule.GetProgram("kprobe__sys_mmap") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } _, err = prog.AttachKprobeOffset(funcSymbol[0].Address) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } go func() { @@ -57,14 +51,3 @@ func main() { time.Sleep(time.Second * 2) } - -func ksymArch() string { - switch runtime.GOARCH { - case "amd64": - return "x64" - case "arm64": - return "arm64" - default: - panic("unsupported architecture") - } -} diff --git a/selftest/tracing/go.mod b/selftest/tracing/go.mod index ed6089c7..7ac8ccb4 100644 --- a/selftest/tracing/go.mod +++ b/selftest/tracing/go.mod @@ -5,10 +5,13 @@ go 1.21 require ( github.com/aquasecurity/libbpfgo v0.0.0 github.com/aquasecurity/libbpfgo/helpers v0.4.5 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 ) -require golang.org/x/sys v0.18.0 // indirect +require golang.org/x/sys v0.25.0 // indirect replace github.com/aquasecurity/libbpfgo => ../../ replace github.com/aquasecurity/libbpfgo/helpers => ../../helpers + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/tracing/go.sum b/selftest/tracing/go.sum index 56d1d2ec..06771930 100644 --- a/selftest/tracing/go.sum +++ b/selftest/tracing/go.sum @@ -2,9 +2,13 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/tracing/main.go b/selftest/tracing/main.go index 652e520a..87d5e35e 100644 --- a/selftest/tracing/main.go +++ b/selftest/tracing/main.go @@ -4,8 +4,7 @@ import "C" import ( "encoding/binary" - "os" - "runtime" + "errors" "syscall" "time" @@ -13,59 +12,52 @@ import ( bpf "github.com/aquasecurity/libbpfgo" "github.com/aquasecurity/libbpfgo/helpers" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } m, err := helpers.NewKernelSymbolTable() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } - funcName := fmt.Sprintf("__%s_sys_mmap", ksymArch()) + funcName := fmt.Sprintf("__%s_sys_mmap", common.KSymArch()) sym, err := m.GetSymbolByName(funcName) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if sym[0].Address == 0 && sym[0].Name == "" { - fmt.Fprintln(os.Stderr, "could not find symbol to attach to") - os.Exit(-1) + common.Error(errors.New("could not find symbol to attach to")) } prog, err := bpfModule.GetProgram("mmap_fentry") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } link, err := prog.AttachGeneric() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } if link.GetFd() == 0 { - os.Exit(-1) + common.Error(errors.New("failed to attach program")) } eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } rb.Poll(300) @@ -80,8 +72,7 @@ recvLoop: for { b := <-eventsChannel if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } numberOfEventsReceived++ if numberOfEventsReceived > 5 { @@ -92,14 +83,3 @@ recvLoop: rb.Stop() rb.Close() } - -func ksymArch() string { - switch runtime.GOARCH { - case "amd64": - return "x64" - case "arm64": - return "arm64" - default: - panic("unsupported architecture") - } -} diff --git a/selftest/uprobe-multi/Makefile b/selftest/uprobe-multi/Makefile new file mode 100644 index 00000000..6a18c666 --- /dev/null +++ b/selftest/uprobe-multi/Makefile @@ -0,0 +1,105 @@ +BASEDIR = $(abspath ../../) + +OUTPUT = ../../output + +LIBBPF_SRC = $(abspath ../../libbpf/src) +LIBBPF_OBJ = $(abspath $(OUTPUT)/libbpf.a) + +CC = gcc +CLANG = clang +GO ?= go +PKGCONFIG = pkg-config + +ARCH := $(shell uname -m | sed 's/x86_64/amd64/g; s/aarch64/arm64/g') + +# libbpf + +LIBBPF_OBJDIR = $(abspath ./$(OUTPUT)/libbpf) + +CFLAGS = -g -O2 -Wall -fpie +LDFLAGS = + +CGO_CFLAGS_STATIC = "-I$(abspath $(OUTPUT)) -I$(abspath ../common)" +CGO_LDFLAGS_STATIC = "$(shell PKG_CONFIG_PATH=$(LIBBPF_OBJDIR) $(PKGCONFIG) --static --libs libbpf)" +CGO_EXTLDFLAGS_STATIC = '-w -extldflags "-static"' + +CGO_CFLAGS_DYN = "-I. -I/usr/include/" +CGO_LDFLAGS_DYN = "$(shell $(PKGCONFIG) --shared --libs libbpf)" + +TEST = main + +.PHONY: $(TEST) +.PHONY: $(TEST).go +.PHONY: $(TEST).bpf.c + +all: $(TEST)-static + +.PHONY: libbpfgo +.PHONY: libbpfgo-static +.PHONY: libbpfgo-dynamic + +## libbpfgo + +libbpfgo-static: + $(MAKE) -C $(BASEDIR) libbpfgo-static + +libbpfgo-dynamic: + $(MAKE) -C $(BASEDIR) libbpfgo-dynamic + +## test (bpf) + +$(TEST).bpf.o: $(TEST).bpf.c + $(CLANG) $(CFLAGS) -target bpf -D__TARGET_ARCH_$(ARCH) -I$(OUTPUT) -I$(abspath ../common) -c $< -o $@ + +## test deps + +DEPS = ctest gotest + +.PHONY: ctest +ctest: + @if [ ! -x ctest ]; then \ + $(CLANG) -o ctest test.c; \ + fi + +.PHONY: gotest +gotest: + @if [ ! -x gotest ]; then \ + $(GO) build -o gotest test.go; \ + fi + +## test + +.PHONY: $(TEST)-static +.PHONY: $(TEST)-dynamic + +$(TEST)-static: libbpfgo-static | $(TEST).bpf.o $(DEPS) + CC=$(CLANG) \ + CGO_CFLAGS=$(CGO_CFLAGS_STATIC) \ + CGO_LDFLAGS=$(CGO_LDFLAGS_STATIC) \ + GOOS=linux GOARCH=$(ARCH) \ + $(GO) build \ + -tags netgo -ldflags $(CGO_EXTLDFLAGS_STATIC) \ + -o $(TEST)-static ./$(TEST).go + +$(TEST)-dynamic: libbpfgo-dynamic | $(TEST).bpf.o $(DEPS) + CC=$(CLANG) \ + CGO_CFLAGS=$(CGO_CFLAGS_DYN) \ + CGO_LDFLAGS=$(CGO_LDFLAGS_DYN) \ + $(GO) build -o ./$(TEST)-dynamic ./$(TEST).go + +## run + +.PHONY: run +.PHONY: run-static +.PHONY: run-dynamic + +run: run-static + +run-static: $(TEST)-static + sudo ./run.sh $(TEST)-static + +run-dynamic: $(TEST)-dynamic + sudo ./run.sh $(TEST)-dynamic + +clean: + rm -f *.o $(TEST)-static $(TEST)-dynamic $(DEPS) diff --git a/selftest/uprobe-multi/go.mod b/selftest/uprobe-multi/go.mod new file mode 100644 index 00000000..b93343da --- /dev/null +++ b/selftest/uprobe-multi/go.mod @@ -0,0 +1,14 @@ +module github.com/aquasecurity/libbpfgo/selftest/uprobe + +go 1.21 + +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) + +replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/helpers => ../../helpers + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/uprobe-multi/go.sum b/selftest/uprobe-multi/go.sum new file mode 100644 index 00000000..964bd12d --- /dev/null +++ b/selftest/uprobe-multi/go.sum @@ -0,0 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/uprobe-multi/main.bpf.c b/selftest/uprobe-multi/main.bpf.c new file mode 100644 index 00000000..d5ba3b8d --- /dev/null +++ b/selftest/uprobe-multi/main.bpf.c @@ -0,0 +1,39 @@ +//+build ignore + +#include + +#include +#include + +struct event_t { + __u64 cookie; +}; + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 1 << 24); +} events SEC(".maps"); + +long ringbuffer_flags = 0; + +SEC("uprobe/test_functions") +int uprobe__test_functions(struct pt_regs *ctx) +{ + __u64 cookie = bpf_get_attach_cookie(ctx); + + bpf_printk("handle user function with cookie %llu\n", cookie); + + // Reserve space on the ringbuffer for the sample + struct event_t *event = bpf_ringbuf_reserve(&events, sizeof(struct event_t), ringbuffer_flags); + if (!event) { + bpf_printk("error submitting event to ring buffer for user function with cookie %llu\n", + cookie); + return 0; + } + + // Send back to userspace the function name + event->cookie = cookie; + bpf_ringbuf_submit(event, ringbuffer_flags); + return 0; +} +char __license[] SEC("license") = "GPL"; diff --git a/selftest/uprobe-multi/main.go b/selftest/uprobe-multi/main.go new file mode 100644 index 00000000..87a6c3fd --- /dev/null +++ b/selftest/uprobe-multi/main.go @@ -0,0 +1,217 @@ +package main + +import "C" +import ( + "bytes" + "debug/elf" + "encoding/binary" + "errors" + "fmt" + "hash/fnv" + "log" + "os" + "strings" + "time" + + bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" +) + +type Event struct { + Cookie uint64 +} + +type FunctionInfo struct { + Name string + Offset uint64 +} + +const ( + attachBatchSize = 256 + bpfProgramName = "uprobe__test_functions" + bpfProgramObject = "main.bpf.o" +) + +var ( + excludePatterns = []string{"runtime.", "go:", "internal"} +) + +func main() { + if len(os.Args) < 3 { + common.Error(errors.New("wrong syntax")) + } + + // Executable and expected symbols to be traced as positional arguments. + binaryPath := os.Args[1] + expectedSymbolNames := strings.Split(os.Args[2], ",") + + // We try to attach uprobes to the maximum amount of functions supported + // as possible. + symbols, err := getFunSyms(binaryPath) + if err != nil { + common.Error(fmt.Errorf("failed to get function symbols: %v", err)) + } + + // Hashmap to correlate a cookie got from BPF to a function. + cookieToFunctionInfo := make(map[uint64]FunctionInfo) + + // cookies and offsets bpf_program__attach_uprobe_multi_opts options. + cookies := make([]uint64, 0) + offsets := make([]uint64, 0) + for _, symbol := range symbols { + // Skip go runtime functions. + if shouldExclude(symbol.Name, excludePatterns) { + continue + } + + offset, err := common.SymbolToOffset(binaryPath, symbol.Name) + if err != nil { + log.Printf("Skipping symbol %s: %v", symbol.Name, err) + continue + } + cookie := hash(symbol.Name) + cookies = append(cookies, cookie) + offsets = append(offsets, offset) + cookieToFunctionInfo[cookie] = FunctionInfo{ + Name: symbol.Name, + Offset: offset, + } + } + + bpfModule, err := bpf.NewModuleFromFile(bpfProgramObject) + if err != nil { + common.Error(err) + } + defer bpfModule.Close() + + if err = common.ResizeMap(bpfModule, "events", 8192); err != nil { + common.Error(err) + } + + log.Println("getting program") + prog, err := bpfModule.GetProgram(bpfProgramName) + if err != nil { + common.Error(err) + } + + log.Println("setting expected attach type uprobe multi before loading") + if err = prog.SetExpectedAttachType(bpf.BPFAttachTypeTraceUprobeMulti); err != nil { + common.Error(err) + } + + log.Println("loading object") + err = bpfModule.BPFLoadObject() + if err != nil { + common.Error(err) + } + + log.Println("attaching multi uprobes") + for i := 0; i < len(offsets); i += attachBatchSize { + end := i + attachBatchSize + if end > len(offsets) { + end = len(offsets) + } + + _, err = prog.AttachUprobeMulti(-1, binaryPath, offsets[i:end], cookies[i:end]) + if err != nil { + common.Error(err) + } + } + + log.Println("initializing events ring buffer") + eventsChannel := make(chan []byte) + rb, err := bpfModule.InitRingBuf("events", eventsChannel) + if err != nil { + common.Error(err) + } + + rb.Poll(300) + + // We get back from BPF and keep track of the function having traced via cookies. + log.Println("consuming events") + got := make(map[string]struct{}) + go func() { + for { + b := <-eventsChannel + var event Event + buf := bytes.NewBuffer(b) + if err = binary.Read(buf, binary.LittleEndian, &event); err != nil { + // Error handling is out of scope for this test. + continue + } + cookie := event.Cookie + info, ok := cookieToFunctionInfo[cookie] + if !ok { + // Error handling is out of scope for this test. + continue + } + got[info.Name] = struct{}{} + } + }() + // Just wait for a minimum amount of time for the tested tracee to call + // the expected functions. + time.Sleep(2 * time.Second) + + // Verify that all uprobes have been executed. + for _, symbolName := range expectedSymbolNames { + if _, ok := got[symbolName]; !ok { + common.Error(fmt.Errorf("function %s has not been traced", symbolName)) + } + } + log.Println("all functions have been traced") + + // Test that it won't cause a panic or block if Stop or Close called multiple times + rb.Stop() + rb.Stop() + rb.Close() + rb.Close() + rb.Stop() +} + +// getFunSyms returns the list of elf.Symbol of type function. +func getFunSyms(name string) ([]elf.Symbol, error) { + var symbols []elf.Symbol + + b, err := elf.Open(name) + defer b.Close() + if err != nil { + return nil, err + } + syms, err := b.Symbols() + if err != nil { + return nil, err + } + log.Printf("found %d symbols in %s\n", len(syms), name) + log.Printf("showing first %d symbols\n", common.Min(10, len(syms))) + for i := 0; i < common.Min(10, len(syms)); i++ { + log.Printf("symbol %d: %v\n", i, syms[i]) + } + for _, sym := range syms { + // Exclude non-function symbols. + if elf.ST_TYPE(sym.Info) != elf.STT_FUNC { + continue + } + + symbols = append(symbols, sym) + } + + return symbols, nil +} + +// shouldExclude returns whether a symbol should be excluded based +// on a list of string patterns. +func shouldExclude(symbol string, excludeList []string) bool { + for _, v := range excludeList { + if strings.Contains(symbol, v) { + return true + } + } + return false +} + +func hash(s string) uint64 { + h := fnv.New64a() + h.Write([]byte(s)) + + return h.Sum64() +} diff --git a/selftest/uprobe-multi/run.sh b/selftest/uprobe-multi/run.sh new file mode 100755 index 00000000..4dadb1fd --- /dev/null +++ b/selftest/uprobe-multi/run.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# SETTINGS + +TEST=$(dirname $0)/$1 # execute +TIMEOUT=10 # seconds + +CTEST=$(dirname $0)/ctest +GOTEST=$(dirname $0)/gotest +CFUNCS="fooFunction,barFunction,bazFunction" +GOFUNCS="main.fooFunction,main.barFunction,main.bazFunction" + +# COMMON + +COMMON="$(dirname $0)/../common/common.sh" +[[ -f $COMMON ]] && { . $COMMON; } || { error "no common"; exit 1; } + +# MAIN + +kern_version gt 4.3 +check_build +check_ppid + +execbg 10 $CTEST +execbg 10 $GOTEST + +execfg 5 $TEST $CTEST $CFUNCS +test_step + +execfg 5 $TEST $GOTEST $GOFUNCS +test_finish + +waitbg + +exit 0 diff --git a/selftest/uprobe-multi/test.c b/selftest/uprobe-multi/test.c new file mode 100644 index 00000000..01fada4d --- /dev/null +++ b/selftest/uprobe-multi/test.c @@ -0,0 +1,20 @@ +//+build ignore +#include + +__attribute__((optnone)) void fooFunction() {} +__attribute__((optnone)) void barFunction() {} +__attribute__((optnone)) void bazFunction() {} + +int main() +{ + int i; + + while (1) { + usleep(100 * 1000); + fooFunction(); + usleep(100 * 1000); + barFunction(); + usleep(100 * 1000); + bazFunction(); + } +} diff --git a/selftest/uprobe-multi/test.go b/selftest/uprobe-multi/test.go new file mode 100644 index 00000000..7aae87e5 --- /dev/null +++ b/selftest/uprobe-multi/test.go @@ -0,0 +1,41 @@ +package main + +import ( + "os" + "time" +) + +//go:noinline +func fooFunction() int { + if os.Getenv("SELFTEST_UPROBE_DO_BRANCH") == "y" { + return 1 + } + return 0 +} + +//go:noinline +func barFunction() int { + if os.Getenv("SELFTEST_UPROBE_DO_BRANCH") == "y" { + return 1 + } + return 0 +} + +//go:noinline +func bazFunction() int { + if os.Getenv("SELFTEST_UPROBE_DO_BRANCH") == "y" { + return 1 + } + return 0 +} + +func main() { + for { + time.Sleep(100 * time.Millisecond) + fooFunction() + time.Sleep(100 * time.Millisecond) + barFunction() + time.Sleep(100 * time.Millisecond) + bazFunction() + } +} diff --git a/selftest/uprobe/go.mod b/selftest/uprobe/go.mod index 0088c8db..f3f40da2 100644 --- a/selftest/uprobe/go.mod +++ b/selftest/uprobe/go.mod @@ -4,11 +4,9 @@ go 1.21 require ( github.com/aquasecurity/libbpfgo v0.0.0 - github.com/aquasecurity/libbpfgo/helpers v0.4.5 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 ) -require golang.org/x/sys v0.18.0 // indirect - replace github.com/aquasecurity/libbpfgo => ../../ -replace github.com/aquasecurity/libbpfgo/helpers => ../../helpers +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/uprobe/go.sum b/selftest/uprobe/go.sum index 56d1d2ec..964bd12d 100644 --- a/selftest/uprobe/go.sum +++ b/selftest/uprobe/go.sum @@ -2,9 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/uprobe/main.go b/selftest/uprobe/main.go index e2ba626d..bc59ca09 100644 --- a/selftest/uprobe/main.go +++ b/selftest/uprobe/main.go @@ -2,19 +2,18 @@ package main import "C" import ( - "debug/elf" "encoding/binary" "errors" "fmt" "os" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { if len(os.Args) < 3 { - fmt.Fprintln(os.Stderr, "wrong syntax") - os.Exit(-1) + common.Error(errors.New("wrong syntax")) } binaryPath := os.Args[1] @@ -22,46 +21,39 @@ func main() { _, err := os.Stat(binaryPath) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() - if err = resizeMap(bpfModule, "events", 8192); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + if err = common.ResizeMap(bpfModule, "events", 8192); err != nil { + common.Error(err) } bpfModule.BPFLoadObject() prog, err := bpfModule.GetProgram("uprobe__test_function") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } - offset, err := symbolToOffset(binaryPath, symbolName) + offset, err := common.SymbolToOffset(binaryPath, symbolName) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } _, err = prog.AttachUprobe(-1, binaryPath, offset) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } rb.Poll(300) @@ -72,8 +64,7 @@ recvLoop: for { b := <-eventsChannel if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } numberOfEventsReceived++ if numberOfEventsReceived > 5 { @@ -88,73 +79,3 @@ recvLoop: rb.Close() rb.Stop() } - -// symbolToOffset attempts to resolve a 'symbol' name in the binary found at -// 'path' to an offset. The offset can be used for attaching a u(ret)probe -func symbolToOffset(path, symbol string) (uint32, error) { - f, err := elf.Open(path) - if err != nil { - return 0, fmt.Errorf("could not open elf file to resolve symbol offset: %w", err) - } - defer f.Close() - - regularSymbols, regularSymbolsErr := f.Symbols() - dynamicSymbols, dynamicSymbolsErr := f.DynamicSymbols() - - // Only if we failed getting both regular and dynamic symbols - then we abort. - if regularSymbolsErr != nil && dynamicSymbolsErr != nil { - return 0, fmt.Errorf("could not open regular or dynamic symbol sections to resolve symbol offset: %w %s", regularSymbolsErr, dynamicSymbolsErr) - } - - // Concatenating into a single list. - // The list can have duplications, but we will find the first occurrence which is sufficient. - syms := append(regularSymbols, dynamicSymbols...) - - sectionsToSearchForSymbol := []*elf.Section{} - - for i := range f.Sections { - if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR { - sectionsToSearchForSymbol = append(sectionsToSearchForSymbol, f.Sections[i]) - } - } - - var executableSection *elf.Section - - for j := range syms { - if syms[j].Name == symbol { - // Find what section the symbol is in by checking the executable section's - // addr space. - for m := range sectionsToSearchForSymbol { - if syms[j].Value > sectionsToSearchForSymbol[m].Addr && - syms[j].Value < sectionsToSearchForSymbol[m].Addr+sectionsToSearchForSymbol[m].Size { - executableSection = sectionsToSearchForSymbol[m] - } - } - - if executableSection == nil { - return 0, errors.New("could not find symbol in executable sections of binary") - } - - return uint32(syms[j].Value - executableSection.Addr + executableSection.Offset), nil - } - } - - return 0, fmt.Errorf("symbol %s not found in %s", symbol, path) -} - -func resizeMap(module *bpf.Module, name string, size uint32) error { - m, err := module.GetMap("events") - if err != nil { - return err - } - - if err = m.SetMaxEntries(size); err != nil { - return err - } - - if actual := m.MaxEntries(); actual != size { - return fmt.Errorf("map resize failed, expected %v, actual %v", size, actual) - } - - return nil -} diff --git a/selftest/usdt/Makefile b/selftest/usdt/Makefile new file mode 100644 index 00000000..c096a4f5 --- /dev/null +++ b/selftest/usdt/Makefile @@ -0,0 +1,100 @@ +BASEDIR = $(abspath ../../) + +OUTPUT = ../../output + +LIBBPF_SRC = $(abspath ../../libbpf/src) +LIBBPF_OBJ = $(abspath $(OUTPUT)/libbpf.a) + +CC = gcc +CLANG = clang +GO = go +PKGCONFIG = pkg-config + +GOARCH := $(shell uname -m | sed 's/x86_64/amd64/g; s/aarch64/arm64/g') +BPFARCH := $(shell uname -m | sed 's/x86_64/x86/g; s/aarch64/arm64/g') + +# libbpf + +LIBBPF_OBJDIR = $(abspath ./$(OUTPUT)/libbpf) + +CFLAGS = -g -O2 -Wall -fpie +LDFLAGS = + +CGO_CFLAGS_STATIC = "-I$(abspath $(OUTPUT)) -I$(abspath ../common)" +CGO_LDFLAGS_STATIC = "$(shell PKG_CONFIG_PATH=$(LIBBPF_OBJDIR) $(PKGCONFIG) --static --libs libbpf)" +CGO_EXTLDFLAGS_STATIC = '-w -extldflags "-static"' + +CGO_CFLAGS_DYN = "-I. -I/usr/include/" +CGO_LDFLAGS_DYN = "$(shell $(PKGCONFIG) --shared --libs libbpf)" + +TEST = main + +.PHONY: $(TEST) +.PHONY: $(TEST).go +.PHONY: $(TEST).bpf.c + +all: $(TEST)-static + +.PHONY: libbpfgo +.PHONY: libbpfgo-static +.PHONY: libbpfgo-dynamic + +## libbpfgo + +libbpfgo-static: + $(MAKE) -C $(BASEDIR) libbpfgo-static + +libbpfgo-dynamic: + $(MAKE) -C $(BASEDIR) libbpfgo-dynamic + +## test (bpf) + +$(TEST).bpf.o: $(TEST).bpf.c + $(CLANG) $(CFLAGS) -target bpf -D__TARGET_ARCH_$(BPFARCH) -I$(OUTPUT) -I$(abspath ../common) -c $< -o $@ + +## test deps + +DEPS = ctest + +.PHONY: ctest +ctest: + @if [ ! -x ctest ]; then \ + $(CLANG) -o ctest test.c; \ + fi + +## test + +.PHONY: $(TEST)-static +.PHONY: $(TEST)-dynamic + +$(TEST)-static: libbpfgo-static | $(TEST).bpf.o $(DEPS) + CC=$(CLANG) \ + CGO_CFLAGS=$(CGO_CFLAGS_STATIC) \ + CGO_LDFLAGS=$(CGO_LDFLAGS_STATIC) \ + GOOS=linux GOARCH=$(GOARCH) \ + $(GO) build \ + -tags netgo -ldflags $(CGO_EXTLDFLAGS_STATIC) \ + -o $(TEST)-static ./$(TEST).go + +$(TEST)-dynamic: libbpfgo-dynamic | $(TEST).bpf.o $(DEPS) + CC=$(CLANG) \ + CGO_CFLAGS=$(CGO_CFLAGS_DYN) \ + CGO_LDFLAGS=$(CGO_LDFLAGS_DYN) \ + $(GO) build -o ./$(TEST)-dynamic ./$(TEST).go + +## run + +.PHONY: run +.PHONY: run-static +.PHONY: run-dynamic + +run: run-static + +run-static: $(TEST)-static + sudo ./run.sh $(TEST)-static + +run-dynamic: $(TEST)-dynamic + sudo ./run.sh $(TEST)-dynamic + +clean: + rm -f *.o $(TEST)-static $(TEST)-dynamic $(DEPS) diff --git a/selftest/usdt/go.mod b/selftest/usdt/go.mod new file mode 100644 index 00000000..85415c1d --- /dev/null +++ b/selftest/usdt/go.mod @@ -0,0 +1,12 @@ +module github.com/aquasecurity/libbpfgo/selftest/usdt + +go 1.21 + +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) + +replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/usdt/go.sum b/selftest/usdt/go.sum new file mode 100644 index 00000000..964bd12d --- /dev/null +++ b/selftest/usdt/go.sum @@ -0,0 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/usdt/main.bpf.c b/selftest/usdt/main.bpf.c new file mode 100644 index 00000000..103b14d9 --- /dev/null +++ b/selftest/usdt/main.bpf.c @@ -0,0 +1,36 @@ +//+build ignore + +#include + +#include +#include +#include + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 1 << 24); +} events SEC(".maps"); + +long ringbuffer_flags = 0; + +SEC("usdt/test_marker") +int usdt__test_marker(struct pt_regs *ctx) +{ + long *value; + + // Reserve space on the ringbuffer for the sample + value = bpf_ringbuf_reserve(&events, sizeof(*value), ringbuffer_flags); + if (!value) { + return 0; + } + + if (bpf_usdt_arg(ctx, 0, value) < 0) { + bpf_ringbuf_discard(value, ringbuffer_flags); + return 0; + } + + bpf_ringbuf_submit(value, ringbuffer_flags); + return 0; +} + +char LICENSE[] SEC("license") = "GPL"; diff --git a/selftest/usdt/main.go b/selftest/usdt/main.go new file mode 100644 index 00000000..2d34d314 --- /dev/null +++ b/selftest/usdt/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "encoding/binary" + "fmt" + "os" + + bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" +) + +func main() { + binaryPath := "./ctest" + providerName := "test" + markerName := "test_marker" + + _, err := os.Stat(binaryPath) + if err != nil { + common.Error(err) + } + + bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") + if err != nil { + common.Error(err) + } + defer bpfModule.Close() + + if err = common.ResizeMap(bpfModule, "events", 8192); err != nil { + common.Error(err) + } + + bpfModule.BPFLoadObject() + prog, err := bpfModule.GetProgram("usdt__test_marker") + if err != nil { + common.Error(err) + } + + _, err = prog.AttachUSDT(-1, binaryPath, providerName, markerName) + if err != nil { + common.Error(err) + } + + eventsChannel := make(chan []byte) + rb, err := bpfModule.InitRingBuf("events", eventsChannel) + if err != nil { + common.Error(err) + } + + rb.Poll(300) + + numberOfEventsReceived := 0 + +recvLoop: + for { + b := <-eventsChannel + if binary.LittleEndian.Uint32(b) != 1234 { + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) + } + numberOfEventsReceived++ + if numberOfEventsReceived > 5 { + break recvLoop + } + } + + rb.Stop() + rb.Close() +} diff --git a/selftest/usdt/run.sh b/selftest/usdt/run.sh new file mode 100755 index 00000000..d6a8a127 --- /dev/null +++ b/selftest/usdt/run.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# SETTINGS + +TEST=$(dirname $0)/$1 # execute +TIMEOUT=10 # seconds + +CTEST=$(dirname $0)/ctest + +# COMMON + +COMMON="$(dirname $0)/../common/common.sh" +[[ -f $COMMON ]] && { . $COMMON; } || { error "no common"; exit 1; } + +# MAIN + +check_build +check_ppid + +execbg 10 $CTEST + +execfg 5 $TEST +test_finish + +waitbg + +exit 0 diff --git a/selftest/usdt/test.c b/selftest/usdt/test.c new file mode 100644 index 00000000..6c5ce5aa --- /dev/null +++ b/selftest/usdt/test.c @@ -0,0 +1,11 @@ +#include +#include + +int main() +{ + while (1) { + usleep(100 * 1000); + DTRACE_PROBE1(test, test_marker, 1234); + } + return 0; +} diff --git a/selftest/userringbuf/Makefile b/selftest/userringbuf/Makefile new file mode 120000 index 00000000..d981720c --- /dev/null +++ b/selftest/userringbuf/Makefile @@ -0,0 +1 @@ +../common/Makefile \ No newline at end of file diff --git a/selftest/userringbuf/go.mod b/selftest/userringbuf/go.mod new file mode 100644 index 00000000..f93ef398 --- /dev/null +++ b/selftest/userringbuf/go.mod @@ -0,0 +1,12 @@ +module github.com/aquasecurity/libbpfgo/selftest/userringbuf + +go 1.21 + +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) + +replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/userringbuf/go.sum b/selftest/userringbuf/go.sum new file mode 100644 index 00000000..964bd12d --- /dev/null +++ b/selftest/userringbuf/go.sum @@ -0,0 +1,12 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/userringbuf/main.bpf.c b/selftest/userringbuf/main.bpf.c new file mode 100644 index 00000000..0db0b3ac --- /dev/null +++ b/selftest/userringbuf/main.bpf.c @@ -0,0 +1,48 @@ +//+build ignore + +#include + +#include +#include + +struct dispatched_ctx { + u64 id; +}; + +struct { + __uint(type, BPF_MAP_TYPE_USER_RINGBUF); + __uint(max_entries, 3 * sizeof(struct dispatched_ctx)); +} dispatched SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 256); +} errEvt SEC(".maps"); + +long ringbuffer_flags = 0; + +static long handle_dispatched_evt(struct bpf_dynptr *dynptr, void *context) +{ + const struct dispatched_ctx *ctx; + + ctx = bpf_dynptr_data(dynptr, 0, sizeof(*ctx)); + + if (!ctx || ctx->id != 0x1122334455667788) { + u64 *id = bpf_ringbuf_reserve(&errEvt, sizeof(u64), ringbuffer_flags); + if (!id) { + return 1; + } + bpf_ringbuf_submit(id, ringbuffer_flags); + return 1; + } + + return 0; +} + +SEC("syscall") +int test_user_ring_buff(struct dispatched_ctx *input) +{ + int retVal; + retVal = bpf_user_ringbuf_drain(&dispatched, handle_dispatched_evt, NULL, 0); + return retVal; +} diff --git a/selftest/userringbuf/main.go b/selftest/userringbuf/main.go new file mode 100644 index 00000000..e7ade0bc --- /dev/null +++ b/selftest/userringbuf/main.go @@ -0,0 +1,72 @@ +package main + +import "C" + +import ( + "bytes" + "encoding/binary" + "time" + + "fmt" + + bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" +) + +type test_arg struct { + id uint64 +} + +func main() { + bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") + if err != nil { + common.Error(err) + } + defer bpfModule.Close() + + bpfModule.BPFLoadObject() + + ch := make(chan []byte, 3) // We will send 3 messages + urb, err := bpfModule.InitUserRingBuf("dispatched", ch) + if err != nil { + common.Error(err) + } + urb.Start() + + evtChan := make(chan []byte) + rb, err := bpfModule.InitRingBuf("errEvt", evtChan) + if err != nil { + common.Error(err) + } + rb.Poll(300) + + // Send 3 messages to the ring buffer + var b bytes.Buffer // Stand-in for a network connection + binary.Write(&b, binary.LittleEndian, test_arg{id: 0x1122334455667788}) + ch <- b.Bytes() + ch <- b.Bytes() + ch <- b.Bytes() + + time.Sleep(1 * time.Second) + + prog, err := bpfModule.GetProgram("test_user_ring_buff") + if err != nil { + common.Error(err) + } + arg := &test_arg{ + id: 0, + } + + var data bytes.Buffer + binary.Write(&data, binary.LittleEndian, arg) + opt := bpf.RunOpts{ + CtxIn: data.Bytes(), + CtxSizeIn: uint32(data.Len()), + } + + // Run the program and check if 3 messages were drained by the program + prog.Run(&opt) + if opt.RetVal != 3 { + common.Error(fmt.Errorf("expected 3, got %d", opt.RetVal)) + } +} diff --git a/selftest/userringbuf/run.sh b/selftest/userringbuf/run.sh new file mode 120000 index 00000000..2c5ef4f0 --- /dev/null +++ b/selftest/userringbuf/run.sh @@ -0,0 +1 @@ +../common/run-6.1.sh \ No newline at end of file diff --git a/selftest/version/go.mod b/selftest/version/go.mod index 72a57bd7..0c8cde43 100644 --- a/selftest/version/go.mod +++ b/selftest/version/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/version go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/version/go.sum b/selftest/version/go.sum index 5496456e..964bd12d 100644 --- a/selftest/version/go.sum +++ b/selftest/version/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/version/main.go b/selftest/version/main.go index 6d425b8c..0d613d46 100644 --- a/selftest/version/main.go +++ b/selftest/version/main.go @@ -1,11 +1,12 @@ package main import ( - "log" + "fmt" "os/exec" "strings" "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) func main() { @@ -14,12 +15,12 @@ func main() { b, err := cmd.CombinedOutput() if err != nil { - log.Fatal(string(b), err) + common.Error(err) } // libbpf doesn't put the patch version in exported version // symbols, so use just prefix to exclude it if strings.HasPrefix(libbpfgo.LibbpfVersionString(), string(b)) { - log.Fatalf("Error reading exported symbols for libbpf major and minor version: %s is not %s", libbpfgo.LibbpfVersionString(), b) + common.Error(fmt.Errorf("libbpf version %s does not match expected version %s", libbpfgo.LibbpfVersionString(), b)) } } diff --git a/selftest/xdp/go.mod b/selftest/xdp/go.mod index 72a57bd7..a9d306f6 100644 --- a/selftest/xdp/go.mod +++ b/selftest/xdp/go.mod @@ -1,7 +1,12 @@ -module github.com/aquasecurity/libbpfgo/selftest/perfbuffers +module github.com/aquasecurity/libbpfgo/selftest/xdp go 1.21 -require github.com/aquasecurity/libbpfgo v0.0.0 +require ( + github.com/aquasecurity/libbpfgo v0.0.0 + github.com/aquasecurity/libbpfgo/selftest/common v0.0.0-00010101000000-000000000000 +) replace github.com/aquasecurity/libbpfgo => ../../ + +replace github.com/aquasecurity/libbpfgo/selftest/common => ../../selftest/common diff --git a/selftest/xdp/go.sum b/selftest/xdp/go.sum index 5496456e..964bd12d 100644 --- a/selftest/xdp/go.sum +++ b/selftest/xdp/go.sum @@ -2,7 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76 h1:mrdLPj8ujM6eIKGtd1PkkuCIodpFFDM42Cfm0YODkIM= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.76/go.mod h1:7V2BQeHnVAQwhCnCPJ977giCeGDiywVewWF+8vkpPlc= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76 h1:3DyzQ30OHt3wiOZVL1se2g1PAPJIU7+tMUyvfMUj1dY= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.76/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= diff --git a/selftest/xdp/main.go b/selftest/xdp/main.go index ebe48d4f..238a0710 100644 --- a/selftest/xdp/main.go +++ b/selftest/xdp/main.go @@ -5,10 +5,10 @@ import "C" import ( "encoding/binary" "fmt" - "os" "os/exec" bpf "github.com/aquasecurity/libbpfgo" + "github.com/aquasecurity/libbpfgo/selftest/common" ) const ( @@ -18,45 +18,38 @@ const ( func main() { bpfModule, err := bpf.NewModuleFromFile("main.bpf.o") if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } defer bpfModule.Close() err = bpfModule.BPFLoadObject() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } xdpProg, err := bpfModule.GetProgram("target") if xdpProg == nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } err = xdpProg.AttachXDPLegacy(deviceName, bpf.XDPFlagsReplace) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } err = xdpProg.DetachXDPLegacy(deviceName, bpf.XDPFlagsReplace) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } _, err = xdpProg.AttachXDP(deviceName) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } eventsChannel := make(chan []byte) rb, err := bpfModule.InitRingBuf("events", eventsChannel) if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } rb.Poll(300) @@ -64,8 +57,7 @@ func main() { go func() { _, err := exec.Command("ping", "localhost", "-c 10").Output() if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + common.Error(err) } }() @@ -74,8 +66,7 @@ recvLoop: for { b := <-eventsChannel if binary.LittleEndian.Uint32(b) != 2021 { - fmt.Fprintf(os.Stderr, "invalid data retrieved\n") - os.Exit(-1) + common.Error(fmt.Errorf("invalid data retrieved: %v", b)) } numberOfEventsReceived++ if numberOfEventsReceived > 5 { diff --git a/user-buf-ring.go b/user-buf-ring.go new file mode 100644 index 00000000..9f61c305 --- /dev/null +++ b/user-buf-ring.go @@ -0,0 +1,84 @@ +package libbpfgo + +/* +#cgo LDFLAGS: -lelf -lz +#include "libbpfgo.h" +*/ +import "C" +import ( + "fmt" + "sync" + "unsafe" +) + +// +// UserRingBuffer +// + +type UserRingBuffer struct { + rb *C.struct_user_ring_buffer + bpfMap *BPFMap + closed bool + stop chan struct{} + w chan []byte + errChan chan error + wg sync.WaitGroup +} + +func (rb *UserRingBuffer) Start() { + rb.stop = make(chan struct{}) + rb.errChan = make(chan error, 1) + rb.wg.Add(1) + go func() { + defer rb.wg.Done() + for { + select { + case b := <-rb.w: + if err := rb.submit(b); err != nil { + rb.errChan <- err + } + case <-rb.stop: + return + } + } + }() +} + +func (rb *UserRingBuffer) Error() error { + select { + case err := <-rb.errChan: + return err + default: + return nil + } +} + +func (rb *UserRingBuffer) submit(b []byte) error { + bSizeC := C.size_t(len(b)) + entry, errno := C.user_ring_buffer__reserve(rb.rb, C.uint(bSizeC)) + if entry == nil { + return fmt.Errorf("user_ring_buffer__reserve failed: %v", errno) + } + + C.memcpy(entry, unsafe.Pointer(&b[0]), bSizeC) + C.user_ring_buffer__submit(rb.rb, entry) + return nil +} + +func (rb *UserRingBuffer) Stop() { + if rb.stop == nil { + return + } + close(rb.stop) + rb.wg.Wait() +} + +func (rb *UserRingBuffer) Close() { + if rb.closed { + return + } + + rb.Stop() + C.user_ring_buffer__free(rb.rb) + rb.closed = true +}