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
arch_uprobe_copy_ixol(struct page * page,unsigned long vaddr,void * src,unsigned long len)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
uprobe_get_swbp_addr(struct pt_regs * regs)299842ceaeSPratyush Anand unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
309842ceaeSPratyush Anand {
319842ceaeSPratyush Anand return instruction_pointer(regs);
329842ceaeSPratyush Anand }
339842ceaeSPratyush Anand
arch_uprobe_analyze_insn(struct arch_uprobe * auprobe,struct mm_struct * mm,unsigned long addr)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
45*8165bf83SMark Rutland insn = le32_to_cpu(auprobe->insn);
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
arch_uprobe_pre_xol(struct arch_uprobe * auprobe,struct pt_regs * regs)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
arch_uprobe_post_xol(struct arch_uprobe * auprobe,struct pt_regs * regs)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 }
arch_uprobe_xol_was_trapped(struct task_struct * t)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
arch_uprobe_skip_sstep(struct arch_uprobe * auprobe,struct pt_regs * regs)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
111*8165bf83SMark Rutland insn = le32_to_cpu(auprobe->insn);
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
arch_uprobe_abort_xol(struct arch_uprobe * auprobe,struct pt_regs * regs)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
arch_uretprobe_is_alive(struct return_instance * ret,enum rp_check ctx,struct pt_regs * regs)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
arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,struct pt_regs * regs)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
arch_uprobe_exception_notify(struct notifier_block * self,unsigned long val,void * data)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
uprobe_breakpoint_handler(struct pt_regs * regs,unsigned long esr)1689842ceaeSPratyush Anand static int uprobe_breakpoint_handler(struct pt_regs *regs,
1698d56e5c5SAlexandru 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
uprobe_single_step_handler(struct pt_regs * regs,unsigned long esr)1779842ceaeSPratyush Anand static int uprobe_single_step_handler(struct pt_regs *regs,
1788d56e5c5SAlexandru 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
arch_init_uprobes(void)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