summaryrefslogtreecommitdiff
path: root/drivers/staging/android
diff options
context:
space:
mode:
authorChristopher Lais <chris+android@zenthought.org>2010-05-01 15:51:48 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-11-30 20:51:37 +0900
commit58526090ece3582516e62779739a7d665a74708c (patch)
tree3bef2705ebe51c3d0e4f0b8dfee3379b9074a57c /drivers/staging/android
parent4755b72e261478b48337e0e54c8448cbea32c5c8 (diff)
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 <chris+android@zenthought.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/android')
-rw-r--r--drivers/staging/android/binder.c5
1 files changed, 4 insertions, 1 deletions
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++;
}