Commit 8eb52a1e authored by Jann Horn's avatar Jann Horn Committed by Greg Kroah-Hartman

binder: Fix race between mmap() and binder_alloc_print_pages()

binder_alloc_print_pages() iterates over
alloc->pages[0..alloc->buffer_size-1] under alloc->mutex.
binder_alloc_mmap_handler() writes alloc->pages and alloc->buffer_size
without holding that lock, and even writes them before the last bailout
point.

Unfortunately we can't take the alloc->mutex in the ->mmap() handler
because mmap_sem can be taken while alloc->mutex is held.
So instead, we have to locklessly check whether the binder_alloc has been
fully initialized with binder_alloc_get_vma(), like in
binder_alloc_new_buf_locked().

Fixes: 8ef4665a ("android: binder: Add page usage in binder stats")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJann Horn <jannh@google.com>
Acked-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
Link: https://lore.kernel.org/r/20191018205631.248274-1-jannh@google.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 60f8a59d
...@@ -840,6 +840,11 @@ void binder_alloc_print_pages(struct seq_file *m, ...@@ -840,6 +840,11 @@ void binder_alloc_print_pages(struct seq_file *m,
int free = 0; int free = 0;
mutex_lock(&alloc->mutex); mutex_lock(&alloc->mutex);
/*
* Make sure the binder_alloc is fully initialized, otherwise we might
* read inconsistent state.
*/
if (binder_alloc_get_vma(alloc) != NULL) {
for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
page = &alloc->pages[i]; page = &alloc->pages[i];
if (!page->page_ptr) if (!page->page_ptr)
...@@ -849,6 +854,7 @@ void binder_alloc_print_pages(struct seq_file *m, ...@@ -849,6 +854,7 @@ void binder_alloc_print_pages(struct seq_file *m,
else else
lru++; lru++;
} }
}
mutex_unlock(&alloc->mutex); mutex_unlock(&alloc->mutex);
seq_printf(m, " pages: %d:%d:%d\n", active, lru, free); seq_printf(m, " pages: %d:%d:%d\n", active, lru, free);
seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high); seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment