Skip to main content
Vulnerability Database/CVE-2026-98647

CVE-2026-98647: Linux Kernel BTF Divide-by-Zero Vulnerability

CVE-2026-98647 is a divide-by-zero flaw in the Linux kernel's btf_struct_walk function that occurs when accessing flexible arrays with zero-sized element types. This post explains the technical details, affected versions, impact, and mitigation steps.

Published:

CVE-2026-98647 Overview

CVE-2026-98647 is a divide-by-zero flaw in the Linux kernel BPF subsystem. The bug lives in btf_struct_walk(), which processes BPF Type Format (BTF) metadata during program load. When a struct ends in a flexible array member and the element type has zero size, the function folds the offset back using (off - moff) % t->size without validating that t->size is non-zero. A local unprivileged user with the ability to load BPF programs can trigger a kernel oops, resulting in denial of service.

Critical Impact

An unprivileged local user able to load eBPF programs can crash the kernel through a divide-by-zero in the BTF verifier, resulting in denial of service.

Affected Products

  • Linux kernel versions containing the vulnerable btf_struct_walk() flexible-array handling logic
  • Distributions shipping affected mainline and stable kernel branches
  • Systems where unprivileged BPF program loading is enabled

Discovery Timeline

  • 2026-10-18 - CVE-2026-98647 published to the National Vulnerability Database (NVD)
  • 2026-10-19 - Last updated in NVD database

Technical Details for CVE-2026-98647

Vulnerability Analysis

The flaw sits in btf_struct_walk(), part of the kernel BPF verifier that validates pointer accesses into BTF-described structures. When an access extends past a struct whose final member is a flexible array, the function normalizes the offset into a single array element using modulo arithmetic against the element type size.

The fixed-array code path in the same function already guards against zero-sized element types by skipping empty arrays. The flexible-array path omits that check, so a BTF entry describing an array of empty structs reaches a division operation with a divisor of zero.

The crash manifests as Oops: divide error: 0000 [#1] SMP KASAN PTI at btf_struct_walk+0x53f/0x1570, propagated through btf_struct_access, check_ptr_to_btf_access, check_mem_access, and finally bpf_prog_load during the bpf() syscall. The kernel oops renders the system unstable or unresponsive depending on panic-on-oops configuration.

Root Cause

The root cause is missing input validation on the BTF element type size before performing modulo and division operations. An empty struct, such as one whose only member is excluded by a preprocessor conditional, yields t->size == 0. btf_struct_walk() must treat zero-sized element types the same way as the fixed-array branch, which skips empty arrays rather than dividing.

Attack Vector

Triggering the bug requires loading a BPF program that holds a PTR_TO_BTF_ID which is not MEM_ALLOC. A plain read of a local kernel pointer stashed in a map from a sleepable program satisfies this condition. The attacker-controlled BTF then describes a container struct whose trailing flexible array has an empty struct element type. When the verifier walks a past-end access against this layout, the division executes and the kernel faults. Exploitation requires local access and the ability to invoke the bpf() syscall with BTF, typically available to privileged users or to unprivileged users on kernels where unprivileged BPF is enabled.

No verified public exploit code is available at the time of writing. The upstream commit message includes a reproducer BTF definition rather than a weaponized payload. Refer to the kernel patch commits for details.

Detection Methods for CVE-2026-98647

Indicators of Compromise

  • Kernel log entries containing divide error: 0000 with a faulting instruction pointer inside btf_struct_walk
  • Call Trace frames including btf_struct_access, check_ptr_to_btf_access, check_mem_access, and bpf_prog_load
  • Unexpected kernel panics or oopses correlated with bpf() syscall activity from unprivileged processes

Detection Strategies

  • Monitor dmesg, /var/log/kern.log, and journald for divide-error oopses referencing BPF verifier functions
  • Audit bpf() syscall activity using the Linux audit subsystem, tracking BPF_PROG_LOAD operations initiated by non-root UIDs
  • Correlate kernel crash telemetry with the executing process and container context to identify the source of malformed BTF

Monitoring Recommendations

  • Collect kernel ring buffer and kdump output centrally so divide-error signatures can be alerted on across the fleet
  • Baseline which workloads legitimately load BPF programs and flag unexpected BPF_PROG_LOAD calls from untrusted namespaces
  • Track kernel versions across hosts to prioritize unpatched systems that permit unprivileged BPF

How to Mitigate CVE-2026-98647

Immediate Actions Required

  • Apply the upstream stable kernel updates that add the zero-size element check to btf_struct_walk()
  • Set kernel.unprivileged_bpf_disabled=1 on hosts that do not require unprivileged BPF program loading
  • Restrict CAP_BPF and CAP_SYS_ADMIN to trusted service accounts and audit container runtimes that grant them
  • Enable kdump and crash reporting so any attempt to trigger the bug produces investigable artifacts

Patch Information

The fix rejects a zero-sized element type in the flexible-array path of btf_struct_walk(), mirroring the existing guard in the fixed-array path. The change is distributed across the following stable backports: commit 172756f, commit 1ea3820, commit 63af086, commit 8eb4cd7, commit 934e9ba, commit b0b3dc6, and commit b8fa567.

Workarounds

  • Disable unprivileged BPF program loading with sysctl -w kernel.unprivileged_bpf_disabled=1 until patched kernels are deployed
  • Remove CAP_BPF from container and workload profiles that do not require eBPF
  • Enforce seccomp or Landlock policies that deny the bpf() syscall for processes that do not need it
bash
# Disable unprivileged BPF at runtime and persist across reboots
sysctl -w kernel.unprivileged_bpf_disabled=1
echo 'kernel.unprivileged_bpf_disabled=1' | sudo tee /etc/sysctl.d/90-bpf-hardening.conf
sysctl --system

# Verify the setting
sysctl kernel.unprivileged_bpf_disabled

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.