xref: /linux/arch/arm/probes/kprobes/actions-arm.c (revision 8c994eff8fcfe8ecb1f1dbebed25b4d7bb75be12)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * arch/arm/probes/kprobes/actions-arm.c
4  *
5  * Copyright (C) 2006, 2007 Motorola Inc.
6  */
7 
8 /*
9  * We do not have hardware single-stepping on ARM, This
10  * effort is further complicated by the ARM not having a
11  * "next PC" register.  Instructions that change the PC
12  * can't be safely single-stepped in a MP environment, so
13  * we have a lot of work to do:
14  *
15  * In the prepare phase:
16  *   *) If it is an instruction that does anything
17  *      with the CPU mode, we reject it for a kprobe.
18  *      (This is out of laziness rather than need.  The
19  *      instructions could be simulated.)
20  *
21  *   *) Otherwise, decode the instruction rewriting its
22  *      registers to take fixed, ordered registers and
23  *      setting a handler for it to run the instruction.
24  *
25  * In the execution phase by an instruction's handler:
26  *
27  *   *) If the PC is written to by the instruction, the
28  *      instruction must be fully simulated in software.
29  *
30  *   *) Otherwise, a modified form of the instruction is
31  *      directly executed.  Its handler calls the
32  *      instruction in insn[0].  In insn[1] is a
33  *      "mov pc, lr" to return.
34  *
35  *      Before calling, load up the reordered registers
36  *      from the original instruction's registers.  If one
37  *      of the original input registers is the PC, compute
38  *      and adjust the appropriate input register.
39  *
40  *	After call completes, copy the output registers to
41  *      the original instruction's original registers.
42  *
43  * We don't use a real breakpoint instruction since that
44  * would have us in the kernel go from SVC mode to SVC
45  * mode losing the link register.  Instead we use an
46  * undefined instruction.  To simplify processing, the
47  * undefined instruction used for kprobes must be reserved
48  * exclusively for kprobes use.
49  *
50  * TODO: ifdef out some instruction decoding based on architecture.
51  */
52 
53 #include <linux/kernel.h>
54 #include <linux/kprobes.h>
55 #include <linux/ptrace.h>
56 
57 #include "../decode-arm.h"
58 #include "core.h"
59 #include "checkers.h"
60 
61 #if  __LINUX_ARM_ARCH__ >= 6
62 #define BLX(reg)	"blx	"reg"		\n\t"
63 #else
64 #define BLX(reg)	"mov	lr, pc		\n\t"	\
65 			"mov	pc, "reg"	\n\t"
66 #endif
67 
68 static void __kprobes
69 emulate_ldrdstrd(probes_opcode_t insn,
70 	struct arch_probes_insn *asi, struct pt_regs *regs)
71 {
72 	unsigned long pc = regs->ARM_pc + 4;
73 	int rt = (insn >> 12) & 0xf;
74 	int rn = (insn >> 16) & 0xf;
75 	int rm = insn & 0xf;
76 
77 	register unsigned long rtv asm("r0") = regs->uregs[rt];
78 	register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
79 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
80 							  : regs->uregs[rn];
81 	register unsigned long rmv asm("r3") = regs->uregs[rm];
82 
83 	__asm__ __volatile__ (
84 		BLX("%[fn]")
85 		: "=r" (rtv), "=r" (rt2v), "=r" (rnv)
86 		: "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
87 		  [fn] "r" (asi->insn_fn)
88 		: "lr", "memory", "cc"
89 	);
90 
91 	regs->uregs[rt] = rtv;
92 	regs->uregs[rt+1] = rt2v;
93 	if (is_writeback(insn))
94 		regs->uregs[rn] = rnv;
95 }
96 
97 static void __kprobes
98 emulate_ldr(probes_opcode_t insn,
99 	struct arch_probes_insn *asi, struct pt_regs *regs)
100 {
101 	unsigned long pc = regs->ARM_pc + 4;
102 	int rt = (insn >> 12) & 0xf;
103 	int rn = (insn >> 16) & 0xf;
104 	int rm = insn & 0xf;
105 
106 	register unsigned long rtv asm("r0");
107 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
108 							  : regs->uregs[rn];
109 	register unsigned long rmv asm("r3") = regs->uregs[rm];
110 
111 	__asm__ __volatile__ (
112 		BLX("%[fn]")
113 		: "=r" (rtv), "=r" (rnv)
114 		: "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
115 		: "lr", "memory", "cc"
116 	);
117 
118 	if (rt == 15)
119 		load_write_pc(rtv, regs);
120 	else
121 		regs->uregs[rt] = rtv;
122 
123 	if (is_writeback(insn))
124 		regs->uregs[rn] = rnv;
125 }
126 
127 static void __kprobes
128 emulate_str(probes_opcode_t insn,
129 	struct arch_probes_insn *asi, struct pt_regs *regs)
130 {
131 	unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
132 	unsigned long rnpc = regs->ARM_pc + 4;
133 	int rt = (insn >> 12) & 0xf;
134 	int rn = (insn >> 16) & 0xf;
135 	int rm = insn & 0xf;
136 
137 	register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
138 							  : regs->uregs[rt];
139 	register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
140 							  : regs->uregs[rn];
141 	register unsigned long rmv asm("r3") = regs->uregs[rm];
142 
143 	__asm__ __volatile__ (
144 		BLX("%[fn]")
145 		: "=r" (rnv)
146 		: "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
147 		: "lr", "memory", "cc"
148 	);
149 
150 	if (is_writeback(insn))
151 		regs->uregs[rn] = rnv;
152 }
153 
154 static void __kprobes
155 emulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
156 	struct arch_probes_insn *asi, struct pt_regs *regs)
157 {
158 	unsigned long pc = regs->ARM_pc + 4;
159 	int rd = (insn >> 12) & 0xf;
160 	int rn = (insn >> 16) & 0xf;
161 	int rm = insn & 0xf;
162 	int rs = (insn >> 8) & 0xf;
163 
164 	register unsigned long rdv asm("r0") = regs->uregs[rd];
165 	register unsigned long rnv asm("r2") = (rn == 15) ? pc
166 							  : regs->uregs[rn];
167 	register unsigned long rmv asm("r3") = (rm == 15) ? pc
168 							  : regs->uregs[rm];
169 	register unsigned long rsv asm("r1") = regs->uregs[rs];
170 	unsigned long cpsr = regs->ARM_cpsr;
171 
172 	__asm__ __volatile__ (
173 		"msr	cpsr_fs, %[cpsr]	\n\t"
174 		BLX("%[fn]")
175 		"mrs	%[cpsr], cpsr		\n\t"
176 		: "=r" (rdv), [cpsr] "=r" (cpsr)
177 		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
178 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
179 		: "lr", "memory", "cc"
180 	);
181 
182 	if (rd == 15)
183 		alu_write_pc(rdv, regs);
184 	else
185 		regs->uregs[rd] = rdv;
186 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
187 }
188 
189 static void __kprobes
190 emulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
191 	struct arch_probes_insn *asi, struct pt_regs *regs)
192 {
193 	int rd = (insn >> 12) & 0xf;
194 	int rn = (insn >> 16) & 0xf;
195 	int rm = insn & 0xf;
196 
197 	register unsigned long rdv asm("r0") = regs->uregs[rd];
198 	register unsigned long rnv asm("r2") = regs->uregs[rn];
199 	register unsigned long rmv asm("r3") = regs->uregs[rm];
200 	unsigned long cpsr = regs->ARM_cpsr;
201 
202 	__asm__ __volatile__ (
203 		"msr	cpsr_fs, %[cpsr]	\n\t"
204 		BLX("%[fn]")
205 		"mrs	%[cpsr], cpsr		\n\t"
206 		: "=r" (rdv), [cpsr] "=r" (cpsr)
207 		: "0" (rdv), "r" (rnv), "r" (rmv),
208 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
209 		: "lr", "memory", "cc"
210 	);
211 
212 	regs->uregs[rd] = rdv;
213 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
214 }
215 
216 static void __kprobes
217 emulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
218 	struct arch_probes_insn *asi,
219 	struct pt_regs *regs)
220 {
221 	int rd = (insn >> 16) & 0xf;
222 	int rn = (insn >> 12) & 0xf;
223 	int rm = insn & 0xf;
224 	int rs = (insn >> 8) & 0xf;
225 
226 	register unsigned long rdv asm("r2") = regs->uregs[rd];
227 	register unsigned long rnv asm("r0") = regs->uregs[rn];
228 	register unsigned long rmv asm("r3") = regs->uregs[rm];
229 	register unsigned long rsv asm("r1") = regs->uregs[rs];
230 	unsigned long cpsr = regs->ARM_cpsr;
231 
232 	__asm__ __volatile__ (
233 		"msr	cpsr_fs, %[cpsr]	\n\t"
234 		BLX("%[fn]")
235 		"mrs	%[cpsr], cpsr		\n\t"
236 		: "=r" (rdv), [cpsr] "=r" (cpsr)
237 		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
238 		  "1" (cpsr), [fn] "r" (asi->insn_fn)
239 		: "lr", "memory", "cc"
240 	);
241 
242 	regs->uregs[rd] = rdv;
243 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
244 }
245 
246 static void __kprobes
247 emulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
248 	struct arch_probes_insn *asi, struct pt_regs *regs)
249 {
250 	int rd = (insn >> 12) & 0xf;
251 	int rm = insn & 0xf;
252 
253 	register unsigned long rdv asm("r0") = regs->uregs[rd];
254 	register unsigned long rmv asm("r3") = regs->uregs[rm];
255 
256 	__asm__ __volatile__ (
257 		BLX("%[fn]")
258 		: "=r" (rdv)
259 		: "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
260 		: "lr", "memory", "cc"
261 	);
262 
263 	regs->uregs[rd] = rdv;
264 }
265 
266 static void __kprobes
267 emulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
268 	struct arch_probes_insn *asi,
269 	struct pt_regs *regs)
270 {
271 	int rdlo = (insn >> 12) & 0xf;
272 	int rdhi = (insn >> 16) & 0xf;
273 	int rn = insn & 0xf;
274 	int rm = (insn >> 8) & 0xf;
275 
276 	register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
277 	register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
278 	register unsigned long rnv asm("r3") = regs->uregs[rn];
279 	register unsigned long rmv asm("r1") = regs->uregs[rm];
280 	unsigned long cpsr = regs->ARM_cpsr;
281 
282 	__asm__ __volatile__ (
283 		"msr	cpsr_fs, %[cpsr]	\n\t"
284 		BLX("%[fn]")
285 		"mrs	%[cpsr], cpsr		\n\t"
286 		: "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
287 		: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
288 		  "2" (cpsr), [fn] "r" (asi->insn_fn)
289 		: "lr", "memory", "cc"
290 	);
291 
292 	regs->uregs[rdlo] = rdlov;
293 	regs->uregs[rdhi] = rdhiv;
294 	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
295 }
296 
297 const union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
298 	[PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
299 	[PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
300 	[PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
301 	[PROBES_MRS] = {.handler = simulate_mrs},
302 	[PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
303 	[PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc},
304 	[PROBES_SATURATING_ARITHMETIC] = {
305 		.handler = emulate_rd12rn16rm0_rwflags_nopc},
306 	[PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
307 	[PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
308 	[PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
309 	[PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd},
310 	[PROBES_LOAD_EXTRA] = {.handler = emulate_ldr},
311 	[PROBES_LOAD] = {.handler = emulate_ldr},
312 	[PROBES_STORE_EXTRA] = {.handler = emulate_str},
313 	[PROBES_STORE] = {.handler = emulate_str},
314 	[PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
315 	[PROBES_DATA_PROCESSING_REG] = {
316 		.handler = emulate_rd12rn16rm0rs8_rwflags},
317 	[PROBES_DATA_PROCESSING_IMM] = {
318 		.handler = emulate_rd12rn16rm0rs8_rwflags},
319 	[PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
320 	[PROBES_SEV] = {.handler = probes_emulate_none},
321 	[PROBES_WFE] = {.handler = probes_simulate_nop},
322 	[PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
323 	[PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
324 	[PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
325 	[PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
326 	[PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc},
327 	[PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
328 	[PROBES_MUL_ADD_LONG] = {
329 		.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
330 	[PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
331 	[PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc},
332 	[PROBES_BRANCH] = {.handler = simulate_bbl},
333 	[PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
334 };
335 
336 const struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL};
337