Skip to content

feat(docker): file capabilities on the eupf binary, so it can run as a non-root user - #672

Merged
pirog-spb merged 1 commit into
edgecomllc:mainfrom
martin-mat:nonroot-image
Oct 22, 2026
Merged

pirog-spb merged 1 commit into
edgecomllc:mainfrom
martin-mat:nonroot-image

Conversation

@martin-mat

@martin-mat martin-mat commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

For #671, the first step: the image. Nothing changes for current users; the image keeps running as root by default.

Change

  • Dockerfile: the runtime stage sets NET_ADMIN, SYS_RESOURCE, BPF, PERFMON and DAC_OVERRIDE as file capabilities (=ep) on /app/bin/eupf. They're what eUPF needs: loading the programs (BPF, PERFMON; the chart requires kernel 5.15, which has CAP_BPF), attaching XDP and setting routes (NET_ADMIN), raising RLIMIT_MEMLOCK (SYS_RESOURCE), and creating the map pin directory under the root-owned /sys/fs/bpf (DAC_OVERRIDE). The container's bounding set still decides which of them the process gets. Whoever runs the image must grant all of them, root or not (the chart's defaults do; docker run needs --privileged or --cap-add): exec of a binary with the effective bit set fails with Operation not permitted when one is missing.
  • entrypoint.sh: mounts bpffs and debugfs only when running as root. A non-root process can't mount, and uses the node's bpffs at /sys/fs/bpf.
  • Chart: the non-root securityContext documented in values.yaml (commented) and in the README's cluster prerequisites, with the bpffs node prerequisite and the kind extraMounts line. The default stays root until an image release carries the file capabilities; that's the second step in eUPF can run as a non-root user with file capabilities; today the chart runs it as root #671. Chart 0.7.2.

Verification

On a fork, the 0.7.1 source built with this Dockerfile and entrypoint, installed with the documented non-root security context on a kind cluster with bpffs bound into the nodes, the CNTi suite's 19 essential tests (run 38950181467): eUPF runs as uid 1000 with exactly the five effective capabilities (CapEff 000000c001001002, no SYS_ADMIN), attaches XDP, and non_root_containers passes: 16 of 19. The same image as root with the chart's current defaults starts as before (run 38942371982, main source).

#673 also bumps the chart to 0.7.2; whichever merges second needs a one-line rebase.

🤖 Generated with Claude Code

…a non-root user

eUPF needs no root: BPF and PERFMON load the programs (SYS_ADMIN on
kernels before CAP_BPF), NET_ADMIN attaches XDP and sets routes,
SYS_RESOURCE raises RLIMIT_MEMLOCK. The one thing uid 0 did that the
capabilities don't is creating the map pin directory under /sys/fs/bpf,
whose root directory belongs to root; DAC_OVERRIDE covers that.

The runtime stage now sets these as file capabilities (=ep) on
/app/bin/eupf. The container's bounding set still decides which of them
the process can have, so nothing changes for a container that doesn't
grant them, and the image keeps running as root by default. The
entrypoint mounts bpffs and debugfs only when it runs as root: a non-root
process cannot, and expects the node's bpffs at /sys/fs/bpf, as systemd
hosts provide.

The chart documents the non-root security context and the bpffs
prerequisite; its default stays root until an image release carries the
file capabilities. Verified on a fork with the 0.7.1 source built this
way: eupf runs as uid 1000 with exactly the intended effective
capabilities, attaches XDP, and the CNTi suite's non_root_containers test
passes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Martin Matyas <martin.matyas@tieto.com>
Comment thread Dockerfile Resolved
@pirog-spb
pirog-spb merged commit d9336b3 into edgecomllc:main Oct 22, 2026
8 checks passed
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.

2 participants