Skip to content

Commit 45d02f7

Browse files
thejhgregkh
authored andcommitted
binder: Don't modify VMA bounds in ->mmap handler
binder_mmap() tries to prevent the creation of overly big binder mappings by silently truncating the size of the VMA to 4MiB. However, this violates the API contract of mmap(). If userspace attempts to create a large binder VMA, and later attempts to unmap that VMA, it will call munmap() on a range beyond the end of the VMA, which may have been allocated to another VMA in the meantime. This can lead to userspace memory corruption. The following sequence of calls leads to a segfault without this commit: int main(void) { int binder_fd = open("/dev/binder", O_RDWR); if (binder_fd == -1) err(1, "open binder"); void *binder_mapping = mmap(NULL, 0x800000UL, PROT_READ, MAP_SHARED, binder_fd, 0); if (binder_mapping == MAP_FAILED) err(1, "mmap binder"); void *data_mapping = mmap(NULL, 0x400000UL, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (data_mapping == MAP_FAILED) err(1, "mmap data"); munmap(binder_mapping, 0x800000UL); *(char*)data_mapping = 1; return 0; } Cc: [email protected] Signed-off-by: Jann Horn <[email protected]> Acked-by: Todd Kjos <[email protected]> Acked-by: Christian Brauner <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4f5cafb commit 45d02f7

File tree

2 files changed

+4
-9
lines changed

2 files changed

+4
-9
lines changed

drivers/android/binder.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,6 @@ DEFINE_SHOW_ATTRIBUTE(proc);
9797
#define SZ_1K 0x400
9898
#endif
9999

100-
#ifndef SZ_4M
101-
#define SZ_4M 0x400000
102-
#endif
103-
104100
#define FORBIDDEN_MMAP_FLAGS (VM_WRITE)
105101

106102
enum {
@@ -5177,9 +5173,6 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
51775173
if (proc->tsk != current->group_leader)
51785174
return -EINVAL;
51795175

5180-
if ((vma->vm_end - vma->vm_start) > SZ_4M)
5181-
vma->vm_end = vma->vm_start + SZ_4M;
5182-
51835176
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
51845177
"%s: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
51855178
__func__, proc->pid, vma->vm_start, vma->vm_end,

drivers/android/binder_alloc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <asm/cacheflush.h>
2323
#include <linux/uaccess.h>
2424
#include <linux/highmem.h>
25+
#include <linux/sizes.h>
2526
#include "binder_alloc.h"
2627
#include "binder_trace.h"
2728

@@ -689,15 +690,16 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
689690
alloc->buffer = (void __user *)vma->vm_start;
690691
mutex_unlock(&binder_alloc_mmap_lock);
691692

692-
alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
693+
alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start,
694+
SZ_4M);
695+
alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE,
693696
sizeof(alloc->pages[0]),
694697
GFP_KERNEL);
695698
if (alloc->pages == NULL) {
696699
ret = -ENOMEM;
697700
failure_string = "alloc page array";
698701
goto err_alloc_pages_failed;
699702
}
700-
alloc->buffer_size = vma->vm_end - vma->vm_start;
701703

702704
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
703705
if (!buffer) {

0 commit comments

Comments
 (0)