x86/kprobes: Convert to insn_decode()

[ Upstream commit 77e768ec1391dc0d6cd89822aa60b9a1c1bd8128 ]

Simplify code, improve decoding error checking.

Signed-off-by: Borislav Petkov <bp@suse.de>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Link: https://lkml.kernel.org/r/20210304174237.31945-12-bp@alien8.de
Stable-dep-of: 63dc6325ff41 ("x86/kprobes: Fix optprobe optimization check with CONFIG_RETHUNK")
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Borislav Petkov 2020-11-16 18:10:11 +01:00 committed by Greg Kroah-Hartman
parent a1766efc5b
commit 5d112deb2a
2 changed files with 18 additions and 8 deletions

View File

@ -293,6 +293,8 @@ static int can_probe(unsigned long paddr)
/* Decode instructions */
addr = paddr - offset;
while (addr < paddr) {
int ret;
/*
* Check if the instruction has been modified by another
* kprobe, in which case we replace the breakpoint by the
@ -304,8 +306,10 @@ static int can_probe(unsigned long paddr)
__addr = recover_probed_instruction(buf, addr);
if (!__addr)
return 0;
kernel_insn_init(&insn, (void *)__addr, MAX_INSN_SIZE);
insn_get_length(&insn);
ret = insn_decode(&insn, (void *)__addr, MAX_INSN_SIZE, INSN_MODE_KERN);
if (ret < 0)
return 0;
#ifdef CONFIG_KGDB
/*
@ -351,8 +355,8 @@ static int is_IF_modifier(kprobe_opcode_t *insn)
int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
{
kprobe_opcode_t buf[MAX_INSN_SIZE];
unsigned long recovered_insn =
recover_probed_instruction(buf, (unsigned long)src);
unsigned long recovered_insn = recover_probed_instruction(buf, (unsigned long)src);
int ret;
if (!recovered_insn || !insn)
return 0;
@ -362,8 +366,9 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn)
MAX_INSN_SIZE))
return 0;
kernel_insn_init(insn, dest, MAX_INSN_SIZE);
insn_get_length(insn);
ret = insn_decode(insn, dest, MAX_INSN_SIZE, INSN_MODE_KERN);
if (ret < 0)
return 0;
/* We can not probe force emulate prefixed instruction */
if (insn_has_emulate_prefix(insn))

View File

@ -312,6 +312,8 @@ static int can_optimize(unsigned long paddr)
addr = paddr - offset;
while (addr < paddr - offset + size) { /* Decode until function end */
unsigned long recovered_insn;
int ret;
if (search_exception_tables(addr))
/*
* Since some fixup code will jumps into this function,
@ -321,8 +323,11 @@ static int can_optimize(unsigned long paddr)
recovered_insn = recover_probed_instruction(buf, addr);
if (!recovered_insn)
return 0;
kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
insn_get_length(&insn);
ret = insn_decode(&insn, (void *)recovered_insn, MAX_INSN_SIZE, INSN_MODE_KERN);
if (ret < 0)
return 0;
/*
* In the case of detecting unknown breakpoint, this could be
* a padding INT3 between functions. Let's check that all the