The binder proc buffers were being allocated with VM_IOREMAP, possibly
to ensure properly aligned allocations. This had the side effect of
allowing get_vm_area to reallocate mapped IO memory instead of
returning a valid usable area. The VIPT aliasing check was never
triggered before, but did not update the offset after the check, so the
cache color was still different between the mappings.
VM_IOREMAP has been replaced with VM_MAP to avoid remapping IO memory, and
the user page offset assignment has been moved to after the vipt aliasing
adjustment, so the userspace mmapped area and proc->buffer have the same
cache color.
To reproduce, create a program which opens, then mmaps many binders.
This will exhaust memory, but before it does it will map proc buffers
to previously-mapped IO ranges. You may need to add debugging that
prints the address returned by get_vm_area to directly see the effect,
but most devices are not happy when IO is remapped.
You may be able to use a program that also munmaps and closes the binders,
to avoid memory exhaustion, if your kernel allocates new pages each time.
Change-Id: Ibc55f6885efa39f3b4722927bdf8ac91476d754d
---
drivers/staging/android/binder.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index 1d06967..53e7515 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -2792,14 +2792,13 @@ static int binder_mmap(struct file *filp, struct
vm_area_struct *vma)
goto err_already_mapped;
}
- area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
+ area = get_vm_area(vma->vm_end - vma->vm_start, VM_MAP);
if (area == NULL) {
ret = -ENOMEM;
failure_string = "get_vm_area";
goto err_get_vm_area_failed;
}
proc->buffer = area->addr;
- proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
#ifdef CONFIG_CPU_CACHE_VIPT
if (cache_is_vipt_aliasing()) {
@@ -2809,6 +2808,7 @@ static int binder_mmap(struct file *filp, struct
vm_area_struct *vma)
}
}
#endif
+ proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end -
vma->vm_start) / PAGE_SIZE), GFP_KERNEL);
if (proc->pages == NULL) {
ret = -ENOMEM;
--
1.7.1
--
unsubscribe: [email protected]
website: http://groups.google.com/group/android-kernel