diff options
author | Rik van Riel <[email protected]> | 2014-01-02 12:58:46 -0800 |
---|---|---|
committer | Linus Torvalds <[email protected]> | 2014-01-02 14:40:30 -0800 |
commit | 4eb919825e6c3c7fb3630d5621f6d11e98a18b3a (patch) | |
tree | 826d9e3d7852f7d2214a31bcca050bcd5573e667 | |
parent | 3b25df93c6e37e323b86a2a8c1e00c0a2821c6c9 (diff) |
mm: fix use-after-free in sys_remap_file_pages
remap_file_pages calls mmap_region, which may merge the VMA with other
existing VMAs, and free "vma". This can lead to a use-after-free bug.
Avoid the bug by remembering vm_flags before calling mmap_region, and
not trying to dereference vma later.
Signed-off-by: Rik van Riel <[email protected]>
Reported-by: Dmitry Vyukov <[email protected]>
Cc: PaX Team <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: Michel Lespinasse <[email protected]>
Cc: Cyrill Gorcunov <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
-rw-r--r-- | mm/fremap.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/mm/fremap.c b/mm/fremap.c index 5bff08147768..bbc4d660221a 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -208,9 +208,10 @@ get_write_lock: if (mapping_cap_account_dirty(mapping)) { unsigned long addr; struct file *file = get_file(vma->vm_file); + /* mmap_region may free vma; grab the info now */ + vm_flags = vma->vm_flags; - addr = mmap_region(file, start, size, - vma->vm_flags, pgoff); + addr = mmap_region(file, start, size, vm_flags, pgoff); fput(file); if (IS_ERR_VALUE(addr)) { err = addr; @@ -218,7 +219,7 @@ get_write_lock: BUG_ON(addr != start); err = 0; } - goto out; + goto out_freed; } mutex_lock(&mapping->i_mmap_mutex); flush_dcache_mmap_lock(mapping); @@ -253,6 +254,7 @@ get_write_lock: out: if (vma) vm_flags = vma->vm_flags; +out_freed: if (likely(!has_write_lock)) up_read(&mm->mmap_sem); else |