From: Andrew Morton Date: Fri, 24 Mar 2006 11:18:14 +0000 (-0800) Subject: [PATCH] msync: fix return value X-Git-Tag: v2.6.17-rc1~899 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=676758bdb7bfca8413a85203921746f446e237be;p=linux-2.6 [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 Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/mm/msync.c b/mm/msync.c index ee9bd67598..d6a50f3f28 100644 --- a/mm/msync.c +++ b/mm/msync.c @@ -146,7 +146,8 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags) { unsigned long end; struct vm_area_struct *vma; - int unmapped_error, error = -EINVAL; + int unmapped_error = 0; + int error = -EINVAL; int done = 0; 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) current->flags |= PF_SYNCWRITE; vma = find_vma(current->mm, start); - unmapped_error = 0; + if (!vma) { + error = -ENOMEM; + goto out_unlock; + } do { unsigned long nr_pages_dirtied = 0; struct file *file; - /* Still start < end. */ - error = -ENOMEM; - if (!vma) - goto out_unlock; /* Here start < vma->vm_end. */ if (start < vma->vm_start) { unmapped_error = -ENOMEM; @@ -239,7 +239,7 @@ asmlinkage long sys_msync(unsigned long start, size_t len, int flags) } else { vma = vma->vm_next; } - } while (!done); + } while (vma && !done); out_unlock: current->flags &= ~PF_SYNCWRITE; up_read(¤t->mm->mmap_sem);