---
id: CVE-2026-98789
title: 'bpf: Fix objects stuck in free_by_rcu_ttrace'
summary: |-
  In the Linux kernel, the following vulnerability has been resolved:

  bpf: Fix objects stuck in free_by_rcu_ttrace

  do_call_rcu_ttrace() returns early when call_rcu_ttrace_in_progress is set
  and leaves the objects in free_by_rcu_ttrace. _…
severity: none
vendor: Linux
product: Linux
affected:
  - >-
    Linux >= 8d5a8011b35d387c490a5c977b1d9eb4798aa071 <
    33d0a5d2fee06a51f2f056dd901296515912e954
  - >-
    Linux >= 8d5a8011b35d387c490a5c977b1d9eb4798aa071 <
    fbd97dd1d3ce32d32fb7be86acc3fdb7c04fa043
  - Linux 6.1
published: '2026-10-18'
updated: '2026-10-18'
sourceUpdated: '2026-10-18T15:48:25.665Z'
source: CVEORG
sourceUrl: 'https://www.cve.org/CVERecord?id=CVE-2026-98789'
references:
  - url: 'https://git.kernel.org/stable/c/33d0a5d2fee06a51f2f056dd901296515912e954'
  - url: 'https://git.kernel.org/stable/c/fbd97dd1d3ce32d32fb7be86acc3fdb7c04fa043'
tags:
  - cve.org
ingestedAt: '2026-10-18T16:47:32.487Z'
---

## Overview

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

bpf: Fix objects stuck in free_by_rcu_ttrace

do_call_rcu_ttrace() returns early when call_rcu_ttrace_in_progress is set
and leaves the objects in free_by_rcu_ttrace. __free_rcu() frees
waiting_for_gp_ttrace only and clears the flag. Hence the objects that
free_bulk() or __free_by_rcu() added while RCU tasks trace GP was in flight
stay in free_by_rcu_ttrace until free_bulk() or alloc_bulk() is called for
the same bpf_mem_cache again, which may never happen. The number of such
objects is not bounded.

Turn call_rcu_ttrace_in_progress into three states:
0 - idle
1 - __free_rcu() is queued
2 - __free_rcu() is queued and free_by_rcu_ttrace got more objects since

do_call_rcu_ttrace() sets 2. __free_rcu() does cmpxchg(1 -> 0) and starts
the next GP when it fails. It cannot clear the flag first and check
free_by_rcu_ttrace later, since bpf_mem_alloc_destroy() frees bpf_mem_cache
without waiting for RCU callbacks when the flag is zero.

Now __free_rcu() queues itself, so the one that didn't see 'draining' may
do call_rcu_tasks_trace() after rcu_barrier_tasks_trace() in
free_mem_alloc(). Queue it under rcu_read_lock() and do synchronize_rcu()
before the barriers. Calling rcu_barrier_tasks_trace() twice works too, but
creating and destroying hash maps in a loop on many cpus slows down to one
free_mem_alloc() per GP and kworkers pile up.

## Affected

- `Linux >= 8d5a8011b35d387c490a5c977b1d9eb4798aa071 < 33d0a5d2fee06a51f2f056dd901296515912e954`
- `Linux >= 8d5a8011b35d387c490a5c977b1d9eb4798aa071 < fbd97dd1d3ce32d32fb7be86acc3fdb7c04fa043`
- `Linux 6.1`

## Remediation

Refer to the linked advisories for vendor-supplied fixes and affected version ranges.
