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