Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Use NOKPROBE_SYMBOL() instead of __kprobes annotation

If define CONFIG_KPROBES, __kprobes annotation forces the whole function
into the ".kprobes.text" section, NOKPROBE_SYMBOL() only stores the given
function address in the "_kprobe_blacklist" section which is introduced
to maintain kprobes blacklist.

Modify the related code to use NOKPROBE_SYMBOL() to protect functions from
kprobes instead of __kprobes annotation under arch/mips.

No obvious functional change in this patch, some more work needs to be done
to fix the kernel panic when execute the following testcase on mips:

# cd tools/testing/selftests/ftrace
# ./ftracetest test.d/kprobe/multiple_kprobes.tc

Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>

authored by

Tiezhu Yang and committed by
Thomas Bogendoerfer
f5e2d818 eab691b1

+28 -14
+24 -12
arch/mips/kernel/kprobes.c
··· 44 44 DEFINE_PER_CPU(struct kprobe *, current_kprobe); 45 45 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); 46 46 47 - static int __kprobes insn_has_delayslot(union mips_instruction insn) 47 + static int insn_has_delayslot(union mips_instruction insn) 48 48 { 49 49 return __insn_has_delay_slot(insn); 50 50 } 51 + NOKPROBE_SYMBOL(insn_has_delayslot); 51 52 52 53 /* 53 54 * insn_has_ll_or_sc function checks whether instruction is ll or sc ··· 57 56 * instructions; cannot do much about breakpoint in the middle of 58 57 * ll/sc pair; it is upto user to avoid those places 59 58 */ 60 - static int __kprobes insn_has_ll_or_sc(union mips_instruction insn) 59 + static int insn_has_ll_or_sc(union mips_instruction insn) 61 60 { 62 61 int ret = 0; 63 62 ··· 73 72 } 74 73 return ret; 75 74 } 75 + NOKPROBE_SYMBOL(insn_has_ll_or_sc); 76 76 77 - int __kprobes arch_prepare_kprobe(struct kprobe *p) 77 + int arch_prepare_kprobe(struct kprobe *p) 78 78 { 79 79 union mips_instruction insn; 80 80 union mips_instruction prev_insn; ··· 134 132 out: 135 133 return ret; 136 134 } 135 + NOKPROBE_SYMBOL(arch_prepare_kprobe); 137 136 138 - void __kprobes arch_arm_kprobe(struct kprobe *p) 137 + void arch_arm_kprobe(struct kprobe *p) 139 138 { 140 139 *p->addr = breakpoint_insn; 141 140 flush_insn_slot(p); 142 141 } 142 + NOKPROBE_SYMBOL(arch_arm_kprobe); 143 143 144 - void __kprobes arch_disarm_kprobe(struct kprobe *p) 144 + void arch_disarm_kprobe(struct kprobe *p) 145 145 { 146 146 *p->addr = p->opcode; 147 147 flush_insn_slot(p); 148 148 } 149 + NOKPROBE_SYMBOL(arch_disarm_kprobe); 149 150 150 - void __kprobes arch_remove_kprobe(struct kprobe *p) 151 + void arch_remove_kprobe(struct kprobe *p) 151 152 { 152 153 if (p->ainsn.insn) { 153 154 free_insn_slot(p->ainsn.insn, 0); 154 155 p->ainsn.insn = NULL; 155 156 } 156 157 } 158 + NOKPROBE_SYMBOL(arch_remove_kprobe); 157 159 158 160 static void save_previous_kprobe(struct kprobe_ctlblk *kcb) 159 161 { ··· 263 257 * breakpoint trap. In case of branch instructions, the target 264 258 * epc to be restored. 265 259 */ 266 - static void __kprobes resume_execution(struct kprobe *p, 260 + static void resume_execution(struct kprobe *p, 267 261 struct pt_regs *regs, 268 262 struct kprobe_ctlblk *kcb) 269 263 { ··· 274 268 regs->cp0_epc = orig_epc + 4; 275 269 } 276 270 } 271 + NOKPROBE_SYMBOL(resume_execution); 277 272 278 - static int __kprobes kprobe_handler(struct pt_regs *regs) 273 + static int kprobe_handler(struct pt_regs *regs) 279 274 { 280 275 struct kprobe *p; 281 276 int ret = 0; ··· 374 367 return ret; 375 368 376 369 } 370 + NOKPROBE_SYMBOL(kprobe_handler); 377 371 378 372 static inline int post_kprobe_handler(struct pt_regs *regs) 379 373 { ··· 423 415 /* 424 416 * Wrapper routine for handling exceptions. 425 417 */ 426 - int __kprobes kprobe_exceptions_notify(struct notifier_block *self, 418 + int kprobe_exceptions_notify(struct notifier_block *self, 427 419 unsigned long val, void *data) 428 420 { 429 421 ··· 454 446 } 455 447 return ret; 456 448 } 449 + NOKPROBE_SYMBOL(kprobe_exceptions_notify); 457 450 458 451 /* 459 452 * Function return probe trampoline: ··· 478 469 479 470 void __kretprobe_trampoline(void); 480 471 481 - void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, 472 + void arch_prepare_kretprobe(struct kretprobe_instance *ri, 482 473 struct pt_regs *regs) 483 474 { 484 475 ri->ret_addr = (kprobe_opcode_t *) regs->regs[31]; ··· 487 478 /* Replace the return addr with trampoline addr */ 488 479 regs->regs[31] = (unsigned long)__kretprobe_trampoline; 489 480 } 481 + NOKPROBE_SYMBOL(arch_prepare_kretprobe); 490 482 491 483 /* 492 484 * Called when the probe at kretprobe trampoline is hit 493 485 */ 494 - static int __kprobes trampoline_probe_handler(struct kprobe *p, 486 + static int trampoline_probe_handler(struct kprobe *p, 495 487 struct pt_regs *regs) 496 488 { 497 489 instruction_pointer(regs) = __kretprobe_trampoline_handler(regs, NULL); ··· 503 493 */ 504 494 return 1; 505 495 } 496 + NOKPROBE_SYMBOL(trampoline_probe_handler); 506 497 507 - int __kprobes arch_trampoline_kprobe(struct kprobe *p) 498 + int arch_trampoline_kprobe(struct kprobe *p) 508 499 { 509 500 if (p->addr == (kprobe_opcode_t *)__kretprobe_trampoline) 510 501 return 1; 511 502 512 503 return 0; 513 504 } 505 + NOKPROBE_SYMBOL(arch_trampoline_kprobe); 514 506 515 507 static struct kprobe trampoline_p = { 516 508 .addr = (kprobe_opcode_t *)__kretprobe_trampoline,
+4 -2
arch/mips/mm/fault.c
··· 35 35 * and the problem, and then passes it off to one of the appropriate 36 36 * routines. 37 37 */ 38 - static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write, 38 + static void __do_page_fault(struct pt_regs *regs, unsigned long write, 39 39 unsigned long address) 40 40 { 41 41 struct vm_area_struct * vma = NULL; ··· 322 322 } 323 323 #endif 324 324 } 325 + NOKPROBE_SYMBOL(__do_page_fault); 325 326 326 - asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, 327 + asmlinkage void do_page_fault(struct pt_regs *regs, 327 328 unsigned long write, unsigned long address) 328 329 { 329 330 enum ctx_state prev_state; ··· 333 332 __do_page_fault(regs, write, address); 334 333 exception_exit(prev_state); 335 334 } 335 + NOKPROBE_SYMBOL(do_page_fault);