aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68k
diff options
context:
space:
mode:
authorDavidlohr Bueso <davidlohr@hp.com>2014-10-09 18:29:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-09 22:26:02 -0400
commitcd2567b6850b1648236a4aab0513a04ebaea6aa8 (patch)
tree7321c0818a0d6af6ef2aa07dcc6e6f65757370cf /arch/m68k
parent7cc36bbddde5cd0c98f0c06e3304ab833d662565 (diff)
m68k: call find_vma with the mmap_sem held in sys_cacheflush()
Performing vma lookups without taking the mm->mmap_sem is asking for trouble. While doing the search, the vma in question can be modified or even removed before returning to the caller. Take the lock (shared) in order to avoid races while iterating through the vmacache and/or rbtree. In addition, this guarantees that the address space will remain intact during the CPU flushing. Signed-off-by: Davidlohr Bueso <davidlohr@hp.com> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/m68k')
-rw-r--r--arch/m68k/kernel/sys_m68k.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index 3a480b3df0d6..9aa01adb407f 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -376,7 +376,6 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
376asmlinkage int 376asmlinkage int
377sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) 377sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
378{ 378{
379 struct vm_area_struct *vma;
380 int ret = -EINVAL; 379 int ret = -EINVAL;
381 380
382 if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL || 381 if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
@@ -389,17 +388,21 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
389 if (!capable(CAP_SYS_ADMIN)) 388 if (!capable(CAP_SYS_ADMIN))
390 goto out; 389 goto out;
391 } else { 390 } else {
391 struct vm_area_struct *vma;
392
393 /* Check for overflow. */
394 if (addr + len < addr)
395 goto out;
396
392 /* 397 /*
393 * Verify that the specified address region actually belongs 398 * Verify that the specified address region actually belongs
394 * to this process. 399 * to this process.
395 */ 400 */
396 vma = find_vma (current->mm, addr);
397 ret = -EINVAL; 401 ret = -EINVAL;
398 /* Check for overflow. */ 402 down_read(&current->mm->mmap_sem);
399 if (addr + len < addr) 403 vma = find_vma(current->mm, addr);
400 goto out; 404 if (!vma || addr < vma->vm_start || addr + len > vma->vm_end)
401 if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end) 405 goto out_unlock;
402 goto out;
403 } 406 }
404 407
405 if (CPU_IS_020_OR_030) { 408 if (CPU_IS_020_OR_030) {
@@ -429,7 +432,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
429 __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr)); 432 __asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
430 } 433 }
431 ret = 0; 434 ret = 0;
432 goto out; 435 goto out_unlock;
433 } else { 436 } else {
434 /* 437 /*
435 * 040 or 060: don't blindly trust 'scope', someone could 438 * 040 or 060: don't blindly trust 'scope', someone could
@@ -446,6 +449,8 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
446 ret = cache_flush_060 (addr, scope, cache, len); 449 ret = cache_flush_060 (addr, scope, cache, len);
447 } 450 }
448 } 451 }
452out_unlock:
453 up_read(&current->mm->mmap_sem);
449out: 454out:
450 return ret; 455 return ret;
451} 456}