diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-28 10:41:51 (GMT) |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-09-28 17:06:21 (GMT) |
commit | aa45ee8fc0ee87c1711b5fe8eb3556d06530c39e (patch) | |
tree | 4fd5a65dd1dda67ba8e2c4857bf1c7f5c19edaf8 /arch/arm/kernel/traps.c | |
parent | 90140c30a7b8c77e8872a389d48678d78e58789f (diff) | |
download | linux-aa45ee8fc0ee87c1711b5fe8eb3556d06530c39e.tar.xz |
ARM: Ensure do_cache_op takes mmap_sem
do_cache_op() uses find_vma() to validate its arguments without holding
any locking. This means that the VMA could vanish beneath us. Fix
this by taking a read lock on mmap_sem.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/traps.c')
-rw-r--r-- | arch/arm/kernel/traps.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 57eb0f6..467b69e 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -418,12 +418,14 @@ static int bad_syscall(int n, struct pt_regs *regs) static inline void do_cache_op(unsigned long start, unsigned long end, int flags) { + struct mm_struct *mm = current->active_mm; struct vm_area_struct *vma; if (end < start || flags) return; - vma = find_vma(current->active_mm, start); + down_read(&mm->mmap_sem); + vma = find_vma(mm, start); if (vma && vma->vm_start < end) { if (start < vma->vm_start) start = vma->vm_start; @@ -432,6 +434,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags) flush_cache_user_range(vma, start, end); } + up_read(&mm->mmap_sem); } /* |