From: Jerome Marchand <jmarchan@redhat.com> Date: Tue, 24 Jun 2008 14:56:12 +0200 Subject: [x86_64] ptrace: sign-extend orig_rax to 64 bits Message-id: 4860EEEC.8030301@redhat.com O-Subject: [RHEL5.3 Patch] x86_64, ptrace: sign-extend orig_rax to 64 bits Bugzilla: 437882 RH-Acked-by: David S. Miller <davem@redhat.com> RH-Acked-by: Chuck Ebbert <cebbert@redhat.com> RH-Acked-by: Roland McGrath <roland@redhat.com> Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=437882 Description: GDB testsuite failure for x86_64 debugger running i386 debuggee. GDB sets orig_rax to 0x00000000ffffffff which is not recognized by kernel as -1. That bug is revealed by the fix of 434998. It could not happen before. Solution: Make ptrace always sign-extend orig_rax to 64 bits Upstream status: commit 84c6f6046c5a2189160a8f0dca8b90427bf690ea Test status: Built on all arch, tested on x86_64 using the reproducer provided on bugzilla. Regards, Jerome diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 2ad504e..053d9d9 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -279,6 +279,16 @@ static int putreg(struct task_struct *child, return -EIO; child->thread.gs = value; return 0; + case offsetof(struct user_regs_struct, orig_rax): + /* + * Orig_rax 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. + */ + value = (long) (s32) value; + break; case offsetof(struct user_regs_struct, eflags): value &= FLAG_MASK; tmp = get_stack_long(child, EFL_OFFSET);