From: Christopher Lais Date: Sat, 1 May 2010 20:51:48 +0000 (-0500) Subject: staging: binder: Fix memory corruption via page aliasing X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=58526090ece3582516e62779739a7d665a74708c;p=linux-beck.git staging: binder: Fix memory corruption via page aliasing binder_deferred_release was not unmapping the page from the buffer before freeing it, causing memory corruption. This only happened when page(s) had not been freed by binder_update_page_range, which properly unmaps the pages. This only happens on architectures with VIPT aliasing. To reproduce, create a program which opens, mmaps, munmaps, then closes the binder very quickly. This should leave a page allocated when the binder is released. When binder_deferrred_release is called on the close, the page will remain mapped to the address in the linear proc->buffer. Later, we may map the same physical page to a different virtual address that has different coloring, and this may cause aliasing to occur. PAGE_POISONING will greatly increase your chances of noticing any problems. Signed-off-by: Christopher Lais Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 6d6fe7bdebd3..7491801a661c 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -3036,11 +3036,14 @@ static void binder_deferred_release(struct binder_proc *proc) int i; for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) { if (proc->pages[i]) { + void *page_addr = proc->buffer + i * PAGE_SIZE; binder_debug(BINDER_DEBUG_BUFFER_ALLOC, "binder_release: %d: " "page %d at %p not freed\n", proc->pid, i, - proc->buffer + i * PAGE_SIZE); + page_addr); + unmap_kernel_range((unsigned long)page_addr, + PAGE_SIZE); __free_page(proc->pages[i]); page_count++; }