diff options
Diffstat (limited to 'arch/x86/kernel/ptrace_64.c')
-rw-r--r-- | arch/x86/kernel/ptrace_64.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/x86/kernel/ptrace_64.c b/arch/x86/kernel/ptrace_64.c index 4abfbced9b2..035d53e99c5 100644 --- a/arch/x86/kernel/ptrace_64.c +++ b/arch/x86/kernel/ptrace_64.c @@ -143,6 +143,15 @@ static int putreg(struct task_struct *child, return 0; case offsetof(struct user_regs_struct, eflags): value &= FLAG_MASK; + /* + * If the user value contains TF, mark that + * it was not "us" (the debugger) that set it. + * If not, make sure it stays set if we had. + */ + if (value & X86_EFLAGS_TF) + clear_tsk_thread_flag(child, TIF_FORCED_TF); + else if (test_tsk_thread_flag(child, TIF_FORCED_TF)) + value |= X86_EFLAGS_TF; tmp = get_stack_long(child, EFL_OFFSET); tmp &= ~FLAG_MASK; value |= tmp; @@ -189,6 +198,17 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno) if (child->thread.gsindex != GS_TLS_SEL) return 0; return get_desc_base(&child->thread.tls_array[GS_TLS]); + case offsetof(struct user_regs_struct, eflags): + /* + * If the debugger set TF, hide it from the readout. + */ + regno = regno - sizeof(struct pt_regs); + val = get_stack_long(child, regno); + if (test_tsk_thread_flag(child, TIF_IA32)) + val &= 0xffffffff; + if (test_tsk_thread_flag(child, TIF_FORCED_TF)) + val &= ~X86_EFLAGS_TF; + return val; default: regno = regno - sizeof(struct pt_regs); val = get_stack_long(child, regno); |