Skip to content

Commit db7adcf

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
x86/alternatives: Introduce int3_emulate_jcc()
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) <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Reviewed-by: Masami Hiramatsu (Google) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 5d1dd96 commit db7adcf

File tree

2 files changed

+39
-30
lines changed

2 files changed

+39
-30
lines changed

arch/x86/include/asm/text-patching.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,37 @@ void int3_emulate_ret(struct pt_regs *regs)
184184
unsigned long ip = int3_emulate_pop(regs);
185185
int3_emulate_jmp(regs, ip);
186186
}
187+
188+
static __always_inline
189+
void int3_emulate_jcc(struct pt_regs *regs, u8 cc, unsigned long ip, unsigned long disp)
190+
{
191+
static const unsigned long jcc_mask[6] = {
192+
[0] = X86_EFLAGS_OF,
193+
[1] = X86_EFLAGS_CF,
194+
[2] = X86_EFLAGS_ZF,
195+
[3] = X86_EFLAGS_CF | X86_EFLAGS_ZF,
196+
[4] = X86_EFLAGS_SF,
197+
[5] = X86_EFLAGS_PF,
198+
};
199+
200+
bool invert = cc & 1;
201+
bool match;
202+
203+
if (cc < 0xc) {
204+
match = regs->flags & jcc_mask[cc >> 1];
205+
} else {
206+
match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
207+
((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
208+
if (cc >= 0xe)
209+
match = match || (regs->flags & X86_EFLAGS_ZF);
210+
}
211+
212+
if ((match && !invert) || (!match && invert))
213+
ip += disp;
214+
215+
int3_emulate_jmp(regs, ip);
216+
}
217+
187218
#endif /* !CONFIG_UML_X86 */
188219

189220
#endif /* _ASM_X86_TEXT_PATCHING_H */

arch/x86/kernel/kprobes/core.c

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -460,50 +460,26 @@ static void kprobe_emulate_call(struct kprobe *p, struct pt_regs *regs)
460460
}
461461
NOKPROBE_SYMBOL(kprobe_emulate_call);
462462

463-
static nokprobe_inline
464-
void __kprobe_emulate_jmp(struct kprobe *p, struct pt_regs *regs, bool cond)
463+
static void kprobe_emulate_jmp(struct kprobe *p, struct pt_regs *regs)
465464
{
466465
unsigned long ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;
467466

468-
if (cond)
469-
ip += p->ainsn.rel32;
467+
ip += p->ainsn.rel32;
470468
int3_emulate_jmp(regs, ip);
471469
}
472-
473-
static void kprobe_emulate_jmp(struct kprobe *p, struct pt_regs *regs)
474-
{
475-
__kprobe_emulate_jmp(p, regs, true);
476-
}
477470
NOKPROBE_SYMBOL(kprobe_emulate_jmp);
478471

479-
static const unsigned long jcc_mask[6] = {
480-
[0] = X86_EFLAGS_OF,
481-
[1] = X86_EFLAGS_CF,
482-
[2] = X86_EFLAGS_ZF,
483-
[3] = X86_EFLAGS_CF | X86_EFLAGS_ZF,
484-
[4] = X86_EFLAGS_SF,
485-
[5] = X86_EFLAGS_PF,
486-
};
487-
488472
static void kprobe_emulate_jcc(struct kprobe *p, struct pt_regs *regs)
489473
{
490-
bool invert = p->ainsn.jcc.type & 1;
491-
bool match;
474+
unsigned long ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;
492475

493-
if (p->ainsn.jcc.type < 0xc) {
494-
match = regs->flags & jcc_mask[p->ainsn.jcc.type >> 1];
495-
} else {
496-
match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
497-
((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
498-
if (p->ainsn.jcc.type >= 0xe)
499-
match = match || (regs->flags & X86_EFLAGS_ZF);
500-
}
501-
__kprobe_emulate_jmp(p, regs, (match && !invert) || (!match && invert));
476+
int3_emulate_jcc(regs, p->ainsn.jcc.type, ip, p->ainsn.rel32);
502477
}
503478
NOKPROBE_SYMBOL(kprobe_emulate_jcc);
504479

505480
static void kprobe_emulate_loop(struct kprobe *p, struct pt_regs *regs)
506481
{
482+
unsigned long ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;
507483
bool match;
508484

509485
if (p->ainsn.loop.type != 3) { /* LOOP* */
@@ -531,7 +507,9 @@ static void kprobe_emulate_loop(struct kprobe *p, struct pt_regs *regs)
531507
else if (p->ainsn.loop.type == 1) /* LOOPE */
532508
match = match && (regs->flags & X86_EFLAGS_ZF);
533509

534-
__kprobe_emulate_jmp(p, regs, match);
510+
if (match)
511+
ip += p->ainsn.rel32;
512+
int3_emulate_jmp(regs, ip);
535513
}
536514
NOKPROBE_SYMBOL(kprobe_emulate_loop);
537515

0 commit comments

Comments
 (0)