x86/kprobes: Convert to insn_decode()
authorBorislav Petkov <bp@suse.de>
Mon, 16 Nov 2020 17:10:11 +0000 (18:10 +0100)
committerBorislav Petkov <bp@suse.de>
Mon, 15 Mar 2021 10:28:20 +0000 (11:28 +0100)
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
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kprobes/opt.c

index df776cd..60a540f 100644 (file)
@@ -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))
index 08eb230..4299fc8 100644 (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