---
id: "CVE-2026-98861"
kind: "vulnerability"
aliases: ["CVE-2026-98861"]
title: "Linux kernel: fprobe handlers can run during RCU idle and use freed memory"
severity: "unknown"
cvss: null
epss: null
exploited: false
status: "open"
category: "other"
products: []
ecosystems: []
tags: ["bpf", "linux-kernel", "other", "self-hosted"]
not_affected_if: ["unknown"]
published_at: "2026-10-18T16:17:40+00:00"
first_seen_at: "2026-10-23T21:57:17+00:00"
updated_at: "2026-10-25T05:12:53+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-98861", "first_seen_at": "2026-10-23T21:57:17+00:00"}]
---

# Linux kernel: fprobe handlers can run during RCU idle and use freed memory

In the Linux kernel's fprobe tracing code, probe handlers can run while RCU is not watching, so unregistering a probe may free it while a handler still uses it. The sources do not state what an attacker can do beyond a possible use-after-free in the kernel.

_Summary, check and fix written by a model from the sources; labelled as such._

## How to check

- `uname -r` to see the running kernel version
- unknown

## Fix

- Update the Linux kernel to a release that includes the upstream fprobe fix (the sources do not name a fixed version)
- unknown

## Timeline

- 2026-10-23T21:57:17+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-98861

## From the sources

In the Linux kernel, the following vulnerability has been resolved:

fprobe: Use guard(rcu_sched_notrace) and check rcu_is_watching()

unregister_fprobe() and unregister_fprobe_async() (used by BPF
kprobe-multi) rely on standard RCU grace periods (synchronize_rcu()
and call_rcu()) to wait until in-flight fprobe handlers complete before
freeing the fprobe.

However, if an fprobe handler executes while RCU is not watching (such
as in the idle loop or nohz_full extended quiescent states), standard
RCU does not track preemption-disabled sections. Consequently,
synchronize_rcu() does not wait for those executions, which can lead
to a use-after-free if the fprobe is freed immediately after
unregistration. Ensure handlers exit early when !rcu_is_watching().

Furthermore, fprobe_fgraph_entry() and fprobe_ftrace_entry() previously
used guard(rcu)() and rcu_read_lock(), which invoke lockdep on every
hit under CONFIG_PROVE_LOCKING. This adds overhead and can cause lockdep
recursion if probed functions interact with lockdep.

Since rhltable_lookup() and rhl_for_each_entry_rcu() use
rcu_dereference_all_check() (which checks rcu_read_lock_any_held()),
holding preemption disabled via rcu_read_lock_sched_notrace() is fully
valid and sufficient so long as rcu_is_watching() is true.

Define and use guard(rcu_sched_notrace)() across fprobe_ftrace_entry(),
fprobe_fgraph_entry(), and fprobe_return(). This eliminates fast-path
rcu_read_lock() and lockdep overhead while guaranteeing safe grace
period synchronization.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
