aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>2015-09-09 18:39:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-10 16:29:01 -0400
commit6dc296e7df4c9a0857491cc3f55da16a9eeeeae7 (patch)
tree0e9d5ce09a9a7a5bda0f9bf5b66d7162146fbb21 /mm
parent1fcfd8db7f82fa1f533a6f0e4155614ff4144d56 (diff)
mm: make sure all file VMAs have ->vm_ops set
We rely on vma->vm_ops == NULL to detect anonymous VMA: see vma_is_anonymous(), but some drivers doesn't set ->vm_ops. As a result we can end up with anonymous page in private file mapping. That should not lead to serious misbehaviour, but nevertheless is wrong. Let's fix by setting up dummy ->vm_ops for file mmapping if f_op->mmap() didn't set its own. The patch also adds sanity check into __vma_link_rb(). It will help catch broken VMAs which inserted directly into mm_struct via insert_vm_struct(). Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Minchan Kim <minchan@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/mmap.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index c739d6db7193..971dd2cb77d2 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -612,6 +612,8 @@ static unsigned long count_vma_pages_range(struct mm_struct *mm,
612void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma, 612void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
613 struct rb_node **rb_link, struct rb_node *rb_parent) 613 struct rb_node **rb_link, struct rb_node *rb_parent)
614{ 614{
615 WARN_ONCE(vma->vm_file && !vma->vm_ops, "missing vma->vm_ops");
616
615 /* Update tracking information for the gap following the new vma. */ 617 /* Update tracking information for the gap following the new vma. */
616 if (vma->vm_next) 618 if (vma->vm_next)
617 vma_gap_update(vma->vm_next); 619 vma_gap_update(vma->vm_next);
@@ -1636,6 +1638,12 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
1636 */ 1638 */
1637 WARN_ON_ONCE(addr != vma->vm_start); 1639 WARN_ON_ONCE(addr != vma->vm_start);
1638 1640
1641 /* All file mapping must have ->vm_ops set */
1642 if (!vma->vm_ops) {
1643 static const struct vm_operations_struct dummy_ops = {};
1644 vma->vm_ops = &dummy_ops;
1645 }
1646
1639 addr = vma->vm_start; 1647 addr = vma->vm_start;
1640 vm_flags = vma->vm_flags; 1648 vm_flags = vma->vm_flags;
1641 } else if (vm_flags & VM_SHARED) { 1649 } else if (vm_flags & VM_SHARED) {