diff options
| author | David Howells <dhowells@redhat.com> | 2012-02-23 08:50:35 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-02-24 11:59:04 -0500 |
| commit | 918e556ec214ed2f584e4cac56d7b29e4bb6bf27 (patch) | |
| tree | cf2ba7c88f4b349d1120517f09ec4588f12eb285 /mm | |
| parent | 37e79cbf7d45451fb4d1213184e484723c25c65a (diff) | |
NOMMU: Lock i_mmap_mutex for access to the VMA prio list
Lock i_mmap_mutex for access to the VMA prio list to prevent concurrent
access. Currently, certain parts of the mmap handling are protected by
the region mutex, but not all.
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/nommu.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/mm/nommu.c b/mm/nommu.c index b982290fd962..ee7e57ebef6a 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -696,9 +696,11 @@ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma) | |||
| 696 | if (vma->vm_file) { | 696 | if (vma->vm_file) { |
| 697 | mapping = vma->vm_file->f_mapping; | 697 | mapping = vma->vm_file->f_mapping; |
| 698 | 698 | ||
| 699 | mutex_lock(&mapping->i_mmap_mutex); | ||
| 699 | flush_dcache_mmap_lock(mapping); | 700 | flush_dcache_mmap_lock(mapping); |
| 700 | vma_prio_tree_insert(vma, &mapping->i_mmap); | 701 | vma_prio_tree_insert(vma, &mapping->i_mmap); |
| 701 | flush_dcache_mmap_unlock(mapping); | 702 | flush_dcache_mmap_unlock(mapping); |
| 703 | mutex_unlock(&mapping->i_mmap_mutex); | ||
| 702 | } | 704 | } |
| 703 | 705 | ||
| 704 | /* add the VMA to the tree */ | 706 | /* add the VMA to the tree */ |
| @@ -760,9 +762,11 @@ static void delete_vma_from_mm(struct vm_area_struct *vma) | |||
| 760 | if (vma->vm_file) { | 762 | if (vma->vm_file) { |
| 761 | mapping = vma->vm_file->f_mapping; | 763 | mapping = vma->vm_file->f_mapping; |
| 762 | 764 | ||
| 765 | mutex_lock(&mapping->i_mmap_mutex); | ||
| 763 | flush_dcache_mmap_lock(mapping); | 766 | flush_dcache_mmap_lock(mapping); |
| 764 | vma_prio_tree_remove(vma, &mapping->i_mmap); | 767 | vma_prio_tree_remove(vma, &mapping->i_mmap); |
| 765 | flush_dcache_mmap_unlock(mapping); | 768 | flush_dcache_mmap_unlock(mapping); |
| 769 | mutex_unlock(&mapping->i_mmap_mutex); | ||
| 766 | } | 770 | } |
| 767 | 771 | ||
| 768 | /* remove from the MM's tree and list */ | 772 | /* remove from the MM's tree and list */ |
| @@ -2052,6 +2056,7 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size, | |||
| 2052 | high = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | 2056 | high = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 2053 | 2057 | ||
| 2054 | down_write(&nommu_region_sem); | 2058 | down_write(&nommu_region_sem); |
| 2059 | mutex_lock(&inode->i_mapping->i_mmap_mutex); | ||
| 2055 | 2060 | ||
| 2056 | /* search for VMAs that fall within the dead zone */ | 2061 | /* search for VMAs that fall within the dead zone */ |
| 2057 | vma_prio_tree_foreach(vma, &iter, &inode->i_mapping->i_mmap, | 2062 | vma_prio_tree_foreach(vma, &iter, &inode->i_mapping->i_mmap, |
| @@ -2059,6 +2064,7 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size, | |||
| 2059 | /* found one - only interested if it's shared out of the page | 2064 | /* found one - only interested if it's shared out of the page |
| 2060 | * cache */ | 2065 | * cache */ |
| 2061 | if (vma->vm_flags & VM_SHARED) { | 2066 | if (vma->vm_flags & VM_SHARED) { |
| 2067 | mutex_unlock(&inode->i_mapping->i_mmap_mutex); | ||
| 2062 | up_write(&nommu_region_sem); | 2068 | up_write(&nommu_region_sem); |
| 2063 | return -ETXTBSY; /* not quite true, but near enough */ | 2069 | return -ETXTBSY; /* not quite true, but near enough */ |
| 2064 | } | 2070 | } |
| @@ -2086,6 +2092,7 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size, | |||
| 2086 | } | 2092 | } |
| 2087 | } | 2093 | } |
| 2088 | 2094 | ||
| 2095 | mutex_unlock(&inode->i_mapping->i_mmap_mutex); | ||
| 2089 | up_write(&nommu_region_sem); | 2096 | up_write(&nommu_region_sem); |
| 2090 | return 0; | 2097 | return 0; |
| 2091 | } | 2098 | } |
