Hi,

I noticed the Sashiko AI review [1] in this thread flagged that
kfree_call_rcu_nolock() dereferences slab->slab_cache even when
virt_to_slab() returns NULL (for large kmalloc objects that bypass
SLUB, or vmalloc addresses).  The VM_WARN_ON_ONCE fires but does not
stop execution, and the subsequent NULL dereference is deterministic.

I was able to reproduce this in QEMU with KASAN.  The trigger is as
simple as passing a large (>8KB) kmalloc buffer to the new function.

On Tue, Jun 16, 2026 at 12:06:14AM +0800, Harry Yoo (Oracle) wrote:
> This commit introduces kfree_rcu_nolock(), a variant of kfree_rcu()
> designed to be safely called from unknown contexts without falling
> back to batched processing.
...
> +void kfree_call_rcu_nolock(struct rcu_head *head, void *ptr)
> +{
> +    struct slab *slab;
> +    struct kmem_cache *s;
> +
> +    VM_WARN_ON_ONCE(is_vmalloc_addr(ptr) || !virt_to_slab(ptr));
> +
> +    slab = virt_to_slab(ptr);
> +    s = slab->slab_cache;

The problem: if ptr is a large kmalloc object (> KMALLOC_MAX_CACHE_SIZE,
which is 8 KB on x86_64), the allocation bypasses SLUB and comes from
the page allocator.  virt_to_slab() returns NULL.  VM_WARN_ON_ONCE
prints a warning but does NOT return, and the next line dereferences
NULL->slab_cache at offset 0x8.

[Reproduction]

I rebuilt the kernel with CONFIG_KASAN=y and added a small late_initcall
that allocates a 16 KB buffer and passes it to kfree_call_rcu_nolock():

  static int __init kfree_rcu_nolock_poc_trigger(void)
  {
      void *p = kmalloc(16384, GFP_KERNEL);
      struct rcu_head *head = kmalloc(sizeof(*head), GFP_KERNEL);
      kfree_call_rcu_nolock(head, p);
      return 0;
  }
  late_initcall(kfree_rcu_nolock_poc_trigger);

[Crash log — kernel 6.19.0-rc5, CONFIG_KASAN=y, CONFIG_DEBUG_VM=y]

  kfree_rcu_nolock PoC: calling kfree_call_rcu_nolock on large obj ffff888026c5c000

  WARNING: mm/slab_common.c:1271 at kfree_call_rcu_nolock+0x1e/0xc0
  VM_WARN_ON_ONCE(is_vmalloc_addr(ptr) || !virt_to_slab(ptr))

  BUG: kernel NULL pointer dereference, address: 0000000000000008
  #PF: supervisor read access in kernel mode
  #PF: error_code(0x0000) - not-present page

  RIP: 0010:kfree_call_rcu_nolock+0x5c/0xc0
  Call Trace:
   <TASK>
   poc_trigger_init+0x2a/0x40
   do_one_initcall+0x131/0x730
   kernel_init_freeable+0x471/0x7e0
   kernel_init+0x28/0x300
   ret_from_fork+0x2c/0xc0
   </TASK>

  Kernel panic - not syncing: Fatal exception

The crash is at offset 0x5c inside kfree_call_rcu_nolock(), which
corresponds to `s = slab->slab_cache`.  The fault address 0x8 is
exactly offsetof(struct slab, slab_cache).


[1] https://sashiko.dev/#/patchset/20260615-kfree_rcu_nolock-v3-0-70a54f3775bb%40kernel.org     (Sashiko AI code review — "Null Pointer Dereference", Severity: Critical)

Thanks,
XIAO



Reply via email to