[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>
This commit is contained in:
parent
707c21c848
commit
676758bdb7
14
mm/msync.c
14
mm/msync.c
@ -146,7 +146,8 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
|
|||||||
{
|
{
|
||||||
unsigned long end;
|
unsigned long end;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
int unmapped_error, error = -EINVAL;
|
int unmapped_error = 0;
|
||||||
|
int error = -EINVAL;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
|
if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
|
||||||
@ -171,15 +172,14 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
|
|||||||
if (flags & MS_SYNC)
|
if (flags & MS_SYNC)
|
||||||
current->flags |= PF_SYNCWRITE;
|
current->flags |= PF_SYNCWRITE;
|
||||||
vma = find_vma(current->mm, start);
|
vma = find_vma(current->mm, start);
|
||||||
unmapped_error = 0;
|
if (!vma) {
|
||||||
|
error = -ENOMEM;
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
unsigned long nr_pages_dirtied = 0;
|
unsigned long nr_pages_dirtied = 0;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
|
||||||
/* Still start < end. */
|
|
||||||
error = -ENOMEM;
|
|
||||||
if (!vma)
|
|
||||||
goto out_unlock;
|
|
||||||
/* Here start < vma->vm_end. */
|
/* Here start < vma->vm_end. */
|
||||||
if (start < vma->vm_start) {
|
if (start < vma->vm_start) {
|
||||||
unmapped_error = -ENOMEM;
|
unmapped_error = -ENOMEM;
|
||||||
@ -239,7 +239,7 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
|
|||||||
} else {
|
} else {
|
||||||
vma = vma->vm_next;
|
vma = vma->vm_next;
|
||||||
}
|
}
|
||||||
} while (!done);
|
} while (vma && !done);
|
||||||
out_unlock:
|
out_unlock:
|
||||||
current->flags &= ~PF_SYNCWRITE;
|
current->flags &= ~PF_SYNCWRITE;
|
||||||
up_read(¤t->mm->mmap_sem);
|
up_read(¤t->mm->mmap_sem);
|
||||||
|
Loading…
Reference in New Issue
Block a user