1 // SPDX-License-Identifier: GPL-2.0-only 1 2 /* 3 * Copyright (C) 2004, 2007-2010, 2011-2012 Sy 4 */ 5 6 #include <linux/types.h> 7 #include <linux/kprobes.h> 8 #include <linux/slab.h> 9 #include <linux/module.h> 10 #include <linux/kdebug.h> 11 #include <linux/sched.h> 12 #include <linux/uaccess.h> 13 #include <asm/cacheflush.h> 14 #include <asm/current.h> 15 #include <asm/disasm.h> 16 17 #define MIN_STACK_SIZE(addr) min((unsigned 18 (unsigned long)current_thread_ 19 20 DEFINE_PER_CPU(struct kprobe *, current_kprobe 21 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ct 22 23 int __kprobes arch_prepare_kprobe(struct kprob 24 { 25 /* Attempt to probe at unaligned addre 26 if ((unsigned long)p->addr & 0x01) 27 return -EINVAL; 28 29 /* Address should not be in exception 30 31 p->ainsn.is_short = is_short_instr((un 32 p->opcode = *p->addr; 33 34 return 0; 35 } 36 37 void __kprobes arch_arm_kprobe(struct kprobe * 38 { 39 *p->addr = UNIMP_S_INSTRUCTION; 40 41 flush_icache_range((unsigned long)p->a 42 (unsigned long)p->a 43 } 44 45 void __kprobes arch_disarm_kprobe(struct kprob 46 { 47 *p->addr = p->opcode; 48 49 flush_icache_range((unsigned long)p->a 50 (unsigned long)p->a 51 } 52 53 void __kprobes arch_remove_kprobe(struct kprob 54 { 55 arch_disarm_kprobe(p); 56 57 /* Can we remove the kprobe in the mid 58 if (p->ainsn.t1_addr) { 59 *(p->ainsn.t1_addr) = p->ainsn 60 61 flush_icache_range((unsigned l 62 (unsigned l 63 sizeof(kpro 64 65 p->ainsn.t1_addr = NULL; 66 } 67 68 if (p->ainsn.t2_addr) { 69 *(p->ainsn.t2_addr) = p->ainsn 70 71 flush_icache_range((unsigned l 72 (unsigned l 73 sizeof(kpro 74 75 p->ainsn.t2_addr = NULL; 76 } 77 } 78 79 static void __kprobes save_previous_kprobe(str 80 { 81 kcb->prev_kprobe.kp = kprobe_running() 82 kcb->prev_kprobe.status = kcb->kprobe_ 83 } 84 85 static void __kprobes restore_previous_kprobe( 86 { 87 __this_cpu_write(current_kprobe, kcb-> 88 kcb->kprobe_status = kcb->prev_kprobe. 89 } 90 91 static inline void __kprobes set_current_kprob 92 { 93 __this_cpu_write(current_kprobe, p); 94 } 95 96 static void __kprobes resume_execution(struct 97 struct 98 { 99 /* Remove the trap instructions insert 100 * restore the original instructions 101 */ 102 if (p->ainsn.t1_addr) { 103 *(p->ainsn.t1_addr) = p->ainsn 104 105 flush_icache_range((unsigned l 106 (unsigned l 107 sizeof(kpro 108 109 p->ainsn.t1_addr = NULL; 110 } 111 112 if (p->ainsn.t2_addr) { 113 *(p->ainsn.t2_addr) = p->ainsn 114 115 flush_icache_range((unsigned l 116 (unsigned l 117 sizeof(kpro 118 119 p->ainsn.t2_addr = NULL; 120 } 121 122 return; 123 } 124 125 static void __kprobes setup_singlestep(struct 126 { 127 unsigned long next_pc; 128 unsigned long tgt_if_br = 0; 129 int is_branch; 130 unsigned long bta; 131 132 /* Copy the opcode back to the kprobe 133 * instruction. Because of this we wil 134 * same kprobe until this kprobe is do 135 */ 136 *(p->addr) = p->opcode; 137 138 flush_icache_range((unsigned long)p->a 139 (unsigned long)p->a 140 141 /* Now we insert the trap at the next 142 * single step. If it is a branch we i 143 * targets 144 */ 145 146 bta = regs->bta; 147 148 if (regs->status32 & 0x40) { 149 /* We are in a delay slot with 150 151 next_pc = bta & ~0x01; 152 153 if (!p->ainsn.is_short) { 154 if (bta & 0x01) 155 regs->blink += 156 else { 157 /* Branch not 158 next_pc += 2; 159 160 /* next pc is 161 * delay slot 162 */ 163 regs->bta += 2 164 } 165 } 166 167 is_branch = 0; 168 } else 169 is_branch = 170 disasm_next_pc((unsigned l 171 (struct callee_regs *) 172 &next_pc, &tgt_if_br); 173 174 p->ainsn.t1_addr = (kprobe_opcode_t *) 175 p->ainsn.t1_opcode = *(p->ainsn.t1_add 176 *(p->ainsn.t1_addr) = TRAP_S_2_INSTRUC 177 178 flush_icache_range((unsigned long)p->a 179 (unsigned long)p->a 180 sizeof(kprobe_opcod 181 182 if (is_branch) { 183 p->ainsn.t2_addr = (kprobe_opc 184 p->ainsn.t2_opcode = *(p->ains 185 *(p->ainsn.t2_addr) = TRAP_S_2 186 187 flush_icache_range((unsigned l 188 (unsigned l 189 sizeof(kpro 190 } 191 } 192 193 static int 194 __kprobes arc_kprobe_handler(unsigned long add 195 { 196 struct kprobe *p; 197 struct kprobe_ctlblk *kcb; 198 199 preempt_disable(); 200 201 kcb = get_kprobe_ctlblk(); 202 p = get_kprobe((unsigned long *)addr); 203 204 if (p) { 205 /* 206 * We have reentered the kprob 207 * was hit while within the ha 208 * kprobes and single step on 209 * without calling any user ha 210 * kprobes. 211 */ 212 if (kprobe_running()) { 213 save_previous_kprobe(k 214 set_current_kprobe(p); 215 kprobes_inc_nmissed_co 216 setup_singlestep(p, re 217 kcb->kprobe_status = K 218 return 1; 219 } 220 221 set_current_kprobe(p); 222 kcb->kprobe_status = KPROBE_HI 223 224 /* If we have no pre-handler o 225 * normal processing. If we ha 226 * non-zero - which means user 227 * to another instruction, we 228 */ 229 if (!p->pre_handler || !p->pre 230 setup_singlestep(p, re 231 kcb->kprobe_status = K 232 } else { 233 reset_current_kprobe() 234 preempt_enable_no_resc 235 } 236 237 return 1; 238 } 239 240 /* no_kprobe: */ 241 preempt_enable_no_resched(); 242 return 0; 243 } 244 245 static int 246 __kprobes arc_post_kprobe_handler(unsigned lon 247 { 248 struct kprobe *cur = kprobe_running(); 249 struct kprobe_ctlblk *kcb = get_kprobe 250 251 if (!cur) 252 return 0; 253 254 resume_execution(cur, addr, regs); 255 256 /* Rearm the kprobe */ 257 arch_arm_kprobe(cur); 258 259 /* 260 * When we return from trap instructio 261 * We restored the actual instruction 262 * return to the same address and exec 263 */ 264 regs->ret = addr; 265 266 if ((kcb->kprobe_status != KPROBE_REEN 267 kcb->kprobe_status = KPROBE_HI 268 cur->post_handler(cur, regs, 0 269 } 270 271 if (kcb->kprobe_status == KPROBE_REENT 272 restore_previous_kprobe(kcb); 273 goto out; 274 } 275 276 reset_current_kprobe(); 277 278 out: 279 preempt_enable_no_resched(); 280 return 1; 281 } 282 283 /* 284 * Fault can be for the instruction being sing 285 * pre/post handlers in the module. 286 * This is applicable for applications like us 287 * probe in user space and the handlers in the 288 */ 289 290 int __kprobes kprobe_fault_handler(struct pt_r 291 { 292 struct kprobe *cur = kprobe_running(); 293 struct kprobe_ctlblk *kcb = get_kprobe 294 295 switch (kcb->kprobe_status) { 296 case KPROBE_HIT_SS: 297 case KPROBE_REENTER: 298 /* 299 * We are here because the ins 300 * caused the fault. We reset 301 * exception handler as if it 302 * case it doesn't matter beca 303 */ 304 resume_execution(cur, (unsigne 305 306 if (kcb->kprobe_status == KPRO 307 restore_previous_kprob 308 else 309 reset_current_kprobe() 310 311 preempt_enable_no_resched(); 312 break; 313 314 case KPROBE_HIT_ACTIVE: 315 case KPROBE_HIT_SSDONE: 316 /* 317 * We are here because the ins 318 * caused the fault. 319 */ 320 321 /* 322 * In case the user-specified 323 * try to fix up. 324 */ 325 if (fixup_exception(regs)) 326 return 1; 327 328 /* 329 * fixup_exception() could not 330 * Let do_page_fault() fix it. 331 */ 332 break; 333 334 default: 335 break; 336 } 337 return 0; 338 } 339 340 int __kprobes kprobe_exceptions_notify(struct 341 unsigne 342 { 343 struct die_args *args = data; 344 unsigned long addr = args->err; 345 int ret = NOTIFY_DONE; 346 347 switch (val) { 348 case DIE_IERR: 349 if (arc_kprobe_handler(addr, a 350 return NOTIFY_STOP; 351 break; 352 353 case DIE_TRAP: 354 if (arc_post_kprobe_handler(ad 355 return NOTIFY_STOP; 356 break; 357 358 default: 359 break; 360 } 361 362 return ret; 363 } 364 365 static void __used kretprobe_trampoline_holder 366 { 367 __asm__ __volatile__(".global __kretpr 368 "__kretprobe_tram 369 "nop\n"); 370 } 371 372 void __kprobes arch_prepare_kretprobe(struct k 373 struct p 374 { 375 376 ri->ret_addr = (kprobe_opcode_t *) reg 377 ri->fp = NULL; 378 379 /* Replace the return addr with trampo 380 regs->blink = (unsigned long)&__kretpr 381 } 382 383 static int __kprobes trampoline_probe_handler( 384 385 { 386 regs->ret = __kretprobe_trampoline_han 387 388 /* By returning a non zero value, we a 389 * that we don't want the post_handler 390 */ 391 return 1; 392 } 393 394 static struct kprobe trampoline_p = { 395 .addr = (kprobe_opcode_t *) &__kretpro 396 .pre_handler = trampoline_probe_handle 397 }; 398 399 int __init arch_init_kprobes(void) 400 { 401 /* Registering the trampoline code for 402 return register_kprobe(&trampoline_p); 403 } 404 405 int __kprobes arch_trampoline_kprobe(struct kp 406 { 407 if (p->addr == (kprobe_opcode_t *) &__ 408 return 1; 409 410 return 0; 411 } 412 413 void trap_is_kprobe(unsigned long address, str 414 { 415 notify_die(DIE_TRAP, "kprobe_trap", re 416 } 417
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.