^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Kernel Probes Jump Optimization (Optprobes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) IBM Corporation, 2002, 2004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) Hitachi Ltd., 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kprobes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/hardirq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/preempt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/extable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kdebug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/ftrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/objtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/pgtable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/static_call.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/text-patching.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/desc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/alternative.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/insn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/debugreg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/set_memory.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/nospec-branch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct optimized_kprobe *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct kprobe *kp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) long offs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) for (i = 0; i < JMP32_INSN_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) kp = get_kprobe((void *)addr - i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* This function only handles jump-optimized kprobe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (kp && kprobe_optimized(kp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) op = container_of(kp, struct optimized_kprobe, kp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* If op->list is not empty, op is under optimizing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (list_empty(&op->list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * If the kprobe can be optimized, original bytes which can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * overwritten by jump destination address. In this case, original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * bytes must be recovered from op->optinsn.copied_insn buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (copy_from_kernel_nofault(buf, (void *)addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return 0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (addr == (unsigned long)kp->addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) buf[0] = kp->opcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) memcpy(buf + 1, op->optinsn.copied_insn, DISP32_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) offs = addr - (unsigned long)kp->addr - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) memcpy(buf, op->optinsn.copied_insn + offs, DISP32_SIZE - offs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return (unsigned long)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static void synthesize_clac(kprobe_opcode_t *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Can't be static_cpu_has() due to how objtool treats this feature bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * This isn't a fast path anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!boot_cpu_has(X86_FEATURE_SMAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) /* Replace the NOP3 with CLAC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) addr[0] = 0x0f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) addr[1] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) addr[2] = 0xca;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /* Insert a move instruction which sets a pointer to eax/rdi (1st arg). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static void synthesize_set_arg1(kprobe_opcode_t *addr, unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #ifdef CONFIG_X86_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) *addr++ = 0x48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *addr++ = 0xbf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *addr++ = 0xb8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) *(unsigned long *)addr = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) asm (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ".pushsection .rodata\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) "optprobe_template_func:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ".pushsection .discard.func_stack_frame_non_standard\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) "__func_stack_frame_non_standard_optprobe_template_func:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #ifdef CONFIG_64BIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ".quad optprobe_template_func\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) ".long optprobe_template_func\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ".popsection\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ".global optprobe_template_entry\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) "optprobe_template_entry:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) #ifdef CONFIG_X86_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* We don't bother saving the ss register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) " pushq %rsp\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) " pushfq\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ".global optprobe_template_clac\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) "optprobe_template_clac:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ASM_NOP3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) SAVE_REGS_STRING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) " movq %rsp, %rsi\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ".global optprobe_template_val\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "optprobe_template_val:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ASM_NOP5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ASM_NOP5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ".global optprobe_template_call\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) "optprobe_template_call:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ASM_NOP5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* Move flags to rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) " movq 18*8(%rsp), %rdx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) " movq %rdx, 19*8(%rsp)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) RESTORE_REGS_STRING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* Skip flags entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) " addq $8, %rsp\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) " popfq\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #else /* CONFIG_X86_32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) " pushl %esp\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) " pushfl\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ".global optprobe_template_clac\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) "optprobe_template_clac:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ASM_NOP3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) SAVE_REGS_STRING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) " movl %esp, %edx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ".global optprobe_template_val\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) "optprobe_template_val:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ASM_NOP5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ".global optprobe_template_call\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) "optprobe_template_call:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ASM_NOP5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Move flags into esp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) " movl 14*4(%esp), %edx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) " movl %edx, 15*4(%esp)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) RESTORE_REGS_STRING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Skip flags entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) " addl $4, %esp\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) " popfl\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ".global optprobe_template_end\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) "optprobe_template_end:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ".popsection\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #define TMPL_CLAC_IDX \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ((long)optprobe_template_clac - (long)optprobe_template_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define TMPL_MOVE_IDX \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ((long)optprobe_template_val - (long)optprobe_template_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #define TMPL_CALL_IDX \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ((long)optprobe_template_call - (long)optprobe_template_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #define TMPL_END_IDX \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ((long)optprobe_template_end - (long)optprobe_template_entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* Optimized kprobe call back function: called from optinsn */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* This is possible if op is under delayed unoptimizing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (kprobe_disabled(&op->kp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) preempt_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (kprobe_running()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) kprobes_inc_nmissed_count(&op->kp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* Save skipped registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) regs->cs = __KERNEL_CS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #ifdef CONFIG_X86_32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) regs->gs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) regs->ip = (unsigned long)op->kp.addr + INT3_INSN_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) regs->orig_ax = ~0UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) __this_cpu_write(current_kprobe, &op->kp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) kcb->kprobe_status = KPROBE_HIT_ACTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) opt_pre_handler(&op->kp, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) __this_cpu_write(current_kprobe, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) preempt_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) NOKPROBE_SYMBOL(optimized_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int copy_optimized_instructions(u8 *dest, u8 *src, u8 *real)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) struct insn insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) int len = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) while (len < JMP32_INSN_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ret = __copy_instruction(dest + len, src + len, real + len, &insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (!ret || !can_boost(&insn, src + len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) len += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* Check whether the address range is reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (ftrace_text_reserved(src, src + len - 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) alternatives_text_reserved(src, src + len - 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) jump_label_text_reserved(src, src + len - 1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static_call_text_reserved(src, src + len - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* Check whether insn is indirect jump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static int __insn_is_indirect_jump(struct insn *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return ((insn->opcode.bytes[0] == 0xff &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) (X86_MODRM_REG(insn->modrm.value) & 6) == 4) || /* Jump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) insn->opcode.bytes[0] == 0xea); /* Segment based jump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Check whether insn jumps into specified address range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static int insn_jump_into_range(struct insn *insn, unsigned long start, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned long target = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) switch (insn->opcode.bytes[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) case 0xe0: /* loopne */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case 0xe1: /* loope */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) case 0xe2: /* loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) case 0xe3: /* jcxz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case 0xe9: /* near relative jump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case 0xeb: /* short relative jump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case 0x0f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if ((insn->opcode.bytes[1] & 0xf0) == 0x80) /* jcc near */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if ((insn->opcode.bytes[0] & 0xf0) == 0x70) /* jcc short */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) target = (unsigned long)insn->next_byte + insn->immediate.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return (start <= target && target <= start + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) static int insn_is_indirect_jump(struct insn *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int ret = __insn_is_indirect_jump(insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) #ifdef CONFIG_RETPOLINE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * Jump to x86_indirect_thunk_* is treated as an indirect jump.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * Note that even with CONFIG_RETPOLINE=y, the kernel compiled with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * older gcc may use indirect jump. So we add this check instead of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * replace indirect-jump check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) ret = insn_jump_into_range(insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) (unsigned long)__indirect_thunk_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) (unsigned long)__indirect_thunk_end -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) (unsigned long)__indirect_thunk_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static bool is_padding_int3(unsigned long addr, unsigned long eaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) unsigned char ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) for (; addr < eaddr; addr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (get_kernel_nofault(ops, (void *)addr) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ops != INT3_INSN_OPCODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* Decode whole function to ensure any instructions don't jump into target */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static int can_optimize(unsigned long paddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) unsigned long addr, size = 0, offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct insn insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) kprobe_opcode_t buf[MAX_INSN_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* Lookup symbol including addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * Do not optimize in the entry code due to the unstable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * stack handling and registers setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (((paddr >= (unsigned long)__entry_text_start) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) (paddr < (unsigned long)__entry_text_end)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* Check there is enough space for a relative jump. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (size - offset < JMP32_INSN_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* Decode instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) addr = paddr - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) while (addr < paddr - offset + size) { /* Decode until function end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) unsigned long recovered_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (search_exception_tables(addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * Since some fixup code will jumps into this function,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * we can't optimize kprobe in this function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) recovered_insn = recover_probed_instruction(buf, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (!recovered_insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) insn_get_length(&insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * In the case of detecting unknown breakpoint, this could be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * a padding INT3 between functions. Let's check that all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * rest of the bytes are also INT3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (insn.opcode.bytes[0] == INT3_INSN_OPCODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return is_padding_int3(addr, paddr - offset + size) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* Recover address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) insn.kaddr = (void *)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) insn.next_byte = (void *)(addr + insn.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* Check any instructions don't jump into target */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (insn_is_indirect_jump(&insn) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) insn_jump_into_range(&insn, paddr + INT3_INSN_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) DISP32_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) addr += insn.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* Check optimized_kprobe can actually be optimized. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) int arch_check_optimized_kprobe(struct optimized_kprobe *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct kprobe *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) for (i = 1; i < op->optinsn.size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) p = get_kprobe(op->kp.addr + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (p && !kprobe_disabled(p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /* Check the addr is within the optimized instructions. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int arch_within_optimized_kprobe(struct optimized_kprobe *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return ((unsigned long)op->kp.addr <= addr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) (unsigned long)op->kp.addr + op->optinsn.size > addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /* Free optimized instruction slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) void __arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) u8 *slot = op->optinsn.insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int len = TMPL_END_IDX + op->optinsn.size + JMP32_INSN_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) /* Record the perf event before freeing the slot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (dirty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) perf_event_text_poke(slot, slot, len, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) free_optinsn_slot(slot, dirty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) op->optinsn.insn = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) op->optinsn.size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) __arch_remove_optimized_kprobe(op, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Copy replacing target instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * Target instructions MUST be relocatable (checked inside)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * This is called when new aggr(opt)probe is allocated or reused.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct kprobe *__unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) u8 *buf = NULL, *slot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) int ret, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) long rel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (!can_optimize((unsigned long)op->kp.addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) return -EILSEQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) buf = kzalloc(MAX_OPTINSN_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) op->optinsn.insn = slot = get_optinsn_slot();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (!slot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * Verify if the address gap is in 2GB range, because this uses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * a relative jump.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) rel = (long)slot - (long)op->kp.addr + JMP32_INSN_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (abs(rel) > 0x7fffffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) ret = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) /* Copy arch-dep-instance from template */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) memcpy(buf, optprobe_template_entry, TMPL_END_IDX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* Copy instructions into the out-of-line buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) ret = copy_optimized_instructions(buf + TMPL_END_IDX, op->kp.addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) slot + TMPL_END_IDX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) op->optinsn.size = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) len = TMPL_END_IDX + op->optinsn.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) synthesize_clac(buf + TMPL_CLAC_IDX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* Set probe information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) synthesize_set_arg1(buf + TMPL_MOVE_IDX, (unsigned long)op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* Set probe function call */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) synthesize_relcall(buf + TMPL_CALL_IDX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) slot + TMPL_CALL_IDX, optimized_callback);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* Set returning jmp instruction at the tail of out-of-line buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) synthesize_reljump(buf + len, slot + len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) (u8 *)op->kp.addr + op->optinsn.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) len += JMP32_INSN_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) * Note len = TMPL_END_IDX + op->optinsn.size + JMP32_INSN_SIZE is also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) * used in __arch_remove_optimized_kprobe().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /* We have to use text_poke() for instruction buffer because it is RO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) perf_event_text_poke(slot, NULL, 0, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) text_poke(slot, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) __arch_remove_optimized_kprobe(op, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * Replace breakpoints (INT3) with relative jumps (JMP.d32).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * Caller must call with locking kprobe_mutex and text_mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * The caller will have installed a regular kprobe and after that issued
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * syncrhonize_rcu_tasks(), this ensures that the instruction(s) that live in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * the 4 bytes after the INT3 are unused and can now be overwritten.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) void arch_optimize_kprobes(struct list_head *oplist)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) struct optimized_kprobe *op, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) u8 insn_buff[JMP32_INSN_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) list_for_each_entry_safe(op, tmp, oplist, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) s32 rel = (s32)((long)op->optinsn.insn -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ((long)op->kp.addr + JMP32_INSN_SIZE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) WARN_ON(kprobe_disabled(&op->kp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* Backup instructions which will be replaced by jump address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_INSN_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) DISP32_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) insn_buff[0] = JMP32_INSN_OPCODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) *(s32 *)(&insn_buff[1]) = rel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) text_poke_bp(op->kp.addr, insn_buff, JMP32_INSN_SIZE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) list_del_init(&op->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * Replace a relative jump (JMP.d32) with a breakpoint (INT3).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * After that, we can restore the 4 bytes after the INT3 to undo what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * arch_optimize_kprobes() scribbled. This is safe since those bytes will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * unused once the INT3 lands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) void arch_unoptimize_kprobe(struct optimized_kprobe *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) u8 new[JMP32_INSN_SIZE] = { INT3_INSN_OPCODE, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) u8 old[JMP32_INSN_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) u8 *addr = op->kp.addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) memcpy(old, op->kp.addr, JMP32_INSN_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) memcpy(new + INT3_INSN_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) op->optinsn.copied_insn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) JMP32_INSN_SIZE - INT3_INSN_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) text_poke(addr, new, INT3_INSN_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) text_poke_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) text_poke(addr + INT3_INSN_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) new + INT3_INSN_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) JMP32_INSN_SIZE - INT3_INSN_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) text_poke_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) perf_event_text_poke(op->kp.addr, old, JMP32_INSN_SIZE, new, JMP32_INSN_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * Recover original instructions and breakpoints from relative jumps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * Caller must call with locking kprobe_mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) extern void arch_unoptimize_kprobes(struct list_head *oplist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct list_head *done_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct optimized_kprobe *op, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) list_for_each_entry_safe(op, tmp, oplist, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) arch_unoptimize_kprobe(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) list_move(&op->list, done_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) int setup_detour_execution(struct kprobe *p, struct pt_regs *regs, int reenter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct optimized_kprobe *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (p->flags & KPROBE_FLAG_OPTIMIZED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) /* This kprobe is really able to run optimized path. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) op = container_of(p, struct optimized_kprobe, kp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /* Detour through copied instructions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) regs->ip = (unsigned long)op->optinsn.insn + TMPL_END_IDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!reenter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) reset_current_kprobe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) NOKPROBE_SYMBOL(setup_detour_execution);