Skip to content

devices: work around kernel OOB write in BPF_PROG_QUERY - #69

Merged
AkihiroSuda merged 1 commit into
opencontainers:mainfrom
kolyshkin:fix-oob
Aug 4, 2026
Merged

devices: work around kernel OOB write in BPF_PROG_QUERY#69
AkihiroSuda merged 1 commit into
opencontainers:mainfrom
kolyshkin:fix-oob

Conversation

@kolyshkin

@kolyshkin kolyshkin commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

bpfAttrQuery only described the query member of union bpf_attr up to prog_cnt, and that size (32 bytes) is what is passed to bpf(2). Since Linux 6.17 (kernel commit 120933984460, "bpf: Implement mprog API on top of existing cgroup progs"), __cgroup_bpf_query copies query.revision back to userspace unconditionally, without looking at the size we passed. As revision sits at offset 56, the kernel writes 8 bytes past the end of the struct on every BPF_PROG_QUERY.

Depending on how the compiler lays out the frame, those 8 bytes either land on unused stack space, and nothing happens, or on live data. In runc this showed up as corrupted defer records, crashing "runc restore" in runtime.copystack, and as garbled strings. This can be seen in e.g. https://github.com/opencontainers/runc/actions/runs/30715630948. A small repro w/o runc is here: bpfcanary.go.

The kernel bug was fixed by commit 21c4b99b27f3 ("bpf: fix BPF_PROG_QUERY OOB write and cgroup backward compat", landed in v7.2).

Passing the larger size is safe on older kernels, as bpf(2) only
requires that the bytes beyond what it knows about are zero.

@kolyshkin
kolyshkin requested a review from a team as a code owner August 1, 2026 22:50
@kolyshkin

Copy link
Copy Markdown
Contributor Author

@opencontainers/cgroups-maintainers I want to release v0.0.9 once this is in. For analysis and repro, see #64 (comment)

@kolyshkin kolyshkin added this to the 0.0.9 milestone Aug 1, 2026
bpfAttrQuery described only the query member of union bpf_attr up to
prog_cnt, and that size (32 bytes) is what is passed to bpf(2).

Since Linux 6.17 (kernel commit 120933984460, "bpf: Implement mprog API
on top of existing cgroup progs"), kernel copies query.revision field
(offset 56) back to userspace unconditionally, without looking at the
size. So, the kernel writes past the end of the struct on every
BPF_PROG_QUERY.

Depending on how the compiler lays out the frame, those 8 bytes either
land on unused stack space, and nothing happens, or on live data. In
runc this showed up as corrupted defer records, crashing "runc restore"
in runtime.copystack, and as garbled strings.

The kernel bug was fixed by commit 21c4b99b27f3 ("bpf: fix
BPF_PROG_QUERY OOB write and cgroup backward compat", landed in v7.2).
Passing the larger size is safe on older kernels, as bpf(2) only
requires that the bytes beyond what it knows about are zero.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@kolyshkin kolyshkin changed the title devices: fix out-of-bounds write in BPF_PROG_QUERY devices: work around kernel OOB write in BPF_PROG_QUERY Aug 3, 2026

@thaJeztah thaJeztah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh; nice one

LGTM

@kolyshkin
kolyshkin requested review from AkihiroSuda and cyphar August 3, 2026 22:50
@AkihiroSuda
AkihiroSuda merged commit 783139a into opencontainers:main Aug 4, 2026
20 of 21 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.

3 participants