bpf: Mark the zero register precise for a register-form NULL check
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 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.
- Products
- Kernel
- Affected versions
- Not specified
- Fixed versions
- 7.2.7
- CVEs
- CVE-2026-98040
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 7 Nov 2026, 13:25 UTC · Revision 1
Source evidence
bpf: Mark the zero register precise for a register-form NULL check
core-osv · Original sourcePublished 25 Sept 2026, 10:23 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 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.
osv:CVE-2026-98040
Kernel
Fixed versions: 7.2.7
Complete source record
{
"id": "8cebbffcb4e777a2ecb8cd44a14247249afcedff8383d452380f6921b1406b98",
"url": "https://osv.dev/vulnerability/CVE-2026-98040",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "bpf: Mark the zero register precise for a register-form NULL check",
"summary": "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 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.",
"evidence": "osv:CVE-2026-98040",
"products": [
{
"name": {
"value": "Kernel",
"evidence": "/affected/1/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "7.2.7",
"evidence": "/affected/1/ranges"
}
],
"affected_versions": []
}
],
"severity": "unknown",
"structured": {
"id": "CVE-2026-98040",
"aliases": [
"CVE-2026-98040"
],
"affected": [
{
"ranges": [
{
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"type": "GIT",
"events": [
{
"introduced": "2f4cb53eed448c1aeb6f4b40cf9c810716d8218c"
},
{
"fixed": "ddca9a3b8833168dda3e62676648a636fb3f221c"
},
{
"fixed": "6aed0134d3cda6382385a734ae0158eb7df6b142"
}
]
}
],
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-98040.json"
}
},
{
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "7.1.0"
},
{
"fixed": "7.2.7"
}
]
}
],
"package": {
"name": "Kernel",
"ecosystem": "Linux"
},
"database_specific": {
"source": "https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-98040.json"
}
}
],
"modified": "2026-10-28T02:30:50.724252296Z",
"provider": "osv",
"references": [
"https://git.kernel.org/stable/c/6aed0134d3cda6382385a734ae0158eb7df6b142",
"https://git.kernel.org/stable/c/ddca9a3b8833168dda3e62676648a636fb3f221c",
"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/98xxx/CVE-2026-98040.json",
"https://nvd.nist.gov/vuln/detail/CVE-2026-98040",
"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
],
"provider_metadata": {
"cna_assigner": "Linux",
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/98xxx/CVE-2026-98040.json"
}
},
"related_cves": [
{
"value": "CVE-2026-98040",
"evidence": "/id"
}
],
"security_relevant": true,
"severity_evidence": null
},
"source_id": "core-osv",
"document_id": 519448,
"published_at": "2026-09-25T10:23:53.001+00:00"
}