Detection And Blocking With BPF Via YAML
BPF allows us to do great things – from hooking practically any kernel function, to blocking actions and killing processes – but it can be quite difficult to use! Wouldn’t it be amazing if you could just write some YAML and a pre-existing, mature, open source, BPF engine did all the hard work? And sent events to your logs? And your email? And maybe even to your phone as a SMS text message, and to your Slack channel? With OSS Tetragon you can! In this talk I will show you how to monitor and block actions with BPF, without actually writing any BPF.
Tetragon is an open source BPF tool that can be configured with YAML to hook almost any kernel function, and any syscall and any tracepoint; interpret the input arguments, make pre-defined decisions based on them, as well as the process instigating them; and then log, trigger or block as a result.
BPF is a revolutionary technology that can be used to run portable code in the kernel, safely, and with great reach. BPF programs can communicate with each other, and with user space, via maps – arrays, hashes, ring buffers, and various other data structures that can be used to store, check and pass data around. As a technology, it has existed for a number of years, and still underpins libpcap today, but it can be quite tricky to use. BPF implements its own virtual architecture, that is portable between different versions of kernel, and even different underlying processors.
The difficulties of programming BPF come partly from the language, but mostly from the verifier. BPF itself is an assembly language with a minimal library of helper functions – you can’t just call any kernel function! It can be compiled from C and rust, and probably other mid-to-low-level languages, and this can be a barrier to those who prefer the higher-level python and .Net. That said, BPF programs tend to be simple, and it is possible to learn enough C (and the special LLVM/Clang incantations) to get a BPF program compiled.
But then in steps the verifier – the gatekeeper that many novice (and even experienced) BPF programmers dread. In order to ensure safety, the verifier checks every BPF program as it is loaded into the kernel, and rejects those that it can’t vouch for. It checks for length and complexity, to ensure programs will always exit; it checks that memory access is bounded and restricted to that allowed; and it checks that only permitted helpers are used, which vary from program type to program type, and attachment point to attachment point.
Satisfying the verifier is the problem that many find the most troubling. To overcome this, the open source Tetragon can be used to abstract all the BPF into YAML, making it much easier to use. All the programming and verifier issues are hidden, and the user just has to specify where they want to hook, what they want to inspect at that point, and what action they want to take if their criteria is met. By default Tetragon can log events to user space, but it can also track file descriptors between programs, it can kill processes directly from the kernel, and it can also trigger web hooks, such as those provided by canary tokens and Thinkst Canaries.
If you want to detect and block on Linux, then you really need to do this from inside the kernel. BPF, and Tetragon, provide the tools to do just that. I will demonstrate typical use cases with simple YAML files that audience members can take away and try for themselves.