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