[REFACTOR] move and rename install_file_probes()
[kernel/swap-modules.git] / driver / us_proc_inst.c
1 ////////////////////////////////////////////////////////////////////////////////////
2 //
3 //      FILE:           us_proc_inst.c
4 //
5 //      DESCRIPTION:
6 //      This file is C source for SWAP driver.
7 //
8 //      SEE ALSO:       us_proc_inst.h
9 //      AUTHOR:         A.Gerenkov, E. Gorelkina
10 //      COMPANY NAME:   Samsung Research Center in Moscow
11 //      DEPT NAME:      Advanced Software Group
12 //      CREATED:        2008.06.02
13 //      VERSION:        1.0
14 //      REVISION DATE:  2008.12.02
15 //
16 ////////////////////////////////////////////////////////////////////////////////////
17
18 #include "module.h"
19 #include "us_proc_inst.h"
20
21 #include "../kprobe/dbi_kprobes_deps.h"
22 #include "../uprobe/swap_uprobes.h"
23
24 #include "sspt/sspt.h"
25 #include "helper.h"
26 #include "us_slot_manager.h"
27
28 #define mm_read_lock(task, mm, atomic, lock)                    \
29         mm = atomic ? task->active_mm : get_task_mm(task);      \
30         if (mm == NULL) {                                       \
31                 /* FIXME: */                                    \
32                 panic("ERRR mm_read_lock: mm == NULL\n");       \
33         }                                                       \
34                                                                 \
35         if (atomic) {                                           \
36                 lock = down_read_trylock(&mm->mmap_sem);        \
37         } else {                                                \
38                 lock = 1;                                       \
39                 down_read(&mm->mmap_sem);                       \
40         }
41
42 #define mm_read_unlock(mm, atomic, lock)                        \
43         if (lock) {                                             \
44                 up_read(&mm->mmap_sem);                         \
45         }                                                       \
46                                                                 \
47         if (!atomic) {                                          \
48                 mmput(mm);                                      \
49         }
50
51 unsigned long ujprobe_event_pre_handler (struct us_ip *ip, struct pt_regs *regs);
52 void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6);
53 int uretprobe_event_handler(struct uretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip);
54
55
56 #define print_event(fmt, args...)                                               \
57 {                                                                               \
58         char *buf[1024];                                                        \
59         sprintf(buf, fmt, ##args);                                              \
60         pack_event_info(US_PROBE_ID, RECORD_ENTRY, "ds", 0x0badc0de, buf);      \
61 }
62
63 int is_libonly(void)
64 {
65         return !strcmp(us_proc_info.path,"*");
66 }
67
68 // is user-space instrumentation
69 int is_us_instrumentation(void)
70 {
71         return !!us_proc_info.path;
72 }
73
74 struct dentry *dentry_by_path(const char *path)
75 {
76         struct dentry *dentry;
77 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
78         struct path st_path;
79         if (kern_path(path, LOOKUP_FOLLOW, &st_path) != 0) {
80 #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
81         struct nameidata nd;
82         if (path_lookup(path, LOOKUP_FOLLOW, &nd) != 0) {
83 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
84                 EPRINTF("failed to lookup dentry for path %s!", path);
85                 return NULL;
86         }
87
88 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
89         dentry = nd.dentry;
90         path_release(&nd);
91 #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38)
92         dentry = nd.path.dentry;
93         path_put(&nd.path);
94 #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
95         dentry = st_path.dentry;
96         path_put(&st_path);
97 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
98         return dentry;
99 }
100
101 int check_vma(struct vm_area_struct *vma)
102 {
103         return vma->vm_file && !(vma->vm_pgoff != 0 || !(vma->vm_flags & VM_EXEC) || (vma->vm_flags & VM_ACCOUNT) ||
104                         !(vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) ||
105                         !(vma->vm_flags & (VM_READ | VM_MAYREAD)));
106 }
107
108 static int find_task_by_path (const char *path, struct task_struct **p_task, struct list_head *tids)
109 {
110         int found = 0;
111         struct task_struct *task;
112         struct vm_area_struct *vma;
113         struct mm_struct *mm;
114         struct dentry *dentry = dentry_by_path(path);
115
116         *p_task = NULL;
117
118         /* find corresponding dir entry, this is also check for valid path */
119         // TODO: test - try to instrument process with non-existing path
120         // TODO: test - try to instrument process  with existing path and delete file just after start
121         if (dentry == NULL) {
122                 return -EINVAL;
123         }
124
125         rcu_read_lock();
126         for_each_process (task) {
127
128                 if  ( 0 != inst_pid && ( inst_pid != task->pid ) )
129                         continue;
130
131                 mm = get_task_mm(task);
132                 if (!mm)
133                         continue;
134                 vma = mm->mmap;
135                 while (vma) {
136                         if (check_vma(vma)) {
137                                 if (vma->vm_file->f_dentry == dentry) {
138                                         if (!*p_task) {
139                                                 *p_task = task;
140                                                 get_task_struct (task);
141                                         }
142                                                 //break;
143                                 }
144                         }
145                         vma = vma->vm_next;
146                 }
147                 // only decrement usage count on mm since we cannot sleep here
148                 atomic_dec(&mm->mm_users);
149                 if (found)
150                         break;
151         }
152         rcu_read_unlock();
153
154         if (*p_task) {
155                 DPRINTF ("found pid %d for %s.", (*p_task)->pid, path);
156                 *p_task = (*p_task)->group_leader;
157                 gl_nNotifyTgid = (*p_task)->tgid;
158         } else {
159                 DPRINTF ("pid for %s not found!", path);
160         }
161
162         return 0;
163 }
164
165 static void set_mapping_file(struct sspt_file *file,
166                 const struct sspt_procs *procs,
167                 const struct task_struct *task,
168                 const struct vm_area_struct *vma);
169
170 int install_otg_ip(unsigned long addr,
171                         kprobe_pre_entry_handler_t pre_handler,
172                         unsigned long jp_handler,
173                         uretprobe_handler_t rp_handler)
174 {
175         int ret = 0;
176         struct task_struct *task = current->group_leader;
177         struct mm_struct *mm = task->mm;
178
179         if (mm) {
180                 struct vm_area_struct *vma = find_vma(mm, addr);
181                 if (vma && (vma->vm_flags & VM_EXEC) &&
182                     vma->vm_file && vma->vm_file->f_dentry) {
183                         unsigned long offset_addr = addr - vma->vm_start;
184                         struct dentry *dentry = vma->vm_file->f_dentry;
185                         char *name = dentry->d_iname;
186                         struct sspt_procs *procs = sspt_procs_get_by_task(task);
187                         struct ip_data pd = {
188                                         .offset = offset_addr,
189                                         .pre_handler = pre_handler,
190                                         .jp_handler = jp_handler,
191                                         .rp_handler = rp_handler,
192                                         .flag_retprobe = 1
193                         };
194
195                         struct sspt_file *file = sspt_procs_find_file_or_new(procs, dentry, name);
196                         struct sspt_page *page = sspt_get_page(file, offset_addr);
197                         struct us_ip *ip = sspt_find_ip(page, offset_addr & ~PAGE_MASK);
198
199                         if (!file->loaded) {
200                                 set_mapping_file(file, procs, task, vma);
201                                 file->loaded = 1;
202                         }
203
204                         if (ip == NULL) {
205                                 // TODO: sspt_procs_find_file_or_new --> sspt_procs_find_file ?!
206                                 struct sspt_file *file = sspt_procs_find_file_or_new(procs, dentry, name);
207                                 sspt_file_add_ip(file, &pd);
208
209                                 /* if addr mapping, that probe install, else it be installed in do_page_fault handler */
210                                 if (page_present(mm, addr)) {
211                                         ip = sspt_find_ip(page, offset_addr & ~PAGE_MASK);
212                                         sspt_set_ip_addr(ip, page, file);
213
214                                         // TODO: error
215                                         ret = sspt_register_usprobe(ip);
216                                         if (ret == 0) {
217                                                 sspt_page_installed(page);
218                                         } else {
219                                                 printk("ERROR install_otg_ip: ret=%d\n", ret);
220                                         }
221                                 }
222                         }
223
224                         sspt_put_page(page);
225                 }
226         }
227
228         return ret;
229 }
230 EXPORT_SYMBOL_GPL(install_otg_ip);
231
232 int deinst_usr_space_proc (void)
233 {
234         int iRet = 0, found = 0;
235         struct task_struct *task = NULL;
236         struct sspt_procs *procs;
237
238         if (!is_us_instrumentation()) {
239                 return 0;
240         }
241
242         unregister_helper();
243
244         if (iRet)
245                 EPRINTF ("uninstall_kernel_probe(do_munmap) result=%d!", iRet);
246
247
248         for_each_process(task) {
249                 procs = sspt_procs_get_by_task(task);
250                 if (procs) {
251                         int ret = uninstall_us_proc_probes(task, procs, US_UNREGS_PROBE);
252                         if (ret) {
253                                 EPRINTF ("failed to uninstall IPs (%d)!", ret);
254                         }
255
256                         dbi_unregister_all_uprobes(task);
257                 }
258         }
259
260         return iRet;
261 }
262
263 int inst_usr_space_proc (void)
264 {
265         int ret, i;
266         struct task_struct *task = NULL;
267
268         if (!is_us_instrumentation()) {
269                 return 0;
270         }
271
272         DPRINTF("User space instr");
273
274         ret = register_helper();
275         if (ret) {
276                 return ret;
277         }
278
279         for (i = 0; i < us_proc_info.libs_count; i++) {
280                 us_proc_info.p_libs[i].loaded = 0;
281         }
282         /* check whether process is already running
283          * 1) if process is running - look for the libraries in the process maps
284          * 1.1) check if page for symbol does exist
285          * 1.1.1) if page exists - instrument it
286          * 1.1.2) if page does not exist - make sure that do_page_fault handler is installed
287          * 2) if process is not running - make sure that do_page_fault handler is installed
288          * */
289
290         if (is_libonly())
291         {
292                 // FIXME: clear_task_inst_info();
293                 for_each_process (task) {
294                         struct sspt_procs *procs;
295
296                         if (task->flags & PF_KTHREAD){
297                                 DPRINTF("ignored kernel thread %d\n",
298                                         task->pid);
299                                 continue;
300                         }
301
302                         procs = sspt_procs_get_by_task_or_new(task);
303                         DPRINTF("trying process");
304                         install_proc_probes(task, procs);
305                         //put_task_struct (task);
306                 }
307         }
308         else
309         {
310                 ret = find_task_by_path(us_proc_info.path, &task, NULL);
311                 if (task) {
312                         struct sspt_procs *procs;
313
314                         procs = sspt_procs_get_by_task_or_new(task);
315
316                         us_proc_info.tgid = task->pid;
317                         install_proc_probes(task, procs);
318                         put_task_struct(task);
319                 }
320         }
321
322         return 0;
323 }
324
325 static void set_mapping_file(struct sspt_file *file,
326                 const struct sspt_procs *procs,
327                 const struct task_struct *task,
328                 const struct vm_area_struct *vma)
329 {
330         int app_flag = (vma->vm_file->f_dentry == procs->dentry);
331
332         file->vm_start = vma->vm_start;
333         file->vm_end = vma->vm_end;
334
335         pack_event_info(DYN_LIB_PROBE_ID, RECORD_ENTRY, "dspdd",
336                         task->tgid, file->name, vma->vm_start,
337                         vma->vm_end - vma->vm_start, app_flag);
338 }
339
340 void print_vma(struct mm_struct *mm);
341
342 void install_page_probes(unsigned long page_addr, struct task_struct *task, struct sspt_procs *procs)
343 {
344         int lock, atomic;
345         struct mm_struct *mm;
346         struct vm_area_struct *vma;
347
348         atomic = in_atomic();
349         mm_read_lock(task, mm, atomic, lock);
350
351         vma = find_vma(mm, page_addr);
352         if (vma && check_vma(vma)) {
353                 struct dentry *dentry = vma->vm_file->f_dentry;
354                 struct sspt_file *file = sspt_procs_find_file(procs, dentry);
355                 if (file) {
356                         struct sspt_page *page;
357                         if (!file->loaded) {
358                                 set_mapping_file(file, procs, task, vma);
359                                 file->loaded = 1;
360                         }
361
362                         page = sspt_find_page_mapped(file, page_addr);
363                         if (page) {
364                                 sspt_register_page(page, file);
365                         }
366                 }
367         }
368
369         mm_read_unlock(mm, atomic, lock);
370 }
371
372 void install_proc_probes(struct task_struct *task, struct sspt_procs *procs)
373 {
374         int lock, atomic;
375         struct vm_area_struct *vma;
376         struct mm_struct *mm;
377
378         atomic = in_atomic();
379         mm_read_lock(task, mm, atomic, lock);
380
381         for (vma = mm->mmap; vma; vma = vma->vm_next) {
382                 if (check_vma(vma)) {
383                         struct dentry *dentry = vma->vm_file->f_dentry;
384                         struct sspt_file *file = sspt_procs_find_file(procs, dentry);
385                         if (file) {
386                                 if (!file->loaded) {
387                                         set_mapping_file(file, procs, task, vma);
388                                         file->loaded = 1;
389                                 }
390
391                                 sspt_file_install(file);
392                         }
393                 }
394         }
395
396         mm_read_unlock(mm, atomic, lock);
397 }
398
399 int unregister_us_file_probes(struct task_struct *task, struct sspt_file *file, enum US_FLAGS flag)
400 {
401         int i, err = 0;
402         int table_size = (1 << file->page_probes_hash_bits);
403         struct sspt_page *page;
404         struct hlist_node *node, *tmp;
405         struct hlist_head *head;
406
407         for (i = 0; i < table_size; ++i) {
408                 head = &file->page_probes_table[i];
409                 swap_hlist_for_each_entry_safe (page, node, tmp, head, hlist) {
410                         err = sspt_unregister_page(page, flag, task);
411                         if (err != 0) {
412                                 // TODO: ERROR
413                                 return err;
414                         }
415                 }
416         }
417
418         if (flag != US_DISARM) {
419                 file->loaded = 0;
420         }
421
422         return err;
423 }
424
425 int uninstall_us_proc_probes(struct task_struct *task, struct sspt_procs *procs, enum US_FLAGS flag)
426 {
427         int err = 0;
428         struct sspt_file *file;
429
430         list_for_each_entry_rcu(file, &procs->file_list, list) {
431                 err = unregister_us_file_probes(task, file, flag);
432                 if (err != 0) {
433                         // TODO:
434                         return err;
435                 }
436         }
437
438         return err;
439 }
440
441 int check_dentry(struct task_struct *task, struct dentry *dentry)
442 {
443         struct vm_area_struct *vma;
444         struct mm_struct *mm = task->active_mm;
445
446         if (mm == NULL) {
447                 return 0;
448         }
449
450         for (vma = mm->mmap; vma; vma = vma->vm_next) {
451                 if (check_vma(vma) && vma->vm_file->f_dentry == dentry) {
452                         return 1;
453                 }
454         }
455
456         return 0;
457 }
458
459 void print_vma(struct mm_struct *mm)
460 {
461         struct vm_area_struct *vma;
462         printk("### print_vma: START\n");\
463         printk("### print_vma: START\n");
464
465         for (vma = mm->mmap; vma; vma = vma->vm_next) {
466                 char *x = vma->vm_flags & VM_EXEC ? "x" : "-";
467                 char *r = vma->vm_flags & VM_READ ? "r" : "-";
468                 char *w = vma->vm_flags & VM_WRITE ? "w" : "-";
469                 char *name = vma->vm_file ? (char *)vma->vm_file->f_dentry->d_iname : "N/A";
470
471                 printk("### [%8lx..%8lx] %s%s%s pgoff=\'%8lu\' %s\n",
472                                 vma->vm_start, vma->vm_end, x, r, w, vma->vm_pgoff, name);
473         }
474         printk("### print_vma:  END\n");
475 }
476
477 static DEFINE_PER_CPU(struct us_ip *, gpCurIp) = NULL;
478 EXPORT_PER_CPU_SYMBOL_GPL(gpCurIp);
479 static DEFINE_PER_CPU(struct pt_regs *, gpUserRegs) = NULL;
480 EXPORT_PER_CPU_SYMBOL_GPL(gpUserRegs);
481
482 unsigned long ujprobe_event_pre_handler(struct us_ip *ip, struct pt_regs *regs)
483 {
484         __get_cpu_var (gpCurIp) = ip;
485         __get_cpu_var (gpUserRegs) = regs;
486         return 0;
487 }
488
489 void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
490 {
491         struct us_ip *ip = __get_cpu_var(gpCurIp);
492         unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
493
494 #if defined(CONFIG_ARM)
495         if (ip->offset & 0x01)
496         {
497                 pack_event_info (US_PROBE_ID, RECORD_ENTRY, "ppppppp", addr | 0x01, arg1, arg2, arg3, arg4, arg5, arg6);
498         }else{
499                 pack_event_info (US_PROBE_ID, RECORD_ENTRY, "ppppppp", addr, arg1, arg2, arg3, arg4, arg5, arg6);
500         }
501 #else
502         pack_event_info (US_PROBE_ID, RECORD_ENTRY, "ppppppp", addr, arg1, arg2, arg3, arg4, arg5, arg6);
503 #endif
504         // Mr_Nobody: uncomment for valencia
505         //unregister_usprobe(current, ip, 1);
506         dbi_uprobe_return ();
507 }
508
509 static void send_plt(struct us_ip *ip)
510 {
511         unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
512         struct vm_area_struct *vma = find_vma(current->mm, addr);
513
514         if (vma && check_vma(vma)) {
515                 char *name = NULL;
516                 unsigned long real_addr;
517                 unsigned long real_got = current->mm->exe_file == vma->vm_file ?
518                                 ip->got_addr :
519                                 ip->got_addr + vma->vm_start;
520
521                 if (!read_proc_vm_atomic(current, real_got, &real_addr, sizeof(real_addr))) {
522                         printk("Failed to read got %lx at memory address %lx!\n", ip->got_addr, real_got);
523                         return;
524                 }
525
526                 vma = find_vma(current->mm, real_addr);
527                 if (vma && (vma->vm_start <= real_addr) && (vma->vm_end > real_addr)) {
528                         name = vma->vm_file ? vma->vm_file->f_dentry->d_iname : NULL;
529                 } else {
530                         printk("Failed to get vma, includes %lx address\n", real_addr);
531                         return;
532                 }
533
534                 if (name) {
535                         pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp", addr, real_addr, name, real_addr - vma->vm_start);
536                 } else {
537                         pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp", addr, real_addr, real_addr - vma->vm_start);
538                 }
539         }
540 }
541
542 int uretprobe_event_handler(struct uretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip)
543 {
544         int retval = regs_return_value(regs);
545         unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
546
547         if (ip->got_addr && ip->flag_got == 0) {
548                 send_plt(ip);
549                 ip->flag_got = 1;
550         }
551
552 #if defined(CONFIG_ARM)
553         if (ip->offset & 0x01)
554         {
555                 pack_event_info (US_PROBE_ID, RECORD_RET, "pd", addr | 0x01, retval);
556         }else{
557                 pack_event_info (US_PROBE_ID, RECORD_RET, "pd", addr, retval);
558         }
559 #else
560         pack_event_info (US_PROBE_ID, RECORD_RET, "pd", addr, retval);
561 #endif
562         // Mr_Nobody: uncomment for valencia
563         //unregister_usprobe(current, ip, 1);
564         return 0;
565 }
566
567 int register_usprobe(struct us_ip *ip)
568 {
569         int ret = 0;
570
571         if (ip->jprobe.entry == NULL) {
572                 ip->jprobe.entry = (void *)ujprobe_event_handler;
573                 DPRINTF("Set default event handler for %x\n", ip->offset);
574         }
575
576         if (ip->jprobe.pre_entry == NULL) {
577                 ip->jprobe.pre_entry = (uprobe_pre_entry_handler_t)ujprobe_event_pre_handler;
578                 DPRINTF("Set default pre handler for %x\n", ip->offset);
579         }
580
581         ip->jprobe.priv_arg = ip;
582         ip->jprobe.up.task = ip->page->file->procs->task;
583         ip->jprobe.up.sm = ip->page->file->procs->sm;
584         ret = dbi_register_ujprobe(&ip->jprobe);
585         if (ret) {
586                 if (ret == -ENOEXEC) {
587                         pack_event_info(ERR_MSG_ID, RECORD_ENTRY, "dp",
588                                         0x1,
589                                         ip->jprobe.up.kp.addr);
590                 }
591                 DPRINTF ("dbi_register_ujprobe() failure %d", ret);
592                 return ret;
593         }
594
595         if (ip->flag_retprobe) {
596                 // Mr_Nobody: comment for valencia
597                 if (ip->retprobe.handler == NULL) {
598                         ip->retprobe.handler = (uretprobe_handler_t)uretprobe_event_handler;
599                         DPRINTF("Set default ret event handler for %x\n", ip->offset);
600                 }
601
602                 ip->retprobe.priv_arg = ip;
603                 ip->retprobe.up.task = ip->page->file->procs->task;
604                 ip->retprobe.up.sm = ip->page->file->procs->sm;
605                 ret = dbi_register_uretprobe(&ip->retprobe);
606                 if (ret) {
607                         EPRINTF ("dbi_register_uretprobe() failure %d", ret);
608                         return ret;
609                 }
610         }
611
612         return 0;
613 }
614
615 int unregister_usprobe(struct us_ip *ip)
616 {
617         dbi_unregister_ujprobe(&ip->jprobe);
618
619         if (ip->flag_retprobe) {
620                 dbi_unregister_uretprobe(&ip->retprobe);
621         }
622
623         return 0;
624 }