2ec59ac64a4ed2218dc97d8283c6be7689f97d2f
[kernel/swap-modules.git] / uprobe / arch / asm-x86 / swap_uprobes.c
1 /*
2  *  Dynamic Binary Instrumentation Module based on KProbes
3  *  modules/uprobe/arch/asm-x86/swap_uprobes.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  * 2008-2009    Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
22  *              Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
23  * 2010         Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
24  *
25  */
26
27 #include <linux/kdebug.h>
28 #include <kprobe/arch/asm/dbi_kprobes.h>
29 #include <uprobe/swap_uprobes.h>
30 #include <uprobe/arch/asm/swap_uprobes.h>
31 #include <kprobe/dbi_insn_slots.h>
32
33 struct uprobe_ctlblk {
34         unsigned long flags;
35         struct kprobe *p;
36 };
37
38 static unsigned long trampoline_addr(struct uprobe *up)
39 {
40         return (unsigned long)(up->kp.ainsn.insn +
41                                UPROBES_TRAMP_RET_BREAK_IDX);
42 }
43
44 static DEFINE_PER_CPU(struct uprobe_ctlblk, ucb) = { 0, NULL };
45
46 static struct kprobe *get_current_probe(void)
47 {
48         return __get_cpu_var(ucb).p;
49 }
50
51 static void set_current_probe(struct kprobe *p)
52 {
53         __get_cpu_var(ucb).p = p;
54 }
55
56 static void reset_current_probe(void)
57 {
58         set_current_probe(NULL);
59 }
60
61 static void save_current_flags(struct pt_regs *regs)
62 {
63         __get_cpu_var(ucb).flags = regs->EREG(flags);
64 }
65
66 static void restore_current_flags(struct pt_regs *regs)
67 {
68         regs->EREG(flags) &= ~IF_MASK;
69         regs->EREG(flags) |= __get_cpu_var(ucb).flags & IF_MASK;
70 }
71
72 int arch_prepare_uprobe(struct uprobe *up)
73 {
74         int ret = 0;
75         struct kprobe *p = up2kp(up);
76         struct task_struct *task = up->task;
77         u8 *tramp = up->atramp.tramp;
78         enum { call_relative_opcode = 0xe8 };
79
80         if (!read_proc_vm_atomic(task, (unsigned long)p->addr,
81                                  tramp, MAX_INSN_SIZE))
82                 panic("failed to read memory %p!\n", p->addr);
83         /* TODO: this is a workaround */
84         if (tramp[0] == call_relative_opcode) {
85                 printk("cannot install probe: 1st instruction is call\n");
86                 return -1;
87         }
88
89         tramp[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
90
91         /* TODO: remove dual info */
92         p->opcode = tramp[0];
93
94         p->ainsn.boostable = can_boost(tramp) ? 0 : -1;
95
96         return ret;
97 }
98
99 int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
100 {
101         struct uprobe *up = container_of(p, struct uprobe, kp);
102         struct ujprobe *jp = container_of(up, struct ujprobe, up);
103         kprobe_pre_entry_handler_t pre_entry = (kprobe_pre_entry_handler_t)jp->pre_entry;
104         entry_point_t entry = (entry_point_t)jp->entry;
105         unsigned long args[6];
106
107         /* FIXME some user space apps crash if we clean interrupt bit */
108         //regs->EREG(flags) &= ~IF_MASK;
109 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
110         trace_hardirqs_off();
111 #endif
112
113         /* read first 6 args from stack */
114         if (!read_proc_vm_atomic(current, regs->EREG(sp) + 4, args, sizeof(args)))
115                 panic("failed to read user space func arguments %lx!\n", regs->EREG(sp) + 4);
116
117         if (pre_entry)
118                 p->ss_addr = (kprobe_opcode_t *)pre_entry(jp->priv_arg, regs);
119
120         if (entry)
121                 entry(args[0], args[1], args[2], args[3], args[4], args[5]);
122         else
123                 arch_ujprobe_return();
124
125         return 0;
126 }
127
128 void arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
129 {
130         /* Replace the return addr with trampoline addr */
131         unsigned long ra = trampoline_addr(&ri->rp->up);
132         ri->sp = (kprobe_opcode_t *)regs->sp;
133
134         if (!read_proc_vm_atomic(current, regs->EREG(sp), &(ri->ret_addr), sizeof(ri->ret_addr)))
135                 panic("failed to read user space func ra %lx!\n", regs->EREG(sp));
136
137         if (!write_proc_vm_atomic(current, regs->EREG(sp), &ra, sizeof(ra)))
138                 panic("failed to write user space func ra %lx!\n", regs->EREG(sp));
139 }
140
141 int arch_disarm_urp_inst(struct uretprobe_instance *ri,
142                          struct task_struct *task)
143 {
144         int len;
145         unsigned long ret_addr;
146         unsigned long sp = (unsigned long)ri->sp;
147         unsigned long tramp_addr = trampoline_addr(&ri->rp->up);
148         len = read_proc_vm_atomic(task, sp, &ret_addr, sizeof(ret_addr));
149         if (len != sizeof(ret_addr)) {
150                 printk("---> %s (%d/%d): failed to read stack from %08lx\n",
151                        task->comm, task->tgid, task->pid, sp);
152                 return -EFAULT;
153         }
154
155         if (tramp_addr == ret_addr) {
156                 len = write_proc_vm_atomic(task, sp, &ri->ret_addr,
157                                            sizeof(ri->ret_addr));
158                 if (len != sizeof(ri->ret_addr)) {
159                         printk("---> %s (%d/%d): failed to write "
160                                "orig_ret_addr to %08lx",
161                                task->comm, task->tgid, task->pid, sp);
162                         return -EFAULT;
163                 }
164         } else {
165                 printk("---> %s (%d/%d): trampoline NOT found at sp = %08lx\n",
166                        task->comm, task->tgid, task->pid, sp);
167                 return -ENOENT;
168         }
169
170         return 0;
171 }
172
173 unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
174 {
175         return trampoline_addr(kp2up(p));
176 }
177
178 void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs)
179 {
180         regs->EREG(ip) = orig_ret_addr;
181 }
182
183 static void set_user_jmp_op(void *from, void *to)
184 {
185         struct __arch_jmp_op
186         {
187                 char op;
188                 long raddr;
189         } __attribute__ ((packed)) jop;
190
191         jop.raddr = (long)(to) - ((long)(from) + 5);
192         jop.op = RELATIVEJUMP_INSTRUCTION;
193
194         if (!write_proc_vm_atomic(current, (unsigned long)from, &jop, sizeof(jop)))
195                 panic("failed to write jump opcode to user space %p!\n", from);
196 }
197
198 static void resume_execution(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
199 {
200         unsigned long *tos, tos_dword = 0;
201         unsigned long copy_eip = (unsigned long)p->ainsn.insn;
202         unsigned long orig_eip = (unsigned long)p->addr;
203         kprobe_opcode_t insns[2];
204
205         regs->EREG(flags) &= ~TF_MASK;
206
207         tos = (unsigned long *)&tos_dword;
208         if (!read_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
209                 panic("failed to read dword from top of the user space stack %lx!\n", regs->EREG(sp));
210
211         if (!read_proc_vm_atomic(current, (unsigned long)p->ainsn.insn, insns, 2 * sizeof(kprobe_opcode_t)))
212                 panic("failed to read first 2 opcodes of instruction copy from user space %p!\n", p->ainsn.insn);
213
214         switch (insns[0]) {
215                 case 0x9c:              /* pushfl */
216                         *tos &= ~(TF_MASK | IF_MASK);
217                         *tos |= flags & (TF_MASK | IF_MASK);
218                         break;
219                 case 0xc2:              /* iret/ret/lret */
220                 case 0xc3:
221                 case 0xca:
222                 case 0xcb:
223                 case 0xcf:
224                 case 0xea:              /* jmp absolute -- eip is correct */
225                         /* eip is already adjusted, no more changes required */
226                         p->ainsn.boostable = 1;
227                         goto no_change;
228                 case 0xe8:              /* call relative - Fix return addr */
229                         *tos = orig_eip + (*tos - copy_eip);
230                         break;
231                 case 0x9a:              /* call absolute -- same as call absolute, indirect */
232                         *tos = orig_eip + (*tos - copy_eip);
233
234                         if (!write_proc_vm_atomic(current, regs->EREG (sp), &tos_dword, sizeof(tos_dword)))
235                                 panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG (sp));
236
237                         goto no_change;
238                 case 0xff:
239                         if ((insns[1] & 0x30) == 0x10) {
240                                 /*
241                                  * call absolute, indirect
242                                  * Fix return addr; eip is correct.
243                                  * But this is not boostable
244                                  */
245                                 *tos = orig_eip + (*tos - copy_eip);
246
247                                 if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
248                                         panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG(sp));
249
250                                 goto no_change;
251                         } else if (((insns[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
252                                    ((insns[1] & 0x31) == 0x21)) {
253                                 /* jmp far, absolute indirect */
254                                 /* eip is correct. And this is boostable */
255                                 p->ainsn.boostable = 1;
256                                 goto no_change;
257                         }
258                 default:
259                         break;
260         }
261
262         if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
263                 panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG(sp));
264
265         if (p->ainsn.boostable == 0) {
266                 if ((regs->EREG(ip) > copy_eip) && (regs->EREG(ip) - copy_eip) + 5 < MAX_INSN_SIZE) {
267                         /*
268                          * These instructions can be executed directly if it
269                          * jumps back to correct address.
270                          */
271                         set_user_jmp_op((void *) regs->EREG(ip), (void *)orig_eip + (regs->EREG(ip) - copy_eip));
272                         p->ainsn.boostable = 1;
273                 } else {
274                         p->ainsn.boostable = -1;
275                 }
276         }
277
278         regs->EREG(ip) = orig_eip + (regs->EREG(ip) - copy_eip);
279
280 no_change:
281         return;
282 }
283
284 static int make_trampoline(struct uprobe *up)
285 {
286         struct kprobe *p = up2kp(up);
287         struct task_struct *task = up->task;
288         void *tramp;
289
290         tramp = alloc_insn_slot(up->sm);
291         if (tramp == 0) {
292                 printk("trampoline out of memory\n");
293                 return -ENOMEM;
294         }
295
296         if (!write_proc_vm_atomic(task, (unsigned long)tramp,
297                                   up->atramp.tramp,
298                                   sizeof(up->atramp.tramp))) {
299                 free_insn_slot(up->sm, tramp);
300                 panic("failed to write memory %p!\n", tramp);
301                 return -EINVAL;
302         }
303
304         p->ainsn.insn = tramp;
305
306         return 0;
307 }
308
309 static int uprobe_handler(struct pt_regs *regs)
310 {
311         struct kprobe *p;
312         kprobe_opcode_t *addr;
313         struct task_struct *task = current;
314         pid_t tgid = task->tgid;
315
316         save_current_flags(regs);
317
318         addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
319         p = get_ukprobe(addr, tgid);
320
321         if (p == NULL) {
322                 void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX;
323
324                 p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs);
325                 if (p == NULL) {
326                         printk("no_uprobe\n");
327                         return 0;
328                 }
329
330                 trampoline_uprobe_handler(p, regs);
331                 return 1;
332         } else {
333                 if (p->ainsn.insn == NULL) {
334                         struct uprobe *up = kp2up(p);
335
336                         make_trampoline(up);
337
338                         /* for uretprobe */
339                         add_uprobe_table(p);
340                 }
341
342                 if (!p->pre_handler || !p->pre_handler(p, regs)) {
343                         if (p->ainsn.boostable == 1 && !p->post_handler) {
344                                 regs->EREG(ip) = (unsigned long)p->ainsn.insn;
345                                 return 1;
346                         }
347
348                         prepare_singlestep(p, regs);
349                 }
350         }
351
352         set_current_probe(p);
353
354         return 1;
355 }
356
357 static int post_uprobe_handler(struct pt_regs *regs)
358 {
359         struct kprobe *p = get_current_probe();
360         unsigned long flags = __get_cpu_var(ucb).flags;
361
362         if (p == NULL)
363                 return 0;
364
365         resume_execution(p, regs, flags);
366         restore_current_flags(regs);
367
368         reset_current_probe();
369
370         return 1;
371 }
372
373 static int uprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data)
374 {
375         struct die_args *args = (struct die_args *)data;
376         int ret = NOTIFY_DONE;
377
378         if (args->regs == NULL || !user_mode_vm(args->regs))
379                 return ret;
380
381         switch (val) {
382 #ifdef CONFIG_KPROBES
383                 case DIE_INT3:
384 #else
385                 case DIE_TRAP:
386 #endif
387                         if (uprobe_handler(args->regs))
388                                 ret = NOTIFY_STOP;
389                         break;
390                 case DIE_DEBUG:
391                         if (post_uprobe_handler(args->regs))
392                                 ret = NOTIFY_STOP;
393                         break;
394                 default:
395                         break;
396         }
397
398         return ret;
399 }
400
401 static struct notifier_block uprobe_exceptions_nb = {
402         .notifier_call = uprobe_exceptions_notify,
403         .priority = INT_MAX
404 };
405
406 int swap_arch_init_uprobes(void)
407 {
408         return register_die_notifier(&uprobe_exceptions_nb);
409 }
410
411 void swap_arch_exit_uprobes(void)
412 {
413         unregister_die_notifier(&uprobe_exceptions_nb);
414 }
415