github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/docs/ebpf/concepts/object-lifecycle.md (about) 1 !!! info "" 2 This is an advanced topic and does not need to be fully understood in order 3 to get started writing useful tools. 4 5 If you find yourself debugging unexpectedly-detached programs, resource 6 leaks, or you want to gain a deeper understanding of how eBPF objects are 7 managed by {{ proj }}, this page should prove helpful. 8 9 ## File Descriptors and Go 10 11 Interacting with eBPF objects from user space is done using file descriptors. 12 Counter-intuitively, 'file' descriptors are used as references to many types of 13 kernel resources in modern Linux, not just files. In {{ proj }}, {{ godoc('Map') 14 }}, {{ godoc('Program') }} and {{ godoc('link/Link') }} are all modeled around 15 these underlying file descriptors. 16 17 Go, being a garbage-collected language, automatically manages the lifecycle of 18 Go objects. Keeping in line with the standard library's `os.File` and friends, 19 eBPF resources in {{ proj }} were designed in a way so their underlying file 20 descriptors are closed when their Go objects are garbage collected. This 21 generally prevents runaway resource leaks, but is not without its drawbacks. 22 23 This has subtle but important repercussions for BPF, since this means the Go 24 runtime will call `Close()` on an object's underlying file descriptor if the 25 object is no longer reachable by the garbage collector. For example, this can 26 happen if an object is created in a function, but is not returned to the caller. 27 One type of map, {{ godoc('ProgramArray') }}, is particularly sensitive to this. 28 More about that in [Program Arrays](#program-arrays). 29 30 ## Extending Object Lifetime 31 32 ### Pinning 33 34 Aside from file descriptors, BPF provides another method of creating references 35 to eBPF objects: pinning. This is the concept of associating a file on a virtual 36 file system (the BPF File System, bpffs for short) with a BPF resource like a 37 Map, Program or Link. Pins can be organized into arbitrary directory structures, 38 just like on any other file system. 39 40 When the Go process exits, the pin will maintain a reference to the object, 41 preventing it from being automatically destroyed. In this scenario, removing the 42 pin using plain `rm` will remove the last reference, causing the kernel to 43 destroy the object. If you're holding an active object in Go, you can also call 44 {{ godoc('Map.Unpin') }}, {{ godoc('Program.Unpin') }} or {{ 45 godoc('link/Link.Unpin') }} if the object was previously pinned. 46 47 !!! warning 48 Pins do **not** persist through a reboot! 49 50 A common use case for pinning is sharing eBPF objects between processes. For 51 example, one could create a Map from Go, pin it, and inspect it using `bpftool 52 map dump pinned /sys/fs/bpf/my_map`. 53 54 ### Attaching 55 56 Attaching a Program to a hook acts as a reference to a Program, since the kernel 57 needs to be able to execute the program's instructions at any point. 58 59 For legacy reasons, some {{ godoc('link/Link') }} types don't support pinning. 60 It is generally safe to assume these links will persist beyond the lifetime of 61 the Go application. 62 63 ## :warning: Program Arrays 64 65 A {{ godoc('ProgramArray') }} is a Map type that holds references to other 66 Programs. This allows programs to 'tail call' into other programs, useful for 67 splitting up long and complex programs. 68 69 Program Arrays have a unique property: they allow cyclic dependencies to be 70 created between the Program Array and a Program (e.g. allowing programs to call 71 into themselves).To avoid ending up with a set of programs loaded into the 72 kernel that cannot be freed, the kernel maintains a hard rule: **Program Arrays 73 require at least one open file descriptor or bpffs pin**. 74 75 !!! warning 76 If all user space/bpffs references are gone, **any tail calls into the array 77 will fail**, but the Map itself will remain loaded as long as there are 78 programs that use it. This property, combined with interactions with Go's 79 garbage collector previously described in [File Descriptors and 80 Go](#file-descriptors-and-go), is a great source of bugs. 81 82 A few tips to handle this problem correctly: 83 84 - Use {{ godoc('CollectionSpec.LoadAndAssign') }}. It will refuse to load the 85 CollectionSpec if doing so would result in a Program Array without a userspace 86 reference. 87 - Pin Program Arrays if execution of your eBPF code needs to continue past the 88 lifetime of your Go application, e.g. for upgrades or short-lived CLI tools. 89 - Retain references to the Map at all times in long-running applications. Note 90 that `#!go defer m.Close()` makes Go retain a reference until the end of the 91 current scope.