cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kprobes.c (11380B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Kernel probes (kprobes) for SuperH
      4 *
      5 * Copyright (C) 2007 Chris Smith <chris.smith@st.com>
      6 * Copyright (C) 2006 Lineo Solutions, Inc.
      7 */
      8#include <linux/kprobes.h>
      9#include <linux/extable.h>
     10#include <linux/ptrace.h>
     11#include <linux/preempt.h>
     12#include <linux/kdebug.h>
     13#include <linux/slab.h>
     14#include <asm/cacheflush.h>
     15#include <linux/uaccess.h>
     16
     17DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
     18DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
     19
     20static DEFINE_PER_CPU(struct kprobe, saved_current_opcode);
     21static DEFINE_PER_CPU(struct kprobe, saved_next_opcode);
     22static DEFINE_PER_CPU(struct kprobe, saved_next_opcode2);
     23
     24#define OPCODE_JMP(x)	(((x) & 0xF0FF) == 0x402b)
     25#define OPCODE_JSR(x)	(((x) & 0xF0FF) == 0x400b)
     26#define OPCODE_BRA(x)	(((x) & 0xF000) == 0xa000)
     27#define OPCODE_BRAF(x)	(((x) & 0xF0FF) == 0x0023)
     28#define OPCODE_BSR(x)	(((x) & 0xF000) == 0xb000)
     29#define OPCODE_BSRF(x)	(((x) & 0xF0FF) == 0x0003)
     30
     31#define OPCODE_BF_S(x)	(((x) & 0xFF00) == 0x8f00)
     32#define OPCODE_BT_S(x)	(((x) & 0xFF00) == 0x8d00)
     33
     34#define OPCODE_BF(x)	(((x) & 0xFF00) == 0x8b00)
     35#define OPCODE_BT(x)	(((x) & 0xFF00) == 0x8900)
     36
     37#define OPCODE_RTS(x)	(((x) & 0x000F) == 0x000b)
     38#define OPCODE_RTE(x)	(((x) & 0xFFFF) == 0x002b)
     39
     40int __kprobes arch_prepare_kprobe(struct kprobe *p)
     41{
     42	kprobe_opcode_t opcode = *(kprobe_opcode_t *) (p->addr);
     43
     44	if (OPCODE_RTE(opcode))
     45		return -EFAULT;	/* Bad breakpoint */
     46
     47	p->opcode = opcode;
     48
     49	return 0;
     50}
     51
     52void __kprobes arch_copy_kprobe(struct kprobe *p)
     53{
     54	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
     55	p->opcode = *p->addr;
     56}
     57
     58void __kprobes arch_arm_kprobe(struct kprobe *p)
     59{
     60	*p->addr = BREAKPOINT_INSTRUCTION;
     61	flush_icache_range((unsigned long)p->addr,
     62			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
     63}
     64
     65void __kprobes arch_disarm_kprobe(struct kprobe *p)
     66{
     67	*p->addr = p->opcode;
     68	flush_icache_range((unsigned long)p->addr,
     69			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
     70}
     71
     72int __kprobes arch_trampoline_kprobe(struct kprobe *p)
     73{
     74	if (*p->addr == BREAKPOINT_INSTRUCTION)
     75		return 1;
     76
     77	return 0;
     78}
     79
     80/**
     81 * If an illegal slot instruction exception occurs for an address
     82 * containing a kprobe, remove the probe.
     83 *
     84 * Returns 0 if the exception was handled successfully, 1 otherwise.
     85 */
     86int __kprobes kprobe_handle_illslot(unsigned long pc)
     87{
     88	struct kprobe *p = get_kprobe((kprobe_opcode_t *) pc + 1);
     89
     90	if (p != NULL) {
     91		printk("Warning: removing kprobe from delay slot: 0x%.8x\n",
     92		       (unsigned int)pc + 2);
     93		unregister_kprobe(p);
     94		return 0;
     95	}
     96
     97	return 1;
     98}
     99
    100void __kprobes arch_remove_kprobe(struct kprobe *p)
    101{
    102	struct kprobe *saved = this_cpu_ptr(&saved_next_opcode);
    103
    104	if (saved->addr) {
    105		arch_disarm_kprobe(p);
    106		arch_disarm_kprobe(saved);
    107
    108		saved->addr = NULL;
    109		saved->opcode = 0;
    110
    111		saved = this_cpu_ptr(&saved_next_opcode2);
    112		if (saved->addr) {
    113			arch_disarm_kprobe(saved);
    114
    115			saved->addr = NULL;
    116			saved->opcode = 0;
    117		}
    118	}
    119}
    120
    121static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
    122{
    123	kcb->prev_kprobe.kp = kprobe_running();
    124	kcb->prev_kprobe.status = kcb->kprobe_status;
    125}
    126
    127static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
    128{
    129	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
    130	kcb->kprobe_status = kcb->prev_kprobe.status;
    131}
    132
    133static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
    134					 struct kprobe_ctlblk *kcb)
    135{
    136	__this_cpu_write(current_kprobe, p);
    137}
    138
    139/*
    140 * Singlestep is implemented by disabling the current kprobe and setting one
    141 * on the next instruction, following branches. Two probes are set if the
    142 * branch is conditional.
    143 */
    144static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
    145{
    146	__this_cpu_write(saved_current_opcode.addr, (kprobe_opcode_t *)regs->pc);
    147
    148	if (p != NULL) {
    149		struct kprobe *op1, *op2;
    150
    151		arch_disarm_kprobe(p);
    152
    153		op1 = this_cpu_ptr(&saved_next_opcode);
    154		op2 = this_cpu_ptr(&saved_next_opcode2);
    155
    156		if (OPCODE_JSR(p->opcode) || OPCODE_JMP(p->opcode)) {
    157			unsigned int reg_nr = ((p->opcode >> 8) & 0x000F);
    158			op1->addr = (kprobe_opcode_t *) regs->regs[reg_nr];
    159		} else if (OPCODE_BRA(p->opcode) || OPCODE_BSR(p->opcode)) {
    160			unsigned long disp = (p->opcode & 0x0FFF);
    161			op1->addr =
    162			    (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
    163
    164		} else if (OPCODE_BRAF(p->opcode) || OPCODE_BSRF(p->opcode)) {
    165			unsigned int reg_nr = ((p->opcode >> 8) & 0x000F);
    166			op1->addr =
    167			    (kprobe_opcode_t *) (regs->pc + 4 +
    168						 regs->regs[reg_nr]);
    169
    170		} else if (OPCODE_RTS(p->opcode)) {
    171			op1->addr = (kprobe_opcode_t *) regs->pr;
    172
    173		} else if (OPCODE_BF(p->opcode) || OPCODE_BT(p->opcode)) {
    174			unsigned long disp = (p->opcode & 0x00FF);
    175			/* case 1 */
    176			op1->addr = p->addr + 1;
    177			/* case 2 */
    178			op2->addr =
    179			    (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
    180			op2->opcode = *(op2->addr);
    181			arch_arm_kprobe(op2);
    182
    183		} else if (OPCODE_BF_S(p->opcode) || OPCODE_BT_S(p->opcode)) {
    184			unsigned long disp = (p->opcode & 0x00FF);
    185			/* case 1 */
    186			op1->addr = p->addr + 2;
    187			/* case 2 */
    188			op2->addr =
    189			    (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
    190			op2->opcode = *(op2->addr);
    191			arch_arm_kprobe(op2);
    192
    193		} else {
    194			op1->addr = p->addr + 1;
    195		}
    196
    197		op1->opcode = *(op1->addr);
    198		arch_arm_kprobe(op1);
    199	}
    200}
    201
    202/* Called with kretprobe_lock held */
    203void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
    204				      struct pt_regs *regs)
    205{
    206	ri->ret_addr = (kprobe_opcode_t *) regs->pr;
    207	ri->fp = NULL;
    208
    209	/* Replace the return addr with trampoline addr */
    210	regs->pr = (unsigned long)__kretprobe_trampoline;
    211}
    212
    213static int __kprobes kprobe_handler(struct pt_regs *regs)
    214{
    215	struct kprobe *p;
    216	int ret = 0;
    217	kprobe_opcode_t *addr = NULL;
    218	struct kprobe_ctlblk *kcb;
    219
    220	/*
    221	 * We don't want to be preempted for the entire
    222	 * duration of kprobe processing
    223	 */
    224	preempt_disable();
    225	kcb = get_kprobe_ctlblk();
    226
    227	addr = (kprobe_opcode_t *) (regs->pc);
    228
    229	/* Check we're not actually recursing */
    230	if (kprobe_running()) {
    231		p = get_kprobe(addr);
    232		if (p) {
    233			if (kcb->kprobe_status == KPROBE_HIT_SS &&
    234			    *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
    235				goto no_kprobe;
    236			}
    237			/* We have reentered the kprobe_handler(), since
    238			 * another probe was hit while within the handler.
    239			 * We here save the original kprobes variables and
    240			 * just single step on the instruction of the new probe
    241			 * without calling any user handlers.
    242			 */
    243			save_previous_kprobe(kcb);
    244			set_current_kprobe(p, regs, kcb);
    245			kprobes_inc_nmissed_count(p);
    246			prepare_singlestep(p, regs);
    247			kcb->kprobe_status = KPROBE_REENTER;
    248			return 1;
    249		}
    250		goto no_kprobe;
    251	}
    252
    253	p = get_kprobe(addr);
    254	if (!p) {
    255		/* Not one of ours: let kernel handle it */
    256		if (*(kprobe_opcode_t *)addr != BREAKPOINT_INSTRUCTION) {
    257			/*
    258			 * The breakpoint instruction was removed right
    259			 * after we hit it. Another cpu has removed
    260			 * either a probepoint or a debugger breakpoint
    261			 * at this address. In either case, no further
    262			 * handling of this interrupt is appropriate.
    263			 */
    264			ret = 1;
    265		}
    266
    267		goto no_kprobe;
    268	}
    269
    270	set_current_kprobe(p, regs, kcb);
    271	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
    272
    273	if (p->pre_handler && p->pre_handler(p, regs)) {
    274		/* handler has already set things up, so skip ss setup */
    275		reset_current_kprobe();
    276		preempt_enable_no_resched();
    277		return 1;
    278	}
    279
    280	prepare_singlestep(p, regs);
    281	kcb->kprobe_status = KPROBE_HIT_SS;
    282	return 1;
    283
    284no_kprobe:
    285	preempt_enable_no_resched();
    286	return ret;
    287}
    288
    289/*
    290 * For function-return probes, init_kprobes() establishes a probepoint
    291 * here. When a retprobed function returns, this probe is hit and
    292 * trampoline_probe_handler() runs, calling the kretprobe's handler.
    293 */
    294static void __used kretprobe_trampoline_holder(void)
    295{
    296	asm volatile (".globl __kretprobe_trampoline\n"
    297		      "__kretprobe_trampoline:\n\t"
    298		      "nop\n");
    299}
    300
    301/*
    302 * Called when we hit the probe point at __kretprobe_trampoline
    303 */
    304int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
    305{
    306	regs->pc = __kretprobe_trampoline_handler(regs, NULL);
    307
    308	return 1;
    309}
    310
    311static int __kprobes post_kprobe_handler(struct pt_regs *regs)
    312{
    313	struct kprobe *cur = kprobe_running();
    314	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
    315	kprobe_opcode_t *addr = NULL;
    316	struct kprobe *p = NULL;
    317
    318	if (!cur)
    319		return 0;
    320
    321	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
    322		kcb->kprobe_status = KPROBE_HIT_SSDONE;
    323		cur->post_handler(cur, regs, 0);
    324	}
    325
    326	p = this_cpu_ptr(&saved_next_opcode);
    327	if (p->addr) {
    328		arch_disarm_kprobe(p);
    329		p->addr = NULL;
    330		p->opcode = 0;
    331
    332		addr = __this_cpu_read(saved_current_opcode.addr);
    333		__this_cpu_write(saved_current_opcode.addr, NULL);
    334
    335		p = get_kprobe(addr);
    336		arch_arm_kprobe(p);
    337
    338		p = this_cpu_ptr(&saved_next_opcode2);
    339		if (p->addr) {
    340			arch_disarm_kprobe(p);
    341			p->addr = NULL;
    342			p->opcode = 0;
    343		}
    344	}
    345
    346	/* Restore back the original saved kprobes variables and continue. */
    347	if (kcb->kprobe_status == KPROBE_REENTER) {
    348		restore_previous_kprobe(kcb);
    349		goto out;
    350	}
    351
    352	reset_current_kprobe();
    353
    354out:
    355	preempt_enable_no_resched();
    356
    357	return 1;
    358}
    359
    360int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
    361{
    362	struct kprobe *cur = kprobe_running();
    363	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
    364	const struct exception_table_entry *entry;
    365
    366	switch (kcb->kprobe_status) {
    367	case KPROBE_HIT_SS:
    368	case KPROBE_REENTER:
    369		/*
    370		 * We are here because the instruction being single
    371		 * stepped caused a page fault. We reset the current
    372		 * kprobe, point the pc back to the probe address
    373		 * and allow the page fault handler to continue as a
    374		 * normal page fault.
    375		 */
    376		regs->pc = (unsigned long)cur->addr;
    377		if (kcb->kprobe_status == KPROBE_REENTER)
    378			restore_previous_kprobe(kcb);
    379		else
    380			reset_current_kprobe();
    381		preempt_enable_no_resched();
    382		break;
    383	case KPROBE_HIT_ACTIVE:
    384	case KPROBE_HIT_SSDONE:
    385		/*
    386		 * In case the user-specified fault handler returned
    387		 * zero, try to fix up.
    388		 */
    389		if ((entry = search_exception_tables(regs->pc)) != NULL) {
    390			regs->pc = entry->fixup;
    391			return 1;
    392		}
    393
    394		/*
    395		 * fixup_exception() could not handle it,
    396		 * Let do_page_fault() fix it.
    397		 */
    398		break;
    399	default:
    400		break;
    401	}
    402
    403	return 0;
    404}
    405
    406/*
    407 * Wrapper routine to for handling exceptions.
    408 */
    409int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
    410				       unsigned long val, void *data)
    411{
    412	struct kprobe *p = NULL;
    413	struct die_args *args = (struct die_args *)data;
    414	int ret = NOTIFY_DONE;
    415	kprobe_opcode_t *addr = NULL;
    416	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
    417
    418	addr = (kprobe_opcode_t *) (args->regs->pc);
    419	if (val == DIE_TRAP &&
    420	    args->trapnr == (BREAKPOINT_INSTRUCTION & 0xff)) {
    421		if (!kprobe_running()) {
    422			if (kprobe_handler(args->regs)) {
    423				ret = NOTIFY_STOP;
    424			} else {
    425				/* Not a kprobe trap */
    426				ret = NOTIFY_DONE;
    427			}
    428		} else {
    429			p = get_kprobe(addr);
    430			if ((kcb->kprobe_status == KPROBE_HIT_SS) ||
    431			    (kcb->kprobe_status == KPROBE_REENTER)) {
    432				if (post_kprobe_handler(args->regs))
    433					ret = NOTIFY_STOP;
    434			} else {
    435				if (kprobe_handler(args->regs))
    436					ret = NOTIFY_STOP;
    437			}
    438		}
    439	}
    440
    441	return ret;
    442}
    443
    444static struct kprobe trampoline_p = {
    445	.addr = (kprobe_opcode_t *)&__kretprobe_trampoline,
    446	.pre_handler = trampoline_probe_handler
    447};
    448
    449int __init arch_init_kprobes(void)
    450{
    451	return register_kprobe(&trampoline_p);
    452}