|
Jiri Slaby |
e152e7 |
From: Peter Zijlstra <peterz@infradead.org>
|
|
Jiri Slaby |
e152e7 |
Date: Mon, 23 Jan 2023 21:59:16 +0100
|
|
Jiri Slaby |
e152e7 |
Subject: [PATCH] x86/alternatives: Introduce int3_emulate_jcc()
|
|
Jiri Slaby |
e152e7 |
References: bsc#1012628
|
|
Jiri Slaby |
e152e7 |
Patch-mainline: 6.2.1
|
|
Jiri Slaby |
e152e7 |
Git-commit: db7adcfd1cec4e95155e37bc066fddab302c6340
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
commit db7adcfd1cec4e95155e37bc066fddab302c6340 upstream.
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
Move the kprobe Jcc emulation into int3_emulate_jcc() so it can be
|
|
Jiri Slaby |
e152e7 |
used by more code -- specifically static_call() will need this.
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
|
|
Jiri Slaby |
e152e7 |
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
|
Jiri Slaby |
e152e7 |
Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
|
|
Jiri Slaby |
e152e7 |
Link: https://lore.kernel.org/r/20230123210607.057678245@infradead.org
|
|
Jiri Slaby |
e152e7 |
Cc: Nathan Chancellor <nathan@kernel.org>
|
|
Jiri Slaby |
e152e7 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
Jiri Slaby |
e152e7 |
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
|
Jiri Slaby |
e152e7 |
---
|
|
Jiri Slaby |
e152e7 |
arch/x86/include/asm/text-patching.h | 31 +++++++++++++++++++++++
|
|
Jiri Slaby |
e152e7 |
arch/x86/kernel/kprobes/core.c | 38 ++++++----------------------
|
|
Jiri Slaby |
e152e7 |
2 files changed, 39 insertions(+), 30 deletions(-)
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
diff --git a/arch/x86/include/asm/text-patching.h b/arch/x86/include/asm/text-patching.h
|
|
Jiri Slaby |
e152e7 |
index f4b87f08..29832c33 100644
|
|
Jiri Slaby |
e152e7 |
--- a/arch/x86/include/asm/text-patching.h
|
|
Jiri Slaby |
e152e7 |
+++ b/arch/x86/include/asm/text-patching.h
|
|
Jiri Slaby |
e152e7 |
@@ -184,6 +184,37 @@ void int3_emulate_ret(struct pt_regs *regs)
|
|
Jiri Slaby |
e152e7 |
unsigned long ip = int3_emulate_pop(regs);
|
|
Jiri Slaby |
e152e7 |
int3_emulate_jmp(regs, ip);
|
|
Jiri Slaby |
e152e7 |
}
|
|
Jiri Slaby |
e152e7 |
+
|
|
Jiri Slaby |
e152e7 |
+static __always_inline
|
|
Jiri Slaby |
e152e7 |
+void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned long disp)
|
|
Jiri Slaby |
e152e7 |
+{
|
|
Jiri Slaby |
e152e7 |
+ static const unsigned long jcc_mask[6] = {
|
|
Jiri Slaby |
e152e7 |
+ [0] = X86_EFLAGS_OF,
|
|
Jiri Slaby |
e152e7 |
+ [1] = X86_EFLAGS_CF,
|
|
Jiri Slaby |
e152e7 |
+ [2] = X86_EFLAGS_ZF,
|
|
Jiri Slaby |
e152e7 |
+ [3] = X86_EFLAGS_CF | X86_EFLAGS_ZF,
|
|
Jiri Slaby |
e152e7 |
+ [4] = X86_EFLAGS_SF,
|
|
Jiri Slaby |
e152e7 |
+ [5] = X86_EFLAGS_PF,
|
|
Jiri Slaby |
e152e7 |
+ };
|
|
Jiri Slaby |
e152e7 |
+
|
|
Jiri Slaby |
e152e7 |
+ bool invert = cc & 1;
|
|
Jiri Slaby |
e152e7 |
+ bool match;
|
|
Jiri Slaby |
e152e7 |
+
|
|
Jiri Slaby |
e152e7 |
+ if (cc < 0xc) {
|
|
Jiri Slaby |
e152e7 |
+ match = regs->flags & jcc_mask[cc >> 1];
|
|
Jiri Slaby |
e152e7 |
+ } else {
|
|
Jiri Slaby |
e152e7 |
+ match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
|
|
Jiri Slaby |
e152e7 |
+ ((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
|
|
Jiri Slaby |
e152e7 |
+ if (cc >= 0xe)
|
|
Jiri Slaby |
e152e7 |
+ match = match || (regs->flags & X86_EFLAGS_ZF);
|
|
Jiri Slaby |
e152e7 |
+ }
|
|
Jiri Slaby |
e152e7 |
+
|
|
Jiri Slaby |
e152e7 |
+ if ((match && !invert) || (!match && invert))
|
|
Jiri Slaby |
e152e7 |
+ ip += disp;
|
|
Jiri Slaby |
e152e7 |
+
|
|
Jiri Slaby |
e152e7 |
+ int3_emulate_jmp(regs, ip);
|
|
Jiri Slaby |
e152e7 |
+}
|
|
Jiri Slaby |
e152e7 |
+
|
|
Jiri Slaby |
e152e7 |
#endif /* !CONFIG_UML_X86 */
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
#endif /* _ASM_X86_TEXT_PATCHING_H */
|
|
Jiri Slaby |
e152e7 |
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
|
|
Jiri Slaby |
e152e7 |
index 695873c0..0ce969ae 100644
|
|
Jiri Slaby |
e152e7 |
--- a/arch/x86/kernel/kprobes/core.c
|
|
Jiri Slaby |
e152e7 |
+++ b/arch/x86/kernel/kprobes/core.c
|
|
Jiri Slaby |
e152e7 |
@@ -464,50 +464,26 @@ static void kprobe_emulate_call(struct kprobe *p, struct pt_regs *regs)
|
|
Jiri Slaby |
e152e7 |
}
|
|
Jiri Slaby |
e152e7 |
NOKPROBE_SYMBOL(kprobe_emulate_call);
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
-static nokprobe_inline
|
|
Jiri Slaby |
e152e7 |
-void __kprobe_emulate_jmp(struct kprobe *p, struct pt_regs *regs, bool cond)
|
|
Jiri Slaby |
e152e7 |
+static void kprobe_emulate_jmp(struct kprobe *p, struct pt_regs *regs)
|
|
Jiri Slaby |
e152e7 |
{
|
|
Jiri Slaby |
e152e7 |
unsigned long ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
- if (cond)
|
|
Jiri Slaby |
e152e7 |
- ip += p->ainsn.rel32;
|
|
Jiri Slaby |
e152e7 |
+ ip += p->ainsn.rel32;
|
|
Jiri Slaby |
e152e7 |
int3_emulate_jmp(regs, ip);
|
|
Jiri Slaby |
e152e7 |
}
|
|
Jiri Slaby |
e152e7 |
-
|
|
Jiri Slaby |
e152e7 |
-static void kprobe_emulate_jmp(struct kprobe *p, struct pt_regs *regs)
|
|
Jiri Slaby |
e152e7 |
-{
|
|
Jiri Slaby |
e152e7 |
- __kprobe_emulate_jmp(p, regs, true);
|
|
Jiri Slaby |
e152e7 |
-}
|
|
Jiri Slaby |
e152e7 |
NOKPROBE_SYMBOL(kprobe_emulate_jmp);
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
-static const unsigned long jcc_mask[6] = {
|
|
Jiri Slaby |
e152e7 |
- [0] = X86_EFLAGS_OF,
|
|
Jiri Slaby |
e152e7 |
- [1] = X86_EFLAGS_CF,
|
|
Jiri Slaby |
e152e7 |
- [2] = X86_EFLAGS_ZF,
|
|
Jiri Slaby |
e152e7 |
- [3] = X86_EFLAGS_CF | X86_EFLAGS_ZF,
|
|
Jiri Slaby |
e152e7 |
- [4] = X86_EFLAGS_SF,
|
|
Jiri Slaby |
e152e7 |
- [5] = X86_EFLAGS_PF,
|
|
Jiri Slaby |
e152e7 |
-};
|
|
Jiri Slaby |
e152e7 |
-
|
|
Jiri Slaby |
e152e7 |
static void kprobe_emulate_jcc(struct kprobe *p, struct pt_regs *regs)
|
|
Jiri Slaby |
e152e7 |
{
|
|
Jiri Slaby |
e152e7 |
- bool invert = p->ainsn.jcc.type & 1;
|
|
Jiri Slaby |
e152e7 |
- bool match;
|
|
Jiri Slaby |
e152e7 |
+ unsigned long ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
- if (p->ainsn.jcc.type < 0xc) {
|
|
Jiri Slaby |
e152e7 |
- match = regs->flags & jcc_mask[p->ainsn.jcc.type >> 1];
|
|
Jiri Slaby |
e152e7 |
- } else {
|
|
Jiri Slaby |
e152e7 |
- match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
|
|
Jiri Slaby |
e152e7 |
- ((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
|
|
Jiri Slaby |
e152e7 |
- if (p->ainsn.jcc.type >= 0xe)
|
|
Jiri Slaby |
e152e7 |
- match = match || (regs->flags & X86_EFLAGS_ZF);
|
|
Jiri Slaby |
e152e7 |
- }
|
|
Jiri Slaby |
e152e7 |
- __kprobe_emulate_jmp(p, regs, (match && !invert) || (!match && invert));
|
|
Jiri Slaby |
e152e7 |
+ int3_emulate_jcc(regs, p->ainsn.jcc.type, ip, p->ainsn.rel32);
|
|
Jiri Slaby |
e152e7 |
}
|
|
Jiri Slaby |
e152e7 |
NOKPROBE_SYMBOL(kprobe_emulate_jcc);
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
static void kprobe_emulate_loop(struct kprobe *p, struct pt_regs *regs)
|
|
Jiri Slaby |
e152e7 |
{
|
|
Jiri Slaby |
e152e7 |
+ unsigned long ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;
|
|
Jiri Slaby |
e152e7 |
bool match;
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
if (p->ainsn.loop.type != 3) { /* LOOP* */
|
|
Jiri Slaby |
e152e7 |
@@ -535,7 +511,9 @@ static void kprobe_emulate_loop(struct kprobe *p, struct pt_regs *regs)
|
|
Jiri Slaby |
e152e7 |
else if (p->ainsn.loop.type == 1) /* LOOPE */
|
|
Jiri Slaby |
e152e7 |
match = match && (regs->flags & X86_EFLAGS_ZF);
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
- __kprobe_emulate_jmp(p, regs, match);
|
|
Jiri Slaby |
e152e7 |
+ if (match)
|
|
Jiri Slaby |
e152e7 |
+ ip += p->ainsn.rel32;
|
|
Jiri Slaby |
e152e7 |
+ int3_emulate_jmp(regs, ip);
|
|
Jiri Slaby |
e152e7 |
}
|
|
Jiri Slaby |
e152e7 |
NOKPROBE_SYMBOL(kprobe_emulate_loop);
|
|
Jiri Slaby |
e152e7 |
|
|
Jiri Slaby |
e152e7 |
--
|
|
Jiri Slaby |
e152e7 |
2.35.3
|
|
Jiri Slaby |
e152e7 |
|