Skip to content

Commit 5cec2d2

Browse files
Todd Kjosgregkh
authored andcommitted
binder: fix race between munmap() and direct reclaim
An munmap() on a binder device causes binder_vma_close() to be called which clears the alloc->vma pointer. If direct reclaim causes binder_alloc_free_page() to be called, there is a race where alloc->vma is read into a local vma pointer and then used later after the mm->mmap_sem is acquired. This can result in calling zap_page_range() with an invalid vma which manifests as a use-after-free in zap_page_range(). The fix is to check alloc->vma after acquiring the mmap_sem (which we were acquiring anyway) and skip zap_page_range() if it has changed to NULL. Signed-off-by: Todd Kjos <tkjos@google.com> Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5997da8 commit 5cec2d2

File tree

1 file changed

+8
-10
lines changed

1 file changed

+8
-10
lines changed

drivers/android/binder_alloc.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -927,14 +927,13 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
927927

928928
index = page - alloc->pages;
929929
page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;
930+
931+
mm = alloc->vma_vm_mm;
932+
if (!mmget_not_zero(mm))
933+
goto err_mmget;
934+
if (!down_write_trylock(&mm->mmap_sem))
935+
goto err_down_write_mmap_sem_failed;
930936
vma = binder_alloc_get_vma(alloc);
931-
if (vma) {
932-
if (!mmget_not_zero(alloc->vma_vm_mm))
933-
goto err_mmget;
934-
mm = alloc->vma_vm_mm;
935-
if (!down_read_trylock(&mm->mmap_sem))
936-
goto err_down_write_mmap_sem_failed;
937-
}
938937

939938
list_lru_isolate(lru, item);
940939
spin_unlock(lock);
@@ -945,10 +944,9 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
945944
zap_page_range(vma, page_addr, PAGE_SIZE);
946945

947946
trace_binder_unmap_user_end(alloc, index);
948-
949-
up_read(&mm->mmap_sem);
950-
mmput(mm);
951947
}
948+
up_write(&mm->mmap_sem);
949+
mmput(mm);
952950

953951
trace_binder_unmap_kernel_start(alloc, index);
954952

0 commit comments

Comments
 (0)