xref: /linux/arch/parisc/kernel/kprobes.c (revision 59a783dbc0d5fd6792aabff933055373b6dcbf2a)
18858ac8eSSven Schnelle // SPDX-License-Identifier: GPL-2.0
28858ac8eSSven Schnelle /*
38858ac8eSSven Schnelle  * arch/parisc/kernel/kprobes.c
48858ac8eSSven Schnelle  *
58858ac8eSSven Schnelle  * PA-RISC kprobes implementation
68858ac8eSSven Schnelle  *
78858ac8eSSven Schnelle  * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
88858ac8eSSven Schnelle  */
98858ac8eSSven Schnelle 
108858ac8eSSven Schnelle #include <linux/types.h>
118858ac8eSSven Schnelle #include <linux/kprobes.h>
128858ac8eSSven Schnelle #include <linux/slab.h>
138858ac8eSSven Schnelle #include <asm/cacheflush.h>
148858ac8eSSven Schnelle #include <asm/patch.h>
158858ac8eSSven Schnelle 
168858ac8eSSven Schnelle DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
178858ac8eSSven Schnelle DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
188858ac8eSSven Schnelle 
198858ac8eSSven Schnelle int __kprobes arch_prepare_kprobe(struct kprobe *p)
208858ac8eSSven Schnelle {
218858ac8eSSven Schnelle 	if ((unsigned long)p->addr & 3UL)
228858ac8eSSven Schnelle 		return -EINVAL;
238858ac8eSSven Schnelle 
248858ac8eSSven Schnelle 	p->ainsn.insn = get_insn_slot();
258858ac8eSSven Schnelle 	if (!p->ainsn.insn)
268858ac8eSSven Schnelle 		return -ENOMEM;
278858ac8eSSven Schnelle 
288858ac8eSSven Schnelle 	memcpy(p->ainsn.insn, p->addr,
298858ac8eSSven Schnelle 		MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
308858ac8eSSven Schnelle 	p->opcode = *p->addr;
318858ac8eSSven Schnelle 	flush_insn_slot(p);
328858ac8eSSven Schnelle 	return 0;
338858ac8eSSven Schnelle }
348858ac8eSSven Schnelle 
358858ac8eSSven Schnelle void __kprobes arch_remove_kprobe(struct kprobe *p)
368858ac8eSSven Schnelle {
378858ac8eSSven Schnelle 	if (!p->ainsn.insn)
388858ac8eSSven Schnelle 		return;
398858ac8eSSven Schnelle 
408858ac8eSSven Schnelle 	free_insn_slot(p->ainsn.insn, 0);
418858ac8eSSven Schnelle 	p->ainsn.insn = NULL;
428858ac8eSSven Schnelle }
438858ac8eSSven Schnelle 
448858ac8eSSven Schnelle void __kprobes arch_arm_kprobe(struct kprobe *p)
458858ac8eSSven Schnelle {
468858ac8eSSven Schnelle 	patch_text(p->addr, PARISC_KPROBES_BREAK_INSN);
478858ac8eSSven Schnelle }
488858ac8eSSven Schnelle 
498858ac8eSSven Schnelle void __kprobes arch_disarm_kprobe(struct kprobe *p)
508858ac8eSSven Schnelle {
518858ac8eSSven Schnelle 	patch_text(p->addr, p->opcode);
528858ac8eSSven Schnelle }
538858ac8eSSven Schnelle 
548858ac8eSSven Schnelle static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
558858ac8eSSven Schnelle {
568858ac8eSSven Schnelle 	kcb->prev_kprobe.kp = kprobe_running();
578858ac8eSSven Schnelle 	kcb->prev_kprobe.status = kcb->kprobe_status;
588858ac8eSSven Schnelle }
598858ac8eSSven Schnelle 
608858ac8eSSven Schnelle static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
618858ac8eSSven Schnelle {
628858ac8eSSven Schnelle 	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
638858ac8eSSven Schnelle 	kcb->kprobe_status = kcb->prev_kprobe.status;
648858ac8eSSven Schnelle }
658858ac8eSSven Schnelle 
668858ac8eSSven Schnelle static inline void __kprobes set_current_kprobe(struct kprobe *p)
678858ac8eSSven Schnelle {
688858ac8eSSven Schnelle 	__this_cpu_write(current_kprobe, p);
698858ac8eSSven Schnelle }
708858ac8eSSven Schnelle 
718858ac8eSSven Schnelle static void __kprobes setup_singlestep(struct kprobe *p,
728858ac8eSSven Schnelle 		struct kprobe_ctlblk *kcb, struct pt_regs *regs)
738858ac8eSSven Schnelle {
748858ac8eSSven Schnelle 	kcb->iaoq[0] = regs->iaoq[0];
758858ac8eSSven Schnelle 	kcb->iaoq[1] = regs->iaoq[1];
768858ac8eSSven Schnelle 	regs->iaoq[0] = (unsigned long)p->ainsn.insn;
778858ac8eSSven Schnelle 	mtctl(0, 0);
788858ac8eSSven Schnelle 	regs->gr[0] |= PSW_R;
798858ac8eSSven Schnelle }
808858ac8eSSven Schnelle 
818858ac8eSSven Schnelle int __kprobes parisc_kprobe_break_handler(struct pt_regs *regs)
828858ac8eSSven Schnelle {
838858ac8eSSven Schnelle 	struct kprobe *p;
848858ac8eSSven Schnelle 	struct kprobe_ctlblk *kcb;
858858ac8eSSven Schnelle 
868858ac8eSSven Schnelle 	preempt_disable();
878858ac8eSSven Schnelle 
888858ac8eSSven Schnelle 	kcb = get_kprobe_ctlblk();
898858ac8eSSven Schnelle 	p = get_kprobe((unsigned long *)regs->iaoq[0]);
908858ac8eSSven Schnelle 
918858ac8eSSven Schnelle 	if (!p) {
928858ac8eSSven Schnelle 		preempt_enable_no_resched();
938858ac8eSSven Schnelle 		return 0;
948858ac8eSSven Schnelle 	}
958858ac8eSSven Schnelle 
968858ac8eSSven Schnelle 	if (kprobe_running()) {
978858ac8eSSven Schnelle 		/*
988858ac8eSSven Schnelle 		 * We have reentered the kprobe_handler, since another kprobe
998858ac8eSSven Schnelle 		 * was hit while within the handler, we save the original
1008858ac8eSSven Schnelle 		 * kprobes and single step on the instruction of the new probe
1018858ac8eSSven Schnelle 		 * without calling any user handlers to avoid recursive
1028858ac8eSSven Schnelle 		 * kprobes.
1038858ac8eSSven Schnelle 		 */
1048858ac8eSSven Schnelle 		save_previous_kprobe(kcb);
1058858ac8eSSven Schnelle 		set_current_kprobe(p);
1068858ac8eSSven Schnelle 		kprobes_inc_nmissed_count(p);
1078858ac8eSSven Schnelle 		setup_singlestep(p, kcb, regs);
1088858ac8eSSven Schnelle 		kcb->kprobe_status = KPROBE_REENTER;
1098858ac8eSSven Schnelle 		return 1;
1108858ac8eSSven Schnelle 	}
1118858ac8eSSven Schnelle 
1128858ac8eSSven Schnelle 	set_current_kprobe(p);
1138858ac8eSSven Schnelle 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
1148858ac8eSSven Schnelle 
1158858ac8eSSven Schnelle 	/* If we have no pre-handler or it returned 0, we continue with
1168858ac8eSSven Schnelle 	 * normal processing. If we have a pre-handler and it returned
1178858ac8eSSven Schnelle 	 * non-zero - which means user handler setup registers to exit
1188858ac8eSSven Schnelle 	 * to another instruction, we must skip the single stepping.
1198858ac8eSSven Schnelle 	 */
1208858ac8eSSven Schnelle 
1218858ac8eSSven Schnelle 	if (!p->pre_handler || !p->pre_handler(p, regs)) {
1228858ac8eSSven Schnelle 		setup_singlestep(p, kcb, regs);
1238858ac8eSSven Schnelle 		kcb->kprobe_status = KPROBE_HIT_SS;
1248858ac8eSSven Schnelle 	} else {
1258858ac8eSSven Schnelle 		reset_current_kprobe();
1268858ac8eSSven Schnelle 		preempt_enable_no_resched();
1278858ac8eSSven Schnelle 	}
1288858ac8eSSven Schnelle 	return 1;
1298858ac8eSSven Schnelle }
1308858ac8eSSven Schnelle 
1318858ac8eSSven Schnelle int __kprobes parisc_kprobe_ss_handler(struct pt_regs *regs)
1328858ac8eSSven Schnelle {
1338858ac8eSSven Schnelle 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
1348858ac8eSSven Schnelle 	struct kprobe *p = kprobe_running();
1358858ac8eSSven Schnelle 
136*59a783dbSHelge Deller 	if (!p)
137*59a783dbSHelge Deller 		return 0;
138*59a783dbSHelge Deller 
1398858ac8eSSven Schnelle 	if (regs->iaoq[0] != (unsigned long)p->ainsn.insn+4)
1408858ac8eSSven Schnelle 		return 0;
1418858ac8eSSven Schnelle 
1428858ac8eSSven Schnelle 	/* restore back original saved kprobe variables and continue */
1438858ac8eSSven Schnelle 	if (kcb->kprobe_status == KPROBE_REENTER) {
1448858ac8eSSven Schnelle 		restore_previous_kprobe(kcb);
1458858ac8eSSven Schnelle 		return 1;
1468858ac8eSSven Schnelle 	}
1478858ac8eSSven Schnelle 
1488858ac8eSSven Schnelle 	/* for absolute branch instructions we can copy iaoq_b. for relative
1498858ac8eSSven Schnelle 	 * branch instructions we need to calculate the new address based on the
1508858ac8eSSven Schnelle 	 * difference between iaoq_f and iaoq_b. We cannot use iaoq_b without
1518858ac8eSSven Schnelle 	 * modificationt because it's based on our ainsn.insn address.
1528858ac8eSSven Schnelle 	 */
1538858ac8eSSven Schnelle 
1548858ac8eSSven Schnelle 	if (p->post_handler)
1558858ac8eSSven Schnelle 		p->post_handler(p, regs, 0);
1568858ac8eSSven Schnelle 
1578858ac8eSSven Schnelle 	switch (regs->iir >> 26) {
1588858ac8eSSven Schnelle 	case 0x38: /* BE */
1598858ac8eSSven Schnelle 	case 0x39: /* BE,L */
1608858ac8eSSven Schnelle 	case 0x3a: /* BV */
1618858ac8eSSven Schnelle 	case 0x3b: /* BVE */
1628858ac8eSSven Schnelle 		/* for absolute branches, regs->iaoq[1] has already the right
1638858ac8eSSven Schnelle 		 * address
1648858ac8eSSven Schnelle 		 */
1658858ac8eSSven Schnelle 		regs->iaoq[0] = kcb->iaoq[1];
1668858ac8eSSven Schnelle 		break;
1678858ac8eSSven Schnelle 	default:
1688858ac8eSSven Schnelle 		regs->iaoq[1] = kcb->iaoq[0];
1698858ac8eSSven Schnelle 		regs->iaoq[1] += (regs->iaoq[1] - regs->iaoq[0]) + 4;
1708858ac8eSSven Schnelle 		regs->iaoq[0] = kcb->iaoq[1];
1718858ac8eSSven Schnelle 		break;
1728858ac8eSSven Schnelle 	}
1738858ac8eSSven Schnelle 	kcb->kprobe_status = KPROBE_HIT_SSDONE;
1748858ac8eSSven Schnelle 	reset_current_kprobe();
1758858ac8eSSven Schnelle 	return 1;
1768858ac8eSSven Schnelle }
1778858ac8eSSven Schnelle 
178e0b59b7bSSven Schnelle static inline void kretprobe_trampoline(void)
179e0b59b7bSSven Schnelle {
180e0b59b7bSSven Schnelle 	asm volatile("nop");
181e0b59b7bSSven Schnelle 	asm volatile("nop");
182e0b59b7bSSven Schnelle }
183e0b59b7bSSven Schnelle 
184e0b59b7bSSven Schnelle static int __kprobes trampoline_probe_handler(struct kprobe *p,
185e0b59b7bSSven Schnelle 					      struct pt_regs *regs);
186e0b59b7bSSven Schnelle 
187e0b59b7bSSven Schnelle static struct kprobe trampoline_p = {
188e0b59b7bSSven Schnelle 	.pre_handler = trampoline_probe_handler
189e0b59b7bSSven Schnelle };
190e0b59b7bSSven Schnelle 
191e0b59b7bSSven Schnelle static int __kprobes trampoline_probe_handler(struct kprobe *p,
192e0b59b7bSSven Schnelle 					      struct pt_regs *regs)
193e0b59b7bSSven Schnelle {
194e0b59b7bSSven Schnelle 	struct kretprobe_instance *ri = NULL;
195e0b59b7bSSven Schnelle 	struct hlist_head *head, empty_rp;
196e0b59b7bSSven Schnelle 	struct hlist_node *tmp;
197e0b59b7bSSven Schnelle 	unsigned long flags, orig_ret_address = 0;
198e0b59b7bSSven Schnelle 	unsigned long trampoline_address = (unsigned long)trampoline_p.addr;
199e0b59b7bSSven Schnelle 	kprobe_opcode_t *correct_ret_addr = NULL;
200e0b59b7bSSven Schnelle 
201e0b59b7bSSven Schnelle 	INIT_HLIST_HEAD(&empty_rp);
202e0b59b7bSSven Schnelle 	kretprobe_hash_lock(current, &head, &flags);
203e0b59b7bSSven Schnelle 
204e0b59b7bSSven Schnelle 	/*
205e0b59b7bSSven Schnelle 	 * It is possible to have multiple instances associated with a given
206e0b59b7bSSven Schnelle 	 * task either because multiple functions in the call path have
207e0b59b7bSSven Schnelle 	 * a return probe installed on them, and/or more than one return
208e0b59b7bSSven Schnelle 	 * probe was registered for a target function.
209e0b59b7bSSven Schnelle 	 *
210e0b59b7bSSven Schnelle 	 * We can handle this because:
211e0b59b7bSSven Schnelle 	 *     - instances are always inserted at the head of the list
212e0b59b7bSSven Schnelle 	 *     - when multiple return probes are registered for the same
213e0b59b7bSSven Schnelle 	 *       function, the first instance's ret_addr will point to the
214e0b59b7bSSven Schnelle 	 *       real return address, and all the rest will point to
215e0b59b7bSSven Schnelle 	 *       kretprobe_trampoline
216e0b59b7bSSven Schnelle 	 */
217e0b59b7bSSven Schnelle 	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
218e0b59b7bSSven Schnelle 		if (ri->task != current)
219e0b59b7bSSven Schnelle 			/* another task is sharing our hash bucket */
220e0b59b7bSSven Schnelle 			continue;
221e0b59b7bSSven Schnelle 
222e0b59b7bSSven Schnelle 		orig_ret_address = (unsigned long)ri->ret_addr;
223e0b59b7bSSven Schnelle 
224e0b59b7bSSven Schnelle 		if (orig_ret_address != trampoline_address)
225e0b59b7bSSven Schnelle 			/*
226e0b59b7bSSven Schnelle 			 * This is the real return address. Any other
227e0b59b7bSSven Schnelle 			 * instances associated with this task are for
228e0b59b7bSSven Schnelle 			 * other calls deeper on the call stack
229e0b59b7bSSven Schnelle 			 */
230e0b59b7bSSven Schnelle 			break;
231e0b59b7bSSven Schnelle 	}
232e0b59b7bSSven Schnelle 
233e0b59b7bSSven Schnelle 	kretprobe_assert(ri, orig_ret_address, trampoline_address);
234e0b59b7bSSven Schnelle 
235e0b59b7bSSven Schnelle 	correct_ret_addr = ri->ret_addr;
236e0b59b7bSSven Schnelle 	hlist_for_each_entry_safe(ri, tmp, head, hlist) {
237e0b59b7bSSven Schnelle 		if (ri->task != current)
238e0b59b7bSSven Schnelle 			/* another task is sharing our hash bucket */
239e0b59b7bSSven Schnelle 			continue;
240e0b59b7bSSven Schnelle 
241e0b59b7bSSven Schnelle 		orig_ret_address = (unsigned long)ri->ret_addr;
242e0b59b7bSSven Schnelle 		if (ri->rp && ri->rp->handler) {
243e0b59b7bSSven Schnelle 			__this_cpu_write(current_kprobe, &ri->rp->kp);
244e0b59b7bSSven Schnelle 			get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
245e0b59b7bSSven Schnelle 			ri->ret_addr = correct_ret_addr;
246e0b59b7bSSven Schnelle 			ri->rp->handler(ri, regs);
247e0b59b7bSSven Schnelle 			__this_cpu_write(current_kprobe, NULL);
248e0b59b7bSSven Schnelle 		}
249e0b59b7bSSven Schnelle 
250e0b59b7bSSven Schnelle 		recycle_rp_inst(ri, &empty_rp);
251e0b59b7bSSven Schnelle 
252e0b59b7bSSven Schnelle 		if (orig_ret_address != trampoline_address)
253e0b59b7bSSven Schnelle 			/*
254e0b59b7bSSven Schnelle 			 * This is the real return address. Any other
255e0b59b7bSSven Schnelle 			 * instances associated with this task are for
256e0b59b7bSSven Schnelle 			 * other calls deeper on the call stack
257e0b59b7bSSven Schnelle 			 */
258e0b59b7bSSven Schnelle 			break;
259e0b59b7bSSven Schnelle 	}
260e0b59b7bSSven Schnelle 
261e0b59b7bSSven Schnelle 	kretprobe_hash_unlock(current, &flags);
262e0b59b7bSSven Schnelle 
263e0b59b7bSSven Schnelle 	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
264e0b59b7bSSven Schnelle 		hlist_del(&ri->hlist);
265e0b59b7bSSven Schnelle 		kfree(ri);
266e0b59b7bSSven Schnelle 	}
267e0b59b7bSSven Schnelle 	instruction_pointer_set(regs, orig_ret_address);
268e0b59b7bSSven Schnelle 	return 1;
269e0b59b7bSSven Schnelle }
270e0b59b7bSSven Schnelle 
271e0b59b7bSSven Schnelle void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
272e0b59b7bSSven Schnelle 				      struct pt_regs *regs)
273e0b59b7bSSven Schnelle {
274e0b59b7bSSven Schnelle 	ri->ret_addr = (kprobe_opcode_t *)regs->gr[2];
275e0b59b7bSSven Schnelle 
276e0b59b7bSSven Schnelle 	/* Replace the return addr with trampoline addr. */
277e0b59b7bSSven Schnelle 	regs->gr[2] = (unsigned long)trampoline_p.addr;
278e0b59b7bSSven Schnelle }
279e0b59b7bSSven Schnelle 
280e0b59b7bSSven Schnelle int __kprobes arch_trampoline_kprobe(struct kprobe *p)
281e0b59b7bSSven Schnelle {
282e0b59b7bSSven Schnelle 	return p->addr == trampoline_p.addr;
283e0b59b7bSSven Schnelle }
2848858ac8eSSven Schnelle bool arch_kprobe_on_func_entry(unsigned long offset)
2858858ac8eSSven Schnelle {
2868858ac8eSSven Schnelle 	return !offset;
2878858ac8eSSven Schnelle }
2888858ac8eSSven Schnelle 
2898858ac8eSSven Schnelle int __init arch_init_kprobes(void)
2908858ac8eSSven Schnelle {
291e0b59b7bSSven Schnelle 	trampoline_p.addr = (kprobe_opcode_t *)
292e0b59b7bSSven Schnelle 		dereference_function_descriptor(kretprobe_trampoline);
293e0b59b7bSSven Schnelle 	return register_kprobe(&trampoline_p);
2948858ac8eSSven Schnelle }
295