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