1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 29842ceaeSPratyush Anand /* 39842ceaeSPratyush Anand * Copyright (C) 2014-2016 Pratyush Anand <panand@redhat.com> 49842ceaeSPratyush Anand */ 59842ceaeSPratyush Anand #include <linux/highmem.h> 69842ceaeSPratyush Anand #include <linux/ptrace.h> 79842ceaeSPratyush Anand #include <linux/uprobes.h> 89842ceaeSPratyush Anand #include <asm/cacheflush.h> 99842ceaeSPratyush Anand 109842ceaeSPratyush Anand #include "decode-insn.h" 119842ceaeSPratyush Anand 129842ceaeSPratyush Anand #define UPROBE_INV_FAULT_CODE UINT_MAX 139842ceaeSPratyush Anand 149842ceaeSPratyush Anand void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, 159842ceaeSPratyush Anand void *src, unsigned long len) 169842ceaeSPratyush Anand { 179842ceaeSPratyush Anand void *xol_page_kaddr = kmap_atomic(page); 189842ceaeSPratyush Anand void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK); 199842ceaeSPratyush Anand 209842ceaeSPratyush Anand /* Initialize the slot */ 219842ceaeSPratyush Anand memcpy(dst, src, len); 229842ceaeSPratyush Anand 239842ceaeSPratyush Anand /* flush caches (dcache/icache) */ 248c28d52cSFuad Tabba sync_icache_aliases((unsigned long)dst, (unsigned long)dst + len); 259842ceaeSPratyush Anand 269842ceaeSPratyush Anand kunmap_atomic(xol_page_kaddr); 279842ceaeSPratyush Anand } 289842ceaeSPratyush Anand 299842ceaeSPratyush Anand unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) 309842ceaeSPratyush Anand { 319842ceaeSPratyush Anand return instruction_pointer(regs); 329842ceaeSPratyush Anand } 339842ceaeSPratyush Anand 349842ceaeSPratyush Anand int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, 359842ceaeSPratyush Anand unsigned long addr) 369842ceaeSPratyush Anand { 379842ceaeSPratyush Anand probe_opcode_t insn; 389842ceaeSPratyush Anand 399842ceaeSPratyush Anand /* TODO: Currently we do not support AARCH32 instruction probing */ 405ce93ab6SYury Norov if (mm->context.flags & MMCF_AARCH32) 41d47422d9SHe Zhe return -EOPNOTSUPP; 429842ceaeSPratyush Anand else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE)) 439842ceaeSPratyush Anand return -EINVAL; 449842ceaeSPratyush Anand 459842ceaeSPratyush Anand insn = *(probe_opcode_t *)(&auprobe->insn[0]); 469842ceaeSPratyush Anand 479842ceaeSPratyush Anand switch (arm_probe_decode_insn(insn, &auprobe->api)) { 489842ceaeSPratyush Anand case INSN_REJECTED: 499842ceaeSPratyush Anand return -EINVAL; 509842ceaeSPratyush Anand 519842ceaeSPratyush Anand case INSN_GOOD_NO_SLOT: 529842ceaeSPratyush Anand auprobe->simulate = true; 539842ceaeSPratyush Anand break; 549842ceaeSPratyush Anand 559842ceaeSPratyush Anand default: 569842ceaeSPratyush Anand break; 579842ceaeSPratyush Anand } 589842ceaeSPratyush Anand 599842ceaeSPratyush Anand return 0; 609842ceaeSPratyush Anand } 619842ceaeSPratyush Anand 629842ceaeSPratyush Anand int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 639842ceaeSPratyush Anand { 649842ceaeSPratyush Anand struct uprobe_task *utask = current->utask; 659842ceaeSPratyush Anand 669842ceaeSPratyush Anand /* Initialize with an invalid fault code to detect if ol insn trapped */ 679842ceaeSPratyush Anand current->thread.fault_code = UPROBE_INV_FAULT_CODE; 689842ceaeSPratyush Anand 699842ceaeSPratyush Anand /* Instruction points to execute ol */ 709842ceaeSPratyush Anand instruction_pointer_set(regs, utask->xol_vaddr); 719842ceaeSPratyush Anand 729842ceaeSPratyush Anand user_enable_single_step(current); 739842ceaeSPratyush Anand 749842ceaeSPratyush Anand return 0; 759842ceaeSPratyush Anand } 769842ceaeSPratyush Anand 779842ceaeSPratyush Anand int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 789842ceaeSPratyush Anand { 799842ceaeSPratyush Anand struct uprobe_task *utask = current->utask; 809842ceaeSPratyush Anand 819842ceaeSPratyush Anand WARN_ON_ONCE(current->thread.fault_code != UPROBE_INV_FAULT_CODE); 829842ceaeSPratyush Anand 839842ceaeSPratyush Anand /* Instruction points to execute next to breakpoint address */ 849842ceaeSPratyush Anand instruction_pointer_set(regs, utask->vaddr + 4); 859842ceaeSPratyush Anand 869842ceaeSPratyush Anand user_disable_single_step(current); 879842ceaeSPratyush Anand 889842ceaeSPratyush Anand return 0; 899842ceaeSPratyush Anand } 909842ceaeSPratyush Anand bool arch_uprobe_xol_was_trapped(struct task_struct *t) 919842ceaeSPratyush Anand { 929842ceaeSPratyush Anand /* 939842ceaeSPratyush Anand * Between arch_uprobe_pre_xol and arch_uprobe_post_xol, if an xol 949842ceaeSPratyush Anand * insn itself is trapped, then detect the case with the help of 959842ceaeSPratyush Anand * invalid fault code which is being set in arch_uprobe_pre_xol 969842ceaeSPratyush Anand */ 979842ceaeSPratyush Anand if (t->thread.fault_code != UPROBE_INV_FAULT_CODE) 989842ceaeSPratyush Anand return true; 999842ceaeSPratyush Anand 1009842ceaeSPratyush Anand return false; 1019842ceaeSPratyush Anand } 1029842ceaeSPratyush Anand 1039842ceaeSPratyush Anand bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 1049842ceaeSPratyush Anand { 1059842ceaeSPratyush Anand probe_opcode_t insn; 1069842ceaeSPratyush Anand unsigned long addr; 1079842ceaeSPratyush Anand 1089842ceaeSPratyush Anand if (!auprobe->simulate) 1099842ceaeSPratyush Anand return false; 1109842ceaeSPratyush Anand 1119842ceaeSPratyush Anand insn = *(probe_opcode_t *)(&auprobe->insn[0]); 1129842ceaeSPratyush Anand addr = instruction_pointer(regs); 1139842ceaeSPratyush Anand 1149842ceaeSPratyush Anand if (auprobe->api.handler) 1159842ceaeSPratyush Anand auprobe->api.handler(insn, addr, regs); 1169842ceaeSPratyush Anand 1179842ceaeSPratyush Anand return true; 1189842ceaeSPratyush Anand } 1199842ceaeSPratyush Anand 1209842ceaeSPratyush Anand void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) 1219842ceaeSPratyush Anand { 1229842ceaeSPratyush Anand struct uprobe_task *utask = current->utask; 1239842ceaeSPratyush Anand 1249842ceaeSPratyush Anand /* 1259842ceaeSPratyush Anand * Task has received a fatal signal, so reset back to probbed 1269842ceaeSPratyush Anand * address. 1279842ceaeSPratyush Anand */ 1289842ceaeSPratyush Anand instruction_pointer_set(regs, utask->vaddr); 1299842ceaeSPratyush Anand 1309842ceaeSPratyush Anand user_disable_single_step(current); 1319842ceaeSPratyush Anand } 1329842ceaeSPratyush Anand 1339842ceaeSPratyush Anand bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx, 1349842ceaeSPratyush Anand struct pt_regs *regs) 1359842ceaeSPratyush Anand { 1369842ceaeSPratyush Anand /* 1379842ceaeSPratyush Anand * If a simple branch instruction (B) was called for retprobed 1389842ceaeSPratyush Anand * assembly label then return true even when regs->sp and ret->stack 1399842ceaeSPratyush Anand * are same. It will ensure that cleanup and reporting of return 1409842ceaeSPratyush Anand * instances corresponding to callee label is done when 1419842ceaeSPratyush Anand * handle_trampoline for called function is executed. 1429842ceaeSPratyush Anand */ 1439842ceaeSPratyush Anand if (ctx == RP_CHECK_CHAIN_CALL) 1449842ceaeSPratyush Anand return regs->sp <= ret->stack; 1459842ceaeSPratyush Anand else 1469842ceaeSPratyush Anand return regs->sp < ret->stack; 1479842ceaeSPratyush Anand } 1489842ceaeSPratyush Anand 1499842ceaeSPratyush Anand unsigned long 1509842ceaeSPratyush Anand arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, 1519842ceaeSPratyush Anand struct pt_regs *regs) 1529842ceaeSPratyush Anand { 1539842ceaeSPratyush Anand unsigned long orig_ret_vaddr; 1549842ceaeSPratyush Anand 1559842ceaeSPratyush Anand orig_ret_vaddr = procedure_link_pointer(regs); 1569842ceaeSPratyush Anand /* Replace the return addr with trampoline addr */ 1579842ceaeSPratyush Anand procedure_link_pointer_set(regs, trampoline_vaddr); 1589842ceaeSPratyush Anand 1599842ceaeSPratyush Anand return orig_ret_vaddr; 1609842ceaeSPratyush Anand } 1619842ceaeSPratyush Anand 1629842ceaeSPratyush Anand int arch_uprobe_exception_notify(struct notifier_block *self, 1639842ceaeSPratyush Anand unsigned long val, void *data) 1649842ceaeSPratyush Anand { 1659842ceaeSPratyush Anand return NOTIFY_DONE; 1669842ceaeSPratyush Anand } 1679842ceaeSPratyush Anand 1689842ceaeSPratyush Anand static int uprobe_breakpoint_handler(struct pt_regs *regs, 169*8d56e5c5SAlexandru Elisei unsigned long esr) 1709842ceaeSPratyush Anand { 171fb610f2aSWill Deacon if (uprobe_pre_sstep_notifier(regs)) 1729842ceaeSPratyush Anand return DBG_HOOK_HANDLED; 1739842ceaeSPratyush Anand 1749842ceaeSPratyush Anand return DBG_HOOK_ERROR; 1759842ceaeSPratyush Anand } 1769842ceaeSPratyush Anand 1779842ceaeSPratyush Anand static int uprobe_single_step_handler(struct pt_regs *regs, 178*8d56e5c5SAlexandru Elisei unsigned long esr) 1799842ceaeSPratyush Anand { 1809842ceaeSPratyush Anand struct uprobe_task *utask = current->utask; 1819842ceaeSPratyush Anand 182fb610f2aSWill Deacon WARN_ON(utask && (instruction_pointer(regs) != utask->xol_vaddr + 4)); 1839842ceaeSPratyush Anand if (uprobe_post_sstep_notifier(regs)) 1849842ceaeSPratyush Anand return DBG_HOOK_HANDLED; 1859842ceaeSPratyush Anand 1869842ceaeSPratyush Anand return DBG_HOOK_ERROR; 1879842ceaeSPratyush Anand } 1889842ceaeSPratyush Anand 1899842ceaeSPratyush Anand /* uprobe breakpoint handler hook */ 1909842ceaeSPratyush Anand static struct break_hook uprobes_break_hook = { 191453b7740SWill Deacon .imm = UPROBES_BRK_IMM, 1929842ceaeSPratyush Anand .fn = uprobe_breakpoint_handler, 1939842ceaeSPratyush Anand }; 1949842ceaeSPratyush Anand 1959842ceaeSPratyush Anand /* uprobe single step handler hook */ 1969842ceaeSPratyush Anand static struct step_hook uprobes_step_hook = { 1979842ceaeSPratyush Anand .fn = uprobe_single_step_handler, 1989842ceaeSPratyush Anand }; 1999842ceaeSPratyush Anand 2009842ceaeSPratyush Anand static int __init arch_init_uprobes(void) 2019842ceaeSPratyush Anand { 20226a04d84SWill Deacon register_user_break_hook(&uprobes_break_hook); 20326a04d84SWill Deacon register_user_step_hook(&uprobes_step_hook); 2049842ceaeSPratyush Anand 2059842ceaeSPratyush Anand return 0; 2069842ceaeSPratyush Anand } 2079842ceaeSPratyush Anand 2089842ceaeSPratyush Anand device_initcall(arch_init_uprobes); 209