aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-05-12 19:33:33 -0400
committerDavid S. Miller <davem@davemloft.net>2008-05-12 19:33:33 -0400
commit94d149c34cda933ff5096aca94bb23bf68602f4e (patch)
tree2c1a33482cd6961b45296979b898881a7a4d71d3 /arch/sparc
parentc714a534d85576af21b06be605ca55cb2fb887ee (diff)
sparc: Fix mremap address range validation.
Just like mmap, we need to validate address ranges regardless of MAP_FIXED. sparc{,64}_mmap_check()'s flag argument is unused, remove. Based upon a report and preliminary patch by Jan Lieskovsky <jlieskov@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/kernel/sys_sparc.c48
1 files changed, 5 insertions, 43 deletions
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index e995491c4436..3c6b49a53ae8 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -219,7 +219,7 @@ out:
219 return err; 219 return err;
220} 220}
221 221
222int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) 222int sparc_mmap_check(unsigned long addr, unsigned long len)
223{ 223{
224 if (ARCH_SUN4C_SUN4 && 224 if (ARCH_SUN4C_SUN4 &&
225 (len > 0x20000000 || 225 (len > 0x20000000 ||
@@ -295,52 +295,14 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr,
295 unsigned long old_len, unsigned long new_len, 295 unsigned long old_len, unsigned long new_len,
296 unsigned long flags, unsigned long new_addr) 296 unsigned long flags, unsigned long new_addr)
297{ 297{
298 struct vm_area_struct *vma;
299 unsigned long ret = -EINVAL; 298 unsigned long ret = -EINVAL;
300 if (ARCH_SUN4C_SUN4) { 299
301 if (old_len > 0x20000000 || new_len > 0x20000000) 300 if (unlikely(sparc_mmap_check(addr, old_len)))
302 goto out; 301 goto out;
303 if (addr < 0xe0000000 && addr + old_len > 0x20000000) 302 if (unlikely(sparc_mmap_check(new_addr, new_len)))
304 goto out;
305 }
306 if (old_len > TASK_SIZE - PAGE_SIZE ||
307 new_len > TASK_SIZE - PAGE_SIZE)
308 goto out; 303 goto out;
309 down_write(&current->mm->mmap_sem); 304 down_write(&current->mm->mmap_sem);
310 if (flags & MREMAP_FIXED) {
311 if (ARCH_SUN4C_SUN4 &&
312 new_addr < 0xe0000000 &&
313 new_addr + new_len > 0x20000000)
314 goto out_sem;
315 if (new_addr + new_len > TASK_SIZE - PAGE_SIZE)
316 goto out_sem;
317 } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
318 addr + new_len > 0x20000000) ||
319 addr + new_len > TASK_SIZE - PAGE_SIZE) {
320 unsigned long map_flags = 0;
321 struct file *file = NULL;
322
323 ret = -ENOMEM;
324 if (!(flags & MREMAP_MAYMOVE))
325 goto out_sem;
326
327 vma = find_vma(current->mm, addr);
328 if (vma) {
329 if (vma->vm_flags & VM_SHARED)
330 map_flags |= MAP_SHARED;
331 file = vma->vm_file;
332 }
333
334 new_addr = get_unmapped_area(file, addr, new_len,
335 vma ? vma->vm_pgoff : 0,
336 map_flags);
337 ret = new_addr;
338 if (new_addr & ~PAGE_MASK)
339 goto out_sem;
340 flags |= MREMAP_FIXED;
341 }
342 ret = do_mremap(addr, old_len, new_len, flags, new_addr); 305 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
343out_sem:
344 up_write(&current->mm->mmap_sem); 306 up_write(&current->mm->mmap_sem);
345out: 307out:
346 return ret; 308 return ret;