Commit 256aa113 authored by Roland McGrath's avatar Roland McGrath Committed by Linus Torvalds

[PATCH] x86: further EFLAGS and ptrace cleanups/fixes

This patch further cleans up the appearance of TF in eflags when ptrace is
involved.  With this, PTRACE_SINGLESTEP will not cause TF to appear in
eflags as seen by PTRACE_GETREGS and the like, when the instruction faulted
for some reason other than the single-step trap.

This moves the check added by Dan's patch from setup_sigcontext to
handle_signal.  This is a cosmetic difference, but I think it makes more
sense to consolidate all the "reset registers to canonical state" work in
the same place (i.e. put it with the syscall rollback code), separate from
the signal handler setup.

The change that matters is moving the similar check out of do_debug,
where it only covers the case of a single-step trap.  Instead, it goes
into the ptrace_signal_deliver macro, which is called before the ptrace
stop for whatever signal results from whatever kind of fault in that
instruction (or asynchronous signal).  With that, the handle_signal
check is still needed only for the case of PTRACE_SINGLESTEP with a
handled signal.
Signed-off-by: default avatarRoland McGrath <roland@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0756f628
......@@ -277,18 +277,6 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
{
int tmp, err = 0;
/*
* If TF is set due to a debugger (PT_DTRACE), clear the TF
* flag so that register information in the sigcontext is
* correct.
*/
if (unlikely(regs->eflags & TF_MASK)) {
if (likely(current->ptrace & PT_DTRACE)) {
current->ptrace &= ~PT_DTRACE;
regs->eflags &= ~TF_MASK;
}
}
tmp = 0;
__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
......@@ -569,6 +557,16 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
}
}
/*
* If TF is set due to a debugger (PT_DTRACE), clear the TF flag so
* that register information in the sigcontext is correct.
*/
if (unlikely(regs->eflags & TF_MASK)
&& likely(current->ptrace & PT_DTRACE)) {
current->ptrace &= ~PT_DTRACE;
regs->eflags &= ~TF_MASK;
}
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(sig, ka, info, oldset, regs);
......
......@@ -707,8 +707,6 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
/*
* Single-stepping through TF: make sure we ignore any events in
* kernel space (but re-enable TF when returning to user mode).
* And if the event was due to a debugger (PT_DTRACE), clear the
* TF flag so that register information is correct.
*/
if (condition & DR_STEP) {
/*
......@@ -718,11 +716,6 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
*/
if ((regs->xcs & 3) == 0)
goto clear_TF_reenable;
if (likely(tsk->ptrace & PT_DTRACE)) {
tsk->ptrace &= ~PT_DTRACE;
regs->eflags &= ~TF_MASK;
}
}
/* Ok, finally something we can handle */
......
......@@ -223,7 +223,14 @@ static __inline__ int sigfindinword(unsigned long word)
struct pt_regs;
extern int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#define ptrace_signal_deliver(regs, cookie) \
do { \
if (current->ptrace & PT_DTRACE) { \
current->ptrace &= ~PT_DTRACE; \
(regs)->eflags &= ~TF_MASK; \
} \
} while (0)
#endif /* __KERNEL__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment