Redesign KProbe module (separating core and arch parts).
[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
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 "../kprobe/dbi_uprobes.h"
23
24
25 static int register_usprobe (struct task_struct *task, struct mm_struct *mm, us_proc_ip_t * ip, int atomic, kprobe_opcode_t * islot);
26 static int unregister_usprobe (struct task_struct *task, us_proc_ip_t * ip, int atomic);
27
28 int us_proc_probes;
29
30 static int
31 find_task_by_path (const char *path, struct task_struct **p_task, struct list_head *tids)
32 {
33         int found = 0;
34         struct task_struct *task;
35         struct vm_area_struct *vma;
36         struct mm_struct *mm;
37         struct nameidata nd;
38         //fp_kallsyms_lookup_name_t fp;
39
40         *p_task = 0;
41
42         /* find corresponding dir entry, this is also check for valid path */
43         // TODO: test - try to instrument process with non-existing path
44         // TODO: test - try to instrument process  with existing path and delete file just after start
45         if (path_lookup (path, LOOKUP_FOLLOW, &nd) != 0)
46         {
47                 EPRINTF ("failed to lookup dentry for path %s!", path);
48                 return -EINVAL;
49         }
50
51         rcu_read_lock ();
52         for_each_process (task) {
53                 mm = get_task_mm (task);
54                 if (!mm)
55                         continue;
56                 down_read (&mm->mmap_sem);
57                 vma = mm->mmap;
58                 while (vma) {
59                         if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
60 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
61                                 if (vma->vm_file->f_dentry == nd.dentry) {
62 #else
63                                 if (vma->vm_file->f_dentry == nd.path.dentry) {
64 #endif
65                                         if (!*p_task) {
66                                                 *p_task = task;
67                                                 get_task_struct (task);
68                                         }
69                                         //break;
70                                 }
71                         }
72                         vma = vma->vm_next;
73                 }
74                 up_read (&mm->mmap_sem);
75                 mmput (mm);
76                 if (found)
77                         break;
78         }
79         rcu_read_unlock ();
80
81         if (*p_task)
82         {
83                 DPRINTF ("found pid %d for %s.", (*p_task)->pid, path);
84                 gl_nNotifyTgid = current->tgid;
85         }
86         else
87         {
88                 DPRINTF ("pid for %s not found!", path);
89         }
90
91 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
92         path_release (&nd);
93 #else
94         path_put (&nd.path);
95 #endif
96         return 0;
97 }
98
99 #if defined(CONFIG_MIPS)
100 #       define ARCH_REG_VAL(regs, idx)  regs->regs[idx]
101 #elif defined(CONFIG_ARM)
102 #       define ARCH_REG_VAL(regs, idx)  regs->uregs[idx]
103 #else
104 #       define ARCH_REG_VAL(regs, idx)  0
105 #       warning ARCH_REG_VAL is not implemented for this architecture. FBI will work improperly or even crash!!!
106 #endif // ARCH
107
108 DEFINE_PER_CPU (us_proc_vtp_t *, gpVtp) = NULL;
109 //EXPORT_PER_CPU_SYMBOL_GPL(gpVtp);
110 DEFINE_PER_CPU (struct pt_regs *, gpCurVtpRegs) = NULL;
111 //EXPORT_PER_CPU_SYMBOL_GPL(gpCurVtpRegs);
112
113 static void
114 us_vtp_event_pre_handler (us_proc_vtp_t * vtp, struct pt_regs *regs)
115 {
116         __get_cpu_var(gpVtp) = vtp;
117         __get_cpu_var(gpCurVtpRegs) = regs;
118 }
119
120 static void
121 us_vtp_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
122 {
123         //static int nCount;
124         us_proc_vtp_t *vtp = __get_cpu_var(gpVtp);
125 #if !defined(CONFIG_X86)
126         struct pt_regs *regs = __get_cpu_var(gpCurVtpRegs);
127 #endif
128         char fmt[3];
129         unsigned long vaddr;
130         long ival;
131         char cval, *sval;
132         //float fval;
133         //struct list_head *pos, *tmp;
134         us_proc_vtp_data_t *vtp_data;
135
136         fmt[0] = 'p';
137         fmt[2] = 0;
138
139         list_for_each_entry_rcu (vtp_data, &vtp->list, list)
140         {
141 //              DPRINTF ("[%d]proc %s(%d): %lx", nCount++, current->comm, current->pid, vtp->addr);
142                 fmt[1] = vtp_data->type;
143                 if (vtp_data->reg == -1)
144                         vaddr = vtp_data->off;
145                 else
146                         vaddr = ARCH_REG_VAL (regs, vtp_data->reg) + vtp_data->off;
147 //              DPRINTF ("VTP type '%c'", vtp_data->type);
148                 switch (vtp_data->type)
149                 {
150                 case 'd':
151                 case 'x':
152                 case 'p':
153                         if (read_proc_vm_atomic (current, vaddr, &ival, sizeof (ival)) < sizeof (ival))
154                                 EPRINTF ("failed to read vm of proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
155                         else
156                                 pack_event_info (VTP_PROBE_ID, RECORD_ENTRY, fmt, vtp->jprobe.kp.addr, ival);
157                         break;
158                 case 'f':
159                         if (read_proc_vm_atomic (current, vaddr, &ival, sizeof (ival)) < sizeof (ival))
160                                 EPRINTF ("failed to read vm of proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
161                         else
162                                 pack_event_info (VTP_PROBE_ID, RECORD_ENTRY, fmt, vtp->jprobe.kp.addr, ival);
163                         break;
164                 case 'c':
165                         if (read_proc_vm_atomic (current, vaddr, &cval, sizeof (cval)) < sizeof (cval))
166                                 EPRINTF ("failed to read vm of proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
167                         else
168                                 pack_event_info (VTP_PROBE_ID, RECORD_ENTRY, fmt, vtp->jprobe.kp.addr, cval);
169                         break;
170                 case 's':
171                         if (current->active_mm)
172                         {
173                                 struct page *page;
174                                 struct vm_area_struct *vma;
175                                 void *maddr;
176                                 int len;
177                                 if (get_user_pages_atomic (current, current->active_mm, vaddr, 1, 0, 1, &page, &vma) <= 0)
178                                 {
179                                         EPRINTF ("get_user_pages_atomic failed for proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
180                                         break;
181                                 }
182                                 maddr = kmap_atomic (page, KM_USER0);
183                                 len = strlen (maddr + (vaddr & ~PAGE_MASK));
184                                 sval = kmalloc (len + 1, GFP_KERNEL);
185                                 if (!sval)
186                                         EPRINTF ("failed to alloc memory for string in proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
187                                 else
188                                 {
189                                         copy_from_user_page (vma, page, vaddr, sval, maddr + (vaddr & ~PAGE_MASK), len + 1);
190                                         pack_event_info (VTP_PROBE_ID, RECORD_ENTRY, fmt, vtp->jprobe.kp.addr, sval);
191                                         kfree (sval);
192                                 }
193                                 kunmap_atomic (maddr, KM_USER0);
194                                 page_cache_release (page);
195                         }
196                         else
197                                 EPRINTF ("task %s/%u has no mm!", current->comm, current->pid);
198                         break;
199                 default:
200                         EPRINTF ("unknown variable type '%c'", vtp_data->type);
201                 }
202         }
203         uprobe_return ();
204 }
205
206 static int
207 install_mapped_ips (struct task_struct *task, int atomic)
208 {
209         struct vm_area_struct *vma;
210         int i, k, err, retry;
211         unsigned long addr;//, slot_idx;
212         //char lib_path[256];
213         //static unsigned npcdep;
214         unsigned int old_ips_count, old_vtps_count;
215         struct mm_struct *mm;
216         struct ip_node {
217                 struct list_head        plist;
218                 us_proc_ip_t *          ip;
219         } * nip, *tnip;
220         LIST_HEAD(iplist);
221         struct vtp_node {
222                 struct list_head        plist;
223                 us_proc_vtp_t *         vtp;            
224         } * nvtp, *tnvtp;
225         LIST_HEAD(vtplist);
226                 
227 _restart:
228         mm = atomic ? task->active_mm : get_task_mm (task);
229         if (!mm){
230 //              DPRINTF ("proc %d has no mm", task->pid);
231                 return us_proc_info.unres_ips_count + us_proc_info.unres_vtps_count;
232         }
233         
234         old_ips_count = us_proc_info.unres_ips_count;
235         old_vtps_count = us_proc_info.unres_vtps_count;
236         if(!atomic) 
237                 down_read (&mm->mmap_sem);
238         vma = mm->mmap;
239         while (vma)
240         {
241                 // skip non-text section
242                 if (!(vma->vm_flags & VM_EXEC) || !vma->vm_file || (vma->vm_flags & VM_ACCOUNT) || 
243                         !(vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) || 
244                         !(vma->vm_flags & (VM_READ | VM_MAYREAD)))
245                 {
246                         vma = vma->vm_next;
247                         continue;
248                 }
249                 //DPRINTF("check mapped lib %s at %lx.", 
250                 //              d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, lib_path, sizeof(lib_path)), vma->vm_start);
251                 //slot_idx = 0;
252                 for (i = 0; i < us_proc_info.libs_count; i++)
253                 {                               
254                         //DPRINTF("lookup lib %s.", us_proc_info.p_libs[i].path);
255                         //TODO: test - try to instrument non-existing libs
256                         if (vma->vm_file->f_dentry == us_proc_info.p_libs[i].m_f_dentry)
257                         {
258                                 //if (strcmp(d_path(vma->vm_file->m_f_dentry, vma->vm_file->f_vfsmnt, lib_path, sizeof(lib_path)),
259                                 //                 us_proc_info.p_libs[i].path) == 0){
260                                 //DPRINTF("found lib %s.", us_proc_info.p_libs[i].path);
261                                 //unsigned oi_count = us_proc_info.unres_ips_count;
262                                 //unsigned ov_count = us_proc_info.unres_vtps_count;
263                                 for (k = 0; k < us_proc_info.p_libs[i].ips_count; k++/*, slot_idx++*/)
264                                 {
265                                         if (!us_proc_info.p_libs[i].p_ips[k].installed)
266                                         {
267                                                 addr = us_proc_info.p_libs[i].p_ips[k].offset;
268                                                 if (!(vma->vm_flags & VM_EXECUTABLE))
269                                                         addr += vma->vm_start;
270                                                 //DPRINTF("check sym %s at %lx.", us_proc_info.p_libs[i].p_ips[k].name, addr);
271                                                 if (page_present (mm, addr))
272                                                 {
273                                                         //DPRINTF ("pid %d, %s sym is present at %lx/%lx.", task->pid, us_proc_info.p_libs[i].path, us_proc_info.p_libs[i].p_ips[k].offset, addr);
274                                                         //if (!us_proc_info.p_libs[i].p_ips[k].installed)
275                                                         {
276                                                                 us_proc_info.unres_ips_count--;
277                                                                 us_proc_info.p_libs[i].p_ips[k].installed = 1;
278                                                                 DPRINTF ("pid %d, %s sym is loaded at %lx/%lx.", task->pid, us_proc_info.p_libs[i].path, us_proc_info.p_libs[i].p_ips[k].offset, addr);
279                                                                 nip = kmalloc(sizeof(struct ip_node), GFP_KERNEL);
280                                                                 if(!nip){
281                                                                         EPRINTF ("failed to allocate list item for IP!");
282                                                                         continue;
283                                                                 }
284                                                                 us_proc_info.p_libs[i].p_ips[k].jprobe.kp.addr = (kprobe_opcode_t *) addr;
285                                                                 us_proc_info.p_libs[i].p_ips[k].retprobe.kp.addr = (kprobe_opcode_t *) addr;
286                                                                 INIT_LIST_HEAD (&nip->plist);
287                                                                 nip->ip = &us_proc_info.p_libs[i].p_ips[k];
288                                                                 list_add_tail (&nip->plist, &iplist);
289                                                         }
290                                                 }
291                                         }
292                                 }
293                                 for (k = 0; k < us_proc_info.p_libs[i].vtps_count; k++/*, slot_idx++*/)
294                                 {
295                                         if (us_proc_info.p_libs[i].p_vtps[k].installed)
296                                         {
297                                                 /*DPRINTF("VTPs at %lx are already installed.", 
298                                                    us_proc_info.p_libs[i].p_ips[k].offset); */
299                                         }
300                                         else
301                                         {
302                                                 addr = us_proc_info.p_libs[i].p_vtps[k].addr;
303                                                 if (!(vma->vm_flags & VM_EXECUTABLE))
304                                                         addr += vma->vm_start;
305                                                 //DPRINTF("check VTPs at %lx.", addr);
306                                                 if (page_present (mm, addr))
307                                                 {
308                                                         //us_proc_vtp_data_t *vtp_data;
309                                                         //DPRINTF("VTPs is loaded at %lx.", addr);
310                                                         us_proc_info.unres_vtps_count--;
311                                                         us_proc_info.p_libs[i].p_vtps[k].installed = 1;
312                                                         /*list_for_each_entry_rcu (vtp_data, &us_proc_info.p_libs[i].p_vtps[k].list, list)
313                                                         {
314                                                                 DPRINTF ("VTP %s is loaded at %lx.", vtp_data->name, addr);
315                                                         }*/
316                                                         us_proc_info.p_libs[i].p_vtps[k].jprobe.kp.tgid = us_proc_info.tgid;
317                                                         us_proc_info.p_libs[i].p_vtps[k].jprobe.kp.addr = (kprobe_opcode_t *) addr;
318                                                         us_proc_info.p_libs[i].p_vtps[k].jprobe.entry = (kprobe_opcode_t *) us_vtp_event_handler;
319                                                         us_proc_info.p_libs[i].p_vtps[k].jprobe.pre_entry = (kprobe_pre_entry_handler_t) us_vtp_event_pre_handler;
320                                                         us_proc_info.p_libs[i].p_vtps[k].jprobe.priv_arg = &us_proc_info.p_libs[i].p_vtps[k];
321                                                         nvtp = kmalloc(sizeof(struct vtp_node), GFP_KERNEL);
322                                                         if(!nvtp){
323                                                                 EPRINTF ("failed to allocate list item for VTP!");
324                                                                 continue;
325                                                         }
326                                                         INIT_LIST_HEAD (&nvtp->plist);
327                                                         nvtp->vtp = &us_proc_info.p_libs[i].p_vtps[k];
328                                                         list_add_tail (&nvtp->plist, &vtplist);
329                                                 }
330                                         }
331                                 }
332                                 if(!(vma->vm_flags & VM_EXECUTABLE) && !us_proc_info.p_libs[i].loaded
333                                    /*((oi_count != us_proc_info.unres_ips_count) || (ov_count != us_proc_info.unres_vtps_count))*/){
334                                         char *p;
335 //                                      DPRINTF ("post dyn lib event %s", us_proc_info.p_libs[i].path);
336                                         // if we installed something, post library info for those IPs
337                                         p = strrchr(us_proc_info.p_libs[i].path, '/');
338                                         if(!p)
339                                                 p = us_proc_info.p_libs[i].path;
340                                         else
341                                                 p++;
342                                         us_proc_info.p_libs[i].loaded = 1;
343                                         pack_event_info (DYN_LIB_PROBE_ID, RECORD_ENTRY, "spd", 
344                                                         p, vma->vm_start, vma->vm_end-vma->vm_start);
345                                 }
346                         }
347                 }
348                 vma = vma->vm_next;
349         }
350         if(!atomic){    
351                 up_read (&mm->mmap_sem);
352                 mmput (mm);
353         }
354         
355         if(!list_empty(&iplist) || !list_empty(&vtplist)){
356 //              DPRINTF ("Unres IPs/VTPs %d/%d -> %d/%d.", old_ips_count, old_vtps_count,
357 //                              us_proc_info.unres_ips_count, us_proc_info.unres_vtps_count);
358         }
359
360         retry = 0;
361         list_for_each_entry_safe(nip, tnip, &iplist, plist) {
362 //              DPRINTF ("Install %p/%d IP at %lx.", task, task->pid, nip->ip->offset);
363                 if((PAGE_SIZE-(nip->ip->offset % PAGE_SIZE)) < MAX_INSN_SIZE){
364                         retry = 1;
365 //                      DPRINTF ("Possibly 1st insn of IP at %lx lies on 2 pages.",  nip->ip->offset);
366                 }
367                 err = register_usprobe (task, mm, nip->ip, atomic, 0);
368                 if (err != 0)
369                         EPRINTF ("failed to install IP at %lx/%p. Error %d!", nip->ip->offset, nip->ip->jprobe.kp.addr, err);
370                 list_del(&nip->plist);
371                 kfree(nip);
372         }
373         list_for_each_entry_safe(nvtp, tnvtp, &vtplist, plist) {
374 //              DPRINTF ("Install VTP at %p.", nvtp->vtp->jprobe.kp.addr);
375                 if((PAGE_SIZE-(nvtp->vtp->addr % PAGE_SIZE)) < MAX_INSN_SIZE){
376                         retry = 1;
377 //                      DPRINTF ("Possibly 1st insn of VTP %lx lies on 2 pages.", nvtp->vtp->addr);
378                 }
379                 err = register_ujprobe (task, mm, &nvtp->vtp->jprobe, atomic);
380                 if (err)
381                         EPRINTF ("failed to install VTP at %p. Error %d!", nvtp->vtp->jprobe.kp.addr, err);
382                 list_del(&nvtp->plist);
383                 kfree(nvtp);
384         }
385                         
386         if(retry) goto _restart;
387                 
388         return us_proc_info.unres_ips_count + us_proc_info.unres_vtps_count;
389 }
390
391 static int
392 uninstall_mapped_ips (struct task_struct *task, int atomic)
393 {
394         int i, k, err;
395
396         for (i = 0; i < us_proc_info.libs_count; i++)
397         {
398 //              DPRINTF ("clear lib %s.", us_proc_info.p_libs[i].path);
399                 for (k = 0; k < us_proc_info.p_libs[i].ips_count; k++)
400                 {
401                         if (us_proc_info.p_libs[i].p_ips[k].installed)
402                         {
403 //                              DPRINTF ("remove IP at %p.", us_proc_info.p_libs[i].p_ips[k].jprobe.kp.addr);
404                                 err = unregister_usprobe (task, &us_proc_info.p_libs[i].p_ips[k], atomic);
405                                 if (err != 0)
406                                 {
407                                         EPRINTF ("failed to uninstall IP at %p. Error %d!", us_proc_info.p_libs[i].p_ips[k].jprobe.kp.addr, err);
408                                         continue;
409                                 }
410                                 us_proc_info.unres_ips_count++;
411                                 us_proc_info.p_libs[i].p_ips[k].installed = 0;
412                         }
413                 }
414                 for (k = 0; k < us_proc_info.p_libs[i].vtps_count; k++)
415                 {
416                         if (us_proc_info.p_libs[i].p_vtps[k].installed)
417                         {
418                                 //us_proc_vtp_data_t *vtp_data;
419                                 /*list_for_each_entry_rcu (vtp_data, &us_proc_info.p_libs[i].p_vtps[k].list, list)
420                                 {
421                                         DPRINTF ("remove VTP %s.", vtp_data->name);
422                                 }*/
423                                 unregister_ujprobe (task, &us_proc_info.p_libs[i].p_vtps[k].jprobe, atomic);
424                                 us_proc_info.unres_vtps_count++;
425                                 us_proc_info.p_libs[i].p_vtps[k].installed = 0;
426                         }
427                 }
428         }
429 //      DPRINTF ("Ures IPs  %d.", us_proc_info.unres_ips_count);
430 //      DPRINTF ("Ures VTPs %d.", us_proc_info.unres_vtps_count);
431
432         return 0;
433 }
434
435 void
436 send_sig_jprobe_event_handler (int sig, struct siginfo *info, struct task_struct *t, struct sigpending *signals)
437 {
438         int iRet, del = 0;
439         struct task_struct *task;
440
441         //DPRINTF("send_signal[%d] %d proc %d", nCount++, sig, t->pid);
442
443         //DPRINTF("%s(%d) send_signal %d for target proc %s(%d)", current->comm, current->pid, sig, t->comm, t->pid);
444         if (sig != SIGKILL)
445                 return;
446
447         if (t->tgid != us_proc_info.tgid)
448                 return;
449
450         del = 1;
451         // look for another process with the same tgid 
452         rcu_read_lock ();
453         for_each_process (task)
454         {
455                 if ((task->pid != t->pid) && (task->tgid == us_proc_info.tgid))
456                 {
457                         del = 0;
458                         break;
459                 }
460         }
461         rcu_read_unlock ();
462         if (del)
463         {
464 //              DPRINTF ("%s(%d) send_signal SIGKILL for the last target proc %s(%d)", current->comm, current->pid, t->comm, t->pid);
465                 iRet = uninstall_mapped_ips (t, 1);
466                 if (iRet != 0)
467                         EPRINTF ("failed to uninstall IPs (%d)!", iRet);
468         }
469 }
470
471 static int
472 uninstall_kernel_probe (unsigned long addr, int uflag, int kflag, kernel_probe_t ** pprobe)
473 {
474         kernel_probe_t *probe = NULL;
475         int iRet = 0;
476
477         if (probes_flags & kflag) {
478                 probe = find_probe(addr);
479                 if (probe) {
480                         iRet = remove_probe_from_list (addr);
481                         if (iRet)
482                                 EPRINTF ("remove_probe_from_list(0x%lx) result=%d!", addr, iRet);
483                         if (pprobe)
484                                 *pprobe = NULL;
485                 }
486                 probes_flags &= ~kflag;
487         }
488
489         if (us_proc_probes & uflag) {
490                 if (!(probes_flags & uflag)) {
491                         if (probe) {
492                                 iRet = unregister_kernel_probe(probe);
493                                 if (iRet) {
494                                         EPRINTF ("unregister_kernel_probe(0x%lx) result=%d!",
495                                                          addr, iRet);
496                                         return iRet;
497                                 }
498                         }
499                 }
500                 us_proc_probes &= ~uflag;
501         }
502
503         return iRet;
504 }
505
506 int
507 deinst_usr_space_proc (void)
508 {
509         int iRet = 0, found = 0;
510         struct task_struct *task = 0;
511
512         iRet = uninstall_kernel_probe (pf_addr, US_PROC_PF_INSTLD,
513                                                                    0, &pf_probe);
514         if (iRet)
515                 EPRINTF ("uninstall_kernel_probe(do_page_fault) result=%d!", iRet);
516
517         iRet = uninstall_kernel_probe (exit_addr, US_PROC_EXIT_INSTLD,
518                                                                    0, &exit_probe);
519         if (iRet)
520                 EPRINTF ("uninstall_kernel_probe(do_exit) result=%d!", iRet);
521
522         if (us_proc_info.tgid == 0)
523                 return 0;
524
525         rcu_read_lock ();
526         for_each_process (task)
527         {
528                 if (task->tgid == us_proc_info.tgid)
529                 {
530                         found = 1;
531                         get_task_struct (task);
532                         break;
533                 }
534         }
535         rcu_read_unlock ();
536         if (found)
537         {
538                 int i;
539                 // uninstall IPs
540                 iRet = uninstall_mapped_ips (task, 0);
541                 if (iRet != 0)
542                         EPRINTF ("failed to uninstall IPs %d!", iRet);
543                 put_task_struct (task);
544                 unregister_all_uprobes(task, 1);
545                 us_proc_info.tgid = 0;
546                 for(i = 0; i < us_proc_info.libs_count; i++)
547                         us_proc_info.p_libs[i].loaded = 0;
548         }
549
550         return iRet;
551 }
552
553 static int
554 install_kernel_probe (unsigned long addr, int uflag, int kflag, kernel_probe_t ** pprobe)
555 {
556         kernel_probe_t *probe = NULL;
557         int iRet = 0;
558
559         DPRINTF("us_proc_probes = 0x%x, uflag = 0x%x, "
560                         "probes_flags = 0x%x, kflag = 0x%x",
561                         us_proc_probes, uflag, probes_flags, kflag);
562
563         if (!(probes_flags & kflag)) {
564                 iRet = add_probe_to_list (addr, &probe);
565                 if (iRet) {
566                         EPRINTF ("add_probe_to_list(0x%lx) result=%d!", addr, iRet);
567                         return iRet;
568                 }
569                 probes_flags |= kflag;
570         }
571
572         if (!(us_proc_probes & uflag)) {
573                 if (!(probes_flags & uflag)) {
574                         iRet = register_kernel_probe (probe);
575                         if (iRet) {
576                                 EPRINTF ("register_kernel_probe(0x%lx) result=%d!", addr, iRet);
577                                 return iRet;
578                         }
579                 }
580                 us_proc_probes |= uflag;
581         }
582
583         if (pprobe)
584                 *pprobe = probe;
585
586         return 0;
587 }
588
589 int
590 inst_usr_space_proc (void)
591 {
592         int iRet, i;
593         struct task_struct *task = 0;
594         //struct mm_struct *mm;
595
596         if (!us_proc_info.path)
597                 return 0;
598
599         for (i = 0; i < us_proc_info.libs_count; i++)
600                 us_proc_info.p_libs[i].loaded = 0;
601         /* check whether process is already running
602          * 1) if process is running - look for the libraries in the process maps 
603          * 1.1) check if page for symbol does exist
604          * 1.1.1) if page exists - instrument it 
605          * 1.1.2) if page does not exist - make sure that do_page_fault handler is installed
606          * 2) if process is not running - make sure that do_page_fault handler is installed
607          * */
608         //iRet = 
609         find_task_by_path (us_proc_info.path, &task, NULL);
610         //if (iRet != 0)
611         //      return iRet;
612
613         if (task)
614         {
615                 us_proc_info.tgid = task->pid;
616                 /*mm = get_task_mm (task);
617                 if (!mm)
618                 {
619                         EPRINTF ("task %d has no mm!", task->pid);
620                         return -1;
621                 }
622                 down_read (&mm->mmap_sem);*/
623                 install_mapped_ips (task, 0);
624                 //up_read (&mm->mmap_sem);
625                 //mmput (mm);
626                 put_task_struct (task);
627         }
628
629         // enable 'do_page_fault' probe to detect when they will be loaded
630         iRet = install_kernel_probe (pf_addr, US_PROC_PF_INSTLD, 0, &pf_probe);
631         if (iRet)
632         {
633                 EPRINTF ("install_kernel_probe(do_page_fault) result=%d!", iRet);
634                 return iRet;
635         }
636         // enable 'do_exit' probe to detect when user proc exits in order to remove user space probes
637         iRet = install_kernel_probe (exit_addr, US_PROC_EXIT_INSTLD, 0, &exit_probe);
638         if (iRet)
639         {
640                 EPRINTF ("install_kernel_probe(do_exit) result=%d!", iRet);
641                 return iRet;
642         }
643         
644         return 0;
645 }
646
647 char expath[512];
648
649 void
650 do_page_fault_ret_pre_code (void)
651 {
652         struct mm_struct *mm;
653         struct vm_area_struct *vma = 0;
654
655         if (!us_proc_info.path)
656                 return;
657
658         if (!strcmp(us_proc_info.path,"*"))
659           {
660             //DPRINTF("us_proc_info.path = * ALL");
661             if (install_mapped_ips (current, 1) == 0)
662               {
663                 /*iRet = unregister_one_probe(pf_probe_id);
664                   if (iRet)
665                   EPRINTF("unregister_one_probe(do_page_fault) result=%d!", iRet); */
666               }
667             return;
668           }
669
670         //DPRINTF("do_page_fault from proc %d-%d-%d", current->pid, us_proc_info.tgid, us_proc_info.unres_ips_count);
671         if ((us_proc_info.unres_ips_count + us_proc_info.unres_vtps_count) == 0)
672         {
673                 //DPRINTF("do_page_fault: there no unresolved IPs");
674                 return;
675         }
676
677         if (us_proc_info.tgid == 0)
678         {
679                 //DPRINTF("do_page_fault check proc %d", current->pid);
680                 // check whether 
681                 /*if( path_lookup(us_proc_info.path, LOOKUP_FOLLOW, &nd) != 0 ) {
682                    EPRINTF("failed to lookup dentry for path %s!", us_proc_info.path);
683                    return; 
684                    } */
685                 mm = get_task_mm (current);//current->active_mm;
686                 if (mm)
687                 {
688                         down_read (&mm->mmap_sem);
689                         //BUG_ON(down_read_trylock(&mm->mmap_sem) == 0);
690                         vma = mm->mmap;
691                         while (vma)
692                         {
693                                 if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
694                                 {
695                                         /*struct path pth = {.dentry=vma->vm_file->f_dentry, .mnt=vma->vm_file->f_vfsmnt};
696                                         DPRINTF("do_page_fault: dentry %p-%p.", vma->vm_file->f_dentry, us_proc_info.m_f_dentry);
697                                         DPRINTF("do_page_fault: expath %s.",
698                                                       d_path(&pth, expath, sizeof(expath)-1));*/
699                                         if (vma->vm_file->f_dentry == us_proc_info.m_f_dentry)
700                                         {
701                                                 //if (strcmp(d_path(vma->vm_file->m_f_dentry, vma->vm_file->f_vfsmnt, expath, sizeof(expath)),
702                                                 //                 us_proc_info.path) == 0){
703                                                 //DPRINTF("do_page_fault: found!");
704                                                 //orig_mm = mm;
705                                                 break;
706                                         }
707                                 }
708                                 vma = vma->vm_next;
709                         }
710                         up_read (&mm->mmap_sem);
711                         mmput (mm);
712                 } else {
713 //                      DPRINTF ("proc %s/%d has no mm", current->comm, current->pid);
714                 }
715                 //path_release(&nd);
716                 if (vma)
717                 {
718                         DPRINTF ("do_page_fault found target proc %s(%d)", current->comm, current->pid);
719                         us_proc_info.tgid = current->pid;
720                         gl_nNotifyTgid = current->tgid;
721                 }
722         }
723         if (us_proc_info.tgid == current->tgid)
724         {
725                 //DPRINTF("do_page_fault from target proc %d", us_proc_info.tgid);
726                 if (install_mapped_ips (current, 1) == 0)
727                 {
728                         /*iRet = unregister_one_probe(pf_probe_id);
729                            if (iRet)
730                            EPRINTF("unregister_one_probe(do_page_fault) result=%d!", iRet); */
731                 }
732         }
733
734         //DPRINTF("do_page_fault from proc %d-%d exit", current->pid, us_proc_info.pid);
735 }
736 EXPORT_SYMBOL_GPL(do_page_fault_ret_pre_code);
737
738 void
739 do_exit_probe_pre_code (void)
740 {
741         int iRet, del = 0;
742         struct task_struct *task;
743
744         //DPRINTF("do_exit from proc %s-%d", current->comm, current->pid);
745
746         if (current->tgid != us_proc_info.tgid)
747                 return;
748
749         //DPRINTF("exit target proc %s-%d", current->comm, current->pid);
750         del = 1;
751         // look for another process with the same tgid 
752         rcu_read_lock ();
753         for_each_process (task)
754         {
755                 //if(task->tgid == us_proc_info.tgid)
756                 //      DPRINTF("check proc %s-%d", task->comm, task->pid);
757                 if ((task->pid != current->pid) && (task->tgid == us_proc_info.tgid))
758                 {
759                         del = 0;
760                         break;
761                 }
762         }
763         rcu_read_unlock ();
764         if (del)
765         {
766                 int i;
767 //              DPRINTF ("do_exit from the last target proc %s-%d", current->comm, current->pid);
768                 iRet = uninstall_mapped_ips (current, 1);
769                 if (iRet != 0)
770                         EPRINTF ("failed to uninstall IPs (%d)!", iRet);
771                 unregister_all_uprobes(current, 1);
772                 us_proc_info.tgid = 0;
773                 for(i = 0; i < us_proc_info.libs_count; i++)
774                         us_proc_info.p_libs[i].loaded = 0;
775         }
776
777 }
778 EXPORT_SYMBOL_GPL(do_exit_probe_pre_code);
779
780 DEFINE_PER_CPU (us_proc_ip_t *, gpCurIp) = NULL;
781 EXPORT_PER_CPU_SYMBOL_GPL(gpCurIp);
782 DEFINE_PER_CPU(struct pt_regs *, gpUserRegs) = NULL;
783 EXPORT_PER_CPU_SYMBOL_GPL(gpUserRegs);
784
785 // XXX MCPP: introduced custom default handlers defined in (exported from) another kernel module(s)
786 unsigned long (* ujprobe_event_pre_handler_custom_p)(us_proc_ip_t *, struct pt_regs *) = NULL;
787 EXPORT_SYMBOL(ujprobe_event_pre_handler_custom_p);
788 void (* ujprobe_event_handler_custom_p)() = NULL;
789 EXPORT_SYMBOL(ujprobe_event_handler_custom_p);
790 int (* uretprobe_event_handler_custom_p)(struct kretprobe_instance *, struct pt_regs *, us_proc_ip_t *) = NULL;
791 EXPORT_SYMBOL(uretprobe_event_handler_custom_p);
792
793 unsigned long
794 ujprobe_event_pre_handler (us_proc_ip_t * ip, struct pt_regs *regs)
795 {
796         __get_cpu_var (gpCurIp) = ip;
797         __get_cpu_var (gpUserRegs) = regs;
798         return 0;
799 }
800
801 void
802 ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
803 {
804         us_proc_ip_t *ip = __get_cpu_var (gpCurIp);
805
806         //static int nCount;
807
808         //DPRINTF("[%d]proc %s(%d): ENTRY %s(%#lx)", nCount++, current->comm, current->pid, ip->name, arg1);
809         pack_event_info (US_PROBE_ID, RECORD_ENTRY, "ppppppp", ip->jprobe.kp.addr, arg1, arg2, arg3, arg4, arg5, arg6);
810         uprobe_return ();
811 }
812
813 int
814 uretprobe_event_handler (struct kretprobe_instance *probe, struct pt_regs *regs, us_proc_ip_t * ip)
815 {
816         //static int nCount;
817         
818         int retval = regs_return_value(regs);
819         //DPRINTF("[%d]proc %s(%d): RETURN %s(%d)", nCount++, current->comm, current->pid, ip->name, retval);   
820         pack_event_info (US_PROBE_ID, RECORD_RET, "pd", ip->retprobe.kp.addr, retval);
821         return 0;
822 }
823
824 static int
825 register_usprobe (struct task_struct *task, struct mm_struct *mm, us_proc_ip_t * ip, int atomic, kprobe_opcode_t * islot)
826 {
827         int ret = 0;
828
829         ip->jprobe.kp.tgid = task->tgid;
830         //ip->jprobe.kp.addr = (kprobe_opcode_t *) addr;
831         if(!ip->jprobe.entry) {
832                 if (ujprobe_event_handler_custom_p != NULL)
833                         ip->jprobe.entry = (kprobe_opcode_t *) ujprobe_event_handler_custom_p;
834                 else {
835                         ip->jprobe.entry = (kprobe_opcode_t *) ujprobe_event_handler;
836                         //DPRINTF("Failed custom ujprobe_event_handler_custom_p");
837                 }
838         }
839         if(!ip->jprobe.pre_entry) {
840                 if (ujprobe_event_pre_handler_custom_p != NULL)
841                         ip->jprobe.pre_entry = (kprobe_pre_entry_handler_t) ujprobe_event_pre_handler_custom_p;
842                 else {
843                         ip->jprobe.pre_entry = (kprobe_pre_entry_handler_t) ujprobe_event_pre_handler;
844                         //DPRINTF("Failed custom ujprobe_event_pre_handler_custom_p");
845                 }
846         }
847         ip->jprobe.priv_arg = ip;
848         ret = register_ujprobe (task, mm, &ip->jprobe, atomic);
849         if (ret)
850         {
851                 EPRINTF ("register_ujprobe() failure %d", ret);
852                 return ret;
853         }
854         
855         //DPRINTF("IP %s boostable = %d", ip->name, ip->jprobe.kp.ainsn.boostable);
856 #if 0//defined(CONFIG_X86)
857         // _start is an entry point of the program, so when control reaches it
858         // return address is not saved on stack and can not be hijacked,
859         // so we can not set retprobe on it
860         if(strcmp(ip->name, "_start")!=0)
861 #endif
862         {
863                 ip->retprobe.kp.tgid = task->tgid;
864                 //ip->retprobe.kp.addr = (kprobe_opcode_t *) addr;
865                 if(!ip->retprobe.handler) {
866                         if (uretprobe_event_handler_custom_p != NULL)
867                                 ip->retprobe.handler = (kretprobe_handler_t) uretprobe_event_handler_custom_p;
868                         else {
869                                 ip->retprobe.handler = (kretprobe_handler_t) uretprobe_event_handler;
870                                 //DPRINTF("Failed custom uretprobe_event_handler_custom_p");
871                         }
872                 }
873                 ip->retprobe.priv_arg = ip;
874                 ret = register_uretprobe (task, mm, &ip->retprobe, atomic);
875                 if (ret)
876                 {
877                         EPRINTF ("register_uretprobe() failure %d", ret);
878                         return ret;
879                 }
880         }
881
882         return 0;
883 }
884
885 static int
886 unregister_usprobe (struct task_struct *task, us_proc_ip_t * ip, int atomic)
887 {
888         unregister_ujprobe (task, &ip->jprobe, atomic);
889 #if 0//defined(CONFIG_X86)
890         // _start is an entry point of the program, so when control reaches it
891         // return address is not saved on stack and can not be hijacked,
892         // so we can not set retprobe on it
893         if(strcmp(ip->name, "_start")!=0)
894 #endif
895                 unregister_uretprobe (task, &ip->retprobe, atomic);
896
897         return 0;
898 }