Commit 77e768ec authored by Borislav Petkov's avatar Borislav Petkov
Browse files

x86/kprobes: Convert to insn_decode()



Simplify code, improve decoding error checking.

Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Acked-by: default avatarMasami Hiramatsu <mhiramat@kernel.org>
Link: https://lkml.kernel.org/r/20210304174237.31945-12-bp@alien8.de
parent 1580f488
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -265,6 +265,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
@@ -276,8 +278,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;

		/*
		 * Another debugging subsystem might insert this breakpoint.
@@ -301,8 +305,8 @@ static int can_probe(unsigned long paddr)
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;
@@ -312,8 +316,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))
+7 −2
Original line number Diff line number Diff line
@@ -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