github.com/cilium/ebpf@v0.16.0/docs/ebpf/concepts/rlimit.md (about) 1 # Resource Limits 2 3 Creating eBPF objects (Maps, Programs, even BTF blobs) requires kernel memory 4 allocation. Before kernel version 5.11, the memory available to a process for 5 creating eBPF objects was restricted by its `RLIMIT_MEMLOCK` rlimit value, 6 visible through the `ulimit -l` command. 7 8 Starting with [version 9 5.11](https://lore.kernel.org/bpf/20201201215900.3569844-1-guro@fb.com), the 10 Linux kernel switched from rlimits to memory cgroup (memcg) accounting for 11 managing memory limits on processes handling eBPF objects in the kernel. eBPF 12 object allocations are tracked alongside regular allocations within the cgroup. 13 Memory consumption and limits can be queried and set through cgroupfs, the same 14 mechanism used for setting memory limits on containers. 15 16 ## Purpose of package `rlimit` 17 18 On kernels supporting memcg accounting, there's no need to manage 19 `RLIMIT_MEMLOCK` for effectively using eBPF, as eBPF object allocations now 20 count towards the cgroup memory limit instead. However, since many Linux 21 distributions still ship pre-5.11 kernels, it's necessary to conditionally 22 manage rlimit for kernels lacking memcg accounting for eBPF. 23 24 To support writing portable Go tools that work across various kernel versions, 25 the `rlimit` package was introduced. It encapsulates two behaviours: 26 27 1. As an **import side effect** of importing the package, it lowers the rlimit 28 of the current process to induce a Map creation failure, then restores the 29 original rlimit. 30 2. {{ godoc('rlimit/RemoveMemlock') }} conditionally increases `RLIMIT_MEMLOCK` 31 to infinity based on the probe's result. If the kernel supports memcg 32 accounting, this is a no-op. 33 34 ## Usage 35 36 Include this in your application: 37 38 {{ go_example('DocRlimit', title="Remove RLIMIT_MEMLOCK if kernel lacks memcg accounting") }} 39 40 !!! note "" 41 You can call `RemoveMemlock()` multiple times if your program has 42 multiple entry points or CLI subcommands. The rlimit operation will only 43 execute once. 44 45 ## Caveats 46 47 ### Race Conditions 48 49 The package was carefully designed with Go's runtime initialization semantics in 50 mind, meaning only one `init()` will execute at a time across all packages, 51 minimizing the risk of racing against other callers to `prlimit(2)` (which 52 should hopefully be rare). 53 54 The rlimit package first gets the process' current `RLIMIT_MEMLOCK` value, drops 55 it to 0, attempts to create a BPF map, then finally resets the rlimit to the old 56 value. It's important to note that this happens **before invoking** 57 `RemoveMemlock()` and has two potential side effects: 58 59 - On kernels before 5.11, other concurrent BPF object creations may fail due to 60 insufficient memory being available while the rlimit is at 0. 61 - Other Go packages interacting with `prlimit(2)` may interfere with this 62 process, leading to a wrong `RLIMIT_MEMLOCK` value being read or restored. 63 Please audit your code and dependencies for potential conflicts. 64 65 ### Why does my application always create a Map on startup? 66 67 !!! note "" 68 The `rlimit` package is entirely optional and serves as a convenience 69 feature. 70 71 Since the package creates a Map from `init()`, there is currently no way to 72 prevent your application from interacting with `bpf(2)`, even if 73 `RemoveMemlock()` is never invoked or if none of your application's eBPF 74 features remain disabled. We consider this a reasonable trade-off to provide 75 maximum value for the majority of use cases. 76 77 If this is not desirable, you can avoid using package `rlimit` altogether and 78 increase the rlimit through other means like Docker's `--ulimit memlock=-1` flag 79 or systemd's `LimitMEMLOCK=infinity` unit limit property. 80