diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-07 20:04:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-05-07 20:04:49 -0400 |
commit | 3de2403e6659d71b36ec820dc9b942762ddfe6eb (patch) | |
tree | 55516c669ffc2cbe9fd52c3a4d2d6f8e90d4644a | |
parent | e0164af66b6ec165836d1d862b3f800890713452 (diff) | |
parent | 1e38c126c9252b612697e34f43b1b3371c8ee31d (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
sparc: Fix fork/clone/vfork system call restart.
sparc: Fix mmap VA span checking.
-rw-r--r-- | arch/sparc/kernel/process.c | 20 | ||||
-rw-r--r-- | arch/sparc/kernel/sys_sparc.c | 3 | ||||
-rw-r--r-- | arch/sparc64/kernel/process.c | 18 | ||||
-rw-r--r-- | arch/sparc64/kernel/sys_sparc.c | 4 |
4 files changed, 34 insertions, 11 deletions
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index e7f35198ae34..36431f377dee 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c | |||
@@ -419,14 +419,26 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, | |||
419 | unsigned long stack_size) | 419 | unsigned long stack_size) |
420 | { | 420 | { |
421 | unsigned long parent_tid_ptr, child_tid_ptr; | 421 | unsigned long parent_tid_ptr, child_tid_ptr; |
422 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
423 | long ret; | ||
422 | 424 | ||
423 | parent_tid_ptr = regs->u_regs[UREG_I2]; | 425 | parent_tid_ptr = regs->u_regs[UREG_I2]; |
424 | child_tid_ptr = regs->u_regs[UREG_I4]; | 426 | child_tid_ptr = regs->u_regs[UREG_I4]; |
425 | 427 | ||
426 | return do_fork(clone_flags, stack_start, | 428 | ret = do_fork(clone_flags, stack_start, |
427 | regs, stack_size, | 429 | regs, stack_size, |
428 | (int __user *) parent_tid_ptr, | 430 | (int __user *) parent_tid_ptr, |
429 | (int __user *) child_tid_ptr); | 431 | (int __user *) child_tid_ptr); |
432 | |||
433 | /* If we get an error and potentially restart the system | ||
434 | * call, we're screwed because copy_thread() clobbered | ||
435 | * the parent's %o1. So detect that case and restore it | ||
436 | * here. | ||
437 | */ | ||
438 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
439 | regs->u_regs[UREG_I1] = orig_i1; | ||
440 | |||
441 | return ret; | ||
430 | } | 442 | } |
431 | 443 | ||
432 | /* Copy a Sparc thread. The fork() return value conventions | 444 | /* Copy a Sparc thread. The fork() return value conventions |
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index f188b5dc9fd0..e995491c4436 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c | |||
@@ -223,8 +223,7 @@ int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) | |||
223 | { | 223 | { |
224 | if (ARCH_SUN4C_SUN4 && | 224 | if (ARCH_SUN4C_SUN4 && |
225 | (len > 0x20000000 || | 225 | (len > 0x20000000 || |
226 | ((flags & MAP_FIXED) && | 226 | (addr < 0xe0000000 && addr + len > 0x20000000))) |
227 | addr < 0xe0000000 && addr + len > 0x20000000))) | ||
228 | return -EINVAL; | 227 | return -EINVAL; |
229 | 228 | ||
230 | /* See asm-sparc/uaccess.h */ | 229 | /* See asm-sparc/uaccess.h */ |
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 500ac6d483a0..4129c0449856 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
@@ -503,6 +503,8 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, | |||
503 | unsigned long stack_size) | 503 | unsigned long stack_size) |
504 | { | 504 | { |
505 | int __user *parent_tid_ptr, *child_tid_ptr; | 505 | int __user *parent_tid_ptr, *child_tid_ptr; |
506 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
507 | long ret; | ||
506 | 508 | ||
507 | #ifdef CONFIG_COMPAT | 509 | #ifdef CONFIG_COMPAT |
508 | if (test_thread_flag(TIF_32BIT)) { | 510 | if (test_thread_flag(TIF_32BIT)) { |
@@ -515,9 +517,19 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, | |||
515 | child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; | 517 | child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; |
516 | } | 518 | } |
517 | 519 | ||
518 | return do_fork(clone_flags, stack_start, | 520 | ret = do_fork(clone_flags, stack_start, |
519 | regs, stack_size, | 521 | regs, stack_size, |
520 | parent_tid_ptr, child_tid_ptr); | 522 | parent_tid_ptr, child_tid_ptr); |
523 | |||
524 | /* If we get an error and potentially restart the system | ||
525 | * call, we're screwed because copy_thread() clobbered | ||
526 | * the parent's %o1. So detect that case and restore it | ||
527 | * here. | ||
528 | */ | ||
529 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
530 | regs->u_regs[UREG_I1] = orig_i1; | ||
531 | |||
532 | return ret; | ||
521 | } | 533 | } |
522 | 534 | ||
523 | /* Copy a Sparc thread. The fork() return value conventions | 535 | /* Copy a Sparc thread. The fork() return value conventions |
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 8d4761f15fa9..0dbc941f130e 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c | |||
@@ -549,13 +549,13 @@ int sparc64_mmap_check(unsigned long addr, unsigned long len, | |||
549 | if (len >= STACK_TOP32) | 549 | if (len >= STACK_TOP32) |
550 | return -EINVAL; | 550 | return -EINVAL; |
551 | 551 | ||
552 | if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len) | 552 | if (addr > STACK_TOP32 - len) |
553 | return -EINVAL; | 553 | return -EINVAL; |
554 | } else { | 554 | } else { |
555 | if (len >= VA_EXCLUDE_START) | 555 | if (len >= VA_EXCLUDE_START) |
556 | return -EINVAL; | 556 | return -EINVAL; |
557 | 557 | ||
558 | if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len)) | 558 | if (invalid_64bit_range(addr, len)) |
559 | return -EINVAL; | 559 | return -EINVAL; |
560 | } | 560 | } |
561 | 561 | ||