aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChuck Ebbert <76306.1226@compuserve.com>2007-11-07 10:48:39 -0500
committerThomas Gleixner <tglx@apollo.(none)>2007-11-09 22:30:36 -0500
commitecd744eec3aa8bbc949ec04ed3fbf7ecb2958a0e (patch)
tree47c398a2e76b2354977df0d72ed91271ce85acf8 /arch
parentfd181c72a3c202a3986bcee7551c0838265aec2a (diff)
x86 - 32-bit ptrace emulation mishandles 6th arg
[ jdike - Pushing Chuck's patch - see http://lkml.org/lkml/2005/9/16/261 for some history and a test program. UML is also broken without this patch - its processes get SIGBUS from the corrupt 6th argument to mmap being interpretted as a file offset ] When the 32-bit vDSO is used to make a system call, the %ebp register for the 6th syscall arg has to be loaded from the user stack (where it's pushed by the vDSO user code). The native i386 kernel always does this before stopping for syscall tracing, so %ebp can be seen and modified via ptrace to access the 6th syscall argument. The x86-64 kernel fails to do this, presenting the stack address to ptrace instead. This makes the %rbp value seen by 64-bit ptrace of a 32-bit process, and the %ebp value seen by a 32-bit caller of ptrace, both differ from the native i386 behavior. This patch fixes the problem by putting the word loaded from the user stack into %rbp before calling syscall_trace_enter, and reloading the 6th syscall argument from there afterwards (so ptrace can change it). This makes the behavior match that of i386 kernels. Original-Patch-By: Roland McGrath <roland@redhat.com> Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/ia32/ia32entry.S19
1 files changed, 6 insertions, 13 deletions
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 18b231810908..df588f0f76e1 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -159,20 +159,16 @@ sysenter_do_call:
159 159
160sysenter_tracesys: 160sysenter_tracesys:
161 CFI_RESTORE_STATE 161 CFI_RESTORE_STATE
162 xchgl %r9d,%ebp
162 SAVE_REST 163 SAVE_REST
163 CLEAR_RREGS 164 CLEAR_RREGS
165 movq %r9,R9(%rsp)
164 movq $-ENOSYS,RAX(%rsp) /* really needed? */ 166 movq $-ENOSYS,RAX(%rsp) /* really needed? */
165 movq %rsp,%rdi /* &pt_regs -> arg1 */ 167 movq %rsp,%rdi /* &pt_regs -> arg1 */
166 call syscall_trace_enter 168 call syscall_trace_enter
167 LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ 169 LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
168 RESTORE_REST 170 RESTORE_REST
169 movl %ebp, %ebp 171 xchgl %ebp,%r9d
170 /* no need to do an access_ok check here because rbp has been
171 32bit zero extended */
1721: movl (%rbp),%r9d
173 .section __ex_table,"a"
174 .quad 1b,ia32_badarg
175 .previous
176 jmp sysenter_do_call 172 jmp sysenter_do_call
177 CFI_ENDPROC 173 CFI_ENDPROC
178ENDPROC(ia32_sysenter_target) 174ENDPROC(ia32_sysenter_target)
@@ -262,20 +258,17 @@ cstar_do_call:
262 258
263cstar_tracesys: 259cstar_tracesys:
264 CFI_RESTORE_STATE 260 CFI_RESTORE_STATE
261 xchgl %r9d,%ebp
265 SAVE_REST 262 SAVE_REST
266 CLEAR_RREGS 263 CLEAR_RREGS
264 movq %r9,R9(%rsp)
267 movq $-ENOSYS,RAX(%rsp) /* really needed? */ 265 movq $-ENOSYS,RAX(%rsp) /* really needed? */
268 movq %rsp,%rdi /* &pt_regs -> arg1 */ 266 movq %rsp,%rdi /* &pt_regs -> arg1 */
269 call syscall_trace_enter 267 call syscall_trace_enter
270 LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ 268 LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
271 RESTORE_REST 269 RESTORE_REST
270 xchgl %ebp,%r9d
272 movl RSP-ARGOFFSET(%rsp), %r8d 271 movl RSP-ARGOFFSET(%rsp), %r8d
273 /* no need to do an access_ok check here because r8 has been
274 32bit zero extended */
2751: movl (%r8),%r9d
276 .section __ex_table,"a"
277 .quad 1b,ia32_badarg
278 .previous
279 jmp cstar_do_call 272 jmp cstar_do_call
280END(ia32_cstar_target) 273END(ia32_cstar_target)
281 274