Skip to content

Add BPF token support for program and map loading #1948

Closed
javiercardona-work wants to merge 4 commits intocilium:mainfrom
javiercardona-work:pr1
Closed

Add BPF token support for program and map loading #1948
javiercardona-work wants to merge 4 commits intocilium:mainfrom
javiercardona-work:pr1

Conversation

@javiercardona-work
Copy link
Copy Markdown

@javiercardona-work javiercardona-work commented Feb 2, 2026

Add support for loading BPF programs and creating maps using BPF tokens,
enabling unprivileged BPF operations in user namespaces with delegated
capabilities.

Changes:

  • Add TokenFD field to ProgramOptions and MapOptions
  • When set, pass token to kernel with BPF_F_TOKEN_FD flag during syscalls
  • Add internal/token package for global token storage
  • Add features.SetGlobalToken()/GetGlobalToken() for feature probe support

Since the original PR, the following commits were added:

  • Thread BPF token through feature probes: Pass the global token to
    all feature probes (program type, map type, BTF, link, and program
    helper probes) so that capability detection works correctly inside user
    namespaces with delegated BPF permissions.
  • Add BPF token integration test program: Standalone test
    (examples/token_test/) that creates a BPF token, optionally drops
    CAP_BPF/CAP_SYS_ADMIN/CAP_PERFMON, and exercises feature probes,
    program loading, and map creation. Validated on a container with
    bpf_token delegation (kernel 6.16.1, unprivileged_bpf_disabled=1).

This is the output of the test program when run on a container with delegated BPF token enabled:

$ /tmp/token-test --drop-caps /run/tw/bpf
Creating BPF token from /run/tw/bpf...
BPF token created: fd=4

Dropping CAP_BPF, CAP_SYS_ADMIN, CAP_PERFMON...
Capabilities dropped. BPF access now depends solely on token.

=== Feature Probes (with token) ===
prog SocketFilter         supported
prog Kprobe               supported
prog SchedCLS             supported
prog XDP                  supported
prog TracePoint           supported
prog CGroupSKB            supported
map  Hash                 supported
map  Array                supported
map  PerfEventArray       supported
map  LRUHash              supported
map  RingBuf              supported

=== Program Load (with token) ===
program load: OK (fd=3)

=== Map Create (with token) ===
map create: OK (fd=3)

=== Without Token (uncached probe) ===
prog PerfEvent (no token):     detect support for PerfEvent: load program: operation not permitted
map  PerCPUHash (no token):     detect support for PerCPUHash: operation not permitted

Done.

Add TokenFD field to ProgramOptions and MapOptions to support
loading BPF programs and creating maps using a BPF token. This
enables unprivileged BPF operations in user namespaces with
delegated BPF capabilities.

When TokenFD is set to a positive value, the token file descriptor
is passed to the kernel with the BPF_F_TOKEN_FD flag during
program load and map creation syscalls.

Also add internal/token package for global token storage and
features.SetGlobalToken/GetGlobalToken for setting a default
token to be used by feature probes.

Signed-off-by: Javier Cardona <jcardona@meta.com>
Add tests for internal/token and features/token packages:

- TestGlobalTokenDefault: verify default value is -1
- TestSetGetGlobalToken: verify set/get operations
- TestGlobalTokenConcurrent: verify thread safety with concurrent
  readers and writers
- TestGlobalTokenWrapper: verify features package correctly wraps
  internal/token

Signed-off-by: Javier Cardona <jcardona@meta.com>
Pass the global BPF token to all feature probes so that capability
detection works correctly inside user namespaces with delegated BPF
permissions.

Updated probes:
- features/map.go: createMap() and probeMapFlag()
- features/prog.go: probeProgram(), haveProgramHelper(), Extension probe
- btf/feature.go: probeBTF()
- features/link.go: uprobe_multi, kprobe_multi, kprobe_session
- link/syscalls.go: haveProgAttach, haveProgAttachReplace, haveTCX, haveNetkit

Signed-off-by: Javier Cardona <jcardona@meta.com>
Add a standalone test program that validates BPF token support
end-to-end by creating a token, optionally dropping BPF-related
capabilities, and exercising feature probes, program loading, and
map creation.

Usage:
  token-test [--drop-caps] [/path/to/bpffs]

With --drop-caps, the program creates the token first, then drops
CAP_BPF, CAP_SYS_ADMIN, and CAP_PERFMON before running probes.
This proves the token is the sole source of BPF access.

Tested on a container with bpf_token delegation enabled (kernel 6.16.1,
unprivileged_bpf_disabled=1):

```
  Creating BPF token from /run/tw/bpf...
  BPF token created: fd=4

  Dropping CAP_BPF, CAP_SYS_ADMIN, CAP_PERFMON...
  Capabilities dropped. BPF access now depends solely on token.

  === Feature Probes (with token) ===
    prog SocketFilter         supported
    prog Kprobe               supported
    prog SchedCLS             supported
    prog XDP                  supported
    prog TracePoint           supported
    prog CGroupSKB            supported
    map  Hash                 supported
    map  Array                supported
    map  PerfEventArray       supported
    map  LRUHash              supported
    map  RingBuf              supported

  === Program Load (with token) ===
    program load: OK (fd=3)

  === Map Create (with token) ===
    map create: OK (fd=3)

  === Without Token (uncached probe) ===
    prog PerfEvent (no token):     operation not permitted
    map  PerCPUHash (no token):    operation not permitted
```

Signed-off-by: Javier Cardona <jcardona@meta.com>
@javiercardona-work
Copy link
Copy Markdown
Author

Closing this PR as it is has been superseded by #1953

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant