CVE-2026-98861
UnknownSummary
A vulnerability was fixed in the Linux kernel's fprobe mechanism where unregister_fprobe() and unregister_fprobe_async() relied on standard RCU grace periods that do not track preemption-disabled sections when RCU is not watching (e.g., in the idle loop or nohz_full extended quiescent states). This could lead to a use-after-free if the fprobe was freed immediately after unregistration. The fix ensures handlers exit early when !rcu_is_watching() and replaces guard(rcu)() and rcu_read_lock() with guard(rcu_sched_notrace)(), eliminating fast-path lockdep overhead.
Risk Assessment
A use-after-free in the kernel can lead to system instability, kernel panic, or potentially privilege escalation by a local attacker. It affects systems using fprobe, including BPF kprobe-multi, especially in nohz_full or CONFIG_PROVE_LOCKING configurations.
Recommendation
Update the Linux kernel to a version containing the fix for CVE-2026-98861. If updating is not possible, consider restricting access to BPF/kprobe mechanisms for untrusted users.
Other vulnerabilities in Linux kernel
See all- CVE-2026-98868Unknown
In the Linux kernel, the following vulnerability has been resolved: dm-pcache: reject a kset that overruns its segment. cache_replay(), the writeback worker and the GC worker read a kset of get_kset_onmedia_size() bytes and advance the position by it. A forged key_num makes that size exceed the segment's remaining space, so the advance walks past the segment and trips the cache_pos_advance() BUG_ON.
- CVE-2026-98867Unknown
In the Linux kernel, the following vulnerability has been resolved: dm-pcache: bound the logical key offset from persistent memory. cache_key_decode() takes a key's logical off from the cache device and later indexes req_key_tree->subtrees[] by it in get_subtree(). An off past the device forms a subtree pointer outside the array, which rb_insert() writes through during replay.
- CVE-2026-98866Unknown
In the Linux kernel, the following vulnerability has been resolved: sched/cache: Introduce task_struct->sched_cache_grp to fix UAF. Add a sched_cache_grp pointer to task_struct so that scheduler code can access the cache group directly via the task, without going through mm->sched_cache_grp. This decouples the scheduler's hot-path accesses from the mm_struct. Each task holds its own refcount on the sched_cache_group, separate from the reference held by its mm_struct. The reference is acquired in copy_mm() (fork) and exec_mmap() (exec), and released in exit_mm(). This fixes the use-after-free when account_mm_sched() reaches the group through a task whose mm is being switched.
- CVE-2026-98865Unknown
In the Linux kernel's sched_ext scheduler, ops.dequeue() was invoked while the source user DSQ lock was still held on the consume and move paths. A BPF scheduler that locks the source DSQ from ops.dequeue() would self-deadlock. The fix moves the invocation after the DSQ unlock on all three paths.
- CVE-2026-98864Unknown
In the Linux kernel's sched_ext, a task could be found on a DSQ while still in SCX_OPSS_DISPATCHING state. The reenqueue paths did not wait for the state to clear, so ops.enqueue() set SCX_OPSS_QUEUED and the dispatcher's final store overwrote it with SCX_OPSS_NONE, dropping later dispatches of the task. The fix waits for SCX_OPSS_DISPATCHING to clear before dequeueing for reenqueue.
- CVE-2026-98863Unknown
In KVM on x86, GET_NESTED_STATE_PAGES was not re-pended when fetching nested pages failed in the KVM_RUN path. If userspace re-ran the vCPU and vmcs02 held valid PFNs from the previous L2 run, KVM could re-enter L2 with stale, unpinned PFNs mapped into e.g. the vAPIC page.
- CVE-2026-98862Unknown
In the Linux kernel audit subsystem, kill_rules() removed mixed AUDIT_DIR and AUDIT_EXE rules when pruning an audit tree, dropping entry->rule.exe before removing the rule from RCU-visible filter lists. Removing the watched directory could race with another task evaluating the rule, causing a use-after-free in audit_mark_compare().
- CVE-2026-98860Unknown
In the Linux kernel HID BPF subsystem, the comparison of the return value from hid_bpf_hw_request against size did not cast size to ssize_t. When a transport driver returned a negative error code (e.g. -EPIPE), it was promoted to size_t and evaluated as a large positive number, making (ret > size) true. This silently converted the hardware error into a success and copied the unmodified buffer back.
- CVE-2026-98859Unknown
In the Linux kernel, the HID multitouch driver's mt_remove() used timer_delete_sync() to stop the sticky-finger release timer. However, the timer could be rearmed by a report arriving after deletion, leading to a use-after-free when the timer fired after the driver was unbound. The fix replaces timer_delete_sync() with timer_shutdown_sync(), which also prevents any subsequent mod_timer() from rearming the timer.
- CVE-2026-98858Unknown
In the Linux kernel io_uring with SQPOLL, the sqpoll thread could pop and complete a request as soon as mpscq_push() published it. If that was the last request holding the ring alive, io_ring_exit_work() freed the ctx, stopped the thread and tctx while io_req_normal_work_add() was still referencing them, causing a use-after-free. The fix holds an RCU read lock across the add and waits for a grace period before freeing the ctx.
Original NVD description (English source)
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.
Vulnerability data from NVD (NIST) · CISA KEV · EPSS

