Skip to content

Commit e884edb

Browse files
jinghao-jiamhiramat
authored andcommitted
x86/kprobes: Prohibit kprobing on INT and UD
Both INT (INT n, INT1, INT3, INTO) and UD (UD0, UD1, UD2) serve special purposes in the kernel, e.g., INT3 is used by KGDB and UD2 is involved in LLVM-KCFI instrumentation. At the same time, attaching kprobes on these instructions (particularly UD) will pollute the stack trace dumped in the kernel ring buffer, since the exception is triggered in the copy buffer rather than the original location. Check for INT and UD in can_probe and reject any kprobes trying to attach to these instructions. Link: https://lore.kernel.org/all/[email protected]/ Suggested-by: Masami Hiramatsu (Google) <[email protected]> Signed-off-by: Jinghao Jia <[email protected]> Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
1 parent e4778a0 commit e884edb

File tree

1 file changed

+39
-9
lines changed

1 file changed

+39
-9
lines changed

arch/x86/kernel/kprobes/core.c

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,28 @@ unsigned long recover_probed_instruction(kprobe_opcode_t *buf, unsigned long add
252252
return __recover_probed_insn(buf, addr);
253253
}
254254

255-
/* Check if paddr is at an instruction boundary */
255+
/* Check if insn is INT or UD */
256+
static inline bool is_exception_insn(struct insn *insn)
257+
{
258+
/* UD uses 0f escape */
259+
if (insn->opcode.bytes[0] == 0x0f) {
260+
/* UD0 / UD1 / UD2 */
261+
return insn->opcode.bytes[1] == 0xff ||
262+
insn->opcode.bytes[1] == 0xb9 ||
263+
insn->opcode.bytes[1] == 0x0b;
264+
}
265+
266+
/* INT3 / INT n / INTO / INT1 */
267+
return insn->opcode.bytes[0] == 0xcc ||
268+
insn->opcode.bytes[0] == 0xcd ||
269+
insn->opcode.bytes[0] == 0xce ||
270+
insn->opcode.bytes[0] == 0xf1;
271+
}
272+
273+
/*
274+
* Check if paddr is at an instruction boundary and that instruction can
275+
* be probed
276+
*/
256277
static bool can_probe(unsigned long paddr)
257278
{
258279
unsigned long addr, __addr, offset = 0;
@@ -291,6 +312,22 @@ static bool can_probe(unsigned long paddr)
291312
#endif
292313
addr += insn.length;
293314
}
315+
316+
/* Check if paddr is at an instruction boundary */
317+
if (addr != paddr)
318+
return false;
319+
320+
__addr = recover_probed_instruction(buf, addr);
321+
if (!__addr)
322+
return false;
323+
324+
if (insn_decode_kernel(&insn, (void *)__addr) < 0)
325+
return false;
326+
327+
/* INT and UD are special and should not be kprobed */
328+
if (is_exception_insn(&insn))
329+
return false;
330+
294331
if (IS_ENABLED(CONFIG_CFI_CLANG)) {
295332
/*
296333
* The compiler generates the following instruction sequence
@@ -305,13 +342,6 @@ static bool can_probe(unsigned long paddr)
305342
* Also, these movl and addl are used for showing expected
306343
* type. So those must not be touched.
307344
*/
308-
__addr = recover_probed_instruction(buf, addr);
309-
if (!__addr)
310-
return false;
311-
312-
if (insn_decode_kernel(&insn, (void *)__addr) < 0)
313-
return false;
314-
315345
if (insn.opcode.value == 0xBA)
316346
offset = 12;
317347
else if (insn.opcode.value == 0x3)
@@ -325,7 +355,7 @@ static bool can_probe(unsigned long paddr)
325355
}
326356

327357
out:
328-
return (addr == paddr);
358+
return true;
329359
}
330360

331361
/* If x86 supports IBT (ENDBR) it must be skipped. */

0 commit comments

Comments
 (0)