Skip to content

Commit

Permalink
mm/mmap.c: fix mmap return value when vma is merged after call_mmap()
Browse files Browse the repository at this point in the history
On success, mmap should return the begin address of newly mapped area,
but patch "mm: mmap: merge vma after call_mmap() if possible" set
vm_start of newly merged vma to return value addr.  Users of mmap will
get wrong address if vma is merged after call_mmap().  We fix this by
moving the assignment to addr before merging vma.

We have a driver which changes vm_flags, and this bug is found by our
testcases.

Fixes: d70cec8 ("mm: mmap: merge vma after call_mmap() if possible")
Signed-off-by: Liu Zixian <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Reviewed-by: Jason Gunthorpe <[email protected]>
Reviewed-by: David Hildenbrand <[email protected]>
Cc: Miaohe Lin <[email protected]>
Cc: Hongxiang Lou <[email protected]>
Cc: Hu Shiyuan <[email protected]>
Cc: Matthew Wilcox <[email protected]>
Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Liu Zixian authored and torvalds committed Dec 6, 2020
1 parent 7a5bde3 commit 309d08d
Showing 1 changed file with 12 additions and 14 deletions.
26 changes: 12 additions & 14 deletions mm/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1808,6 +1808,17 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
if (error)
goto unmap_and_free_vma;

/* Can addr have changed??
*
* Answer: Yes, several device drivers can do it in their
* f_op->mmap method. -DaveM
* Bug: If addr is changed, prev, rb_link, rb_parent should
* be updated for vma_link()
*/
WARN_ON_ONCE(addr != vma->vm_start);

addr = vma->vm_start;

/* If vm_flags changed after call_mmap(), we should try merge vma again
* as we may succeed this time.
*/
Expand All @@ -1822,25 +1833,12 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
fput(vma->vm_file);
vm_area_free(vma);
vma = merge;
/* Update vm_flags and possible addr to pick up the change. We don't
* warn here if addr changed as the vma is not linked by vma_link().
*/
addr = vma->vm_start;
/* Update vm_flags to pick up the change. */
vm_flags = vma->vm_flags;
goto unmap_writable;
}
}

/* Can addr have changed??
*
* Answer: Yes, several device drivers can do it in their
* f_op->mmap method. -DaveM
* Bug: If addr is changed, prev, rb_link, rb_parent should
* be updated for vma_link()
*/
WARN_ON_ONCE(addr != vma->vm_start);

addr = vma->vm_start;
vm_flags = vma->vm_flags;
} else if (vm_flags & VM_SHARED) {
error = shmem_zero_setup(vma);
Expand Down

0 comments on commit 309d08d

Please sign in to comment.