Commit 676758bdb7bfca8413a85203921746f446e237be
Committed by
Linus Torvalds
1 parent
707c21c848
Exists in
master
and in
4 other branches
[PATCH] msync: fix return value
msync() does a strange thing. Essentially: vma = find_vma(); for ( ; ; ) { if (!vma) return -ENOMEM; ... vma = vma->vm_next; } so an msync() request which starts within or before a valid VMA and which ends within or beyond the final VMA will incorrectly return -ENOMEM. Fix. Cc: Hugh Dickins <hugh@veritas.com> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 1 changed file with 7 additions and 7 deletions Side-by-side Diff
mm/msync.c
... | ... | @@ -146,7 +146,8 @@ |
146 | 146 | { |
147 | 147 | unsigned long end; |
148 | 148 | struct vm_area_struct *vma; |
149 | - int unmapped_error, error = -EINVAL; | |
149 | + int unmapped_error = 0; | |
150 | + int error = -EINVAL; | |
150 | 151 | int done = 0; |
151 | 152 | |
152 | 153 | if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC)) |
153 | 154 | |
... | ... | @@ -171,15 +172,14 @@ |
171 | 172 | if (flags & MS_SYNC) |
172 | 173 | current->flags |= PF_SYNCWRITE; |
173 | 174 | vma = find_vma(current->mm, start); |
174 | - unmapped_error = 0; | |
175 | + if (!vma) { | |
176 | + error = -ENOMEM; | |
177 | + goto out_unlock; | |
178 | + } | |
175 | 179 | do { |
176 | 180 | unsigned long nr_pages_dirtied = 0; |
177 | 181 | struct file *file; |
178 | 182 | |
179 | - /* Still start < end. */ | |
180 | - error = -ENOMEM; | |
181 | - if (!vma) | |
182 | - goto out_unlock; | |
183 | 183 | /* Here start < vma->vm_end. */ |
184 | 184 | if (start < vma->vm_start) { |
185 | 185 | unmapped_error = -ENOMEM; |
... | ... | @@ -239,7 +239,7 @@ |
239 | 239 | } else { |
240 | 240 | vma = vma->vm_next; |
241 | 241 | } |
242 | - } while (!done); | |
242 | + } while (vma && !done); | |
243 | 243 | out_unlock: |
244 | 244 | current->flags &= ~PF_SYNCWRITE; |
245 | 245 | up_read(¤t->mm->mmap_sem); |