github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/README.md (about) 1 # GoBPFLD 2 3 [![GoDoc](https://pkg.go.dev/badge/github.com/dylandreimerink/gobpfld)](https://pkg.go.dev/github.com/dylandreimerink/gobpfld) 4 5 GoBPFLD is a pure go eBPF loader/userspace library as an alternative to using [gobpf](https://github.com/iovisor/gobpf) which requires CGO to work. The goal of GoBPFLD is to provide a library for eBPF development which is comparable to libbpf(C library) but without CGO which improves the development experience. 6 7 > **WARNING** GoBPFLD is currently not (yet) feature complete, and may lack critical features for some eBPF program types. This library is still fairly young and the API is still subject to change. 8 9 > **WARNING** GoBPFLD has only been tested on X86_64 machines, due to the nature of interacting with the kernel via syscalls it is likely that architecture dependant bugs may arise. For now it is not recommended to trust this library with any architecture other than X86_64. 10 11 ## Requirements 12 13 eBPF is a Linux specific feature (ignoring [userspace eBPF](https://github.com/generic-ebpf/generic-ebpf)) which was introduced in kernel 3.18. This means that for this library to work the executable must be run on a Linux machine with 3.18 or above. 14 15 This library detects (at runtime) which version of the linux kernel is being used. Higher level features will attempt to fallback to still offer as much functionality as possible. This library attempts to catch the usage of unsupported features and return nice verbose human readable errors. If this fails the kernel will still return an error, which is less verbose. For some features running on a newer kernel version may be required. You can find a great overview of features per kernel version [here](https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md). 16 17 ## Security 18 19 Programs which interact with the kernel via the [bpf syscall](https://man7.org/linux/man-pages/man2/bpf.2.html) need to have extra [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html) if they are not running as the root user. In particular the `CAP_BPF` or `CAP_SYS_ADMIN` capability. `CAP_BPF` is available since kernel 5.8 and is preferred since it has the least privileges needed. If you run on a kernel version lower than 5.8, `CAP_SYS_ADMIN` is the only option you have to grant non-root users access to the `bpf` syscall. In this case it might be a better option to run you program as root and switch to a non-root user when not using the bpf syscall. This can be accomplished by using the [seteuid](https://man7.org/linux/man-pages/man3/seteuid.3p.html) syscall via the [syscall.Seteuid](https://golang.org/pkg/syscall/#Setuid) function. 20 21 Programs that use tracepoints, kprobes, and/or uprobes also require the `CAP_SYS_ADMIN` capability in kernels versions below 5.8. Since kernel 5.8 the `CAP_PERFMON` capability can be assigned which specifically grants the permissions required and no more. 22 23 There are a number of eBPF related vulnerabilities known so far: [CVE-2016-2383](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2383), [CVE-2016-4557](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-4557), [CVE-2021-20268](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-20268). The kernel has the ability to JIT eBPF programs which translates the eBPF instruction into actual machine code to be executed. Not only that but it executes in the kernel with all associated privileges. To ensure that eBPF programs don't access memory outside the eBPF vm, the kernel attempts to detect illegal code, if the verifier fails we have security issues. Programs using this library therefor must be sure that the eBPF programs don't contain user input without sanitization. Even normal features of eBPF such as packet manipulation or dropping may be considered security issues in some cases. More info about eBPF JIT and eBPF hardening can be found in the [cilium reference guide](https://docs.cilium.io/en/latest/bpf/#jit) 24 25 ## Features 26 27 * Pure Go - no CGO, missing libraries, forced dynamic linking, ect. 28 * Load pre-compiled eBPF programs from ELF files 29 * eBPF bytecode decoder 30 * eBPF instructions to bytecode encoder 31 * eBPF clang style assembly parser/assembler 32 * Loading eBPF maps into the kernel 33 * Loading eBPF programs into the kernel 34 * Interacting with eBPF maps (lookup, set, delete, batch-lookup, batch-set, and batch-delete) 35 * Map iterators 36 * Attaching eBPF programs to network interfaces as XDP programs 37 * Attaching eBPF programs to sockets 38 * Attaching eBPF programs to tracepoints, kprobes, and uprobes 39 * XSK/AF_XDP socket support 40 * Go wrappers around all bpf syscall commands 41 * XDP program testing 42 * Array map memory mapping 43 * BTF loading 44 45 ## Motivation 46 47 GoBPFLD is a loader/library to make eBPF tool development in Go smoother. It is not a standalone tool like [bpftool](https://manpages.ubuntu.com/manpages/focal/man8/bpftool-prog.8.html) but rather more like libbpf or gobpf. 48 49 The kernel developers also maintain [libbpf](https://github.com/libbpf/libbpf) which is the most up-to-date library for eBPF program loading. This is great for C or C++ developers, but we userspace programmers would like to also use different programming languages. The most common solution is to create a wrapper library around the C API. In the case of go we would use CGO for this, the downside of CGO is that it has negative effects on features of Go like static linking, dependency management, and cross-compiling. GoBPFLD is written in pure Go so we still retain all the benefits and feature we love in Go. 50 51 Once catch is that there currently is no way(that I know of) to generate eBPF programs from higher level programing languages other than C. Altho technically possible since LLVM is used in clang to compile the programs, it has not yet been done. This means that you will still need to compile any eBPF programs with a clang pipeline if you are not willing to create eBPF programs in eBPF-assembly. But since the eBPF programs are a separate code base the generated ELF files can just be embedded in your Go application or shipped and loaded from file without compromise. 52 53 In a number of use cases you might want to generate an eBPF program completely dynamically, a classic example of this is `tcpdump`. In this case no C code is required at all. As far as I know there are no libraries with specific support for this, and creating the required eBPF bytecode yourself is quite hard. 54 The `ebpf` sub-package attempts to improve the process of crafting your own dynamic programs by providing an abstraction between the instructions and byte representation. The package allows you to decompile a program into its instructions, every instruction has a Go type so properties can be changed without worrying about the binary representation. These instruction types can be used to craft a program fully from Go and to recompile them into a program which can be loaded. The package also provides a assembler which is compatible with the text assembly used by clang, thus allowing you to write your program as an assembly string and turn that into a program. Using the text based assembler can be easier since it allows you to use labels without manually tracking offsets in the instructions. So developers will require some knowledge about the eBPF instruction set, but should be able to focus more on the the functionality of their own application. 55 56 ## Examples 57 58 The cmd/examples directory contains examples programs which demonstrate how to use this library, its capabilities, and the capabilities of eBPF. 59 60 ## eBPF useful links 61 62 * [Cilium BPF and XDP Reference Guide](https://docs.cilium.io/en/stable/bpf/) 63 * [IOVisor eBPF features per kernel version](https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md) 64 * [XDP tutorial and simple examples](https://github.com/xdp-project/xdp-tutorial) 65 * [BPF helper functions manual page](https://man7.org/linux/man-pages/man7/bpf-helpers.7.html) 66 * [Linux kernel (e)BPF socket filter document](https://github.com/torvalds/linux/blob/master/Documentation/networking/filter.rst) 67 * [Linux kernel (e)BPF documentation](https://github.com/torvalds/linux/tree/master/Documentation/bpf) 68 * [Linux kernel example programs](https://github.com/torvalds/linux/tree/master/samples/bpf) 69 70 ## TODO/Roadmap/Scope limits 71 72 As mentioned earlier the first milestone/focus area of this project has been on implementing basic eBPF and XDP related features, and thus is missing a lot of stuff. At some point the API of this library should become backwards compatible along the lines of the [go 1 compatibility promise](https://golang.org/doc/go1compat), though I don't yet know when this will be. 73 74 This is a list of features to be added later, just to keep track. 75 76 ### Must have 77 78 Features/tasks in this list are commonly used/requested because they are used in common use cases / scenarios. 79 80 * ~~Data relocation from ELF files(static global variables)~~ 81 * ~~Attach to sockets~~ 82 * ~~Attach to kprobes~~ 83 * ~~Attach to kretprobes~~ 84 * ~~Attach to uprobes~~ 85 * ~~Attach to tracepoints~~ 86 * ~~Tailcall support~~ 87 * ~~Map pinning and unpinning~~ 88 * ~~Bulk map ops~~ 89 * ~~Program pinning and unpinning~~ 90 * ~~BPF2BPF function calls~~ 91 * ~~Map iterator construct (looping over maps is very common)~~ 92 * Support perf event array maps 93 * Support stack trace maps 94 * Support dev and devhash map 95 * Support sock and sockhash map 96 * Support cpu map 97 * ~~Support queue map~~ 98 * ~~Support stack map~~ 99 * Support ringbuffer map 100 * Attach to tc (traffic control) 101 * ~~Linux kernel version detection (so programs can programmatically decide which features they can use, then error, warn or be backwards compatible)~~ 102 * Library testing framework (We need some way to guarantee the library works, and stays working) 103 * ~~Library+kernel testing, verify the ABI is implemented correctly~~ 104 * Fuzzing, we parse a lot like ELF files, eBPF programs, assembly. Panics are not desirable. 105 * Race condition testing 106 * Cross architecture testing, [QEMU](https://www.qemu.org/) supports [emulation](https://www.qemu.org/docs/master/system/index.html) of other architectures which we should be able to use to test architectures like ARM and RISC-V without dedicated testing hardware. 107 * ~~Cross kernel version testing, we should run the tests on a number of kernels, both older and newer, to test version dependant fallbacks and kernel ABI issues.~~ 108 109 ### Should have 110 111 Features/tasks in this list are not critical for most users but still important for a significant portion. 112 113 * ~~XSK/AF_XDP support (useful for kernel bypass and packet capture)~~ 114 * ~~Map access via memory mapping https://lwn.net/Articles/805043/ (could improve performance)~~ 115 * ~~Map in map support (useful but not widely used)~~ 116 * XSK multiple sockets per netdev,queue pair (currently only one socket per pair is supported) 117 * (partially implemented) Program testing (Being able to unit test an XDP program would be great) 118 * Support reuse port sock array map 119 * Support cGroup storage maps 120 * Support SK storage map 121 * Support struct ops map 122 * Support inode storage map 123 * Support task storage map 124 * Support for LWT programs (Light weight tunnel) 125 * ~~BTF support (So we have more type info to work with, some newer features require BTF support in the loader)~~ 126 * ARM64 support / testing (ARM is on the rise) 127 * ARM32 support / testing (ARM is on the rise) 128 * ELF symbols to offset functionality for perf package 129 130 ### Could have 131 132 Features/tasks in this list are cool to have but secondary to the primary goal of this project. 133 134 * Built-in XSK kernel program (like libbpf) (only useful for people intrested in full kernel bypass without additional logic in XDP/eBPF) 135 * RISC-V support / testing (RISC-V has promise, would be cool, but not yet widely used) 136 * x86_32 support / testing (32 bit is not very popular anymore, but maybe still useful for IOT or raspberry pi like machines) 137 * ~~Userspace VM (It would be cool to be able to run eBPF in Go, for testing or as plugin mechanism like LUA and WASM. But not an important feature related to eBPF loading)~~ 138 * Userspace map caching (Depending on the map flags and eBPF program, maps can be cached in the userspace without requesting value via syscalls (userspace -> kernel only maps)) 139 140 ### Won't have 141 142 Features/tasks in this list are out of the scope of the project. We have to draw the line somewhere to avoid feature creep. 143 144 * cBPF support (cBPF is not even supported by Linux anymore, just converted to eBPF, which you can also do with [tools](https://github.com/cloudflare/cbpfc) for any exiting program)