eBPF library for Go based on Linux libbpf

Related tags

golang bpf
Overview

libbpfgo


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

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

Installing

libbpfgo is using 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 the libbpf as a shared object in the system. Libbpf may already be packaged for you distribution, 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 and you can take example from it's Makefile.

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

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.

Learn more

Issues
  • Use map definition for key and value sizes instead of arguments

    Use map definition for key and value sizes instead of arguments

    Previously this was quite error prone and somewhat unnecessary, as one had to keep sizes consistent in Go and C code, but we can actually read the sizes from the map definition improving developer experience and making the API less error prone.

    Already verified these changes in my usage of libbpfgo.

    @grantseltzer @yanivagman @eyakubovich

    opened by brancz 12
  • Uprobe support

    Uprobe support

    This allows users to use the libbpf API for uprobes. This gives you the ability to safely attach to symbols in a userspace binary.

    The API allows users to specify a pid, binary, and symbol name. We could instead have the API allow users to specify specific offsets (instead of symbols) and then make the symbol->offset resolution a public helper function.

    Before we merge this i'd like to verify how architecture specific this is. Right now symbol resolution is handled by parsing ELF binaries. We should think about if there's another object format we should support

    opened by grantseltzer 3
  • Add selftest and run script for map iterator

    Add selftest and run script for map iterator

    opened by grantseltzer 1
  • add tc api

    add tc api

    This PR adds the low level tc api as described in https://github.com/libbpf/libbpf/commit/d71ff87a2dd7b92787719aab233767e9c74fbd48

    opened by yanivagman 1
  • Add uprobe support to libbpfgo

    Add uprobe support to libbpfgo

    I have an example of using uprobes with libbpf here

    opened by grantseltzer 0
  • Create selftest for map iterators

    Create selftest for map iterators

    opened by grantseltzer 0
  • Improve readme intro

    Improve readme intro

    opened by itaysk 0
  • Add LICENSE file

    Add LICENSE file

    @itaysk I'm copying this over from Tracee, just want to double check with you on it.

    opened by grantseltzer 0
  • Readme improvements

    Readme improvements

    • Add logo (The tux image is released via a permisive CC license)
    • Fix numbering markdown
    • Add "Learn More" section

    Signed-off-by: grantseltzer [email protected]

    opened by grantseltzer 0
  • Ensure support for libbpf 0.4

    Ensure support for libbpf 0.4

    libbpf just released 0.4: https://github.com/libbpf/libbpf/releases

    We should link against git submodules of different versions of libbpf and run our selftests

    libbpf-1.0-prep 
    opened by grantseltzer 0
  • Add a selftest for the TC API

    Add a selftest for the TC API

    We recently merged #24 which adds support for the new libbpf (0.4) tc API. We need to add a small selftest for this as well

    opened by yanivagman 0
  • Add support for fentry/fexit bpf program type

    Add support for fentry/fexit bpf program type

    Documentation is non-existent so here's a dump of different links that have some info on kfuncs:

    Good example: https://github.com/libbpf/libbpf-bootstrap

    https://lwn.net/Articles/804112/

    https://github.com/iovisor/bpftrace/issues/1833

    opened by grantseltzer 0
  • Implement libbpf bpf_map API

    Implement libbpf bpf_map API

    We should expose all of the bpf_map api, just being careful about what is deprecated and/or discouraged when 1.0 is released.

    • [ ] bpf_map__def
    • [ ] bpf_map__name
    • [ ] bpf_map__type
    • [ ] bpf_map__set_type
    • [ ] bpf_map__max_entries
    • [ ] bpf_map__set_max_entries
    • [ ] bpf_map__resize (alias of above, probably shouldn't be exposed)
    • [ ] bpf_map_map_flags
    • [ ] bpf_map__set_map_flags
    • [ ] bpf_map__numa_node
    • [ ] bpf_map__set_numa_node
    • [ ] bpf_map__key_size
    • [ ] bpf_map__set_key_size
    • [ ] bpf_map__value_size
    • [ ] bpf_map__set_value_size
    • [ ] bpf_map__btf_key_type_id
    • [ ] bpf_map__btf_value_type_id
    • [ ] bpf_map__ifindex
    • [ ] bpf_map__set_ifindex
    • [ ] bpf_map__fd
    • [ ] bpf_map__reuse_fd
    • [ ] bpf_map__priv
    • [ ] bpf_map__set_priv
    • [ ] bpf_map__set_initial_value
    • [ ] bpf_map__is_offload_neutral
    • [ ] bpf_map__is_internal
    • [ ] bpf_map__set_pin_path
    • [ ] bpf_map__is_pinned
    • [ ] bpf_map__pin
    • [ ] bpf_map__unpin
    • [ ] bpf_map__inner_map
    • [ ] bpf_map__set_inner_map_fd
    opened by grantseltzer 0
  • Use bpf_map__set_max_entries instead of bpf_map__resize

    Use bpf_map__set_max_entries instead of bpf_map__resize

    bpf_map__resize is an alias of bpf_map__set_max_entries, and use of it is discouraged.

    libbpf-1.0-prep 
    opened by grantseltzer 0
  • Use bpf_object__open_mem/bpf_object__open_file in NewModuleFromFile

    Use bpf_object__open_mem/bpf_object__open_file in NewModuleFromFile

    In the libbpf public 1.0 roadmap it states that bpf_object__open (how we currently open bpf objects) will be deprecated in favor of bpf_object__open_mem and bpf_object__open_file.

    libbpf-1.0-prep 
    opened by grantseltzer 0
  • Verify checking of errno is correct low level APIs, and deprecation post 1.0

    Verify checking of errno is correct low level APIs, and deprecation post 1.0

    Currently low level libbpf APIs, specifically APIs in bpf.h use errno for representing errors. In 1.0 this will be completely removed and all error codes will be returned directly from API functions.

    libbpf-1.0-prep 
    opened by grantseltzer 0
  • Using `go get` causes linker errors

    Using `go get` causes linker errors

    When building a project that uses libbpfgo, the go compiler must be given a linker flag pointing to libbpf. If libbpf is installed in a standard location -lbpf can be passed. They can also point to a specific location. Since go get attempts to build the package without any ldflags, this will cause the errors pasted below.

    Users could do something like: CGO_LDFLAGS="-lbpf" go get github.com/aquasecurity/tracee. Alternatively we can add a line for CGO_LDFLAGS in the CGO code.

    This shouldn't cause any related issues if not using go get.

    For example:

    [*] go get github.com/aquasecurity/libbpfgo
    
    go: downloading github.com/aquasecurity/libbpfgo v0.0.0-20210517223445-485e1cdc10ae
    go: downloading golang.org/x/sys v0.0.0-20210514084401-e8d321eab015
    # github.com/aquasecurity/libbpfgo
    /usr/bin/ld: $WORK/b001/_x003.o: in function `init_ring_buf':
    ../../../../../pkg/mod/github.com/aquasecurity/[email protected]/libbpfgo.go:40: undefined reference to `ring_buffer__new'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `init_perf_buf':
    ../../../../../pkg/mod/github.com/aquasecurity/[email protected]/libbpfgo.go:54: undefined reference to `perf_buffer__new'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `attach_kprobe_legacy':
    ../../../../../pkg/mod/github.com/aquasecurity/[email protected]/libbpfgo.go:158: undefined reference to `bpf_program__attach_perf_event'
    /usr/bin/ld: ../../../../../pkg/mod/github.com/aquasecurity/[email protected]/libbpfgo.go:159: undefined reference to `libbpf_get_error'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_link__destroy':
    /tmp/go-build/cgo-gcc-prolog:74: undefined reference to `bpf_link__destroy'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map__fd':
    /tmp/go-build/cgo-gcc-prolog:93: undefined reference to `bpf_map__fd'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map__max_entries':
    /tmp/go-build/cgo-gcc-prolog:112: undefined reference to `bpf_map__max_entries'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map__pin':
    /tmp/go-build/cgo-gcc-prolog:132: undefined reference to `bpf_map__pin'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map__resize':
    /tmp/go-build/cgo-gcc-prolog:153: undefined reference to `bpf_map__resize'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map__set_pin_path':
    /tmp/go-build/cgo-gcc-prolog:173: undefined reference to `bpf_map__set_pin_path'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map__unpin':
    /tmp/go-build/cgo-gcc-prolog:193: undefined reference to `bpf_map__unpin'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map_delete_elem':
    /tmp/go-build/cgo-gcc-prolog:214: undefined reference to `bpf_map_delete_elem'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map_lookup_elem':
    /tmp/go-build/cgo-gcc-prolog:236: undefined reference to `bpf_map_lookup_elem'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_map_update_elem':
    /tmp/go-build/cgo-gcc-prolog:259: undefined reference to `bpf_map_update_elem'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_object__find_map_by_name':
    /tmp/go-build/cgo-gcc-prolog:290: undefined reference to `bpf_object__find_map_by_name'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_object__find_program_by_name':
    /tmp/go-build/cgo-gcc-prolog:309: undefined reference to `bpf_object__find_program_by_name'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_object__load':
    /tmp/go-build/cgo-gcc-prolog:328: undefined reference to `bpf_object__load'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_object__open':
    /tmp/go-build/cgo-gcc-prolog:346: undefined reference to `bpf_object__open'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_object__open_buffer':
    /tmp/go-build/cgo-gcc-prolog:366: undefined reference to `bpf_object__open_buffer'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_program__attach_kprobe':
    /tmp/go-build/cgo-gcc-prolog:387: undefined reference to `bpf_program__attach_kprobe'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_program__attach_lsm':
    /tmp/go-build/cgo-gcc-prolog:405: undefined reference to `bpf_program__attach_lsm'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_program__attach_raw_tracepoint':
    /tmp/go-build/cgo-gcc-prolog:424: undefined reference to `bpf_program__attach_raw_tracepoint'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_program__attach_tracepoint':
    /tmp/go-build/cgo-gcc-prolog:444: undefined reference to `bpf_program__attach_tracepoint'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_program__fd':
    /tmp/go-build/cgo-gcc-prolog:463: undefined reference to `bpf_program__fd'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_program__get_type':
    /tmp/go-build/cgo-gcc-prolog:482: undefined reference to `bpf_program__get_type'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_program__set_autoload':
    /tmp/go-build/cgo-gcc-prolog:503: undefined reference to `bpf_program__set_autoload'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_program__set_tracepoint':
    /tmp/go-build/cgo-gcc-prolog:522: undefined reference to `bpf_program__set_tracepoint'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_perf_buffer__poll':
    /tmp/go-build/cgo-gcc-prolog:607: undefined reference to `perf_buffer__poll'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_ring_buffer__poll':
    /tmp/go-build/cgo-gcc-prolog:661: undefined reference to `ring_buffer__poll'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `set_print_fn':
    ../../../../../pkg/mod/github.com/aquasecurity/[email protected]/libbpfgo.go:35: undefined reference to `libbpf_set_print'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_bpf_object__close':
    /tmp/go-build/cgo-gcc-prolog:274: undefined reference to `bpf_object__close'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_perf_buffer__free':
    /tmp/go-build/cgo-gcc-prolog:589: undefined reference to `perf_buffer__free'
    /usr/bin/ld: $WORK/b001/_x003.o: in function `_cgo_a66f50300837_Cfunc_ring_buffer__free':
    /tmp/go-build/cgo-gcc-prolog:643: undefined reference to `ring_buffer__free'
    collect2: error: ld returned 1 exit status
    
    bug 
    opened by grantseltzer 0
  • Global application configuration

    Global application configuration

    This article section describes how globals can be used to configure a BPF program before loading. I'm curious if we could have some helpers for setting some simple configurations from Go. For my use case, I want to configure a single uint32, for which an entire map and the lookup overhead seem a little drastic. Any ideas on how we could maybe achieve this?

    @yanivagman @eyakubovich @grantseltzer

    opened by brancz 4
  • add examples and getting started guide to libbpfgo

    add examples and getting started guide to libbpfgo

    add example "hello world" programs, a sample makefile, etc. related: https://github.com/lizrice/libbpfgo-beginners

    opened by itaysk 0
Releases(v0.1.1)
  • v0.1.1(Jun 15, 2021)

    The main new feature of this release is support for loading/attaching of tc bpf programs.

    • Adds support for tc programs
    • Adds support for uprobe programs
    • Selftests
    • Improved logo
    • Improved README
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(May 19, 2021)

    An initial baseline release which includes the following features:

    • Loading of bpf objects to initialize a type Module.
    • Attachment of bpf programs to hooks of the following types:
      • Kprobe
      • Kretprobe
      • LSM
      • Raw tracepoint
      • tracepoint
    • A generic BPFMap mechanism for interacting with (updating, getting values, deleting keys, iterating, resizing,...) bpf maps.
    • Reading of perf buffers and ring buffers

    See the discussion here about moving libbpfgo to its own repository from tracee.

    Source code(tar.gz)
    Source code(zip)
Owner
Aqua Security
Full lifecycle security for containers and cloud-native applications
Aqua Security
Library to work with eBPF programs from Go

Go eBPF A nice and convenient way to work with eBPF programs / perf events from Go. Requirements Go 1.10+ Linux Kernel 4.15+ Supported eBPF features e

Dropbox 705 Jun 14, 2021
NFF-Go -Network Function Framework for GO (former YANFF)

Network Function Framework for Go (former YANFF) Wonderful news : we are now supporting AF_XDP and supporting(almost) getting packets directly from Li

Intel Go Team 1.1k Jun 13, 2021
Trace Go program execution with uprobes and eBPF

Weaver PLEASE READ! - I am currently refactoring Weaver to use libbpf instead of bcc which would include various other major improvements. If you're c

grantseltzer 186 May 18, 2021
eBPF based TCP observability.

TCPDog is a total solution from exporting TCP statistics from Linux kernel by eBPF very efficiently to store them at your Elasticsearch or InfluxDB da

Mehrdad Arshad Rad 127 May 18, 2021
Packiffer is a lightweight cross-platform networking toolkit that let you sniff/analyze/inject/filter packets.

Packiffer is a lightweight cross-platform networking toolkit that let you sniff/analyze/inject/filter packets.

Massoud Asadi 41 Jun 3, 2021
netcat using netstack userspace library

netkat netcat version using raw sockets to avoid iptables and/or other OS filtering mechanisms. Install make build Usage It requires root privileges:

Antonio Ojea 91 Jun 17, 2021
Official IVPN Desktop app

IVPN for Desktop (Windows/macOS/Linux) IVPN for Desktop is the official IVPN app for desktop platforms. Some of the features include: multiple protoco

IVPN 8 Jun 13, 2021
IPFS implementation in Go

go-ipfs What is IPFS? IPFS is a global, versioned, peer-to-peer filesystem. It combines good ideas from previous systems such as Git, BitTorrent, Kade

IPFS 11.5k Jun 12, 2021
Network-wide ads & trackers blocking DNS server

Privacy protection center for you and your devices Free and open source, powerful network-wide ads & trackers blocking DNS server. AdGuard.com | Wiki

AdGuard 8k Jun 17, 2021
Automatically spawn a reverse shell fully interactive for Linux or Windows victim

Girsh (Golang Interactive Reverse SHell) Who didn't get bored of manually typing the few lines to upgrade a reverse shell to a full interactive revers

null 161 Jun 11, 2021
:alarm_clock: :fire: A TCP proxy to simulate network and system conditions for chaos and resiliency testing

Toxiproxy Toxiproxy is a framework for simulating network conditions. It's made specifically to work in testing, CI and development environments, supp

Shopify 5.5k Jun 12, 2021
Deskreen turns any device with a web browser into a secondary screen for your computer

Deskreen Website: https://deskreen.com ▶️ Deskreen Youtube channel (video tutorials, demos, use cases for Deskreen day to day usage) Deskreen turns an

Paul Pavlo Buidenkov 10.8k Jun 14, 2021
🚀 gnet is a high-performance, lightweight, non-blocking, event-driven networking framework written in pure Go./ gnet 是一个高性能、轻量级、非阻塞的事件驱动 Go 网络框架。

English | ???? 中文 ?? Introduction gnet is an event-driven networking framework that is fast and lightweight. It makes direct epoll and kqueue syscalls

Andy Pan 4.7k Jun 13, 2021