Skip to content

Commit a43cfc8

Browse files
howlettakpm00
authored andcommitted
android: binder: stop saving a pointer to the VMA
Do not record a pointer to a VMA outside of the mmap_lock for later use. This is unsafe and there are a number of failure paths *after* the recorded VMA pointer may be freed during setup. There is no callback to the driver to clear the saved pointer from generic mm code. Furthermore, the VMA pointer may become stale if any number of VMA operations end up freeing the VMA so saving it was fragile to being with. Instead, change the binder_alloc struct to record the start address of the VMA and use vma_lookup() to get the vma when needed. Add lockdep mmap_lock checks on updates to the vma pointer to ensure the lock is held and depend on that lock for synchronization of readers and writers - which was already the case anyways, so the smp_wmb()/smp_rmb() was not necessary. [[email protected]: fix drivers/android/binder_alloc_selftest.c] Link: https://lkml.kernel.org/r/20220621140212.vpkio64idahetbyf@revolver Fixes: da1b956 ("android: binder: fix the race mmap and alloc_new_buf_locked") Reported-by: [email protected] Signed-off-by: Liam R. Howlett <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Christian Brauner (Microsoft) <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Cc: Hridya Valsaraju <[email protected]> Cc: Joel Fernandes <[email protected]> Cc: Martijn Coenen <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Cc: Todd Kjos <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 15d2ce7 commit a43cfc8

File tree

3 files changed

+16
-18
lines changed

3 files changed

+16
-18
lines changed

drivers/android/binder_alloc.c

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
213213

214214
if (mm) {
215215
mmap_read_lock(mm);
216-
vma = alloc->vma;
216+
vma = vma_lookup(mm, alloc->vma_addr);
217217
}
218218

219219
if (!vma && need_mm) {
@@ -313,28 +313,25 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate,
313313
static inline void binder_alloc_set_vma(struct binder_alloc *alloc,
314314
struct vm_area_struct *vma)
315315
{
316-
if (vma)
316+
unsigned long vm_start = 0;
317+
318+
if (vma) {
319+
vm_start = vma->vm_start;
317320
alloc->vma_vm_mm = vma->vm_mm;
318-
/*
319-
* If we see alloc->vma is not NULL, buffer data structures set up
320-
* completely. Look at smp_rmb side binder_alloc_get_vma.
321-
* We also want to guarantee new alloc->vma_vm_mm is always visible
322-
* if alloc->vma is set.
323-
*/
324-
smp_wmb();
325-
alloc->vma = vma;
321+
}
322+
323+
mmap_assert_write_locked(alloc->vma_vm_mm);
324+
alloc->vma_addr = vm_start;
326325
}
327326

328327
static inline struct vm_area_struct *binder_alloc_get_vma(
329328
struct binder_alloc *alloc)
330329
{
331330
struct vm_area_struct *vma = NULL;
332331

333-
if (alloc->vma) {
334-
/* Look at description in binder_alloc_set_vma */
335-
smp_rmb();
336-
vma = alloc->vma;
337-
}
332+
if (alloc->vma_addr)
333+
vma = vma_lookup(alloc->vma_vm_mm, alloc->vma_addr);
334+
338335
return vma;
339336
}
340337

@@ -817,7 +814,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc)
817814

818815
buffers = 0;
819816
mutex_lock(&alloc->mutex);
820-
BUG_ON(alloc->vma);
817+
BUG_ON(alloc->vma_addr &&
818+
vma_lookup(alloc->vma_vm_mm, alloc->vma_addr));
821819

822820
while ((n = rb_first(&alloc->allocated_buffers))) {
823821
buffer = rb_entry(n, struct binder_buffer, rb_node);

drivers/android/binder_alloc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ struct binder_lru_page {
100100
*/
101101
struct binder_alloc {
102102
struct mutex mutex;
103-
struct vm_area_struct *vma;
103+
unsigned long vma_addr;
104104
struct mm_struct *vma_vm_mm;
105105
void __user *buffer;
106106
struct list_head buffers;

drivers/android/binder_alloc_selftest.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ void binder_selftest_alloc(struct binder_alloc *alloc)
287287
if (!binder_selftest_run)
288288
return;
289289
mutex_lock(&binder_selftest_lock);
290-
if (!binder_selftest_run || !alloc->vma)
290+
if (!binder_selftest_run || !alloc->vma_addr)
291291
goto done;
292292
pr_info("STARTED\n");
293293
binder_selftest_alloc_offset(alloc, end_offset, 0);

0 commit comments

Comments
 (0)