mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Bo Zhang <zhangbo0325@gmail.com>
To: aliceryhl@google.com, gregkh@linuxfoundation.org, cmllamas@google.com
Cc: arve@android.com, tkjos@android.com, christian@brauner.io,
	surenb@google.com, baohua@kernel.org, zhanghongru06@gmail.com,
	linux-kernel@vger.kernel.org
Subject: Re: [RFC PATCH v3 2/2] binder: add install_mutex to serialize page install and shrinker zap
Date: Sat,  5 Sep 2026 00:19:06 +0800	[thread overview]
Message-ID: <20260904161906.67595-1-zhangbo0325@gmail.com> (raw)
In-Reply-To: <20260904110448.23086-3-zhangbo0325@gmail.com>

Thanks for the review. All three are valid; I'll address them together
in v4 by tightening the roles of the two locks: install_mutex only
serializes page install vs shrinker zap, while alloc->lock (spinlock)
exclusively owns pages[] and the LRU. Details per point below.

1) AA self-deadlock via direct reclaim

Sashiko says
"binder_install_single_page() acquires alloc->install_mutex here, then
calls binder_page_insert() which invokes vm_insert_page(). vm_insert_page()
can trigger page table allocations using GFP_KERNEL semantics, which may
enter direct reclaim. If direct reclaim iterates over list_lru shrinkers
and invokes binder_alloc_free_page() for this same allocator on the same
thread, the shrinker callback will unconditionally try to lock the
already-held install_mutex."

Correct. In v4 the shrinker uses mutex_trylock(&install_mutex) and skips
the page (LRU_SKIP) on failure, so a reclaim recursion from the install
side's vm_insert_page() cannot deadlock on the same thread. The original
shrinker already used trylock on alloc->mutex; restoring trylock here also
removes the ABBA concern with mmap_lock, since a trylock does not
participate in a blocking lock cycle.

2) RT task livelock on the -EAGAIN retry

Sashiko says
"a race window exists where the shrinker has isolated a page from the
buffer's range (causing list_lru_del to fail and return -EAGAIN) but is
preempted before acquiring install_mutex. Because the mutex is uncontended,
the allocating thread acquires and drops it instantly, thinks the shrinker
is done, and retries. It will again find the page installed, fail
list_lru_del, and spin in a tight loop."

Correct. The root cause is that the current approach splits the
shrinker's pages[index]=NULL and list_lru_isolate() such that
binder_lru_freelist_del() can observe an inconsistent state. In v4 the
shrinker performs pages[index]=NULL and list_lru_isolate() together under
alloc->lock, so binder_lru_freelist_del() always sees a consistent
pages[]/LRU state and list_lru_del() never fails. This removes the
-EAGAIN retry path entirely, so the livelock cannot occur.

3) Use-after-free from clearing pages[index] outside alloc->lock

Sashiko says
"By moving binder_set_installed_page(alloc, index, NULL) outside the
alloc->lock critical section, a concurrent allocating thread holding
alloc->lock in binder_lru_freelist_del() can read the stale pointer:
page = alloc->pages[index] (which is not yet NULL). ... When the allocating
thread resumes, it will pass the dangling pointer to page_to_lru(page) and
page_to_nid(page), dereferencing the freed page_private."

Correct. In v4 pages[index]=NULL is moved back inside alloc->lock (together
with list_lru_isolate), so binder_lru_freelist_del() reading pages[index]
under alloc->lock can no longer observe a pointer that the shrinker is
about to free.

v4 will carry all three fixes.

Bo

      reply	other threads:[~2026-09-04 16:19 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04 11:04 [RFC PATCH v3 0/2] binder: split alloc->mutex to improve performance Bo Zhang
2026-09-04 11:04 ` [RFC PATCH v3 1/2] binder: switch alloc->mutex to spinlock for buffer metadata Bo Zhang
2026-09-04 11:04 ` [RFC PATCH v3 2/2] binder: add install_mutex to serialize page install and shrinker zap Bo Zhang
2026-09-04 16:19   ` Bo Zhang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260904161906.67595-1-zhangbo0325@gmail.com \
    --to=zhangbo0325@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=arve@android.com \
    --cc=baohua@kernel.org \
    --cc=christian@brauner.io \
    --cc=cmllamas@google.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=surenb@google.com \
    --cc=tkjos@android.com \
    --cc=zhanghongru06@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®