aboutsummaryrefslogtreecommitdiff
path: root/arch/x86/kernel/ptrace.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 08:29:57 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 08:29:57 -0700
commit547ad5ac665234953e32678f6a32385b58edefc3 (patch)
tree4c7aa651224d2b106a2f9da6dfb8b4233173cec2 /arch/x86/kernel/ptrace.c
parent4fefce9abaeef0d6ec45e06a882db23a65135272 (diff)
parent8cb3ed13935b9b523c2de7afc8f68473fe1d4531 (diff)
Merge branch 'x86/orig_ax' of git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-roland
* 'x86/orig_ax' of git://git.kernel.org/pub/scm/linux/kernel/git/frob/linux-2.6-roland: x86: ptrace: set TS_COMPAT when 32-bit ptrace sets orig_eax>=0 x86: ptrace: do not sign-extend orig_ax on write x86: syscall_get_nr returns int asm-generic: syscall_get_nr returns int
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r--arch/x86/kernel/ptrace.c21
1 files changed, 8 insertions, 13 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 8d7d5c9c1be..7b058a2dc66 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -325,16 +325,6 @@ static int putreg(struct task_struct *child,
return set_flags(child, value);
#ifdef CONFIG_X86_64
- /*
- * Orig_ax is really just a flag with small positive and
- * negative values, so make sure to always sign-extend it
- * from 32 bits so that it works correctly regardless of
- * whether we come from a 32-bit environment or not.
- */
- case offsetof(struct user_regs_struct, orig_ax):
- value = (long) (s32) value;
- break;
-
case offsetof(struct user_regs_struct,fs_base):
if (value >= TASK_SIZE_OF(child))
return -EIO;
@@ -1126,10 +1116,15 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value)
case offsetof(struct user32, regs.orig_eax):
/*
- * Sign-extend the value so that orig_eax = -1
- * causes (long)orig_ax < 0 tests to fire correctly.
+ * A 32-bit debugger setting orig_eax means to restore
+ * the state of the task restarting a 32-bit syscall.
+ * Make sure we interpret the -ERESTART* codes correctly
+ * in case the task is not actually still sitting at the
+ * exit from a 32-bit syscall with TS_COMPAT still set.
*/
- regs->orig_ax = (long) (s32) value;
+ regs->orig_ax = value;
+ if (syscall_get_nr(child, regs) >= 0)
+ task_thread_info(child)->status |= TS_COMPAT;
break;
case offsetof(struct user32, regs.eflags):