diff options
Diffstat (limited to 'arch/s390/kernel/kprobes.c')
-rw-r--r-- | arch/s390/kernel/kprobes.c | 178 |
1 files changed, 119 insertions, 59 deletions
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 014d4729b134..1e4c710dfb92 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/hardirq.h> | 31 | #include <linux/hardirq.h> |
32 | #include <linux/ftrace.h> | ||
32 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
33 | #include <asm/sections.h> | 34 | #include <asm/sections.h> |
34 | #include <asm/dis.h> | 35 | #include <asm/dis.h> |
@@ -58,12 +59,23 @@ struct kprobe_insn_cache kprobe_dmainsn_slots = { | |||
58 | .insn_size = MAX_INSN_SIZE, | 59 | .insn_size = MAX_INSN_SIZE, |
59 | }; | 60 | }; |
60 | 61 | ||
61 | static void __kprobes copy_instruction(struct kprobe *p) | 62 | static void copy_instruction(struct kprobe *p) |
62 | { | 63 | { |
64 | unsigned long ip = (unsigned long) p->addr; | ||
63 | s64 disp, new_disp; | 65 | s64 disp, new_disp; |
64 | u64 addr, new_addr; | 66 | u64 addr, new_addr; |
65 | 67 | ||
66 | memcpy(p->ainsn.insn, p->addr, insn_length(p->opcode >> 8)); | 68 | if (ftrace_location(ip) == ip) { |
69 | /* | ||
70 | * If kprobes patches the instruction that is morphed by | ||
71 | * ftrace make sure that kprobes always sees the branch | ||
72 | * "jg .+24" that skips the mcount block | ||
73 | */ | ||
74 | ftrace_generate_nop_insn((struct ftrace_insn *)p->ainsn.insn); | ||
75 | p->ainsn.is_ftrace_insn = 1; | ||
76 | } else | ||
77 | memcpy(p->ainsn.insn, p->addr, insn_length(*p->addr >> 8)); | ||
78 | p->opcode = p->ainsn.insn[0]; | ||
67 | if (!probe_is_insn_relative_long(p->ainsn.insn)) | 79 | if (!probe_is_insn_relative_long(p->ainsn.insn)) |
68 | return; | 80 | return; |
69 | /* | 81 | /* |
@@ -79,25 +91,14 @@ static void __kprobes copy_instruction(struct kprobe *p) | |||
79 | new_disp = ((addr + (disp * 2)) - new_addr) / 2; | 91 | new_disp = ((addr + (disp * 2)) - new_addr) / 2; |
80 | *(s32 *)&p->ainsn.insn[1] = new_disp; | 92 | *(s32 *)&p->ainsn.insn[1] = new_disp; |
81 | } | 93 | } |
94 | NOKPROBE_SYMBOL(copy_instruction); | ||
82 | 95 | ||
83 | static inline int is_kernel_addr(void *addr) | 96 | static inline int is_kernel_addr(void *addr) |
84 | { | 97 | { |
85 | return addr < (void *)_end; | 98 | return addr < (void *)_end; |
86 | } | 99 | } |
87 | 100 | ||
88 | static inline int is_module_addr(void *addr) | 101 | static int s390_get_insn_slot(struct kprobe *p) |
89 | { | ||
90 | #ifdef CONFIG_64BIT | ||
91 | BUILD_BUG_ON(MODULES_LEN > (1UL << 31)); | ||
92 | if (addr < (void *)MODULES_VADDR) | ||
93 | return 0; | ||
94 | if (addr > (void *)MODULES_END) | ||
95 | return 0; | ||
96 | #endif | ||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | static int __kprobes s390_get_insn_slot(struct kprobe *p) | ||
101 | { | 102 | { |
102 | /* | 103 | /* |
103 | * Get an insn slot that is within the same 2GB area like the original | 104 | * Get an insn slot that is within the same 2GB area like the original |
@@ -111,8 +112,9 @@ static int __kprobes s390_get_insn_slot(struct kprobe *p) | |||
111 | p->ainsn.insn = get_insn_slot(); | 112 | p->ainsn.insn = get_insn_slot(); |
112 | return p->ainsn.insn ? 0 : -ENOMEM; | 113 | return p->ainsn.insn ? 0 : -ENOMEM; |
113 | } | 114 | } |
115 | NOKPROBE_SYMBOL(s390_get_insn_slot); | ||
114 | 116 | ||
115 | static void __kprobes s390_free_insn_slot(struct kprobe *p) | 117 | static void s390_free_insn_slot(struct kprobe *p) |
116 | { | 118 | { |
117 | if (!p->ainsn.insn) | 119 | if (!p->ainsn.insn) |
118 | return; | 120 | return; |
@@ -122,8 +124,9 @@ static void __kprobes s390_free_insn_slot(struct kprobe *p) | |||
122 | free_insn_slot(p->ainsn.insn, 0); | 124 | free_insn_slot(p->ainsn.insn, 0); |
123 | p->ainsn.insn = NULL; | 125 | p->ainsn.insn = NULL; |
124 | } | 126 | } |
127 | NOKPROBE_SYMBOL(s390_free_insn_slot); | ||
125 | 128 | ||
126 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 129 | int arch_prepare_kprobe(struct kprobe *p) |
127 | { | 130 | { |
128 | if ((unsigned long) p->addr & 0x01) | 131 | if ((unsigned long) p->addr & 0x01) |
129 | return -EINVAL; | 132 | return -EINVAL; |
@@ -132,54 +135,79 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
132 | return -EINVAL; | 135 | return -EINVAL; |
133 | if (s390_get_insn_slot(p)) | 136 | if (s390_get_insn_slot(p)) |
134 | return -ENOMEM; | 137 | return -ENOMEM; |
135 | p->opcode = *p->addr; | ||
136 | copy_instruction(p); | 138 | copy_instruction(p); |
137 | return 0; | 139 | return 0; |
138 | } | 140 | } |
141 | NOKPROBE_SYMBOL(arch_prepare_kprobe); | ||
139 | 142 | ||
140 | struct ins_replace_args { | 143 | int arch_check_ftrace_location(struct kprobe *p) |
141 | kprobe_opcode_t *ptr; | 144 | { |
142 | kprobe_opcode_t opcode; | 145 | return 0; |
146 | } | ||
147 | |||
148 | struct swap_insn_args { | ||
149 | struct kprobe *p; | ||
150 | unsigned int arm_kprobe : 1; | ||
143 | }; | 151 | }; |
144 | 152 | ||
145 | static int __kprobes swap_instruction(void *aref) | 153 | static int swap_instruction(void *data) |
146 | { | 154 | { |
147 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 155 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
148 | unsigned long status = kcb->kprobe_status; | 156 | unsigned long status = kcb->kprobe_status; |
149 | struct ins_replace_args *args = aref; | 157 | struct swap_insn_args *args = data; |
150 | 158 | struct ftrace_insn new_insn, *insn; | |
159 | struct kprobe *p = args->p; | ||
160 | size_t len; | ||
161 | |||
162 | new_insn.opc = args->arm_kprobe ? BREAKPOINT_INSTRUCTION : p->opcode; | ||
163 | len = sizeof(new_insn.opc); | ||
164 | if (!p->ainsn.is_ftrace_insn) | ||
165 | goto skip_ftrace; | ||
166 | len = sizeof(new_insn); | ||
167 | insn = (struct ftrace_insn *) p->addr; | ||
168 | if (args->arm_kprobe) { | ||
169 | if (is_ftrace_nop(insn)) | ||
170 | new_insn.disp = KPROBE_ON_FTRACE_NOP; | ||
171 | else | ||
172 | new_insn.disp = KPROBE_ON_FTRACE_CALL; | ||
173 | } else { | ||
174 | ftrace_generate_call_insn(&new_insn, (unsigned long)p->addr); | ||
175 | if (insn->disp == KPROBE_ON_FTRACE_NOP) | ||
176 | ftrace_generate_nop_insn(&new_insn); | ||
177 | } | ||
178 | skip_ftrace: | ||
151 | kcb->kprobe_status = KPROBE_SWAP_INST; | 179 | kcb->kprobe_status = KPROBE_SWAP_INST; |
152 | probe_kernel_write(args->ptr, &args->opcode, sizeof(args->opcode)); | 180 | probe_kernel_write(p->addr, &new_insn, len); |
153 | kcb->kprobe_status = status; | 181 | kcb->kprobe_status = status; |
154 | return 0; | 182 | return 0; |
155 | } | 183 | } |
184 | NOKPROBE_SYMBOL(swap_instruction); | ||
156 | 185 | ||
157 | void __kprobes arch_arm_kprobe(struct kprobe *p) | 186 | void arch_arm_kprobe(struct kprobe *p) |
158 | { | 187 | { |
159 | struct ins_replace_args args; | 188 | struct swap_insn_args args = {.p = p, .arm_kprobe = 1}; |
160 | 189 | ||
161 | args.ptr = p->addr; | ||
162 | args.opcode = BREAKPOINT_INSTRUCTION; | ||
163 | stop_machine(swap_instruction, &args, NULL); | 190 | stop_machine(swap_instruction, &args, NULL); |
164 | } | 191 | } |
192 | NOKPROBE_SYMBOL(arch_arm_kprobe); | ||
165 | 193 | ||
166 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 194 | void arch_disarm_kprobe(struct kprobe *p) |
167 | { | 195 | { |
168 | struct ins_replace_args args; | 196 | struct swap_insn_args args = {.p = p, .arm_kprobe = 0}; |
169 | 197 | ||
170 | args.ptr = p->addr; | ||
171 | args.opcode = p->opcode; | ||
172 | stop_machine(swap_instruction, &args, NULL); | 198 | stop_machine(swap_instruction, &args, NULL); |
173 | } | 199 | } |
200 | NOKPROBE_SYMBOL(arch_disarm_kprobe); | ||
174 | 201 | ||
175 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 202 | void arch_remove_kprobe(struct kprobe *p) |
176 | { | 203 | { |
177 | s390_free_insn_slot(p); | 204 | s390_free_insn_slot(p); |
178 | } | 205 | } |
206 | NOKPROBE_SYMBOL(arch_remove_kprobe); | ||
179 | 207 | ||
180 | static void __kprobes enable_singlestep(struct kprobe_ctlblk *kcb, | 208 | static void enable_singlestep(struct kprobe_ctlblk *kcb, |
181 | struct pt_regs *regs, | 209 | struct pt_regs *regs, |
182 | unsigned long ip) | 210 | unsigned long ip) |
183 | { | 211 | { |
184 | struct per_regs per_kprobe; | 212 | struct per_regs per_kprobe; |
185 | 213 | ||
@@ -199,10 +227,11 @@ static void __kprobes enable_singlestep(struct kprobe_ctlblk *kcb, | |||
199 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); | 227 | regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT); |
200 | regs->psw.addr = ip | PSW_ADDR_AMODE; | 228 | regs->psw.addr = ip | PSW_ADDR_AMODE; |
201 | } | 229 | } |
230 | NOKPROBE_SYMBOL(enable_singlestep); | ||
202 | 231 | ||
203 | static void __kprobes disable_singlestep(struct kprobe_ctlblk *kcb, | 232 | static void disable_singlestep(struct kprobe_ctlblk *kcb, |
204 | struct pt_regs *regs, | 233 | struct pt_regs *regs, |
205 | unsigned long ip) | 234 | unsigned long ip) |
206 | { | 235 | { |
207 | /* Restore control regs and psw mask, set new psw address */ | 236 | /* Restore control regs and psw mask, set new psw address */ |
208 | __ctl_load(kcb->kprobe_saved_ctl, 9, 11); | 237 | __ctl_load(kcb->kprobe_saved_ctl, 9, 11); |
@@ -210,41 +239,43 @@ static void __kprobes disable_singlestep(struct kprobe_ctlblk *kcb, | |||
210 | regs->psw.mask |= kcb->kprobe_saved_imask; | 239 | regs->psw.mask |= kcb->kprobe_saved_imask; |
211 | regs->psw.addr = ip | PSW_ADDR_AMODE; | 240 | regs->psw.addr = ip | PSW_ADDR_AMODE; |
212 | } | 241 | } |
242 | NOKPROBE_SYMBOL(disable_singlestep); | ||
213 | 243 | ||
214 | /* | 244 | /* |
215 | * Activate a kprobe by storing its pointer to current_kprobe. The | 245 | * Activate a kprobe by storing its pointer to current_kprobe. The |
216 | * previous kprobe is stored in kcb->prev_kprobe. A stack of up to | 246 | * previous kprobe is stored in kcb->prev_kprobe. A stack of up to |
217 | * two kprobes can be active, see KPROBE_REENTER. | 247 | * two kprobes can be active, see KPROBE_REENTER. |
218 | */ | 248 | */ |
219 | static void __kprobes push_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p) | 249 | static void push_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p) |
220 | { | 250 | { |
221 | kcb->prev_kprobe.kp = __this_cpu_read(current_kprobe); | 251 | kcb->prev_kprobe.kp = __this_cpu_read(current_kprobe); |
222 | kcb->prev_kprobe.status = kcb->kprobe_status; | 252 | kcb->prev_kprobe.status = kcb->kprobe_status; |
223 | __this_cpu_write(current_kprobe, p); | 253 | __this_cpu_write(current_kprobe, p); |
224 | } | 254 | } |
255 | NOKPROBE_SYMBOL(push_kprobe); | ||
225 | 256 | ||
226 | /* | 257 | /* |
227 | * Deactivate a kprobe by backing up to the previous state. If the | 258 | * Deactivate a kprobe by backing up to the previous state. If the |
228 | * current state is KPROBE_REENTER prev_kprobe.kp will be non-NULL, | 259 | * current state is KPROBE_REENTER prev_kprobe.kp will be non-NULL, |
229 | * for any other state prev_kprobe.kp will be NULL. | 260 | * for any other state prev_kprobe.kp will be NULL. |
230 | */ | 261 | */ |
231 | static void __kprobes pop_kprobe(struct kprobe_ctlblk *kcb) | 262 | static void pop_kprobe(struct kprobe_ctlblk *kcb) |
232 | { | 263 | { |
233 | __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); | 264 | __this_cpu_write(current_kprobe, kcb->prev_kprobe.kp); |
234 | kcb->kprobe_status = kcb->prev_kprobe.status; | 265 | kcb->kprobe_status = kcb->prev_kprobe.status; |
235 | } | 266 | } |
267 | NOKPROBE_SYMBOL(pop_kprobe); | ||
236 | 268 | ||
237 | void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, | 269 | void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) |
238 | struct pt_regs *regs) | ||
239 | { | 270 | { |
240 | ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14]; | 271 | ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14]; |
241 | 272 | ||
242 | /* Replace the return addr with trampoline addr */ | 273 | /* Replace the return addr with trampoline addr */ |
243 | regs->gprs[14] = (unsigned long) &kretprobe_trampoline; | 274 | regs->gprs[14] = (unsigned long) &kretprobe_trampoline; |
244 | } | 275 | } |
276 | NOKPROBE_SYMBOL(arch_prepare_kretprobe); | ||
245 | 277 | ||
246 | static void __kprobes kprobe_reenter_check(struct kprobe_ctlblk *kcb, | 278 | static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p) |
247 | struct kprobe *p) | ||
248 | { | 279 | { |
249 | switch (kcb->kprobe_status) { | 280 | switch (kcb->kprobe_status) { |
250 | case KPROBE_HIT_SSDONE: | 281 | case KPROBE_HIT_SSDONE: |
@@ -264,8 +295,9 @@ static void __kprobes kprobe_reenter_check(struct kprobe_ctlblk *kcb, | |||
264 | BUG(); | 295 | BUG(); |
265 | } | 296 | } |
266 | } | 297 | } |
298 | NOKPROBE_SYMBOL(kprobe_reenter_check); | ||
267 | 299 | ||
268 | static int __kprobes kprobe_handler(struct pt_regs *regs) | 300 | static int kprobe_handler(struct pt_regs *regs) |
269 | { | 301 | { |
270 | struct kprobe_ctlblk *kcb; | 302 | struct kprobe_ctlblk *kcb; |
271 | struct kprobe *p; | 303 | struct kprobe *p; |
@@ -339,6 +371,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) | |||
339 | preempt_enable_no_resched(); | 371 | preempt_enable_no_resched(); |
340 | return 0; | 372 | return 0; |
341 | } | 373 | } |
374 | NOKPROBE_SYMBOL(kprobe_handler); | ||
342 | 375 | ||
343 | /* | 376 | /* |
344 | * Function return probe trampoline: | 377 | * Function return probe trampoline: |
@@ -355,8 +388,7 @@ static void __used kretprobe_trampoline_holder(void) | |||
355 | /* | 388 | /* |
356 | * Called when the probe at kretprobe trampoline is hit | 389 | * Called when the probe at kretprobe trampoline is hit |
357 | */ | 390 | */ |
358 | static int __kprobes trampoline_probe_handler(struct kprobe *p, | 391 | static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) |
359 | struct pt_regs *regs) | ||
360 | { | 392 | { |
361 | struct kretprobe_instance *ri; | 393 | struct kretprobe_instance *ri; |
362 | struct hlist_head *head, empty_rp; | 394 | struct hlist_head *head, empty_rp; |
@@ -444,6 +476,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
444 | */ | 476 | */ |
445 | return 1; | 477 | return 1; |
446 | } | 478 | } |
479 | NOKPROBE_SYMBOL(trampoline_probe_handler); | ||
447 | 480 | ||
448 | /* | 481 | /* |
449 | * Called after single-stepping. p->addr is the address of the | 482 | * Called after single-stepping. p->addr is the address of the |
@@ -453,12 +486,30 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
453 | * single-stepped a copy of the instruction. The address of this | 486 | * single-stepped a copy of the instruction. The address of this |
454 | * copy is p->ainsn.insn. | 487 | * copy is p->ainsn.insn. |
455 | */ | 488 | */ |
456 | static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) | 489 | static void resume_execution(struct kprobe *p, struct pt_regs *regs) |
457 | { | 490 | { |
458 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 491 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
459 | unsigned long ip = regs->psw.addr & PSW_ADDR_INSN; | 492 | unsigned long ip = regs->psw.addr & PSW_ADDR_INSN; |
460 | int fixup = probe_get_fixup_type(p->ainsn.insn); | 493 | int fixup = probe_get_fixup_type(p->ainsn.insn); |
461 | 494 | ||
495 | /* Check if the kprobes location is an enabled ftrace caller */ | ||
496 | if (p->ainsn.is_ftrace_insn) { | ||
497 | struct ftrace_insn *insn = (struct ftrace_insn *) p->addr; | ||
498 | struct ftrace_insn call_insn; | ||
499 | |||
500 | ftrace_generate_call_insn(&call_insn, (unsigned long) p->addr); | ||
501 | /* | ||
502 | * A kprobe on an enabled ftrace call site actually single | ||
503 | * stepped an unconditional branch (ftrace nop equivalent). | ||
504 | * Now we need to fixup things and pretend that a brasl r0,... | ||
505 | * was executed instead. | ||
506 | */ | ||
507 | if (insn->disp == KPROBE_ON_FTRACE_CALL) { | ||
508 | ip += call_insn.disp * 2 - MCOUNT_INSN_SIZE; | ||
509 | regs->gprs[0] = (unsigned long)p->addr + sizeof(*insn); | ||
510 | } | ||
511 | } | ||
512 | |||
462 | if (fixup & FIXUP_PSW_NORMAL) | 513 | if (fixup & FIXUP_PSW_NORMAL) |
463 | ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn; | 514 | ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn; |
464 | 515 | ||
@@ -476,8 +527,9 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) | |||
476 | 527 | ||
477 | disable_singlestep(kcb, regs, ip); | 528 | disable_singlestep(kcb, regs, ip); |
478 | } | 529 | } |
530 | NOKPROBE_SYMBOL(resume_execution); | ||
479 | 531 | ||
480 | static int __kprobes post_kprobe_handler(struct pt_regs *regs) | 532 | static int post_kprobe_handler(struct pt_regs *regs) |
481 | { | 533 | { |
482 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 534 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
483 | struct kprobe *p = kprobe_running(); | 535 | struct kprobe *p = kprobe_running(); |
@@ -504,8 +556,9 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs) | |||
504 | 556 | ||
505 | return 1; | 557 | return 1; |
506 | } | 558 | } |
559 | NOKPROBE_SYMBOL(post_kprobe_handler); | ||
507 | 560 | ||
508 | static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) | 561 | static int kprobe_trap_handler(struct pt_regs *regs, int trapnr) |
509 | { | 562 | { |
510 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 563 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
511 | struct kprobe *p = kprobe_running(); | 564 | struct kprobe *p = kprobe_running(); |
@@ -567,8 +620,9 @@ static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) | |||
567 | } | 620 | } |
568 | return 0; | 621 | return 0; |
569 | } | 622 | } |
623 | NOKPROBE_SYMBOL(kprobe_trap_handler); | ||
570 | 624 | ||
571 | int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | 625 | int kprobe_fault_handler(struct pt_regs *regs, int trapnr) |
572 | { | 626 | { |
573 | int ret; | 627 | int ret; |
574 | 628 | ||
@@ -579,12 +633,13 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
579 | local_irq_restore(regs->psw.mask & ~PSW_MASK_PER); | 633 | local_irq_restore(regs->psw.mask & ~PSW_MASK_PER); |
580 | return ret; | 634 | return ret; |
581 | } | 635 | } |
636 | NOKPROBE_SYMBOL(kprobe_fault_handler); | ||
582 | 637 | ||
583 | /* | 638 | /* |
584 | * Wrapper routine to for handling exceptions. | 639 | * Wrapper routine to for handling exceptions. |
585 | */ | 640 | */ |
586 | int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | 641 | int kprobe_exceptions_notify(struct notifier_block *self, |
587 | unsigned long val, void *data) | 642 | unsigned long val, void *data) |
588 | { | 643 | { |
589 | struct die_args *args = (struct die_args *) data; | 644 | struct die_args *args = (struct die_args *) data; |
590 | struct pt_regs *regs = args->regs; | 645 | struct pt_regs *regs = args->regs; |
@@ -616,8 +671,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
616 | 671 | ||
617 | return ret; | 672 | return ret; |
618 | } | 673 | } |
674 | NOKPROBE_SYMBOL(kprobe_exceptions_notify); | ||
619 | 675 | ||
620 | int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | 676 | int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) |
621 | { | 677 | { |
622 | struct jprobe *jp = container_of(p, struct jprobe, kp); | 678 | struct jprobe *jp = container_of(p, struct jprobe, kp); |
623 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 679 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
@@ -635,13 +691,15 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) | |||
635 | memcpy(kcb->jprobes_stack, (void *) stack, MIN_STACK_SIZE(stack)); | 691 | memcpy(kcb->jprobes_stack, (void *) stack, MIN_STACK_SIZE(stack)); |
636 | return 1; | 692 | return 1; |
637 | } | 693 | } |
694 | NOKPROBE_SYMBOL(setjmp_pre_handler); | ||
638 | 695 | ||
639 | void __kprobes jprobe_return(void) | 696 | void jprobe_return(void) |
640 | { | 697 | { |
641 | asm volatile(".word 0x0002"); | 698 | asm volatile(".word 0x0002"); |
642 | } | 699 | } |
700 | NOKPROBE_SYMBOL(jprobe_return); | ||
643 | 701 | ||
644 | int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | 702 | int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) |
645 | { | 703 | { |
646 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 704 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
647 | unsigned long stack; | 705 | unsigned long stack; |
@@ -655,6 +713,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
655 | preempt_enable_no_resched(); | 713 | preempt_enable_no_resched(); |
656 | return 1; | 714 | return 1; |
657 | } | 715 | } |
716 | NOKPROBE_SYMBOL(longjmp_break_handler); | ||
658 | 717 | ||
659 | static struct kprobe trampoline = { | 718 | static struct kprobe trampoline = { |
660 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, | 719 | .addr = (kprobe_opcode_t *) &kretprobe_trampoline, |
@@ -666,7 +725,8 @@ int __init arch_init_kprobes(void) | |||
666 | return register_kprobe(&trampoline); | 725 | return register_kprobe(&trampoline); |
667 | } | 726 | } |
668 | 727 | ||
669 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | 728 | int arch_trampoline_kprobe(struct kprobe *p) |
670 | { | 729 | { |
671 | return p->addr == (kprobe_opcode_t *) &kretprobe_trampoline; | 730 | return p->addr == (kprobe_opcode_t *) &kretprobe_trampoline; |
672 | } | 731 | } |
732 | NOKPROBE_SYMBOL(arch_trampoline_kprobe); | ||