Skip to content

Commit ee6a735

Browse files
mhiramatKAGA-KOKO
authored andcommitted
kprobes/x86: Prohibit probing on exception masking instructions
Since MOV SS and POP SS instructions will delay the exceptions until the next instruction is executed, single-stepping on it by kprobes must be prohibited. However, kprobes usually executes those instructions directly on trampoline buffer (a.k.a. kprobe-booster), except for the kprobes which has post_handler. Thus if kprobe user probes MOV SS with post_handler, it will do single-stepping on the MOV SS. This means it is safe that if it is used via ftrace or perf/bpf since those don't use the post_handler. Anyway, since the stack switching is a rare case, it is safer just rejecting kprobes on such instructions. Signed-off-by: Masami Hiramatsu <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: Ricardo Neri <[email protected]> Cc: Francis Deslauriers <[email protected]> Cc: Oleg Nesterov <[email protected]> Cc: Alexei Starovoitov <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: "H . Peter Anvin" <[email protected]> Cc: Yonghong Song <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: "David S . Miller" <[email protected]> Link: https://lkml.kernel.org/r/152587069574.17316.3311695234863248641.stgit@devbox
1 parent a466ef7 commit ee6a735

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

arch/x86/include/asm/insn.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,22 @@ static inline int insn_offset_immediate(struct insn *insn)
208208
return insn_offset_displacement(insn) + insn->displacement.nbytes;
209209
}
210210

211+
#define POP_SS_OPCODE 0x1f
212+
#define MOV_SREG_OPCODE 0x8e
213+
214+
/*
215+
* Intel SDM Vol.3A 6.8.3 states;
216+
* "Any single-step trap that would be delivered following the MOV to SS
217+
* instruction or POP to SS instruction (because EFLAGS.TF is 1) is
218+
* suppressed."
219+
* This function returns true if @insn is MOV SS or POP SS. On these
220+
* instructions, single stepping is suppressed.
221+
*/
222+
static inline int insn_masking_exception(struct insn *insn)
223+
{
224+
return insn->opcode.bytes[0] == POP_SS_OPCODE ||
225+
(insn->opcode.bytes[0] == MOV_SREG_OPCODE &&
226+
X86_MODRM_REG(insn->modrm.bytes[0]) == 2);
227+
}
228+
211229
#endif /* _ASM_X86_INSN_H */

arch/x86/kernel/kprobes/core.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,10 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
370370
if (insn->opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
371371
return 0;
372372

373+
/* We should not singlestep on the exception masking instructions */
374+
if (insn_masking_exception(insn))
375+
return 0;
376+
373377
#ifdef CONFIG_X86_64
374378
/* Only x86_64 has RIP relative instructions */
375379
if (insn_rip_relative(insn)) {

0 commit comments

Comments
 (0)