Merge branch 'tizen_2.4' into tizen_2.4_dev
[kernel/swap-modules.git] / uprobe / arch / x86 / swap-asm / swap_uprobes.c
1 /**
2  * uprobe/arch/asm-x86/swap_uprobes.c
3  * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial
4  * implementation; Support x86/ARM/MIPS for both user and kernel spaces.
5  * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for
6  * separating core and arch parts
7  *
8  * @section LICENSE
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23  *
24  * @section COPYRIGHT
25  *
26  * Copyright (C) Samsung Electronics, 2006-2010
27  *
28  * @section DESCRIPTION
29  *
30  * Arch-dependent uprobe interface implementation for x86.
31  */
32
33
34 #include <linux/kdebug.h>
35
36 #include <kprobe/swap_slots.h>
37 #include <uprobe/swap_uprobes.h>
38
39 #include "swap_uprobes.h"
40
41
42 /**
43  * @struct uprobe_ctlblk
44  * @brief Uprobe control block
45  */
46 struct uprobe_ctlblk {
47         unsigned long flags;            /**< Flags */
48         struct kprobe *p;               /**< Pointer to the uprobe's kprobe */
49 };
50
51 static unsigned long trampoline_addr(struct uprobe *up)
52 {
53         return (unsigned long)(up->kp.ainsn.insn +
54                                UPROBES_TRAMP_RET_BREAK_IDX);
55 }
56
57 static DEFINE_PER_CPU(struct uprobe_ctlblk, ucb) = { 0, NULL };
58
59 static struct kprobe *get_current_probe(void)
60 {
61         return __get_cpu_var(ucb).p;
62 }
63
64 static void set_current_probe(struct kprobe *p)
65 {
66         __get_cpu_var(ucb).p = p;
67 }
68
69 static void reset_current_probe(void)
70 {
71         set_current_probe(NULL);
72 }
73
74 static void save_current_flags(struct pt_regs *regs)
75 {
76         __get_cpu_var(ucb).flags = regs->EREG(flags);
77 }
78
79 static void restore_current_flags(struct pt_regs *regs)
80 {
81         regs->EREG(flags) &= ~IF_MASK;
82         regs->EREG(flags) |= __get_cpu_var(ucb).flags & IF_MASK;
83 }
84
85 /**
86  * @brief Prepares uprobe for x86.
87  *
88  * @param up Pointer to the uprobe.
89  * @return 0 on success,\n
90  * -1 on error.
91  */
92 int arch_prepare_uprobe(struct uprobe *up)
93 {
94         int ret = 0;
95         struct kprobe *p = up2kp(up);
96         struct task_struct *task = up->task;
97         u8 *tramp = up->atramp.tramp;
98         enum { call_relative_opcode = 0xe8 };
99
100         if (!read_proc_vm_atomic(task, (unsigned long)p->addr,
101                                  tramp, MAX_INSN_SIZE))
102                 panic("failed to read memory %p!\n", p->addr);
103         /* TODO: this is a workaround */
104         if (tramp[0] == call_relative_opcode) {
105                 printk(KERN_INFO "cannot install probe: 1st instruction is call\n");
106                 return -1;
107         }
108
109         tramp[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
110
111         /* TODO: remove dual info */
112         p->opcode = tramp[0];
113
114         p->ainsn.boostable = swap_can_boost(tramp) ? 0 : -1;
115
116         return ret;
117 }
118
119 /**
120  * @brief Jump pre-handler.
121  *
122  * @param p Pointer to the uprobe's kprobe.
123  * @param regs Pointer to CPU register data.
124  * @return 0.
125  */
126 int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
127 {
128         struct uprobe *up = container_of(p, struct uprobe, kp);
129         struct ujprobe *jp = container_of(up, struct ujprobe, up);
130         kprobe_pre_entry_handler_t pre_entry =
131                 (kprobe_pre_entry_handler_t)jp->pre_entry;
132         entry_point_t entry = (entry_point_t)jp->entry;
133         unsigned long args[6];
134
135         /* FIXME some user space apps crash if we clean interrupt bit */
136         /* regs->EREG(flags) &= ~IF_MASK; */
137 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
138         trace_hardirqs_off();
139 #endif
140
141         /* read first 6 args from stack */
142         if (!read_proc_vm_atomic(current, regs->EREG(sp) + 4,
143                                  args, sizeof(args)))
144                 panic("failed to read user space func arguments %lx!\n",
145                       regs->EREG(sp) + 4);
146
147         if (pre_entry)
148                 p->ss_addr[smp_processor_id()] = (kprobe_opcode_t *)
149                                                  pre_entry(jp->priv_arg, regs);
150
151         if (entry)
152                 entry(args[0], args[1], args[2], args[3], args[4], args[5]);
153         else
154                 arch_ujprobe_return();
155
156         return 0;
157 }
158
159 /**
160  * @brief Prepares uretprobe for x86.
161  *
162  * @param ri Pointer to the uretprobe instance.
163  * @param regs Pointer to CPU register data.
164  * @return Void.
165  */
166 void arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
167 {
168         /* Replace the return addr with trampoline addr */
169         unsigned long ra = trampoline_addr(&ri->rp->up);
170         ri->sp = (kprobe_opcode_t *)regs->sp;
171
172         if (!read_proc_vm_atomic(current, regs->EREG(sp), &(ri->ret_addr),
173                                  sizeof(ri->ret_addr)))
174                 panic("failed to read user space func ra %lx!\n",
175                       regs->EREG(sp));
176
177         if (!write_proc_vm_atomic(current, regs->EREG(sp), &ra, sizeof(ra)))
178                 panic("failed to write user space func ra %lx!\n",
179                       regs->EREG(sp));
180 }
181
182 /**
183  * @brief Disarms uretprobe on x86 arch.
184  *
185  * @param ri Pointer to the uretprobe instance.
186  * @param task Pointer to the task for which the probe.
187  * @return 0 on success,\n
188  * negative error code on error.
189  */
190 int arch_disarm_urp_inst(struct uretprobe_instance *ri,
191                          struct task_struct *task)
192 {
193         int len;
194         unsigned long ret_addr;
195         unsigned long sp = (unsigned long)ri->sp;
196         unsigned long tramp_addr = trampoline_addr(&ri->rp->up);
197         len = read_proc_vm_atomic(task, sp, &ret_addr, sizeof(ret_addr));
198         if (len != sizeof(ret_addr)) {
199                 printk(KERN_INFO "---> %s (%d/%d): failed to read stack from %08lx\n",
200                        task->comm, task->tgid, task->pid, sp);
201                 return -EFAULT;
202         }
203
204         if (tramp_addr == ret_addr) {
205                 len = write_proc_vm_atomic(task, sp, &ri->ret_addr,
206                                            sizeof(ri->ret_addr));
207                 if (len != sizeof(ri->ret_addr)) {
208                         printk(KERN_INFO "---> %s (%d/%d): failed to write "
209                                "orig_ret_addr to %08lx",
210                                task->comm, task->tgid, task->pid, sp);
211                         return -EFAULT;
212                 }
213         } else {
214                 printk(KERN_INFO "---> %s (%d/%d): trampoline NOT found at sp = %08lx\n",
215                        task->comm, task->tgid, task->pid, sp);
216                 return -ENOENT;
217         }
218
219         return 0;
220 }
221
222 /**
223  * @brief Gets trampoline address.
224  *
225  * @param p Pointer to the uprobe's kprobe.
226  * @param regs Pointer to CPU register data.
227  * @return Trampoline address.
228  */
229 unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
230 {
231         return trampoline_addr(kp2up(p));
232 }
233
234 /**
235  * @brief Restores return address.
236  *
237  * @param orig_ret_addr Original return address.
238  * @param regs Pointer to CPU register data.
239  * @return Void.
240  */
241 void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs)
242 {
243         regs->EREG(ip) = orig_ret_addr;
244 }
245
246 /**
247  * @brief Removes uprobe.
248  *
249  * @param up Pointer to the target uprobe.
250  * @return Void.
251  */
252 void arch_remove_uprobe(struct uprobe *up)
253 {
254         struct kprobe *p = up2kp(up);
255
256         swap_slot_free(up->sm, p->ainsn.insn);
257 }
258
259 static void set_user_jmp_op(void *from, void *to)
260 {
261         struct __arch_jmp_op {
262                 char op;
263                 long raddr;
264         } __packed jop;
265
266         jop.raddr = (long)(to) - ((long)(from) + 5);
267         jop.op = RELATIVEJUMP_INSTRUCTION;
268
269         if (!write_proc_vm_atomic(current, (unsigned long)from, &jop,
270                                   sizeof(jop)))
271                 panic("failed to write jump opcode to user space %p!\n", from);
272 }
273
274 static void resume_execution(struct kprobe *p,
275                              struct pt_regs *regs,
276                              unsigned long flags)
277 {
278         unsigned long *tos, tos_dword = 0;
279         unsigned long copy_eip = (unsigned long)p->ainsn.insn;
280         unsigned long orig_eip = (unsigned long)p->addr;
281         kprobe_opcode_t insns[2];
282
283         regs->EREG(flags) &= ~TF_MASK;
284
285         tos = (unsigned long *)&tos_dword;
286         if (!read_proc_vm_atomic(current, regs->EREG(sp), &tos_dword,
287                                  sizeof(tos_dword)))
288                 panic("failed to read dword from top of the user space stack "
289                       "%lx!\n", regs->EREG(sp));
290
291         if (!read_proc_vm_atomic(current, (unsigned long)p->ainsn.insn, insns,
292                                  2 * sizeof(kprobe_opcode_t)))
293                 panic("failed to read first 2 opcodes of instruction copy "
294                       "from user space %p!\n", p->ainsn.insn);
295
296         switch (insns[0]) {
297         case 0x9c: /* pushfl */
298                 *tos &= ~(TF_MASK | IF_MASK);
299                 *tos |= flags & (TF_MASK | IF_MASK);
300                 break;
301         case 0xc2: /* iret/ret/lret */
302         case 0xc3:
303         case 0xca:
304         case 0xcb:
305         case 0xcf:
306         case 0xea: /* jmp absolute -- eip is correct */
307                 /* eip is already adjusted, no more changes required */
308                 p->ainsn.boostable = 1;
309                 goto no_change;
310         case 0xe8: /* call relative - Fix return addr */
311                 *tos = orig_eip + (*tos - copy_eip);
312                 break;
313         case 0x9a: /* call absolute -- same as call absolute, indirect */
314                 *tos = orig_eip + (*tos - copy_eip);
315
316                 if (!write_proc_vm_atomic(current,
317                                           regs->EREG(sp),
318                                           &tos_dword,
319                                           sizeof(tos_dword)))
320                         panic("failed to write dword to top of the"
321                               " user space stack %lx!\n",
322                               regs->EREG(sp));
323
324                 goto no_change;
325         case 0xff:
326                 if ((insns[1] & 0x30) == 0x10) {
327                         /*
328                          * call absolute, indirect
329                          * Fix return addr; eip is correct.
330                          * But this is not boostable
331                          */
332                         *tos = orig_eip + (*tos - copy_eip);
333
334                         if (!write_proc_vm_atomic(current, regs->EREG(sp),
335                                                   &tos_dword,
336                                                   sizeof(tos_dword)))
337                                 panic("failed to write dword to top of the "
338                                       "user space stack %lx!\n",
339                                       regs->EREG(sp));
340
341                         goto no_change;
342                 } else if (((insns[1] & 0x31) == 0x20) || /* jmp near, absolute
343                                                            * indirect */
344                            ((insns[1] & 0x31) == 0x21)) {
345                         /* jmp far, absolute indirect */
346                         /* eip is correct. And this is boostable */
347                         p->ainsn.boostable = 1;
348                         goto no_change;
349                 }
350         case 0xf3:
351                 if (insns[1] == 0xc3)
352                         /* repz ret special handling: no more changes */
353                         goto no_change;
354                 break;
355         default:
356                 break;
357         }
358
359         if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword,
360                                   sizeof(tos_dword)))
361                 panic("failed to write dword to top of the user space stack "
362                       "%lx!\n", regs->EREG(sp));
363
364         if (p->ainsn.boostable == 0) {
365                 if ((regs->EREG(ip) > copy_eip) && (regs->EREG(ip) - copy_eip) +
366                     5 < MAX_INSN_SIZE) {
367                         /*
368                          * These instructions can be executed directly if it
369                          * jumps back to correct address.
370                          */
371                         set_user_jmp_op((void *) regs->EREG(ip),
372                                         (void *)orig_eip +
373                                         (regs->EREG(ip) - copy_eip));
374                         p->ainsn.boostable = 1;
375                 } else {
376                         p->ainsn.boostable = -1;
377                 }
378         }
379
380         regs->EREG(ip) = orig_eip + (regs->EREG(ip) - copy_eip);
381
382 no_change:
383         return;
384 }
385
386 static int make_trampoline(struct uprobe *up)
387 {
388         struct kprobe *p = up2kp(up);
389         struct task_struct *task = up->task;
390         void *tramp;
391
392         tramp = swap_slot_alloc(up->sm);
393         if (tramp == 0) {
394                 printk(KERN_INFO "trampoline out of memory\n");
395                 return -ENOMEM;
396         }
397
398         if (!write_proc_vm_atomic(task, (unsigned long)tramp,
399                                   up->atramp.tramp,
400                                   sizeof(up->atramp.tramp))) {
401                 swap_slot_free(up->sm, tramp);
402                 panic("failed to write memory %p!\n", tramp);
403                 return -EINVAL;
404         }
405
406         p->ainsn.insn = tramp;
407
408         return 0;
409 }
410
411 static int uprobe_handler(struct pt_regs *regs)
412 {
413         struct kprobe *p;
414         kprobe_opcode_t *addr;
415         struct task_struct *task = current;
416         pid_t tgid = task->tgid;
417
418         save_current_flags(regs);
419
420         addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
421         p = get_ukprobe(addr, tgid);
422
423         if (p == NULL) {
424                 void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX;
425
426                 p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs);
427                 if (p == NULL) {
428                         printk(KERN_INFO "no_uprobe\n");
429                         return 0;
430                 }
431
432                 trampoline_uprobe_handler(p, regs);
433                 return 1;
434         } else {
435                 if (p->ainsn.insn == NULL) {
436                         struct uprobe *up = kp2up(p);
437
438                         make_trampoline(up);
439
440                         /* for uretprobe */
441                         add_uprobe_table(p);
442                 }
443
444                 if (!p->pre_handler || !p->pre_handler(p, regs)) {
445
446                         if (p->ainsn.boostable == 1 && !p->post_handler) {
447                                 if (p->ss_addr[smp_processor_id()]) {
448                                         regs->EREG(ip) = (unsigned long)p->ss_addr[smp_processor_id()];
449                                         p->ss_addr[smp_processor_id()] = NULL;
450                                 } else {
451                                         regs->EREG(ip) = (unsigned long)p->ainsn.insn;
452                                 }
453                                 return 1;
454                         }
455
456                         prepare_singlestep(p, regs);
457                 }
458         }
459
460         set_current_probe(p);
461
462         return 1;
463 }
464
465 static int post_uprobe_handler(struct pt_regs *regs)
466 {
467         struct kprobe *p = get_current_probe();
468         unsigned long flags = __get_cpu_var(ucb).flags;
469
470         if (p == NULL)
471                 return 0;
472
473         resume_execution(p, regs, flags);
474         restore_current_flags(regs);
475
476         reset_current_probe();
477
478         return 1;
479 }
480
481 static int uprobe_exceptions_notify(struct notifier_block *self,
482                                     unsigned long val, void *data)
483 {
484         struct die_args *args = (struct die_args *)data;
485         int ret = NOTIFY_DONE;
486
487         if (args->regs == NULL || !user_mode_vm(args->regs))
488                 return ret;
489
490         switch (val) {
491 #ifdef CONFIG_KPROBES
492         case DIE_INT3:
493 #else
494         case DIE_TRAP:
495 #endif
496                 if (uprobe_handler(args->regs))
497                         ret = NOTIFY_STOP;
498                 break;
499         case DIE_DEBUG:
500                 if (post_uprobe_handler(args->regs))
501                         ret = NOTIFY_STOP;
502                 break;
503         default:
504                 break;
505         }
506
507         return ret;
508 }
509
510 static struct notifier_block uprobe_exceptions_nb = {
511         .notifier_call = uprobe_exceptions_notify,
512         .priority = INT_MAX
513 };
514
515 /**
516  * @brief Registers notify.
517  *
518  * @return register_die_notifier result.
519  */
520 int swap_arch_init_uprobes(void)
521 {
522         return register_die_notifier(&uprobe_exceptions_nb);
523 }
524
525 /**
526  * @brief Unregisters notify.
527  *
528  * @return Void.
529  */
530 void swap_arch_exit_uprobes(void)
531 {
532         unregister_die_notifier(&uprobe_exceptions_nb);
533 }
534