mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 22:37:45 -04:00
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
This commit is contained in:
1 parent
a466ef76b8
commit
ee6a7354a3
2 files changed
+22
No files matched your search
@@ -208,4 +208,22 @@ static inline int insn_offset_immediate(struct insn *insn)
|
||||
return insn_offset_displacement(insn) + insn->displacement.nbytes;
|
||||
}
|
||||
|
||||
#define POP_SS_OPCODE 0x1f
|
||||
#define MOV_SREG_OPCODE 0x8e
|
||||
|
||||
/*
|
||||
* Intel SDM Vol.3A 6.8.3 states;
|
||||
* "Any single-step trap that would be delivered following the MOV to SS
|
||||
* instruction or POP to SS instruction (because EFLAGS.TF is 1) is
|
||||
* suppressed."
|
||||
* This function returns true if @insn is MOV SS or POP SS. On these
|
||||
* instructions, single stepping is suppressed.
|
||||
*/
|
||||
static inline int insn_masking_exception(struct insn *insn)
|
||||
{
|
||||
return insn->opcode.bytes[0] == POP_SS_OPCODE ||
|
||||
(insn->opcode.bytes[0] == MOV_SREG_OPCODE &&
|
||||
X86_MODRM_REG(insn->modrm.bytes[0]) == 2);
|
||||
}
|
||||
|
||||
#endif /* _ASM_X86_INSN_H */
|
||||
@@ -370,6 +370,10 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
|
||||
if (insn->opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
|
||||
return 0;
|
||||
|
||||
/* We should not singlestep on the exception masking instructions */
|
||||
if (insn_masking_exception(insn))
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/* Only x86_64 has RIP relative instructions */
|
||||
if (insn_rip_relative(insn)) {
|
||||
|
||||
Reference in new issue
Block a user