1.. SPDX-License-Identifier: GPL-2.0 2 3============ 4BPF signing 5============ 6 7This document describes how BPF programs are cryptographically signed, how the 8kernel verifies them at load time, and how Linux Security Modules (LSMs) - 9including the BPF LSM - use the resulting verdict to enforce policy. It is 10written for developers who want to produce signed BPF objects, understand what 11the signature actually guarantees, or build a policy on top of it. 12 13Motivation 14========== 15 16A signed BPF program lets the kernel establish that the bytecode being loaded 17originates from a trusted producer and was not modified in transit. On its own 18the kernel does not *require* signatures - an unsigned program loads exactly as 19before - but it records a verdict (see `The verdict`_) that an LSM can gate on. 20This is the building block for policies such as "only run BPF that was signed by 21a key in the trusted keyring", as could in the future be enforced by an LSM 22such as IPE. 23 24Signing is orthogonal to the existing permission model: it does not replace the 25capability checks or the verifier. A signed load still requires the usual 26privileges (``CAP_BPF`` and any program-type-specific capability, subject to 27``kernel.unprivileged_bpf_disabled``), and the loader's instructions are still 28checked by the verifier like any other program. A valid signature establishes 29*origin and integrity*, not safety - it lets a policy trust where the bytecode 30came from, it does not let a load skip any check it would otherwise face. 31 32The hard part is *what* gets signed. A naive scheme would sign a program's 33instruction buffer at build time and verify that signature at 34``BPF_PROG_LOAD``. That does not survive contact with real BPF objects, because 35the bytes the kernel finally loads are not the bytes the developer built and 36signed. Between the two, libbpf and the kernel rewrite the program: 37 38- **map file descriptors** are patched into ``ld_imm64`` instructions 39 (``BPF_PSEUDO_MAP_FD``), and a map's fd is assigned at load time, so it 40 differs on every run; 41- **CO-RE relocations** rewrite field offsets, sizes and existence flags against 42 the *running* kernel's BTF, so the result differs from one kernel to the next; 43- **kfunc and ksym references** are resolved to ids/addresses in the running 44 kernel; 45- **global data** (``.rodata``/``.data``/``.bss``) is created and seeded as maps 46 at load. 47 48So a signature over the original instructions cannot match the relocated 49instructions the verifier ends up checking, and the relocated form cannot be 50produced ahead of time because it depends on the target kernel. There is no 51fixed byte string that is both signable at build time and what the kernel 52actually loads - which is why a program cannot simply be signed and loaded 53directly. 54 55The trusted loader 56================== 57 58The solution is to move that setup work *into* a small BPF program - the 59**loader** - and sign the loader instead of the individual programs. libbpf's 60``gen_loader`` machinery (``bpftool gen skeleton -L``, the "light skeleton") 61emits a ``BPF_PROG_TYPE_SYSCALL`` program whose body performs the bpf() syscalls 62that create maps, apply relocations, and load the real programs. The payload it 63installs - the serialized programs, map descriptions, relocation data and 64initial values - lives in a separate array map, the **metadata map** 65(``__loader.map``). 66 67So the unit of trust is the loader, and the signing contract is:: 68 69 Sig(I_loader || D_meta) 70 71where ``I_loader`` is the loader's instruction stream and ``D_meta`` is the 72content of the metadata map. Verifying the loader's signature establishes that 73both the loader *and* the payload it is about to install are authentic. The 74loader is reproducible: ``gen_loader`` builds it from primitives so the same 75object yields the same bytes on any build host. 76 77Why the loader is signable when the program is not 78-------------------------------------------------- 79 80The loader sidesteps every rewrite listed above, because the bytes that are 81signed are *relocation-invariant*: 82 83- The loader's own instructions are a fixed sequence of bpf() syscalls emitted 84 by ``gen_loader``; they carry no CO-RE relocations and resolve no ksyms, so 85 they are identical on every kernel. The metadata map is referenced by *index* 86 into ``fd_array`` (``BPF_PSEUDO_MAP_IDX_VALUE``), not by a baked-in file 87 descriptor, so even that reference does not change between build and load. 88 The loader instruction bytes the kernel verifies are exactly the bytes that 89 were signed. 90- The metadata map is opaque, frozen data - the serialized target programs, 91 their relocation records, map descriptions and initial values. Its bytes are 92 identical at build time and at load time, so they are simply appended to the 93 instructions and covered by the same signature (there is no separate metadata 94 hash to compute or compare). 95 96All the host-specific rewriting - creating maps, patching their fds into the 97target programs, applying CO-RE, resolving ksyms, seeding global data - still 98happens, but it happens *inside the loader at runtime*, on the verified 99metadata, **after** the kernel has verified the ``insns || metadata`` signature. 100The kernel never has to verify the relocated target programs: it verifies the 101loader and its inputs once, and trust transfers to whatever that now-trusted, 102deterministic loader installs. The relocation step is moved from "before the 103signature can be checked" to "after a trusted program runs" - which is exactly 104what makes it signable. 105 106Because the metadata map is the loader's only untrusted input, two existing map 107properties are reused to keep it trustworthy across the load: 108 109Exclusive maps 110 A map created with ``excl_prog_hash`` (see ``BPF_MAP_CREATE``) may only be 111 accessed by a program whose digest matches that hash. The verifier enforces 112 ``map->excl_prog_sha == prog->digest`` for every map a program uses, so the 113 metadata map is bound to exactly the signed loader and cannot be shared with 114 or mutated by another program. 115 116Frozen maps 117 The metadata map is frozen (``BPF_MAP_FREEZE``) before the loader is loaded. 118 Freezing blocks further userspace writes, so the bytes folded into the 119 signature cannot change before the loader runs. (Freezing does not make the 120 map read-only to the loader program itself, which still writes created file 121 descriptors back into the blob's scratch area.) 122 123Load-time verification 124======================= 125 126Rather than have the loader check its own metadata from within BPF, the kernel 127verifies it directly at ``BPF_PROG_LOAD``, with no new UAPI. The mechanism 128reuses the existing ``fd_array``: 129 130#. Userspace creates the metadata map with ``excl_prog_hash`` set to the 131 loader's digest, populates it, and freezes it. 132#. The loader is loaded with ``signature``/``signature_size``/``keyring_id`` 133 set, the metadata map referenced through ``fd_array``, and ``fd_array_cnt`` 134 set so the kernel knows the array's length. 135#. Signature verification runs inside the verifier (``bpf_check()``), once it 136 has resolved the ``fd_array`` entries into the program's ``used_maps``. The 137 maps folded into the signature are therefore the very objects the program 138 binds - a single resolution of ``fd_array``, not a separate read, so the 139 verified bytes cannot be swapped for a different map after the check (no 140 time-of-check/time-of-use window). Each folded map must be exclusive (carry 141 ``excl_prog_sha``) and a plain array map (``BPF_MAP_TYPE_ARRAY``); only an 142 array map exposes its value buffer through ``map_direct_value_addr()`` as a 143 kernel address spanning ``value_size`` bytes. A map that is not exclusive, not 144 frozen, or not a plain array is rejected, with a verifier log message naming 145 the offending map. The kernel appends each map's frozen 146 contents to the instruction buffer and verifies the PKCS#7 signature over the 147 concatenation ``insns || metadata_0 || metadata_1 || ...`` in ``used_maps`` 148 order, before it rewrites the (signed) instructions. 149 150A signed program therefore takes one of exactly two shapes, both fully 151supported: 152 153- **No bound maps** (``fd_array_cnt == 0``): there is nothing to append, so the 154 kernel verifies the signature over the instructions alone. A valid signature 155 yields ``BPF_SIG_VERIFIED`` and the program loads. This is the ordinary case 156 for a directly-loaded signed program with no separate payload; it is *not* 157 rejected for "missing" metadata, because it has none to cover. 158- **Exclusive bound maps** (``fd_array_cnt > 0``): every entry is exclusive and 159 folded, so the signature covers ``insns || metadata``. 160 161There is no third shape: a non-exclusive map in a signed program's ``fd_array`` 162is rejected rather than silently left out of the signature, so a signed loader 163never binds a map its signature does not cover. 164 165The digest binding (``excl_prog_sha == prog->digest``) is enforced by the 166verifier as usual; because that check runs while ``fd_array`` is resolved - 167before the verifier would otherwise compute the tag - ``prog->digest`` is 168computed up front in the verifier, over the unmodified (signature-covered) 169instructions, for any signed load. 170 171Coverage is then enforced as the verifier resolves instructions, at the point 172each object is bound rather than by a count taken afterwards. Once the signature 173has been verified, binding any further map is refused: a map reached by a 174directly-referenced fd, or a map swapped into an ``fd_array`` slot the loader 175reads, is not among those already folded, so it is rejected the moment the 176verifier tries to bind it. A BTF is refused outright for a signed program - a 177ksym or a BTF fd in ``fd_array``, whether resolved up front or lazily for a 178module kfunc, is rejected when it would be bound. Together with the fold rule 179above this keeps the verdict binary: a signed program cannot use a map its 180signature does not cover, and a different but equally digest-bound map cannot be 181substituted at an ``fd_array`` slot. Non-exclusive maps are never folded, so a 182signed program cannot use one at all. 183 184The verdict 185=========== 186 187A program is either unsigned or fully verified - there is no intermediate 188state. The outcome is recorded in ``prog->aux->sig.verdict``: 189 190.. code-block:: c 191 192 enum bpf_sig_verdict { 193 BPF_SIG_UNSIGNED = 0, 194 BPF_SIG_VERIFIED, 195 }; 196 197``BPF_SIG_VERIFIED`` means the signature is valid and covers the instructions 198*and* the frozen contents of every exclusive map the program uses: 199 200- For an ordinary, directly-loaded signed program the instructions are the whole 201 artifact and it uses no exclusive maps, so a valid instruction signature is 202 the complete verification. 203- For a signed loader the metadata map is exclusive, so its contents are folded 204 in and the signature covers ``insns || metadata``. 205 206There is deliberately no "instructions verified but metadata not" verdict: a 207signed loader that fails to cover its metadata is *rejected* (see above), not 208recorded with a weaker verdict. ``BPF_SIG_VERIFIED`` therefore always means the 209program and everything the signature is responsible for are authentic, which is 210what a policy can rely on. 211 212Alongside the verdict the kernel records which keyring validated the signature; 213see `Keyrings`_. 214 215Enforcement via LSMs 216==================== 217 218Signing only *records* a verdict; an LSM turns it into policy. The verdict and 219keyring fields live in ``struct bpf_prog_aux``, so a BPF LSM program can read 220them directly (see Documentation/bpf/prog_lsm.rst for writing and attaching BPF 221LSM programs); the same fields are equally available to in-tree LSMs. Two hooks 222are useful at different points of the load: the dedicated 223``security_bpf_prog_load()`` gates admission before the main verification work, 224and the existing ``security_bpf_prog()`` observes a program that has fully 225loaded. 226 227Admission: ``security_bpf_prog_load()`` 228--------------------------------------- 229 230This hook gates admission **for every load**, from a single call site inside the 231verifier (``bpf_check()``), before the main verification work. It runs after the 232optional signature verification, so the verdict and keyring fields are final - the 233hook can see whether, and how strongly, the program was signed, which keyring 234validated it, the load ``attr``, the BPF token and whether the load came from the 235kernel. For a signed load the verdict is ``BPF_SIG_VERIFIED`` here (the signature 236has just been checked); for an unsigned load it is ``BPF_SIG_UNSIGNED``. 237 238This is the place for *coarse admission* that must also see unsigned and 239not-yet-verified loads: require a signature at all, restrict the acceptable 240keyring, restrict which token/credentials may load BPF, apply per-program-type 241rules, or audit every load attempt that makes it past signature verification - 242attempts failing the signature or the metadata binding abort before this hook 243fires. It is the primary deny point. 244 245One subtlety: this hook runs *before* the verifier finishes its work, so 246``BPF_SIG_VERIFIED`` *here* means only "validly signed" - not "loaded". Allowing 247a load at this point lets it *proceed*; it does not guarantee the program will 248load. A validly signed program can still be rejected afterwards on two 249independent grounds: the verifier may reject it like any other program (unsafe 250memory access, bad control flow, resource limits, ...), and the kernel separately 251refuses - as the verifier resolves instructions and binds each object - any map 252the signature does not cover or any BTF at all, regardless of what this hook 253returned. Only after the program has fully loaded, at the next hook 254(``security_bpf_prog()``), does ``BPF_SIG_VERIFIED`` carry its full meaning: 255validly signed *and* fully verified. 256 257A more realistic admission policy than "is it signed at all": accept programs 258signed by a system keyring, accept a user-keyring signature only if the 259key/keyring it was verified against is on an explicit allowlist, and emit a 260tamper-evident record of every decision so that even denied attempts are 261auditable. (Illustrative - error checking elided.) 262 263.. code-block:: c 264 265 /* Serials of user keys/keyrings we additionally trust. */ 266 struct { 267 __uint(type, BPF_MAP_TYPE_HASH); 268 __type(key, __s32); /* keyring_serial */ 269 __type(value, __u8); 270 __uint(max_entries, 64); 271 } trusted_user_keys SEC(".maps"); 272 273 /* Audit stream consumed by a userspace logger. */ 274 struct { 275 __uint(type, BPF_MAP_TYPE_RINGBUF); 276 __uint(max_entries, 1 << 16); 277 } audit SEC(".maps"); 278 279 struct decision { __u32 prog_type, verdict, ktype; __s32 serial, ret; }; 280 281 SEC("lsm/bpf_prog_load") 282 int BPF_PROG(admit, struct bpf_prog *prog, union bpf_attr *attr, 283 struct bpf_token *token, bool kernel) 284 { 285 __u32 verdict = prog->aux->sig.verdict; 286 __u32 ktype = prog->aux->sig.keyring_type; 287 __s32 serial = prog->aux->sig.keyring_serial; 288 struct decision *d; 289 int ret = 0; 290 291 if (kernel) 292 return 0; /* trust in-kernel loads */ 293 294 if (verdict != BPF_SIG_VERIFIED) 295 ret = -EPERM; /* must be validly signed */ 296 else if (ktype == BPF_SIG_KEYRING_USER && 297 !bpf_map_lookup_elem(&trusted_user_keys, &serial)) 298 ret = -EPERM; /* key/keyring not allowlisted */ 299 300 d = bpf_ringbuf_reserve(&audit, sizeof(*d), 0); 301 if (d) { 302 d->prog_type = attr->prog_type; 303 d->verdict = verdict; 304 d->ktype = ktype; 305 d->serial = serial; 306 d->ret = ret; 307 bpf_ringbuf_submit(d, 0); /* record allow *and* deny */ 308 } 309 return ret; 310 } 311 312Observing a verified load: ``security_bpf_prog()`` 313-------------------------------------------------- 314 315There is deliberately no separate "metadata attested" hook. The coverage check 316above is enforced by the kernel unconditionally, so a signed loader that fails 317to cover its metadata never loads and an LSM never has to re-establish that 318fact. To *act on* a program that has successfully and fully loaded, use the 319existing ``security_bpf_prog()`` hook (``lsm/bpf_prog``), which fires from 320``bpf_prog_new_fd()`` - after the verifier, after the coverage check, and after 321``bpf_prog_alloc_id()``. Relative to the admission hook this point is strictly 322later and stronger: 323 324- the program has an id (``prog->aux->id``), so it can be recorded or correlated 325 with later events; 326- ``verdict == BPF_SIG_VERIFIED`` *here* means **fully** verified - a program 327 that used a map the signature does not cover was already rejected, so it cannot 328 reach this point; 329- it observes only programs that actually loaded; a failed load never mints an 330 fd, so it never reaches this hook. 331 332It takes only the ``prog`` and a non-zero return still aborts (the fd is not 333handed out), so it can veto as well as observe. One wrinkle: it also fires on 334other paths that mint a new program fd - notably ``bpf_prog_get_fd_by_id()`` - 335not just on a fresh load. Because the program already has its id here, an LSM 336can tell the two apart with a small hash map: the *first* time an id is seen is 337the load; a later sighting of the same id is just another fd to a program that 338already exists. 339 340To bound the map and let a reused id read as a fresh load, this can be paired 341with ``security_bpf_prog_free()`` (``lsm/bpf_prog_free``), which deletes the 342entry on teardown - keyed by the same ``prog`` pointer, since 343``bpf_prog_free_id()`` has already cleared ``prog->aux->id`` to ``0`` by the time 344that hook runs. (Illustrative - privileged LSM, error checking elided.) 345 346.. code-block:: c 347 348 struct rec { __u32 id, ktype; __s32 serial; }; 349 350 struct { 351 __uint(type, BPF_MAP_TYPE_HASH); 352 __type(key, __u64); /* struct bpf_prog * -- stable id */ 353 __type(value, struct rec); 354 __uint(max_entries, 4096); 355 } live SEC(".maps"); 356 357 SEC("lsm/bpf_prog") /* fires after load and on every later fd */ 358 int BPF_PROG(observe, struct bpf_prog *prog) 359 { 360 __u64 key = (__u64)(unsigned long)prog; 361 struct rec r; 362 363 if (prog->aux->sig.verdict != BPF_SIG_VERIFIED) 364 return 0; 365 if (bpf_map_lookup_elem(&live, &key)) 366 return 0; /* seen before: a later fd, not a load */ 367 368 /* First sighting == this program just loaded; id is valid here. */ 369 r.id = prog->aux->id; 370 r.ktype = prog->aux->sig.keyring_type; 371 r.serial = prog->aux->sig.keyring_serial; 372 bpf_map_update_elem(&live, &key, &r, BPF_NOEXIST); 373 /* ... newly-loaded verified-program action, e.g. record r.id ... */ 374 return 0; 375 } 376 377Putting them together: to *require* verified BPF, deny at the admission hook 378unless the verdict is ``BPF_SIG_VERIFIED`` (and, if desired, restrict the 379keyring). The kernel then guarantees that any program which actually loads with 380that verdict covered all of its exclusive maps, rejecting any that did not - so 381a deny-by-default admission policy needs no second enforcement point. Use 382``security_bpf_prog()`` to record or finally gate the verified programs once 383they carry an id. The ``verdict``, ``keyring_type`` and ``keyring_serial`` fields 384let a policy distinguish, for example, "verified and signed by a builtin key" 385from "verified by a user key". A policy LSM such as IPE could consume the same 386hooks to enforce system policy without writing any BPF, though none implements 387this today. 388 389Keyrings 390======== 391 392``keyring_id`` selects the trusted keyring the PKCS#7 signature is verified 393against. The well-known ids ``0`` (builtin), ``VERIFY_USE_SECONDARY_KEYRING`` 394and ``VERIFY_USE_PLATFORM_KEYRING`` select the corresponding system keyrings; 395any other value is treated as the serial of a user/session key or keyring. 396The keyring is looked up first, before the signature bytes are examined, so a 397signature naming a non-existent keyring is rejected up front, and a failed 398verification aborts the load - so a program that loads successfully with a 399signature always has consistent keyring fields recorded. 400 401Two fields are recorded in ``prog->aux->sig`` for an LSM to inspect: 402 403``keyring_type`` (``enum bpf_sig_keyring``) 404 Classified purely from ``keyring_id`` whenever the program is signed: 405 ``BPF_SIG_KEYRING_BUILTIN``, ``_SECONDARY``, ``_PLATFORM`` for the system 406 keyrings, or ``_USER`` for a user/session keyring. It is 407 ``BPF_SIG_KEYRING_NONE`` for an unsigned program. 408 409``keyring_serial`` (``s32``) 410 Set **only** on a successful verification, to the serial of the 411 **user/session key or keyring** that ``keyring_id`` resolved to - the 412 object the signature was verified against, not the individual asymmetric 413 key inside it that matched the signer. Passing 414 ``KEY_SPEC_SESSION_KEYRING``, for example, records the session keyring's 415 serial. The system keyrings are trusted as a whole and expose no serial 416 here, so the serial is ``0`` for builtin, secondary and platform 417 signatures, and ``0`` for unsigned programs. In other words, a non-zero 418 ``keyring_serial`` is exactly "verified against the user key/keyring with 419 this serial". 420 421.. list-table:: 422 :header-rows: 1 423 424 * - ``keyring_id`` 425 - ``keyring_type`` 426 - ``keyring_serial`` 427 * - (no signature) 428 - ``BPF_SIG_KEYRING_NONE`` 429 - ``0`` 430 * - ``0`` 431 - ``BPF_SIG_KEYRING_BUILTIN`` 432 - ``0`` 433 * - ``VERIFY_USE_SECONDARY_KEYRING`` 434 - ``BPF_SIG_KEYRING_SECONDARY`` 435 - ``0`` 436 * - ``VERIFY_USE_PLATFORM_KEYRING`` 437 - ``BPF_SIG_KEYRING_PLATFORM`` 438 - ``0`` 439 * - other (a user/session key serial) 440 - ``BPF_SIG_KEYRING_USER`` 441 - serial of the resolved key/keyring 442 443Producing a signed object 444========================== 445 446``bpftool`` generates and signs a light skeleton in one step:: 447 448 bpftool gen skeleton -L -S -k <private_key.pem> -i <certificate.x509> \ 449 obj.bpf.o > obj.lskel.h 450 451``-L`` selects the light-skeleton (``gen_loader``) backend and ``-S`` enables 452signing; ``-k`` and ``-i`` supply the signing key and its X.509 certificate. 453``bpftool`` signs ``insns || metadata`` - the exact bytes the kernel 454reconstructs - and also computes ``excl_prog_hash`` as the digest of the loader 455instructions so the metadata map can be bound to the loader. The signature and 456hash are embedded in the generated header; the certificate is used only for 457signing and is not included. Loading the skeleton performs the 458create/populate/freeze/load sequence described above. 459 460At runtime the trusted public key must be present in the chosen keyring (for 461example added to the session keyring, or built into the kernel's builtin trusted 462keyring) for verification to succeed. 463 464UAPI reference 465============== 466 467``BPF_PROG_LOAD`` (``union bpf_attr``): 468 469``signature``, ``signature_size`` 470 Pointer to and length of the PKCS#7 signature blob. 471 472``keyring_id`` 473 Trusted keyring selector (see `Keyrings`_). 474 475``fd_array``, ``fd_array_cnt`` 476 Array of map (and module BTF) file descriptors bound to the program. 477 ``fd_array_cnt`` must be set for the kernel to scan the array. When a 478 signature is present, a BTF entry is rejected outright, and every map must 479 be exclusive; its frozen contents are folded into the verified buffer, and 480 a non-exclusive entry is rejected. 481 482``BPF_MAP_CREATE`` (``union bpf_attr``): 483 484``excl_prog_hash``, ``excl_prog_hash_size`` 485 SHA-256 digest of the program permitted to access this (exclusive) map. This 486 binds the metadata map to the loader; it is not a hash of the map *content*. 487 The map content is not hashed separately at all - it is covered, as bytes, 488 by the program signature. 489 490Notes and limitations 491====================== 492 493- The instructions plus folded metadata are verified as one ``bpf_dynptr``, 494 which bounds the combined size (currently ~16 MiB); very large objects can 495 exceed it. 496- The metadata container is a single-element array map, accessed through 497 ``map_direct_value_addr``. 498