Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap bpf_prog_attach and bpf_prog_detach2 #335

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions libbpfgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -1711,6 +1711,35 @@ func doAttachUprobe(prog *BPFProg, isUretprobe bool, pid int, path string, offse
return bpfLink, nil
}

type AttachFlag uint32

const (
BPFFNone AttachFlag = 0
BPFFAllowOverride AttachFlag = C.BPF_F_ALLOW_OVERRIDE
BPFFAllowMulti AttachFlag = C.BPF_F_ALLOW_MULTI
BPFFReplace AttachFlag = C.BPF_F_REPLACE
)

// AttachGenericFD attaches the BPFProgram to a targetFd at the specified attachType hook.
func (p *BPFProg) AttachGenericFD(targetFd int, attachType BPFAttachType, flags AttachFlag) error {
progFd := C.bpf_program__fd(p.prog)
errC := C.bpf_prog_attach(progFd, C.int(targetFd), C.enum_bpf_attach_type(int(attachType)), C.uint(uint(flags)))
if errC < 0 {
return fmt.Errorf("failed to attach: %w", syscall.Errno(-errC))
}
return nil
}

// DetachGenericFD detaches the BPFProgram associated with the targetFd at the hook specified by attachType.
func (p *BPFProg) DetachGenericFD(targetFd int, attachType BPFAttachType) error {
progFd := C.bpf_program__fd(p.prog)
errC := C.bpf_prog_detach2(progFd, C.int(targetFd), C.enum_bpf_attach_type(int(attachType)))
if errC < 0 {
return fmt.Errorf("failed to detach: %w", syscall.Errno(-errC))
}
return nil
}

var eventChannels = newRWArray(maxEventChannels)

func (m *Module) InitRingBuf(mapName string, eventsChan chan []byte) (*RingBuffer, error) {
Expand Down
1 change: 1 addition & 0 deletions selftest/attachgenericfd/Makefile
9 changes: 9 additions & 0 deletions selftest/attachgenericfd/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module github.com/aquasecurity/libbpfgo/selftest/attachgenericfd

go 1.18

require github.com/aquasecurity/libbpfgo v0.4.7-libbpf-1.2.0-b2e29a1

require golang.org/x/sys v0.9.0 // indirect

replace github.com/aquasecurity/libbpfgo => ../../
6 changes: 6 additions & 0 deletions selftest/attachgenericfd/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
28 changes: 28 additions & 0 deletions selftest/attachgenericfd/main.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//+build ignore

#include <vmlinux.h>

#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

struct {
__uint(type, BPF_MAP_TYPE_SOCKMAP);
__uint(max_entries, 1);
__type(key, int);
__type(value, int);
} sock_map_rx SEC(".maps");

SEC("sk_skb/stream_parser")
int bpf_prog_parser(struct __sk_buff *skb)
{
return skb->len;
}

SEC("sk_skb/stream_verdict")
int bpf_prog_verdict(struct __sk_buff *skb)
{
int idx = 0;
return bpf_sk_redirect_map(skb, &sock_map_rx, idx, 0);
}

char LICENSE[] SEC("license") = "GPL";
102 changes: 102 additions & 0 deletions selftest/attachgenericfd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package main

import "C"

import (
"fmt"
"net"
"os"
"unsafe"

bpf "github.com/aquasecurity/libbpfgo"
"golang.org/x/sys/unix"
)

func main() {
bpfModule, err := bpf.NewModuleFromFile("main.bpf.o")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
defer bpfModule.Close()

err = bpfModule.BPFLoadObject()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}

serverFD, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, unix.IPPROTO_IP)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
defer unix.Close(serverFD)
serverAddr := &unix.SockaddrInet4{
Port: 22345,
Addr: [4]byte{127, 0, 0, 1},
}
if err := unix.Bind(serverFD, serverAddr); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
if err := unix.Listen(serverFD, 100); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}

sockMapRx, err := bpfModule.GetMap("sock_map_rx")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}

prog1, err := bpfModule.GetProgram("bpf_prog_parser")
prog1.AttachGenericFD(sockMapRx.FileDescriptor(),
bpf.BPFAttachTypeSKSKBStreamParser, bpf.BPFFNone)
defer func() {
if err := prog1.DetachGenericFD(sockMapRx.FileDescriptor(), bpf.BPFAttachTypeSKSKBStreamParser); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
}()
prog2, err := bpfModule.GetProgram("bpf_prog_verdict")
prog2.AttachGenericFD(sockMapRx.FileDescriptor(),
bpf.BPFAttachTypeSKSKBStreamVerdict, bpf.BPFFNone)
defer func() {
if err := prog2.DetachGenericFD(sockMapRx.FileDescriptor(), bpf.BPFAttachTypeSKSKBStreamVerdict); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
}()

go func() {
acceptedFD, _, err := unix.Accept(serverFD)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
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)
}
}()

c, err := net.Dial("tcp", "127.0.0.1:22345")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
defer c.Close()
if _, err = c.Write([]byte("foobar")); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
data := make([]byte, 10)
if _, err = c.Read(data); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}
}
1 change: 1 addition & 0 deletions selftest/attachgenericfd/run.sh