Bug 2541197 (CVE-2026-98040)

Summary: CVE-2026-98040 kernel: bpf: Mark the zero register precise for a register-form NULL check
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security DevOps Team <prodsec-dev>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: akhatavk, aos-team-art-private, asdas, dpaolell, jdelft, jupierce, lgarciaa, mbiarnes, ppalepu, ppostler, prdhamdh, rhel-process-autobot, sghai, sidsharm, suppawar, vlaad, watson-tool-maintainers
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in the Linux kernel's Berkeley Packet Filter (BPF) verifier. When validating conditional jump operations using register comparisons against null values, the verifier fails to properly track register precision across different execution paths. A local user capable of loading BPF programs can exploit this flaw to bypass safety checks and trigger a null pointer dereference, leading to a system crash and Denial of Service (DoS).
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-09-25 10:58:52 UTC
In the Linux kernel, the following vulnerability has been resolved:

bpf: Mark the zero register precise for a register-form NULL check

check_cond_jmp_op() accepts "if rA <op> rB" as a NULL check for a
nullable pointer rA when rB is a scalar known to be zero,
lifts PTR_MAYBE_NULL from rA in the corresponding branch and does not
mark rB precise. Consider the following program:

  r0 = bpf_get_prandom_u32();
  r6 = 1;                  /* the r6 == 0 path is explored first */
  if (r0 == 0) goto 1f;
  r6 = 0;
1:
  r0 = bpf_map_lookup_elem(map, &0);  /* absent, NULL at runtime */
  if (r0 == r6) goto 2f;   /* taken as a NULL check for r0       */
  *(u8 *)(r0 + 0);         /* verifier: map value; runtime: zero */
2:
  return 0;

The r6 == 0 path is explored first and the dereference is accepted.
The r6 == 1 path is pruned at the checkpoint recorded for (1),
so the comparison is never verified with a non-zero r6. At runtime a
failed lookup returns NULL, NULL != 1 takes the non-NULL edge and the
program dereferences a pointer that is zero.