1 /*
2  * Copyright (C) 2014-2016 Pratyush Anand <panand@redhat.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8 #include <linux/highmem.h>
9 #include <linux/ptrace.h>
10 #include <linux/uprobes.h>
11 #include <asm/cacheflush.h>
12 
13 #include "decode-insn.h"
14 
15 #define UPROBE_INV_FAULT_CODE	UINT_MAX
16 
arch_uprobe_copy_ixol(struct page * page,unsigned long vaddr,void * src,unsigned long len)17 void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
18 		void *src, unsigned long len)
19 {
20 	void *xol_page_kaddr = kmap_atomic(page);
21 	void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK);
22 
23 	/* Initialize the slot */
24 	memcpy(dst, src, len);
25 
26 	/* flush caches (dcache/icache) */
27 	sync_icache_aliases(dst, len);
28 
29 	kunmap_atomic(xol_page_kaddr);
30 }
31 
uprobe_get_swbp_addr(struct pt_regs * regs)32 unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
33 {
34 	return instruction_pointer(regs);
35 }
36 
arch_uprobe_analyze_insn(struct arch_uprobe * auprobe,struct mm_struct * mm,unsigned long addr)37 int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
38 		unsigned long addr)
39 {
40 	probe_opcode_t insn;
41 
42 	/* TODO: Currently we do not support AARCH32 instruction probing */
43 	if (mm->context.flags & MMCF_AARCH32)
44 		return -ENOTSUPP;
45 	else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE))
46 		return -EINVAL;
47 
48 	insn = *(probe_opcode_t *)(&auprobe->insn[0]);
49 
50 	switch (arm_probe_decode_insn(insn, &auprobe->api)) {
51 	case INSN_REJECTED:
52 		return -EINVAL;
53 
54 	case INSN_GOOD_NO_SLOT:
55 		auprobe->simulate = true;
56 		break;
57 
58 	default:
59 		break;
60 	}
61 
62 	return 0;
63 }
64 
arch_uprobe_pre_xol(struct arch_uprobe * auprobe,struct pt_regs * regs)65 int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
66 {
67 	struct uprobe_task *utask = current->utask;
68 
69 	/* Initialize with an invalid fault code to detect if ol insn trapped */
70 	current->thread.fault_code = UPROBE_INV_FAULT_CODE;
71 
72 	/* Instruction points to execute ol */
73 	instruction_pointer_set(regs, utask->xol_vaddr);
74 
75 	user_enable_single_step(current);
76 
77 	return 0;
78 }
79 
arch_uprobe_post_xol(struct arch_uprobe * auprobe,struct pt_regs * regs)80 int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
81 {
82 	struct uprobe_task *utask = current->utask;
83 
84 	WARN_ON_ONCE(current->thread.fault_code != UPROBE_INV_FAULT_CODE);
85 
86 	/* Instruction points to execute next to breakpoint address */
87 	instruction_pointer_set(regs, utask->vaddr + 4);
88 
89 	user_disable_single_step(current);
90 
91 	return 0;
92 }
arch_uprobe_xol_was_trapped(struct task_struct * t)93 bool arch_uprobe_xol_was_trapped(struct task_struct *t)
94 {
95 	/*
96 	 * Between arch_uprobe_pre_xol and arch_uprobe_post_xol, if an xol
97 	 * insn itself is trapped, then detect the case with the help of
98 	 * invalid fault code which is being set in arch_uprobe_pre_xol
99 	 */
100 	if (t->thread.fault_code != UPROBE_INV_FAULT_CODE)
101 		return true;
102 
103 	return false;
104 }
105 
arch_uprobe_skip_sstep(struct arch_uprobe * auprobe,struct pt_regs * regs)106 bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
107 {
108 	probe_opcode_t insn;
109 	unsigned long addr;
110 
111 	if (!auprobe->simulate)
112 		return false;
113 
114 	insn = *(probe_opcode_t *)(&auprobe->insn[0]);
115 	addr = instruction_pointer(regs);
116 
117 	if (auprobe->api.handler)
118 		auprobe->api.handler(insn, addr, regs);
119 
120 	return true;
121 }
122 
arch_uprobe_abort_xol(struct arch_uprobe * auprobe,struct pt_regs * regs)123 void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
124 {
125 	struct uprobe_task *utask = current->utask;
126 
127 	/*
128 	 * Task has received a fatal signal, so reset back to probbed
129 	 * address.
130 	 */
131 	instruction_pointer_set(regs, utask->vaddr);
132 
133 	user_disable_single_step(current);
134 }
135 
arch_uretprobe_is_alive(struct return_instance * ret,enum rp_check ctx,struct pt_regs * regs)136 bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
137 		struct pt_regs *regs)
138 {
139 	/*
140 	 * If a simple branch instruction (B) was called for retprobed
141 	 * assembly label then return true even when regs->sp and ret->stack
142 	 * are same. It will ensure that cleanup and reporting of return
143 	 * instances corresponding to callee label is done when
144 	 * handle_trampoline for called function is executed.
145 	 */
146 	if (ctx == RP_CHECK_CHAIN_CALL)
147 		return regs->sp <= ret->stack;
148 	else
149 		return regs->sp < ret->stack;
150 }
151 
152 unsigned long
arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,struct pt_regs * regs)153 arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
154 				  struct pt_regs *regs)
155 {
156 	unsigned long orig_ret_vaddr;
157 
158 	orig_ret_vaddr = procedure_link_pointer(regs);
159 	/* Replace the return addr with trampoline addr */
160 	procedure_link_pointer_set(regs, trampoline_vaddr);
161 
162 	return orig_ret_vaddr;
163 }
164 
arch_uprobe_exception_notify(struct notifier_block * self,unsigned long val,void * data)165 int arch_uprobe_exception_notify(struct notifier_block *self,
166 				 unsigned long val, void *data)
167 {
168 	return NOTIFY_DONE;
169 }
170 
uprobe_breakpoint_handler(struct pt_regs * regs,unsigned int esr)171 static int uprobe_breakpoint_handler(struct pt_regs *regs,
172 		unsigned int esr)
173 {
174 	if (user_mode(regs) && uprobe_pre_sstep_notifier(regs))
175 		return DBG_HOOK_HANDLED;
176 
177 	return DBG_HOOK_ERROR;
178 }
179 
uprobe_single_step_handler(struct pt_regs * regs,unsigned int esr)180 static int uprobe_single_step_handler(struct pt_regs *regs,
181 		unsigned int esr)
182 {
183 	struct uprobe_task *utask = current->utask;
184 
185 	if (user_mode(regs)) {
186 		WARN_ON(utask &&
187 			(instruction_pointer(regs) != utask->xol_vaddr + 4));
188 
189 		if (uprobe_post_sstep_notifier(regs))
190 			return DBG_HOOK_HANDLED;
191 	}
192 
193 	return DBG_HOOK_ERROR;
194 }
195 
196 /* uprobe breakpoint handler hook */
197 static struct break_hook uprobes_break_hook = {
198 	.esr_mask = BRK64_ESR_MASK,
199 	.esr_val = BRK64_ESR_UPROBES,
200 	.fn = uprobe_breakpoint_handler,
201 };
202 
203 /* uprobe single step handler hook */
204 static struct step_hook uprobes_step_hook = {
205 	.fn = uprobe_single_step_handler,
206 };
207 
arch_init_uprobes(void)208 static int __init arch_init_uprobes(void)
209 {
210 	register_break_hook(&uprobes_break_hook);
211 	register_step_hook(&uprobes_step_hook);
212 
213 	return 0;
214 }
215 
216 device_initcall(arch_init_uprobes);
217