x86: ptrace: set TS_COMPAT when 32-bit ptrace sets orig_eax>=0
authorRoland McGrath <roland@redhat.com>
Wed, 23 Sep 2009 03:12:07 +0000 (20:12 -0700)
committerRoland McGrath <roland@redhat.com>
Wed, 23 Sep 2009 05:49:24 +0000 (22:49 -0700)
commit8cb3ed13935b9b523c2de7afc8f68473fe1d4531
tree8c9d53ac4e9facc5750cc6bd7bd07260845b9797
parent08ff18e299b1a1c91f4911fe9f35c4550218c73f
x86: ptrace: set TS_COMPAT when 32-bit ptrace sets orig_eax>=0

The 32-bit ptrace syscall on a 64-bit kernel (32-bit debugger on
32-bit task) behaves differently than a native 32-bit kernel.  When
setting a register state of orig_eax>=0 and eax=-ERESTART* when the
debugged task is NOT on its way out of a 32-bit syscall, the task will
fail to do the syscall restart logic that it should do.

Test case available at http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/erestartsys-trap.c?cvsroot=systemtap

This happens because the 32-bit ptrace syscall sets eax=0xffffffff
when it sets orig_eax>=0.  The resuming task will not sign-extend this
for the -ERESTART* check because TS_COMPAT is not set.  (So the task
thinks it is restarting after a 64-bit syscall, not a 32-bit one.)

The fix is to have 32-bit ptrace calls set TS_COMPAT when setting
orig_eax>=0.  This ensures that the 32-bit syscall restart logic
will apply when the child resumes.

Signed-off-by: Roland McGrath <roland@redhat.com>
arch/x86/kernel/ptrace.c