diff options
Diffstat (limited to 'mm/mmap.c')
-rw-r--r-- | mm/mmap.c | 17 |
1 files changed, 14 insertions, 3 deletions
@@ -1279,8 +1279,9 @@ munmap_back: | |||
1279 | vma->vm_pgoff = pgoff; | 1279 | vma->vm_pgoff = pgoff; |
1280 | INIT_LIST_HEAD(&vma->anon_vma_chain); | 1280 | INIT_LIST_HEAD(&vma->anon_vma_chain); |
1281 | 1281 | ||
1282 | error = -EINVAL; /* when rejecting VM_GROWSDOWN|VM_GROWSUP */ | ||
1283 | |||
1282 | if (file) { | 1284 | if (file) { |
1283 | error = -EINVAL; | ||
1284 | if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) | 1285 | if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP)) |
1285 | goto free_vma; | 1286 | goto free_vma; |
1286 | if (vm_flags & VM_DENYWRITE) { | 1287 | if (vm_flags & VM_DENYWRITE) { |
@@ -1306,6 +1307,8 @@ munmap_back: | |||
1306 | pgoff = vma->vm_pgoff; | 1307 | pgoff = vma->vm_pgoff; |
1307 | vm_flags = vma->vm_flags; | 1308 | vm_flags = vma->vm_flags; |
1308 | } else if (vm_flags & VM_SHARED) { | 1309 | } else if (vm_flags & VM_SHARED) { |
1310 | if (unlikely(vm_flags & (VM_GROWSDOWN|VM_GROWSUP))) | ||
1311 | goto free_vma; | ||
1309 | error = shmem_zero_setup(vma); | 1312 | error = shmem_zero_setup(vma); |
1310 | if (error) | 1313 | if (error) |
1311 | goto free_vma; | 1314 | goto free_vma; |
@@ -1618,7 +1621,6 @@ EXPORT_SYMBOL(find_vma); | |||
1618 | 1621 | ||
1619 | /* | 1622 | /* |
1620 | * Same as find_vma, but also return a pointer to the previous VMA in *pprev. | 1623 | * Same as find_vma, but also return a pointer to the previous VMA in *pprev. |
1621 | * Note: pprev is set to NULL when return value is NULL. | ||
1622 | */ | 1624 | */ |
1623 | struct vm_area_struct * | 1625 | struct vm_area_struct * |
1624 | find_vma_prev(struct mm_struct *mm, unsigned long addr, | 1626 | find_vma_prev(struct mm_struct *mm, unsigned long addr, |
@@ -1627,7 +1629,16 @@ find_vma_prev(struct mm_struct *mm, unsigned long addr, | |||
1627 | struct vm_area_struct *vma; | 1629 | struct vm_area_struct *vma; |
1628 | 1630 | ||
1629 | vma = find_vma(mm, addr); | 1631 | vma = find_vma(mm, addr); |
1630 | *pprev = vma ? vma->vm_prev : NULL; | 1632 | if (vma) { |
1633 | *pprev = vma->vm_prev; | ||
1634 | } else { | ||
1635 | struct rb_node *rb_node = mm->mm_rb.rb_node; | ||
1636 | *pprev = NULL; | ||
1637 | while (rb_node) { | ||
1638 | *pprev = rb_entry(rb_node, struct vm_area_struct, vm_rb); | ||
1639 | rb_node = rb_node->rb_right; | ||
1640 | } | ||
1641 | } | ||
1631 | return vma; | 1642 | return vma; |
1632 | } | 1643 | } |
1633 | 1644 | ||