CVE-2026-98642

CVE-2026-98642

published October 18, 2026

CVSS
—
EPSS
0%
Percentile
5.7
In the wild
Unconfirmed
What it is

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

bpf: Fix UAF due to concurrent consumption of ttrace lists in alloc_bulk

Syzkaller repeatedly triggered UAF splats related to nodes in

waiting_for_gp_ttrace within the bpf memalloc:

BUG: KASAN: slab-use-after-free in llist_del_first+0x85/0x110 lib/llist.c:61

Read of size 8 at addr ffff8881572cd080 by task syz.4.470/5112

...

llist_del_first+0x85/0x110 lib/llist.c:61

alloc_bulk+0x193/0x460 kernel/bpf/memalloc.c:229

bpf_mem_refill+0x386/0x560 kernel/bpf/memalloc.c:436

Freed by task 14:

...

__free_rcu kernel/bpf/memalloc.c:281 [inline]

__free_rcu_tasks_trace+0x48/0xd0 kernel/bpf/memalloc.c:291

rcu_tasks_invoke_cbs+0x1ec/0x3e0 kernel/rcu/tasks.h:571

rcu_tasks_one_gp+0x13d/0x220 kernel/rcu/tasks.h:621

rcu_tasks_kthread+0xf3/0x120 kernel/rcu/tasks.h:651

The reason is that the UAF occurs after the RCU Tasks Trace GP expires:

when the __free_rcu() callback runs, there is no synchronization

protecting llist_del_all() against concurrent alloc_bulk() operating on

waiting_for_gp_ttrace, leading to the race condition below:

CPU0 CPU1

__free_rcu (RCU Tasks Trace callback)

alloc_bulk

llist_del_first(&c->waiting_for_gp_ttrace)

entry = smp_load_acquire(&head->first);

do {

if (entry == NULL)

return NULL;

free_all(llist_del_all(&c->waiting_for_gp_ttrace))

llist_for_each_safe(pos, t, llnode)

free_one(pos);

next = READ_ONCE(entry->next); <-- trigger UAF

} while (!try_cmpxchg(&head->first, &entry, next));

In addition, there is also a theoretical race condition on the

free_by_rcu_ttrace list. This race requires two preconditions: an

in-flight Tasks Trace GP keeping c->call_rcu_ttrace_in_progress == 1,

and concurrent cross-CPU frees repopulating c->free_by_rcu_ttrace with

new nodes. Under these conditions, the following scenario triggers UAF:

// CPU0

// irq work is still busy (on PREEMPT_RT)

alloc_bulk()

llist_del_first(&c->free_by_rcu_ttrace)

entry = smp_load_acquire(&head->first);

do {

if (entry == NULL)

return NULL;

// CPU1

bpf_mem_alloc_destroy()

WRITE_ONCE(c->draining, true)

// wait for CPU0

irq_work_sync()

// CPU2

do_call_rcu_ttrace(tgt(CPU0))

if (c->draining) {

llist_del_all(&c->free_by_rcu_ttrace)

free_all()

}

// CPU0 continue

next = READ_ONCE(entry->next); <-- trigger UAF

while (!try_cmpxchg(&head->first, &entry, next));

Fix this by introducing a raw spinlock to synchronize the concurrent

consumption on waiting_for_gp_ttrace and free_by_rcu_ttrace.

The record
Technical detail
CVSS
Not scored
CVSS v4.0
Not supplied
EPSS
0.00168 · 5.7th percentile
Published
2026-10-18T20:17Z
References (4)
EPSS history
Timeline
  • 20 OCT 03:34Z
    EPSS moved — → 0%
    epss
  • 18 OCT 15:20Z
    bpf: Fix UAF due to concurrent consumption of ttrace lists in alloc_bulk
    cvelistv5
  • 18 OCT 15:20Z
    bpf: Fix UAF due to concurrent consumption of ttrace lists in alloc_bulk
    cvelistv5