libbpfgo

package module
v0.2.3-libbpf-0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 10, 2022 License: Apache-2.0 Imports: 9 Imported by: 120

README

libbpfgo


libbpfgo is a Go library for Linux's eBPF project. It was created for Tracee, our open source Runtime Security, and eBPF tracing tool, written in Go. If you are interested in eBPF and its applications, check out Tracee at Github: https://github.com/aquasecurity/tracee.

libbpfgo is built around libbpf - the standard library for interacting with eBPF programs from userspace - which is a C library maintained in Linux upstream. We have created libbpfgo as a thin Go wrapper around the libbpf project.

Installing

libbpfgo uses CGO to interop with libbpf and will expect to be linked with libbpf at run or link time. Simply importing libbpfgo is not enough to get started, and you will need to fulfill the required dependency in one of the following ways:

  1. Install libbpf as a shared object in the system. Libbpf may already be packaged for your distribution and, if not, you can build and install from source. More info here.
  2. Embed libbpf into your Go project as a vendored dependency. This means that the libbpf code is statically linked into the resulting binary, and there are no runtime dependencies. Tracee takes this approach.

Building

Currently you will find the following GNU Makefile rules:

Makefile Rule Description
all builds libbpfgo (dynamic)
clean cleans entire tree
selftest builds all selftests (static)
selftest-run runs all selftests (static)
  • libbpf dynamically linked (libbpf from OS)
Makefile Rule Description
libbpfgo-dynamic builds dynamic libbpfgo (libbpf)
libbpfgo-dynamic-test 'go test' with dynamic libbpfgo
selftest-dynamic build tests with dynamic libbpfgo
selftest-dynamic-run run tests using dynamic libbpfgo
  • statically compiled (libbpf submodule)
Makefile Rule Description
libbpfgo-static builds static libbpfgo (libbpf)
libbpfgo-static-test 'go test' with static libbpfgo
selftest-static build tests with static libbpfgo
selftest-static-run run tests using static libbpfgo
  • examples
$ make libbpfgo-static => libbpfgo statically linked with libbpf
$ make -C selftest/perfbuffers => single selftest build (static libbpf)
$ make -C selftest/perfbuffers run-dynamic => single selftest run (dynamic libbpf)
$ make selftest-static-run => will build & run all static selftests

Note 01: dynamic builds need your OS to have a recent enough libbpf package (and its headers) installed. Sometimes, recent features might require the use of backported OS packages in order for your OS to contain latest libbpf features (sometimes required by libbpfgo). Note 02: static builds need git submodule init first. Make sure to sync the libbpf git submodule before trying to statically compile or test the libbpfgo repository.

Concepts

libbpfgo tries to make it natural for Go developers to use, by abstracting away C technicalities. For example, it will translate low level return codes into Go error, it will organize functionality around Go struct, and it will use channel as to let you consume events.

In a high level, this is a typical workflow for working with the library:

  1. Compile your bpf program into an object file.
  2. Initialize a Module struct - that is a unit of BPF functionality around your compiled object file.
  3. Load bpf programs from the object file using the BPFProg struct.
  4. Attach BPFProg to system facilities, for example to "raw tracepoints" or "kprobes" using the BPFProg's associated functions.
  5. Instantiate and manipulate BPF Maps via the BPFMap struct and it's associated methods.
  6. Instantiate and manipulate Perf Buffer for communicating events from your BPF program to the driving userspace program, using the RingBuffer struct and it's associated objects.

Example

// initializing
import bpf "github.com/aquasecurity/libbpfgo"
...
bpfModule := bpf.NewModuleFromFile(bpfObjectPath)
bpfModule.BPFLoadObject()

// maps
mymap, _ := bpfModule.GetMap("mymap")
mymap.Update(key, value)

// ring buffer
rb, _ := bpfModule.InitRingBuffer("events", eventsChannel, buffSize)
rb.Start()
e := <-eventsChannel

Releases

libbpfgo does not yet have a regular schedule for cutting releases. There has not yet been a major release but API backwards compatibility will be maintained for all releases with the same major release number. Milestones are created when preparing for release.

  • Major releases are cut when backwards compatibility is broken or major milestones are completed, such as reaching parity with libbpf's API.
  • Minor releases are cut to incorporate new support for libbpf APIs.
  • Patch releases are cut to incorporate important individual or groupings of bug fixes.
  • libbpf support numbering indicates the minimum required libbpf version that must be linked in order to ensure libbpfgo compatibility. For example, v0.2.1-libbpf-0.4.0 means that version 0.2.1 of libbpfgo requires v0.4.0 or newer of libbpf.

Note: some distributions might have local changes to their libbpf package and their version might include backports and/or fixes differently than upstream versions. In those cases we recommend that libbpfgo is used statically compiled.

Learn more

Please check our github milestones for an idea of the project roadmap. The general goal is to fully implement/expose libbpf's API in Go as seamlessly as possible.

Documentation

Index

Constants

View Source
const (
	BPFProgTypeUnspec uint32 = iota
	BPFProgTypeSocketFilter
	BPFProgTypeKprobe
	BPFProgTypeSchedCls
	BPFProgTypeSchedAct
	BPFProgTypeTracepoint
	BPFProgTypeXdp
	BPFProgTypePerfEvent
	BPFProgTypeCgroupSkb
	BPFProgTypeCgroupSock
	BPFProgTypeLwtIn
	BPFProgTypeLwtOut
	BPFProgTypeLwtXmit
	BPFProgTypeSockOps
	BPFProgTypeSkSkb
	BPFProgTypeCgroupDevice
	BPFProgTypeSkMsg
	BPFProgTypeRawTracepoint
	BPFProgTypeCgroupSockAddr
	BPFProgTypeLwtSeg6Local
	BPFProgTypeLircMode2
	BPFProgTypeSkReuseport
	BPFProgTypeFlowDissector
	BPFProgTypeCgroupSysctl
	BPFProgTypeRawTracepointWritable
	BPFProgTypeCgroupSockopt
	BPFProgTypeTracing
	BPFProgTypeStructOps
	BPFProgTypeExt
	BPFProgTypeLsm
	BPFProgTypeSkLookup
)

Variables

This section is empty.

Functions

func GetUnsafePointer

func GetUnsafePointer(data interface{}) (unsafe.Pointer, error)

Types

type BPFLink struct {
	// contains filtered or unexported fields
}

func (*BPFLink) Destroy

func (l *BPFLink) Destroy() error

func (*BPFLink) GetFd

func (l *BPFLink) GetFd() int

type BPFMap

type BPFMap struct {
	// contains filtered or unexported fields
}

func (*BPFMap) DeleteKey

func (b *BPFMap) DeleteKey(key unsafe.Pointer) error

DeleteKey takes a pointer to the key which is stored in the map. It removes the key and associated value from the BPFMap. All basic types, and structs are supported as keys.

NOTE: Slices and arrays are also supported but special care should be taken as to take a reference to the first element in the slice or array instead of the slice/array itself, as to avoid undefined behavior.

func (*BPFMap) DeleteKeyBatch

func (b *BPFMap) DeleteKeyBatch(keys unsafe.Pointer, count uint32) error

DeleteKeyBatch will delete `count` keys from the map, returning the keys deleted in the slice pointed to by `keys`.

func (*BPFMap) GetFd

func (b *BPFMap) GetFd() int

func (*BPFMap) GetMaxEntries

func (b *BPFMap) GetMaxEntries() uint32

GetMaxEntries returns the map's capacity. Note: for ring buffer and perf buffer, maxEntries is the capacity in bytes.

func (*BPFMap) GetModule

func (b *BPFMap) GetModule() *Module

func (*BPFMap) GetName

func (b *BPFMap) GetName() string

func (*BPFMap) GetPinPath

func (b *BPFMap) GetPinPath() string

func (*BPFMap) GetValue

func (b *BPFMap) GetValue(key unsafe.Pointer) ([]byte, error)

GetValue takes a pointer to the key which is stored in the map. It returns the associated value as a slice of bytes. All basic types, and structs are supported as keys.

NOTE: Slices and arrays are also supported but special care should be taken as to take a reference to the first element in the slice or array instead of the slice/array itself, as to avoid undefined behavior.

func (*BPFMap) GetValueAndDeleteBatch

func (b *BPFMap) GetValueAndDeleteBatch(keys, startKey, nextKey unsafe.Pointer, count uint32) ([][]byte, error)

GetValueAndDeleteBatch allows for batch lookups of multiple keys and deletes those keys.

func (*BPFMap) GetValueBatch

func (b *BPFMap) GetValueBatch(keys unsafe.Pointer, startKey, nextKey unsafe.Pointer, count uint32) ([][]byte, error)

GetValueBatch allows for batch lookups of multiple keys. The first argument is a pointer to an array or slice of keys which will be populated with the keys returned from this operation. It returns the associated values as a slice of slices of bytes. This API allows for batch lookups of multiple keys, potentially in steps over multiple iterations. For example, you provide the last key seen (or nil) for the startKey, and the first key to start the next iteration with in nextKey. Once the first iteration is complete you can provide the last key seen in the previous iteration as the startKey for the next iteration and repeat until nextKey is nil.

func (*BPFMap) IsPinned

func (b *BPFMap) IsPinned() bool

func (*BPFMap) Iterator

func (b *BPFMap) Iterator() *BPFMapIterator

func (*BPFMap) KeySize

func (b *BPFMap) KeySize() int

func (*BPFMap) Pin

func (b *BPFMap) Pin(pinPath string) error

func (*BPFMap) Resize

func (b *BPFMap) Resize(maxEntries uint32) error

Resize changes the map's capacity to maxEntries. It should be called after the module was initialized but prior to it being loaded with BPFLoadObject. Note: for ring buffer and perf buffer, maxEntries is the capacity in bytes.

func (*BPFMap) SetPinPath

func (b *BPFMap) SetPinPath(pinPath string) error

func (*BPFMap) Unpin

func (b *BPFMap) Unpin(pinPath string) error

func (*BPFMap) Update

func (b *BPFMap) Update(key, value unsafe.Pointer) error

Update takes a pointer to a key and a value to associate it with in the BPFMap. The unsafe.Pointer should be taken on a reference to the underlying datatype. All basic types, and structs are supported

NOTE: Slices and arrays are supported but references should be passed to the first element in the slice or array.

For example:

key := 1
value := []byte{'a', 'b', 'c'}
keyPtr := unsafe.Pointer(&key)
valuePtr := unsafe.Pointer(&value[0])
bpfmap.Update(keyPtr, valuePtr)

func (*BPFMap) UpdateBatch

func (b *BPFMap) UpdateBatch(keys, values unsafe.Pointer, count uint32) error

UpdateBatch takes a pointer to an array of keys and values which are then stored in the map.

func (*BPFMap) ValueSize

func (b *BPFMap) ValueSize() int

type BPFMapBatchOpts

type BPFMapBatchOpts struct {
	Sz        uint64
	ElemFlags uint64
	Flags     uint64
}

BPFMapBatchOpts mirrors the C structure bpf_map_batch_opts.

type BPFMapIterator

type BPFMapIterator struct {
	// contains filtered or unexported fields
}

func (*BPFMapIterator) Err

func (it *BPFMapIterator) Err() error

Err returns the last error that ocurred while table.Iter or iter.Next

func (*BPFMapIterator) Key

func (it *BPFMapIterator) Key() []byte

Key returns the current key value of the iterator, if the most recent call to Next returned true. The slice is valid only until the next call to Next.

func (*BPFMapIterator) Next

func (it *BPFMapIterator) Next() bool

type BPFProg

type BPFProg struct {
	// contains filtered or unexported fields
}

func (*BPFProg) AttachKprobe

func (p *BPFProg) AttachKprobe(kp string) (*BPFLink, error)

this API should be used for kernels > 4.17

func (*BPFProg) AttachKprobeLegacy

func (p *BPFProg) AttachKprobeLegacy(kp string) (*BPFLink, error)

func (*BPFProg) AttachKretprobe

func (p *BPFProg) AttachKretprobe(kp string) (*BPFLink, error)

this API should be used for kernels > 4.17

func (*BPFProg) AttachKretprobeLegacy

func (p *BPFProg) AttachKretprobeLegacy(kp string) (*BPFLink, error)

func (*BPFProg) AttachLSM

func (p *BPFProg) AttachLSM() (*BPFLink, error)

func (*BPFProg) AttachPerfEvent

func (p *BPFProg) AttachPerfEvent(fd int) (*BPFLink, error)

func (*BPFProg) AttachRawTracepoint

func (p *BPFProg) AttachRawTracepoint(tpEvent string) (*BPFLink, error)

func (*BPFProg) AttachTracepoint

func (p *BPFProg) AttachTracepoint(category, name string) (*BPFLink, error)

func (*BPFProg) AttachURetprobe

func (p *BPFProg) AttachURetprobe(pid int, path string, offset uint32) (*BPFLink, error)

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 (*BPFProg) AttachUprobe

func (p *BPFProg) AttachUprobe(pid int, path string, offset uint32) (*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 (*BPFProg) GetFd

func (p *BPFProg) GetFd() int

func (*BPFProg) GetModule

func (p *BPFProg) GetModule() *Module

func (*BPFProg) GetName

func (p *BPFProg) GetName() string

func (*BPFProg) GetPinPath

func (p *BPFProg) GetPinPath() string

func (*BPFProg) GetType

func (p *BPFProg) GetType() uint32

func (*BPFProg) Pin

func (p *BPFProg) Pin(path string) error

func (*BPFProg) SetAutoload

func (p *BPFProg) SetAutoload(autoload bool) error

func (*BPFProg) SetTracepoint

func (p *BPFProg) SetTracepoint() error

func (*BPFProg) Unpin

func (p *BPFProg) Unpin(path string) error

type BPFProgType

type BPFProgType uint32

BPFProgType is an enum as defined in https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/bpf.h

type LinkType

type LinkType int
const (
	Tracepoint LinkType = iota
	RawTracepoint
	Kprobe
	Kretprobe
	KprobeLegacy
	KretprobeLegacy
	LSM
	PerfEvent
	Uprobe
	Uretprobe
)

type Module

type Module struct {
	// contains filtered or unexported fields
}

func NewModuleFromBuffer

func NewModuleFromBuffer(bpfObjBuff []byte, bpfObjName string) (*Module, error)

func NewModuleFromBufferArgs

func NewModuleFromBufferArgs(args NewModuleArgs) (*Module, error)

func NewModuleFromFile

func NewModuleFromFile(bpfObjPath string) (*Module, error)

func NewModuleFromFileArgs

func NewModuleFromFileArgs(args NewModuleArgs) (*Module, error)

func (*Module) BPFLoadObject

func (m *Module) BPFLoadObject() error

func (*Module) Close

func (m *Module) Close()

func (*Module) GetMap

func (m *Module) GetMap(mapName string) (*BPFMap, error)

func (*Module) GetProgram

func (m *Module) GetProgram(progName string) (*BPFProg, error)

func (*Module) InitPerfBuf

func (m *Module) InitPerfBuf(mapName string, eventsChan chan []byte, lostChan chan uint64, pageCnt int) (*PerfBuffer, error)

func (*Module) InitRingBuf

func (m *Module) InitRingBuf(mapName string, eventsChan chan []byte) (*RingBuffer, error)

func (*Module) TcHookInit

func (m *Module) TcHookInit() *TcHook

type NewModuleArgs

type NewModuleArgs struct {
	KConfigFilePath string
	BTFObjPath      string
	BPFObjName      string
	BPFObjPath      string
	BPFObjBuff      []byte
}

type PerfBuffer

type PerfBuffer struct {
	// contains filtered or unexported fields
}

func (*PerfBuffer) Close

func (pb *PerfBuffer) Close()

func (*PerfBuffer) Start

func (pb *PerfBuffer) Start()

func (*PerfBuffer) Stop

func (pb *PerfBuffer) Stop()

type RingBuffer

type RingBuffer struct {
	// contains filtered or unexported fields
}

func (*RingBuffer) Close

func (rb *RingBuffer) Close()

func (*RingBuffer) Start

func (rb *RingBuffer) Start()

func (*RingBuffer) Stop

func (rb *RingBuffer) Stop()

type TcAttachPoint

type TcAttachPoint uint32
const (
	BPFTcIngress       TcAttachPoint = C.BPF_TC_INGRESS
	BPFTcEgress        TcAttachPoint = C.BPF_TC_EGRESS
	BPFTcIngressEgress TcAttachPoint = C.BPF_TC_INGRESS | C.BPF_TC_EGRESS
	BPFTcCustom        TcAttachPoint = C.BPF_TC_CUSTOM
)

type TcFlags

type TcFlags uint32
const (
	BpfTcFReplace TcFlags = C.BPF_TC_F_REPLACE
)

type TcHook

type TcHook struct {
	// contains filtered or unexported fields
}

func (*TcHook) Attach

func (hook *TcHook) Attach(tcOpts *TcOpts) error

func (*TcHook) Create

func (hook *TcHook) Create() error

func (*TcHook) Destroy

func (hook *TcHook) Destroy() error

func (*TcHook) Detach

func (hook *TcHook) Detach(tcOpts *TcOpts) error

func (*TcHook) GetInterfaceIndex

func (hook *TcHook) GetInterfaceIndex() int

func (*TcHook) Query

func (hook *TcHook) Query(tcOpts *TcOpts) error

func (*TcHook) SetAttachPoint

func (hook *TcHook) SetAttachPoint(attachPoint TcAttachPoint)

func (*TcHook) SetInterfaceByIndex

func (hook *TcHook) SetInterfaceByIndex(ifaceIdx int)

func (*TcHook) SetInterfaceByName

func (hook *TcHook) SetInterfaceByName(ifaceName string) error

func (*TcHook) SetParent

func (hook *TcHook) SetParent(a int, b int)

type TcOpts

type TcOpts struct {
	ProgFd   int
	Flags    TcFlags
	ProgId   uint
	Handle   uint
	Priority uint
}

Directories

Path Synopsis
selftest
iter Module
iterators Module
log-callbacks Module
map-pin-info Module
map-update Module
perfbuffers Module
tracing Module
uprobe Module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL