f4faca56849ee44dbad8fe7d50c9ed421dccf648
[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("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 = (kprobe_pre_entry_handler_t)jp->pre_entry;
131         entry_point_t entry = (entry_point_t)jp->entry;
132         unsigned long args[6];
133
134         /* FIXME some user space apps crash if we clean interrupt bit */
135         //regs->EREG(flags) &= ~IF_MASK;
136 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
137         trace_hardirqs_off();
138 #endif
139
140         /* read first 6 args from stack */
141         if (!read_proc_vm_atomic(current, regs->EREG(sp) + 4, args, sizeof(args)))
142                 panic("failed to read user space func arguments %lx!\n", regs->EREG(sp) + 4);
143
144         if (pre_entry)
145                 p->ss_addr[smp_processor_id()] = (kprobe_opcode_t *)
146                                                  pre_entry(jp->priv_arg, regs);
147
148         if (entry)
149                 entry(args[0], args[1], args[2], args[3], args[4], args[5]);
150         else
151                 arch_ujprobe_return();
152
153         return 0;
154 }
155
156 /**
157  * @brief Prepares uretprobe for x86.
158  *
159  * @param ri Pointer to the uretprobe instance.
160  * @param regs Pointer to CPU register data.
161  * @return Void.
162  */
163 void arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
164 {
165         /* Replace the return addr with trampoline addr */
166         unsigned long ra = trampoline_addr(&ri->rp->up);
167         ri->sp = (kprobe_opcode_t *)regs->sp;
168
169         if (!read_proc_vm_atomic(current, regs->EREG(sp), &(ri->ret_addr), sizeof(ri->ret_addr)))
170                 panic("failed to read user space func ra %lx!\n", regs->EREG(sp));
171
172         if (!write_proc_vm_atomic(current, regs->EREG(sp), &ra, sizeof(ra)))
173                 panic("failed to write user space func ra %lx!\n", regs->EREG(sp));
174 }
175
176 /**
177  * @brief Disarms uretprobe on x86 arch.
178  *
179  * @param ri Pointer to the uretprobe instance.
180  * @param task Pointer to the task for which the probe.
181  * @return 0 on success,\n
182  * negative error code on error.
183  */
184 int arch_disarm_urp_inst(struct uretprobe_instance *ri,
185                          struct task_struct *task)
186 {
187         int len;
188         unsigned long ret_addr;
189         unsigned long sp = (unsigned long)ri->sp;
190         unsigned long tramp_addr = trampoline_addr(&ri->rp->up);
191         len = read_proc_vm_atomic(task, sp, &ret_addr, sizeof(ret_addr));
192         if (len != sizeof(ret_addr)) {
193                 printk("---> %s (%d/%d): failed to read stack from %08lx\n",
194                        task->comm, task->tgid, task->pid, sp);
195                 return -EFAULT;
196         }
197
198         if (tramp_addr == ret_addr) {
199                 len = write_proc_vm_atomic(task, sp, &ri->ret_addr,
200                                            sizeof(ri->ret_addr));
201                 if (len != sizeof(ri->ret_addr)) {
202                         printk("---> %s (%d/%d): failed to write "
203                                "orig_ret_addr to %08lx",
204                                task->comm, task->tgid, task->pid, sp);
205                         return -EFAULT;
206                 }
207         } else {
208                 printk("---> %s (%d/%d): trampoline NOT found at sp = %08lx\n",
209                        task->comm, task->tgid, task->pid, sp);
210                 return -ENOENT;
211         }
212
213         return 0;
214 }
215
216 /**
217  * @brief Gets trampoline address.
218  *
219  * @param p Pointer to the uprobe's kprobe.
220  * @param regs Pointer to CPU register data.
221  * @return Trampoline address.
222  */
223 unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
224 {
225         return trampoline_addr(kp2up(p));
226 }
227
228 /**
229  * @brief Restores return address.
230  *
231  * @param orig_ret_addr Original return address.
232  * @param regs Pointer to CPU register data.
233  * @return Void.
234  */
235 void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs)
236 {
237         regs->EREG(ip) = orig_ret_addr;
238 }
239
240 /**
241  * @brief Removes uprobe.
242  *
243  * @param up Pointer to the target uprobe.
244  * @return Void.
245  */
246 void arch_remove_uprobe(struct uprobe *up)
247 {
248         struct kprobe *p = up2kp(up);
249
250         swap_slot_free(up->sm, p->ainsn.insn);
251 }
252
253 static void set_user_jmp_op(void *from, void *to)
254 {
255         struct __arch_jmp_op
256         {
257                 char op;
258                 long raddr;
259         } __attribute__ ((packed)) jop;
260
261         jop.raddr = (long)(to) - ((long)(from) + 5);
262         jop.op = RELATIVEJUMP_INSTRUCTION;
263
264         if (!write_proc_vm_atomic(current, (unsigned long)from, &jop, sizeof(jop)))
265                 panic("failed to write jump opcode to user space %p!\n", from);
266 }
267
268 static void resume_execution(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
269 {
270         unsigned long *tos, tos_dword = 0;
271         unsigned long copy_eip = (unsigned long)p->ainsn.insn;
272         unsigned long orig_eip = (unsigned long)p->addr;
273         kprobe_opcode_t insns[2];
274
275         regs->EREG(flags) &= ~TF_MASK;
276
277         tos = (unsigned long *)&tos_dword;
278         if (!read_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
279                 panic("failed to read dword from top of the user space stack %lx!\n", regs->EREG(sp));
280
281         if (!read_proc_vm_atomic(current, (unsigned long)p->ainsn.insn, insns, 2 * sizeof(kprobe_opcode_t)))
282                 panic("failed to read first 2 opcodes of instruction copy from user space %p!\n", p->ainsn.insn);
283
284         switch (insns[0]) {
285                 case 0x9c:              /* pushfl */
286                         *tos &= ~(TF_MASK | IF_MASK);
287                         *tos |= flags & (TF_MASK | IF_MASK);
288                         break;
289                 case 0xc2:              /* iret/ret/lret */
290                 case 0xc3:
291                 case 0xca:
292                 case 0xcb:
293                 case 0xcf:
294                 case 0xea:              /* jmp absolute -- eip is correct */
295                         /* eip is already adjusted, no more changes required */
296                         p->ainsn.boostable = 1;
297                         goto no_change;
298                 case 0xe8:              /* call relative - Fix return addr */
299                         *tos = orig_eip + (*tos - copy_eip);
300                         break;
301                 case 0x9a:              /* call absolute -- same as call absolute, indirect */
302                         *tos = orig_eip + (*tos - copy_eip);
303
304                         if (!write_proc_vm_atomic(current, regs->EREG (sp), &tos_dword, sizeof(tos_dword)))
305                                 panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG (sp));
306
307                         goto no_change;
308                 case 0xff:
309                         if ((insns[1] & 0x30) == 0x10) {
310                                 /*
311                                  * call absolute, indirect
312                                  * Fix return addr; eip is correct.
313                                  * But this is not boostable
314                                  */
315                                 *tos = orig_eip + (*tos - copy_eip);
316
317                                 if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
318                                         panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG(sp));
319
320                                 goto no_change;
321                         } else if (((insns[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
322                                    ((insns[1] & 0x31) == 0x21)) {
323                                 /* jmp far, absolute indirect */
324                                 /* eip is correct. And this is boostable */
325                                 p->ainsn.boostable = 1;
326                                 goto no_change;
327                         }
328                 case 0xf3:
329                         if (insns[1] == 0xc3)
330                                 /* repz ret special handling: no more changes */
331                                 goto no_change;
332                         break;
333                 default:
334                         break;
335         }
336
337         if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
338                 panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG(sp));
339
340         if (p->ainsn.boostable == 0) {
341                 if ((regs->EREG(ip) > copy_eip) && (regs->EREG(ip) - copy_eip) + 5 < MAX_INSN_SIZE) {
342                         /*
343                          * These instructions can be executed directly if it
344                          * jumps back to correct address.
345                          */
346                         set_user_jmp_op((void *) regs->EREG(ip), (void *)orig_eip + (regs->EREG(ip) - copy_eip));
347                         p->ainsn.boostable = 1;
348                 } else {
349                         p->ainsn.boostable = -1;
350                 }
351         }
352
353         regs->EREG(ip) = orig_eip + (regs->EREG(ip) - copy_eip);
354
355 no_change:
356         return;
357 }
358
359 static int make_trampoline(struct uprobe *up)
360 {
361         struct kprobe *p = up2kp(up);
362         struct task_struct *task = up->task;
363         void *tramp;
364
365         tramp = swap_slot_alloc(up->sm);
366         if (tramp == 0) {
367                 printk("trampoline out of memory\n");
368                 return -ENOMEM;
369         }
370
371         if (!write_proc_vm_atomic(task, (unsigned long)tramp,
372                                   up->atramp.tramp,
373                                   sizeof(up->atramp.tramp))) {
374                 swap_slot_free(up->sm, tramp);
375                 panic("failed to write memory %p!\n", tramp);
376                 return -EINVAL;
377         }
378
379         p->ainsn.insn = tramp;
380
381         return 0;
382 }
383
384 static int uprobe_handler(struct pt_regs *regs)
385 {
386         struct kprobe *p;
387         kprobe_opcode_t *addr;
388         struct task_struct *task = current;
389         pid_t tgid = task->tgid;
390
391         save_current_flags(regs);
392
393         addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
394         p = get_ukprobe(addr, tgid);
395
396         if (p == NULL) {
397                 void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX;
398
399                 p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs);
400                 if (p == NULL) {
401                         printk("no_uprobe\n");
402                         return 0;
403                 }
404
405                 trampoline_uprobe_handler(p, regs);
406                 return 1;
407         } else {
408                 if (p->ainsn.insn == NULL) {
409                         struct uprobe *up = kp2up(p);
410
411                         make_trampoline(up);
412
413                         /* for uretprobe */
414                         add_uprobe_table(p);
415                 }
416
417                 if (!p->pre_handler || !p->pre_handler(p, regs)) {
418                         if (p->ainsn.boostable == 1 && !p->post_handler) {
419                                 regs->EREG(ip) = (unsigned long)p->ainsn.insn;
420                                 return 1;
421                         }
422
423                         prepare_singlestep(p, regs);
424                 }
425         }
426
427         set_current_probe(p);
428
429         return 1;
430 }
431
432 static int post_uprobe_handler(struct pt_regs *regs)
433 {
434         struct kprobe *p = get_current_probe();
435         unsigned long flags = __get_cpu_var(ucb).flags;
436
437         if (p == NULL)
438                 return 0;
439
440         resume_execution(p, regs, flags);
441         restore_current_flags(regs);
442
443         reset_current_probe();
444
445         return 1;
446 }
447
448 static int uprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data)
449 {
450         struct die_args *args = (struct die_args *)data;
451         int ret = NOTIFY_DONE;
452
453         if (args->regs == NULL || !user_mode_vm(args->regs))
454                 return ret;
455
456         switch (val) {
457 #ifdef CONFIG_KPROBES
458                 case DIE_INT3:
459 #else
460                 case DIE_TRAP:
461 #endif
462                         if (uprobe_handler(args->regs))
463                                 ret = NOTIFY_STOP;
464                         break;
465                 case DIE_DEBUG:
466                         if (post_uprobe_handler(args->regs))
467                                 ret = NOTIFY_STOP;
468                         break;
469                 default:
470                         break;
471         }
472
473         return ret;
474 }
475
476 static struct notifier_block uprobe_exceptions_nb = {
477         .notifier_call = uprobe_exceptions_notify,
478         .priority = INT_MAX
479 };
480
481 /**
482  * @brief Registers notify.
483  *
484  * @return register_die_notifier result.
485  */
486 int swap_arch_init_uprobes(void)
487 {
488         return register_die_notifier(&uprobe_exceptions_nb);
489 }
490
491 /**
492  * @brief Unregisters notify.
493  *
494  * @return Void.
495  */
496 void swap_arch_exit_uprobes(void)
497 {
498         unregister_die_notifier(&uprobe_exceptions_nb);
499 }
500