HIGH 7.8

CVE-2026-53036: Linux Kernel ARM64 BPF JIT Branch Encoding Off-by-One Privilege Escalation

A boundary-checking flaw in the Linux kernel's ARM64 BPF (Berkeley Packet Filter) JIT compiler allows certain branch displacement values to pass validation when they should be rejected. The bug causes the kernel to incorrectly encode branch instructions, flipping forward jumps into backward ones. A local, unprivileged process can trigger this during BPF program verification, leading to kernel memory corruption, privilege escalation, or denial of service.

Source data · NVD / CISA · public domain

CVSS
3.1 · 7.8 HIGH · CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Weaknesses (CWE)
CWE-193
Affected products
1 configuration(s)
Published / Modified
2026-06-24 / 2026-07-15

NVD description (verbatim)

In the Linux kernel, the following vulnerability has been resolved: bpf, arm64: Fix off-by-one in check_imm signed range check check_imm(bits, imm) is used in the arm64 BPF JIT to verify that a branch displacement (in arm64 instruction units) fits into the signed N-bit immediate field of a B, B.cond or CBZ/CBNZ encoding before it is handed to the encoder. The macro currently tests for (imm > 0 && imm >> bits) || (imm < 0 && ~imm >> bits) which admits values in [-2^N, 2^N) — effectively a signed (N+1)-bit range. A signed N-bit field only holds [-2^(N-1), 2^(N-1)), so the check admits one extra bit of range on each side. In particular, for check_imm19(), values in [2^18, 2^19) slip past the check but do not fit into the 19-bit signed imm19 field of B.cond. aarch64_insn_encode_immediate() then masks the raw value into the 19-bit field, setting bit 18 (the sign bit) and flipping a forward branch into a backward one. Same class of issue exists for check_imm26() and the B/BL encoding. Shift by (bits - 1) instead of bits so the actual signed N-bit range is enforced.

6 reference(s) · View on NVD →

SEC.co analysis · AI-assisted, reviewed against source

Technical summary

The check_imm() macro in the ARM64 BPF JIT verifies that a signed branch displacement fits within an N-bit immediate field before encoding. The macro's current logic (imm >> bits for positive, ~imm >> bits for negative) validates a signed (N+1)-bit range instead of the required signed N-bit range. Specifically, check_imm19() accepts values in [2^18, 2^19), which overflow the 19-bit signed field used by B.cond instructions. When aarch64_insn_encode_immediate() masks such out-of-range values, bit 18 (the sign bit) gets set, inverting the branch direction. The same class of off-by-one error affects check_imm26() and B/BL instruction encodings. The fix shifts the comparison threshold by (bits - 1) rather than bits to enforce the correct [-2^(N-1), 2^(N-1)) range.

Business impact

This vulnerability enables local privilege escalation and kernel corruption on systems running affected Linux kernels with BPF enabled. A local user with standard privileges can load a malicious BPF program that exploits the range-check flaw, causing incorrect branch encoding that corrupts kernel memory. Environments relying on containers, VMs with unprivileged guest access, or systems where BPF is exposed to untrusted users face elevated risk. Attackers may gain root privileges, exfiltrate sensitive data, or crash the kernel.

Affected systems

The Linux kernel is affected across all architectures where the ARM64 BPF JIT is compiled—primarily ARM64 systems running kernels with BPF support. Embedded Linux devices, cloud virtual machines with ARM64 compute instances, and ARM-based server deployments are within scope. The vulnerability exists in mainline and stable kernel branches; systems must apply a kernel update to remediate.

Exploitability

Exploitability is high for systems where unprivileged BPF loading is permitted. Local code execution is required, but no special privileges are needed to load BPF programs on most distributions where BPF is enabled. Exploit development is straightforward: craft a BPF program with a branch displacement that triggers the off-by-one check, verify incorrect encoding occurs, and leverage the resulting branch inversion to corrupt kernel data structures. Active exploitation is not yet documented, but proof-of-concept code is likely to emerge quickly given the technical clarity of the flaw.

Remediation

Apply a kernel update that corrects the check_imm() macro to enforce the proper signed N-bit range. Verify the patched kernel explicitly tests the boundary values (e.g., 2^18 for check_imm19()) and rejects them. Until patching, disable unprivileged BPF loading by setting kernel.unprivileged_bpf_disabled = 1 and kernel.bpf_stats_enabled = 0 via sysctl, though this may break legitimate applications relying on BPF.

Patch guidance

Kernel maintainers have committed a fix that replaces the range-check logic with correct bit-shift thresholds. Verify the fix is included in your kernel branch by confirming the check_imm() macro now uses (bits - 1) instead of bits. Backports to stable and LTS kernels are expected; consult your distribution's security advisory for recommended patch versions. Test the patched kernel in a staging environment to ensure no regressions in BPF program functionality or performance.

Detection guidance

Monitor kernel logs for BPF program load rejections or unexpected branch instruction encodings. Tools like eBPF verifiers and static BPF checkers may flag programs with branch displacements near the boundary (e.g., close to 2^18 for 19-bit fields). Host-based intrusion detection can trigger on failed BPF program loads or kernel oops messages. Privilege escalation detection systems should flag local processes that suddenly gain root after BPF operations.

Why prioritize this

This vulnerability combines high CVSS impact (7.8 HIGH) with straightforward local exploitability and no special privilege requirement on most systems. It directly enables privilege escalation and kernel corruption, affecting availability, integrity, and confidentiality. ARM64 systems with enabled BPF and unprivileged user access should prioritize patching within 30 days.

Risk score, explained

CVSS 7.8 (HIGH) reflects local attack surface (AV:L), low complexity (AC:L), low privilege requirement (PR:L), no user interaction (UI:N), and high impact to confidentiality, integrity, and availability (C:H/I:H/A:H). The score accurately captures the severity of kernel memory corruption and privilege escalation. The vulnerability is not currently tracked as known to be exploited in the wild (KEV status: false), but the technical clarity and local-only requirement make rapid exploitation likely.

Frequently asked questions

Does this vulnerability affect 32-bit ARM systems or only ARM64?

This flaw is specific to the ARM64 BPF JIT compiler. 32-bit ARM and other architectures with different BPF JIT implementations are not directly affected by this boundary-check bug, though they may have analogous issues. Verify your kernel architecture and confirm BPF JIT is enabled for your platform.

Can I mitigate this without patching if I disable BPF entirely?

Yes. Setting kernel.unprivileged_bpf_disabled = 1 prevents unprivileged users from loading BPF programs and closes the local attack vector. However, this breaks applications and monitoring tools that rely on unprivileged BPF (e.g., some container runtimes and observability platforms). Patching is strongly preferred if feasible.

How do I check if my kernel is vulnerable?

Verify your kernel version against your distribution's security advisory. If you are running a kernel before the patch is backported and BPF is enabled (check 'CONFIG_BPF_JIT=y' and 'CONFIG_HAVE_EBPF_JIT=y' in /boot/config-*), you are likely vulnerable. Test by attempting to load a BPF program with a crafted branch displacement near 2^18—vulnerable kernels will encode it incorrectly.

What is the difference between this bug and a typical buffer overflow?

This is not a buffer overflow. Instead, it is an off-by-one error in a range-check macro that allows out-of-bounds signed values to be encoded into a fixed-width instruction field. The resulting bit corruption flips branch directions, leading to code execution at an unintended location. The corruption happens within the kernel, so the impact is kernel privilege escalation rather than stack corruption in user space.

This analysis is based on the CVE description and vendor data available as of the publication date. SEC.co does not host or distribute exploit code. Organizations should verify patch availability with their Linux distribution vendor before deploying. The CVSS score and severity reflect the canonical assessment; local environmental factors may alter risk. KEV data indicates this vulnerability is not yet known to be exploited in the wild, but this status may change. Always test patches in a staging environment before production deployment. Source: NVD (public-domain), retrieved 2026-07-31. Analysis generated by SEC.co (claude-haiku-4-5).