0ae73082ee25867bb56bfdd600a9bf486de912b4
[kernel/swap-modules.git] / kprobe / arch / asm-arm / dbi_kprobes.c
1 /*
2  *  Dynamic Binary Instrumentation Module based on KProbes
3  *  modules/kprobe/arch/asm-arm/dbi_kprobes.c
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Copyright (C) Samsung Electronics, 2006-2010
20  *
21  * 2006-2007    Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM/MIPS
22  * 2008-2009    Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
23  *              Probes initial implementation; Support x86.
24  * 2010         Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
25  * 2010-2011    Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
26  * 2012         Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
27  * 2012         Stanislav Andreev <s.andreev@samsung.com>: redesign of kprobe functionality -
28  *              kprobe_handler() now called via undefined instruction hooks
29  * 2012         Stanislav Andreev <s.andreev@samsung.com>: hash tables search implemented for uprobes
30  */
31
32 #include <linux/module.h>
33 #include <linux/mm.h>
34
35 #include "dbi_kprobes.h"
36 #include "trampoline_arm.h"
37 #include <kprobe/dbi_kprobes.h>
38
39 #include <kprobe/dbi_kdebug.h>
40 #include <kprobe/dbi_insn_slots.h>
41 #include <kprobe/dbi_kprobes_deps.h>
42 #include <ksyms/ksyms.h>
43
44 #include <asm/cacheflush.h>
45 #include <asm/traps.h>
46 #include <asm/ptrace.h>
47 #include <linux/list.h>
48 #include <linux/hash.h>
49
50 #define SUPRESS_BUG_MESSAGES
51
52 #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
53 #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
54
55 extern struct kprobe * per_cpu__current_kprobe;
56 extern struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
57
58 static void (*__swap_register_undef_hook)(struct undef_hook *hook);
59 static void (*__swap_unregister_undef_hook)(struct undef_hook *hook);
60
61 static unsigned long get_addr_b(unsigned long insn, unsigned long addr)
62 {
63         /* real position less then PC by 8 */
64         return (kprobe_opcode_t)((long)addr + 8 + branch_displacement(insn));
65 }
66
67 static int prep_pc_dep_insn_execbuf(kprobe_opcode_t *insns,
68                                     kprobe_opcode_t insn, int uregs)
69 {
70         int i;
71
72         if (uregs & 0x10) {
73                 int reg_mask = 0x1;
74                 //search in reg list
75                 for (i = 0; i < 13; i++, reg_mask <<= 1) {
76                         if (!(insn & reg_mask))
77                                 break;
78                 }
79         } else {
80                 for (i = 0; i < 13; i++) {
81                         if ((uregs & 0x1) && (ARM_INSN_REG_RN(insn) == i))
82                                 continue;
83                         if ((uregs & 0x2) && (ARM_INSN_REG_RD(insn) == i))
84                                 continue;
85                         if ((uregs & 0x4) && (ARM_INSN_REG_RS(insn) == i))
86                                 continue;
87                         if ((uregs & 0x8) && (ARM_INSN_REG_RM(insn) == i))
88                                 continue;
89                         break;
90                 }
91         }
92
93         if (i == 13) {
94                 DBPRINTF ("there are no free register %x in insn %lx!", uregs, insn);
95                 return -EINVAL;
96         }
97         DBPRINTF ("prep_pc_dep_insn_execbuf: using R%d, changing regs %x", i, uregs);
98
99         // set register to save
100         ARM_INSN_REG_SET_RD(insns[0], i);
101         // set register to load address to
102         ARM_INSN_REG_SET_RD(insns[1], i);
103         // set instruction to execute and patch it
104         if (uregs & 0x10) {
105                 ARM_INSN_REG_CLEAR_MR(insn, 15);
106                 ARM_INSN_REG_SET_MR(insn, i);
107         } else {
108                 if ((uregs & 0x1) && (ARM_INSN_REG_RN(insn) == 15))
109                         ARM_INSN_REG_SET_RN(insn, i);
110                 if ((uregs & 0x2) && (ARM_INSN_REG_RD(insn) == 15))
111                         ARM_INSN_REG_SET_RD(insn, i);
112                 if ((uregs & 0x4) && (ARM_INSN_REG_RS(insn) == 15))
113                         ARM_INSN_REG_SET_RS(insn, i);
114                 if ((uregs & 0x8) && (ARM_INSN_REG_RM(insn) == 15))
115                         ARM_INSN_REG_SET_RM(insn, i);
116         }
117
118         insns[UPROBES_TRAMP_INSN_IDX] = insn;
119         // set register to restore
120         ARM_INSN_REG_SET_RD(insns[3], i);
121
122         return 0;
123 }
124
125 static int arch_check_insn_arm(unsigned long insn)
126 {
127         /* check instructions that can change PC by nature */
128         if (
129          /* ARM_INSN_MATCH(UNDEF, insn) || */
130             ARM_INSN_MATCH(AUNDEF, insn) ||
131             ARM_INSN_MATCH(SWI, insn) ||
132             ARM_INSN_MATCH(BREAK, insn) ||
133             ARM_INSN_MATCH(BXJ, insn)) {
134                 goto bad_insn;
135 #ifndef CONFIG_CPU_V7
136         /* check instructions that can write result to PC */
137         } else if ((ARM_INSN_MATCH(DPIS, insn) ||
138                     ARM_INSN_MATCH(DPRS, insn) ||
139                     ARM_INSN_MATCH(DPI, insn) ||
140                     ARM_INSN_MATCH(LIO, insn) ||
141                     ARM_INSN_MATCH(LRO, insn)) &&
142                    (ARM_INSN_REG_RD(insn) == 15)) {
143                 goto bad_insn;
144 #endif /* CONFIG_CPU_V7 */
145         /* check special instruction loads store multiple registers */
146         } else if ((ARM_INSN_MATCH(LM, insn) || ARM_INSN_MATCH(SM, insn)) &&
147                         /* store PC or load to PC */
148                    (ARM_INSN_REG_MR(insn, 15) ||
149                          /* store/load with PC update */
150                     ((ARM_INSN_REG_RN(insn) == 15) && (insn & 0x200000)))) {
151                 goto bad_insn;
152         }
153
154         return 0;
155
156 bad_insn:
157         printk("Bad insn arch_check_insn_arm: %lx\n", insn);
158         return -EFAULT;
159 }
160
161 static int make_branch_tarmpoline(unsigned long addr, unsigned long insn,
162                                   unsigned long *tramp)
163 {
164         int ok = 0;
165
166         /* B */
167         if (ARM_INSN_MATCH(B, insn) &&
168             !ARM_INSN_MATCH(BLX1, insn)) {
169                 /* B check can be false positive on BLX1 instruction */
170                 memcpy(tramp, b_cond_insn_execbuf, KPROBES_TRAMP_LEN);
171                 tramp[KPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
172                 tramp[0] |= insn & 0xf0000000;
173                 tramp[6] = get_addr_b(insn, addr);
174                 tramp[7] = addr + 4;
175                 ok = 1;
176         /* BX, BLX (Rm) */
177         } else if (ARM_INSN_MATCH(BX, insn) ||
178                    ARM_INSN_MATCH(BLX2, insn)) {
179                 memcpy(tramp, b_r_insn_execbuf, KPROBES_TRAMP_LEN);
180                 tramp[0] = insn;
181                 tramp[KPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
182                 tramp[7] = addr + 4;
183                 ok = 1;
184         /* BL, BLX (Off) */
185         } else if (ARM_INSN_MATCH(BLX1, insn)) {
186                 memcpy(tramp, blx_off_insn_execbuf, KPROBES_TRAMP_LEN);
187                 tramp[0] |= 0xe0000000;
188                 tramp[1] |= 0xe0000000;
189                 tramp[KPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
190                 tramp[6] = get_addr_b(insn, addr) +
191                            2 * (insn & 01000000) + 1; /* jump to thumb */
192                 tramp[7] = addr + 4;
193                 ok = 1;
194         /* BL */
195         } else if (ARM_INSN_MATCH(BL, insn)) {
196                 memcpy(tramp, blx_off_insn_execbuf, KPROBES_TRAMP_LEN);
197                 tramp[0] |= insn & 0xf0000000;
198                 tramp[1] |= insn & 0xf0000000;
199                 tramp[KPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
200                 tramp[6] = get_addr_b(insn, addr);
201                 tramp[7] = addr + 4;
202                 ok = 1;
203         }
204
205         return ok;
206 }
207
208 int arch_make_trampoline_arm(unsigned long addr, unsigned long insn,
209                              unsigned long *tramp)
210 {
211         int ret, uregs, pc_dep;
212
213         if (addr & 0x03) {
214                 printk("Error in %s at %d: attempt to register uprobe "
215                        "at an unaligned address\n", __FILE__, __LINE__);
216                 return -EINVAL;
217         }
218
219         ret = arch_check_insn_arm(insn);
220         if (ret)
221                 return ret;
222
223         if (make_branch_tarmpoline(addr, insn, tramp))
224                 return 0;
225
226         uregs = pc_dep = 0;
227         /* Rn, Rm ,Rd */
228         if (ARM_INSN_MATCH(DPIS, insn) || ARM_INSN_MATCH(LRO, insn) ||
229             ARM_INSN_MATCH(SRO, insn)) {
230                 uregs = 0xb;
231                 if ((ARM_INSN_REG_RN(insn) == 15) ||
232                     (ARM_INSN_REG_RM(insn) == 15) ||
233                     (ARM_INSN_MATCH(SRO, insn) &&
234                      (ARM_INSN_REG_RD(insn) == 15))) {
235                         pc_dep = 1;
236                 }
237         /* Rn ,Rd */
238         } else if (ARM_INSN_MATCH(DPI, insn) || ARM_INSN_MATCH(LIO, insn) ||
239                    ARM_INSN_MATCH(SIO, insn)) {
240                 uregs = 0x3;
241                 if ((ARM_INSN_REG_RN(insn) == 15) ||
242                     (ARM_INSN_MATCH(SIO, insn) &&
243                     (ARM_INSN_REG_RD(insn) == 15))) {
244                         pc_dep = 1;
245                 }
246         /* Rn, Rm, Rs */
247         } else if (ARM_INSN_MATCH(DPRS, insn)) {
248                 uregs = 0xd;
249                 if ((ARM_INSN_REG_RN(insn) == 15) ||
250                     (ARM_INSN_REG_RM(insn) == 15) ||
251                     (ARM_INSN_REG_RS(insn) == 15)) {
252                         pc_dep = 1;
253                 }
254         /* register list */
255         } else if (ARM_INSN_MATCH(SM, insn)) {
256                 uregs = 0x10;
257                 if (ARM_INSN_REG_MR(insn, 15)) {
258                         pc_dep = 1;
259                 }
260         }
261
262         /* check instructions that can write result to SP and uses PC */
263         if (pc_dep && (ARM_INSN_REG_RD(insn) == 13)) {
264                 printk("Error in %s at %d: instruction check failed (arm)\n",
265                        __FILE__, __LINE__);
266                 return -EFAULT;
267         }
268
269         if (unlikely(uregs && pc_dep)) {
270                 memcpy(tramp, pc_dep_insn_execbuf, KPROBES_TRAMP_LEN);
271                 if (prep_pc_dep_insn_execbuf(tramp, insn, uregs) != 0) {
272                         printk("Error in %s at %d: failed "
273                                "to prepare exec buffer for insn %lx!",
274                                __FILE__, __LINE__, insn);
275                         return -EINVAL;
276                 }
277
278                 tramp[6] = addr + 8;
279         } else {
280                 memcpy(tramp, gen_insn_execbuf, KPROBES_TRAMP_LEN);
281                 tramp[KPROBES_TRAMP_INSN_IDX] = insn;
282         }
283
284         /* TODO: remove for kprobe */
285         tramp[KPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
286         tramp[7] = addr + 4;
287
288         return 0;
289 }
290 EXPORT_SYMBOL_GPL(arch_make_trampoline_arm);
291
292 int arch_prepare_kprobe(struct kprobe *p, struct slot_manager *sm)
293 {
294         unsigned long addr = (unsigned long)p->addr;
295         unsigned long insn = p->opcode = *p->addr;
296         unsigned long *tramp;
297         int ret;
298
299         tramp = alloc_insn_slot(sm);
300         if (tramp == NULL)
301                 return -ENOMEM;
302
303         ret = arch_make_trampoline_arm(addr, insn, tramp);
304         if (ret) {
305                 free_insn_slot(sm, tramp);
306                 return ret;
307         }
308
309         flush_icache_range((unsigned long)tramp,
310                            (unsigned long)tramp + KPROBES_TRAMP_LEN);
311
312         p->ainsn.insn = tramp;
313
314         return 0;
315 }
316
317 void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
318 {
319         if (p->ss_addr) {
320                 regs->ARM_pc = (unsigned long)p->ss_addr;
321                 p->ss_addr = NULL;
322         } else {
323                 regs->ARM_pc = (unsigned long)p->ainsn.insn;
324         }
325 }
326 EXPORT_SYMBOL_GPL(prepare_singlestep);
327
328 void save_previous_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p_run)
329 {
330         kcb->prev_kprobe.kp = kprobe_running();
331         kcb->prev_kprobe.status = kcb->kprobe_status;
332 }
333
334 void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
335 {
336         __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
337         kcb->kprobe_status = kcb->prev_kprobe.status;
338 }
339
340 void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
341 {
342         __get_cpu_var(current_kprobe) = p;
343         DBPRINTF ("set_current_kprobe: p=%p addr=%p\n", p, p->addr);
344 }
345
346 static int kprobe_handler(struct pt_regs *regs)
347 {
348         struct kprobe *p, *cur;
349         struct kprobe_ctlblk *kcb;
350
351         kcb = get_kprobe_ctlblk();
352         cur = kprobe_running();
353         p = get_kprobe((void *)regs->ARM_pc);
354
355         if (p) {
356                 if (cur) {
357                         /* Kprobe is pending, so we're recursing. */
358                         switch (kcb->kprobe_status) {
359                         case KPROBE_HIT_ACTIVE:
360                         case KPROBE_HIT_SSDONE:
361                                 /* A pre- or post-handler probe got us here. */
362                                 kprobes_inc_nmissed_count(p);
363                                 save_previous_kprobe(kcb, NULL);
364                                 set_current_kprobe(p, 0, 0);
365                                 kcb->kprobe_status = KPROBE_REENTER;
366                                 prepare_singlestep(p, regs);
367                                 restore_previous_kprobe(kcb);
368                                 break;
369                         default:
370                                 /* impossible cases */
371                                 BUG();
372                         }
373                 } else {
374                         set_current_kprobe(p, 0, 0);
375                         kcb->kprobe_status = KPROBE_HIT_ACTIVE;
376
377                         if (!p->pre_handler || !p->pre_handler(p, regs)) {
378                                 kcb->kprobe_status = KPROBE_HIT_SS;
379                                 prepare_singlestep(p, regs);
380                                 reset_current_kprobe();
381                         }
382                 }
383         } else {
384                 goto no_kprobe;
385         }
386
387         return 0;
388
389 no_kprobe:
390         printk("no_kprobe: Not one of ours: let kernel handle it %p\n",
391                         (unsigned long *)regs->ARM_pc);
392         return 1;
393 }
394
395 int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
396 {
397         int ret;
398         unsigned long flags;
399
400 #ifdef SUPRESS_BUG_MESSAGES
401         int swap_oops_in_progress;
402         /* oops_in_progress used to avoid BUG() messages
403          * that slow down kprobe_handler() execution */
404         swap_oops_in_progress = oops_in_progress;
405         oops_in_progress = 1;
406 #endif
407
408         local_irq_save(flags);
409         preempt_disable();
410         ret = kprobe_handler(regs);
411         preempt_enable_no_resched();
412         local_irq_restore(flags);
413
414 #ifdef SUPRESS_BUG_MESSAGES
415         oops_in_progress = swap_oops_in_progress;
416 #endif
417
418         return ret;
419 }
420
421 int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
422 {
423         struct jprobe *jp = container_of(p, struct jprobe, kp);
424         kprobe_pre_entry_handler_t pre_entry = (kprobe_pre_entry_handler_t)jp->pre_entry;
425         entry_point_t entry = (entry_point_t)jp->entry;
426         pre_entry = (kprobe_pre_entry_handler_t)jp->pre_entry;
427
428         if (pre_entry) {
429                 p->ss_addr = (void *)pre_entry (jp->priv_arg, regs);
430         }
431
432         if (entry) {
433                 entry(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2,
434                       regs->ARM_r3, regs->ARM_r4, regs->ARM_r5);
435         } else {
436                 dbi_jprobe_return();
437         }
438
439         return 0;
440 }
441
442 void dbi_jprobe_return (void)
443 {
444 }
445
446 int longjmp_break_handler (struct kprobe *p, struct pt_regs *regs)
447 {
448         return 0;
449 }
450 EXPORT_SYMBOL_GPL(longjmp_break_handler);
451
452 #ifdef CONFIG_STRICT_MEMORY_RWX
453 extern void mem_text_write_kernel_word(unsigned long *addr, unsigned long word);
454 #endif
455
456 void arch_arm_kprobe(struct kprobe *p)
457 {
458 #ifdef CONFIG_STRICT_MEMORY_RWX
459         mem_text_write_kernel_word(p->addr, BREAKPOINT_INSTRUCTION);
460 #else
461         *p->addr = BREAKPOINT_INSTRUCTION;
462         flush_icache_range((unsigned long)p->addr, (unsigned long)p->addr + sizeof(kprobe_opcode_t));
463 #endif
464 }
465
466 void arch_disarm_kprobe(struct kprobe *p)
467 {
468 #ifdef CONFIG_STRICT_MEMORY_RWX
469         mem_text_write_kernel_word(p->addr, p->opcode);
470 #else
471         *p->addr = p->opcode;
472         flush_icache_range((unsigned long)p->addr, (unsigned long)p->addr + sizeof(kprobe_opcode_t));
473 #endif
474 }
475
476 void __naked kretprobe_trampoline(void)
477 {
478         __asm__ __volatile__ (
479                 "stmdb  sp!, {r0 - r11}         \n\t"
480                 "mov    r1, sp                  \n\t"
481                 "mov    r0, #0                  \n\t"
482                 "bl     trampoline_probe_handler\n\t"
483                 "mov    lr, r0                  \n\t"
484                 "ldmia  sp!, {r0 - r11}         \n\t"
485                 "bx     lr                      \n\t"
486                 : : : "memory");
487 }
488
489 void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
490 {
491         unsigned long *ptr_ret_addr;
492
493         /* for __switch_to probe */
494         if ((unsigned long)ri->rp->kp.addr == sched_addr) {
495                 struct thread_info *tinfo = (struct thread_info *)regs->ARM_r2;
496
497                 ptr_ret_addr = (unsigned long *)&tinfo->cpu_context.pc;
498                 ri->sp = NULL;
499                 ri->task = tinfo->task;
500         } else {
501                 ptr_ret_addr = (unsigned long *)&regs->ARM_lr;
502                 ri->sp = (unsigned long *)regs->ARM_sp;
503         }
504
505         /* Save the return address */
506         ri->ret_addr = (unsigned long *)*ptr_ret_addr;
507
508         /* Replace the return addr with trampoline addr */
509         *ptr_ret_addr = (unsigned long)&kretprobe_trampoline;
510 }
511
512 void swap_register_undef_hook(struct undef_hook *hook)
513 {
514         __swap_register_undef_hook(hook);
515 }
516 EXPORT_SYMBOL_GPL(swap_register_undef_hook);
517
518 void swap_unregister_undef_hook(struct undef_hook *hook)
519 {
520         __swap_unregister_undef_hook(hook);
521 }
522 EXPORT_SYMBOL_GPL(swap_unregister_undef_hook);
523
524 // kernel probes hook
525 static struct undef_hook undef_ho_k = {
526         .instr_mask     = 0xffffffff,
527         .instr_val      = BREAKPOINT_INSTRUCTION,
528         .cpsr_mask      = MODE_MASK,
529         .cpsr_val       = SVC_MODE,
530         .fn             = kprobe_trap_handler
531 };
532
533 int arch_init_kprobes(void)
534 {
535         // Register hooks (kprobe_handler)
536         __swap_register_undef_hook = (void *)swap_ksyms("register_undef_hook");
537         if (__swap_register_undef_hook == NULL) {
538                 printk("no register_undef_hook symbol found!\n");
539                 return -1;
540         }
541
542         // Unregister hooks (kprobe_handler)
543         __swap_unregister_undef_hook = (void *)swap_ksyms("unregister_undef_hook");
544         if (__swap_unregister_undef_hook == NULL) {
545                 printk("no unregister_undef_hook symbol found!\n");
546                 return -1;
547         }
548
549         swap_register_undef_hook(&undef_ho_k);
550
551         return 0;
552 }
553
554 void arch_exit_kprobes(void)
555 {
556         swap_unregister_undef_hook(&undef_ho_k);
557 }
558
559 /* export symbol for trampoline_arm.h */
560 EXPORT_SYMBOL_GPL(gen_insn_execbuf);
561 EXPORT_SYMBOL_GPL(pc_dep_insn_execbuf);
562 EXPORT_SYMBOL_GPL(b_r_insn_execbuf);
563 EXPORT_SYMBOL_GPL(b_cond_insn_execbuf);
564 EXPORT_SYMBOL_GPL(blx_off_insn_execbuf);