binder: fix NULL lock dereference in shrinker on Linux >= 6.13

Since Linux 6.13 the list_lru walk callback no longer receives the lru
lock; it lives in struct list_lru_one. binder_alloc_free_page_no_lock()
passes NULL as the lock, so binder_alloc_free_page() ends up calling
spin_unlock(NULL) as soon as kswapd runs the binder shrinker:

  BUG: kernel NULL pointer dereference, address: 0000000000000000
  RIP: 0010:_raw_spin_unlock+0x9/0x40
  Call Trace:
   binder_alloc_free_page+0xe1/0x360 [binder_linux]
   __list_lru_walk_one+0xdf/0x230
   list_lru_walk_node+0x52/0x230
   binder_shrink_scan+0xa7/0x100 [binder_linux]
   do_shrink_slab+0x154/0x3a0
   ...
   kswapd+0x1e2/0x360

The machine then hangs, typically under memory pressure, right after
resuming from suspend, or while writing a hibernation image.

Fall back to &lru->lock when no lock is passed, as upstream binder does.
This commit is contained in:
Anthony 2026-10-03 00:02:40 +02:00
parent 3f65f66a87
commit 96d5d960fe

View File

@ -1003,6 +1003,10 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
size_t index; size_t index;
struct vm_area_struct *vma; struct vm_area_struct *vma;
/* Since 6.13 the list_lru callback gets no lock; it lives in lru. */
if (!lock)
lock = &lru->lock;
alloc = page->alloc; alloc = page->alloc;
if (!mutex_trylock(&alloc->mutex)) if (!mutex_trylock(&alloc->mutex))
goto err_get_alloc_mutex_failed; goto err_get_alloc_mutex_failed;