This adjusts the x86 kprobes implementation to cope with per-thread
MSR_IA32_DEBUGCTLMSR being set for user mode. I haven't delved deep
enough into the kprobes code to be really sure this covers all the
cases where the user-mode BTF setting needs to be cleared or restored.
It looks about right to me.
Signed-off-by: Roland McGrath <roland@redhat.com>
---
arch/x86/kernel/kprobes_32.c | 15 +++++++++++++++
arch/x86/kernel/kprobes_64.c | 15 +++++++++++++++
2 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c
index d87a523..f151f06 100644
--- a/arch/x86/kernel/kprobes_32.c
+++ b/arch/x86/kernel/kprobes_32.c
@@ -217,8 +217,21 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_saved_eflags &= ~IF_MASK;
}
+static __always_inline void clear_btf(void)
+{
+ if (test_thread_flag(TIF_DEBUGCTLMSR))
+ wrmsr(MSR_IA32_DEBUGCTLMSR, 0, 0);
+}
+
+static __always_inline void restore_btf(void)
+{
+ if (test_thread_flag(TIF_DEBUGCTLMSR))
+ wrmsr(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr, 0);
+}
+
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
+ clear_btf();
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
/*single step inline if the instruction is an int3*/
@@ -542,6 +555,8 @@ static void __kprobes resume_execution(struct kprobe *p,
regs->eip = orig_eip + (regs->eip - copy_eip);
no_change:
+ restore_btf();
+
return;
}
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c
index 3db3611..d3be418 100644
--- a/arch/x86/kernel/kprobes_64.c
+++ b/arch/x86/kernel/kprobes_64.c
@@ -256,8 +256,21 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
kcb->kprobe_saved_rflags &= ~IF_MASK;
}
+static __always_inline void clear_btf(void)
+{
+ if (test_thread_flag(TIF_DEBUGCTLMSR))
+ wrmsrl(MSR_IA32_DEBUGCTLMSR, 0);
+}
+
+static __always_inline void restore_btf(void)
+{
+ if (test_thread_flag(TIF_DEBUGCTLMSR))
+ wrmsrl(MSR_IA32_DEBUGCTLMSR, current->thread.debugctlmsr);
+}
+
static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
+ clear_btf();
regs->eflags |= TF_MASK;
regs->eflags &= ~IF_MASK;
/*single step inline if the instruction is an int3*/
@@ -534,6 +547,8 @@ static void __kprobes resume_execution(struct kprobe *p,
} else {
regs->rip = orig_rip + (regs->rip - copy_rip);
}
+
+ restore_btf();
}
int __kprobes post_kprobe_handler(struct pt_regs *regs)
-
| david | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Greg KH | [2.6.22.2 review 05/84] Fix deadlocks in sparc serial console. |
| Greg KH | [GIT PATCH] driver core patches against 2.6.24 |
| Andrew Morton | -mm merge plans for 2.6.23 |
git: | |
| Jeff Kirsher | [RESEND][NET-NEXT PATCH 01/29] ixgbe: fix bug where using wake queue instead of st... |
| Gerrit Renker | [PATCH 27/37] dccp: Integration of dynamic feature activation - part 2 (server side) |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Patrick McHardy | Re: [GIT]: Networking |
| Manuel Bouyer | Re: Interactive performance in -current |
| Christian Limpach | Re: newfs: determining file system parameters |
| YAMAMOTO Takashi | Re: statvfs(2) replacement for statfs(2) patch |
| Charles M. Hannum | Re: kern/22869: Slave IDE drive not detected |
