{"dataType":"CVE_RECORD","dataVersion":"5.2","cveMetadata":{"cveId":"CVE-2026-90317","assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","state":"PUBLISHED","assignerShortName":"Linux","dateReserved":"2026-09-11T19:38:34.801Z","datePublished":"2026-09-17T16:08:35.537Z","dateUpdated":"2026-09-18T17:54:32.573Z"},"containers":{"cna":{"providerMetadata":{"orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","shortName":"Linux","dateUpdated":"2026-09-18T17:54:32.573Z"},"descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nbpf: Invalidate RCU pointers after final spin unlock\n\nIn a sleepable BPF program, a spin lock can provide the only RCU protection\nfor a kptr. The final bpf_spin_unlock() ends that protection, but the\nverifier leaves the pointer valid. Another CPU can then free the object\nbefore the pointer is used. A capability-limited runtime PoC triggered a\ntask_struct use-after-free in __bpf_get_task_stack().\n\nRecord whether the program is in an RCU-protected context before releasing\nthe lock. Invalidate RCU-protected pointers only when the unlock leaves the\nfinal such context. This preserves valid pointers in non-sleepable programs\nand inside an explicit RCU read-side section."}],"metrics":[{"cvssV3_1":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","baseScore":7.8,"baseSeverity":"HIGH"},"scenarios":[{"lang":"en","value":"AV:L - The attacker-controlled input is a sleepable BPF program loaded via bpf(BPF_PROG_LOAD) whose bytecode reaches process_spin_lock() in kernel/bpf/verifier.c, takes bpf_spin_lock, LDXes a map kptr, then bpf_spin_unlock. That program image arrives through the local bpf() syscall, not a network protocol message.\nAC:L - The attacker drives both sides: a sleepable fentry.s or BPF_PROG_TYPE_SYSCALL program loads a task kptr under bpf_spin_lock, unlocks, then uses it, while another thread bpf_kptr_xchg's the same slot to NULL so bpf_task_release_dtor/put_task_struct_rcu_user can call_rcu it. After unlock, preempt/IRQs are re-enabled so the grace period can finish; a PoC hit the UAF.\nPR:L - A sleepable BPF_PROG_TYPE_SYSCALL program is sufficient: bpf_prog_load() requires only bpf_token_capable(CAP_BPF) because is_perfmon_prog_type() is false for SYSCALL, and map_check_btf() needs CAP_BPF for BPF_SPIN_LOCK|BPF_KPTR fields. CAP_BPF is delegable via BPF tokens into a user namespace; the report used a capability-limited PoC, not init-namespace root.\nUI:N - The attacker loads the sleepable program, creates the lock+kptr ARRAY map, stores a task with bpf_task_from_pid/bpf_kptr_xchg, and runs it via bpf(BPF_PROG_TEST_RUN) (bpf_prog_test_run_syscall) or by calling getpgid after attaching fentry.s; no victim mount or file open is required.\nS:U - The use-after-free is of a host kernel task_struct consumed by bpf_task_acquire and __bpf_get_task_stack in the same kernel that accepted the program. That is local privilege escalation inside one kernel authority, not a VM, IOMMU, or guest-to-host crossing.\nC:H - After the final bpf_spin_unlock, process_spin_lock() leaves the map-loaded task kptr as MEM_RCU, so the program can LDX task_struct fields or call bpf_task_acquire (refcount_inc_not_zero on rcu_users) and __bpf_get_task_stack (try_get_task_stack/task_pt_regs) on a call_rcu-freed object. Spraying that slot yields an arbitrary kernel read.\nI:H - The same stale MEM_RCU task_struct pointer can be passed to bpf_task_acquire after bpf_task_release_dtor has dropped rcu_users and delayed_put_task_struct has freed it; a sprayed replacement becomes an owned kptr the attacker can feed to other kfuncs or store back with bpf_kptr_xchg, giving a write and control-flow primitive.\nA:H - Using the dangling task pointer in __bpf_get_task_stack (try_get_task_stack/task_pt_regs) or bpf_task_acquire after put_task_struct_rcu_user's call_rcu has run oopses or panics the kernel even without a full exploit."}]}],"affected":[{"product":"Linux","vendor":"Linux","defaultStatus":"unaffected","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["kernel/bpf/verifier.c"],"versions":[{"version":"5861d1e8dbc4e1a03ebffb96ac041026cdd34c07","lessThan":"7ae71629357d0a6d0bdadb929c7b296d5b7e61c2","status":"affected","versionType":"git"},{"version":"5861d1e8dbc4e1a03ebffb96ac041026cdd34c07","lessThan":"180c7000712db77063b3a26f4c97e7dd9038f449","status":"affected","versionType":"git"}]},{"product":"Linux","vendor":"Linux","defaultStatus":"affected","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["kernel/bpf/verifier.c"],"versions":[{"version":"6.6","status":"affected"},{"version":"0","lessThan":"6.6","status":"unaffected","versionType":"semver"},{"version":"7.2.6","lessThanOrEqual":"7.2.*","status":"unaffected","versionType":"semver"},{"version":"7.3-rc1","lessThanOrEqual":"*","status":"unaffected","versionType":"original_commit_for_fix"}]}],"cpeApplicability":[{"nodes":[{"operator":"OR","negate":false,"cpeMatch":[{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.6","versionEndExcluding":"7.2.6"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.6","versionEndExcluding":"7.3-rc1"}]}]}],"references":[{"url":"https://git.kernel.org/stable/c/7ae71629357d0a6d0bdadb929c7b296d5b7e61c2"},{"url":"https://git.kernel.org/stable/c/180c7000712db77063b3a26f4c97e7dd9038f449"}],"title":"bpf: Invalidate RCU pointers after final spin unlock","x_generator":{"engine":"bippy-1.2.0"}}}}