1 ////////////////////////////////////////////////////////////////////////////////////
3 // FILE: us_proc_inst.c
6 // This file is C source for SWAP driver.
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
14 // REVISION DATE: 2008.12.02
16 ////////////////////////////////////////////////////////////////////////////////////
19 #include "us_proc_inst.h"
21 #include "../kprobe/dbi_kprobes_deps.h"
22 #include "../uprobe/swap_uprobes.h"
24 #include "sspt/sspt.h"
26 #include "us_slot_manager.h"
28 #define mm_read_lock(task, mm, atomic, lock) \
29 mm = atomic ? task->active_mm : get_task_mm(task); \
32 panic("ERRR mm_read_lock: mm == NULL\n"); \
36 lock = down_read_trylock(&mm->mmap_sem); \
39 down_read(&mm->mmap_sem); \
42 #define mm_read_unlock(mm, atomic, lock) \
44 up_read(&mm->mmap_sem); \
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);
56 #define print_event(fmt, args...) \
59 sprintf(buf, fmt, ##args); \
60 pack_event_info(US_PROBE_ID, RECORD_ENTRY, "ds", 0x0badc0de, buf); \
65 return !strcmp(us_proc_info.path,"*");
68 // is user-space instrumentation
69 int is_us_instrumentation(void)
71 return !!us_proc_info.path;
74 struct dentry *dentry_by_path(const char *path)
76 struct dentry *dentry;
77 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
79 if (kern_path(path, LOOKUP_FOLLOW, &st_path) != 0) {
80 #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
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);
88 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
91 #elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38)
92 dentry = nd.path.dentry;
94 #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
95 dentry = st_path.dentry;
97 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
101 int check_vma(struct vm_area_struct *vma)
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)));
108 static int find_task_by_path (const char *path, struct task_struct **p_task, struct list_head *tids)
111 struct task_struct *task;
112 struct vm_area_struct *vma;
113 struct mm_struct *mm;
114 struct dentry *dentry = dentry_by_path(path);
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) {
126 for_each_process (task) {
128 if ( 0 != inst_pid && ( inst_pid != task->pid ) )
131 mm = get_task_mm(task);
136 if (check_vma(vma)) {
137 if (vma->vm_file->f_dentry == dentry) {
140 get_task_struct (task);
147 // only decrement usage count on mm since we cannot sleep here
148 atomic_dec(&mm->mm_users);
155 DPRINTF ("found pid %d for %s.", (*p_task)->pid, path);
156 *p_task = (*p_task)->group_leader;
157 gl_nNotifyTgid = (*p_task)->tgid;
159 DPRINTF ("pid for %s not found!", path);
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);
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)
176 struct task_struct *task = current->group_leader;
177 struct mm_struct *mm = task->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,
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);
200 set_mapping_file(file, procs, task, vma);
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);
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);
215 ret = sspt_register_usprobe(task, ip);
217 sspt_page_installed(page);
219 printk("ERROR install_otg_ip: ret=%d\n", ret);
230 EXPORT_SYMBOL_GPL(install_otg_ip);
232 int deinst_usr_space_proc (void)
234 int iRet = 0, found = 0;
235 struct task_struct *task = NULL;
236 struct sspt_procs *procs;
238 if (!is_us_instrumentation()) {
245 EPRINTF ("uninstall_kernel_probe(do_munmap) result=%d!", iRet);
248 for_each_process(task) {
249 procs = sspt_procs_get_by_task(task);
251 int ret = uninstall_us_proc_probes(task, procs, US_UNREGS_PROBE);
253 EPRINTF ("failed to uninstall IPs (%d)!", ret);
256 dbi_unregister_all_uprobes(task);
263 int inst_usr_space_proc (void)
266 struct task_struct *task = NULL;
268 if (!is_us_instrumentation()) {
272 DPRINTF("User space instr");
274 ret = register_helper();
279 for (i = 0; i < us_proc_info.libs_count; i++) {
280 us_proc_info.p_libs[i].loaded = 0;
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
292 // FIXME: clear_task_inst_info();
293 for_each_process (task) {
294 struct sspt_procs *procs;
296 if (task->flags & PF_KTHREAD){
297 DPRINTF("ignored kernel thread %d\n",
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);
310 ret = find_task_by_path(us_proc_info.path, &task, NULL);
312 struct sspt_procs *procs;
314 procs = sspt_procs_get_by_task_or_new(task);
316 us_proc_info.tgid = task->pid;
317 install_proc_probes(task, procs);
318 put_task_struct(task);
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)
330 int app_flag = (vma->vm_file->f_dentry == procs->dentry);
332 file->vm_start = vma->vm_start;
333 file->vm_end = vma->vm_end;
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);
340 void print_vma(struct mm_struct *mm);
342 void install_page_probes(unsigned long page_addr, struct task_struct *task, struct sspt_procs *procs)
345 struct mm_struct *mm;
346 struct vm_area_struct *vma;
348 atomic = in_atomic();
349 mm_read_lock(task, mm, atomic, lock);
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);
356 struct sspt_page *page;
358 set_mapping_file(file, procs, task, vma);
362 page = sspt_find_page_mapped(file, page_addr);
364 sspt_register_page(page, file, task);
369 mm_read_unlock(mm, atomic, lock);
372 static void install_file_probes(struct task_struct *task, struct mm_struct *mm, struct sspt_file *file)
374 struct sspt_page *page = NULL;
375 struct hlist_node *node = NULL;
376 struct hlist_head *head = NULL;
377 int i, table_size = (1 << file->page_probes_hash_bits);
379 for (i = 0; i < table_size; ++i) {
380 head = &file->page_probes_table[i];
381 swap_hlist_for_each_entry_rcu(page, node, head, hlist) {
382 sspt_register_page(page, file, task);
387 void install_proc_probes(struct task_struct *task, struct sspt_procs *procs)
390 struct vm_area_struct *vma;
391 struct mm_struct *mm;
393 atomic = in_atomic();
394 mm_read_lock(task, mm, atomic, lock);
396 for (vma = mm->mmap; vma; vma = vma->vm_next) {
397 if (check_vma(vma)) {
398 struct dentry *dentry = vma->vm_file->f_dentry;
399 struct sspt_file *file = sspt_procs_find_file(procs, dentry);
402 set_mapping_file(file, procs, task, vma);
406 install_file_probes(task, mm, file);
411 mm_read_unlock(mm, atomic, lock);
414 int check_install_pages_in_file(struct task_struct *task, struct sspt_file *file)
417 int table_size = (1 << file->page_probes_hash_bits);
418 struct sspt_page *page;
419 struct hlist_node *node, *tmp;
420 struct hlist_head *head;
422 for (i = 0; i < table_size; ++i) {
423 head = &file->page_probes_table[i];
424 swap_hlist_for_each_entry_safe (page, node, tmp, head, hlist) {
434 int unregister_us_file_probes(struct task_struct *task, struct sspt_file *file, enum US_FLAGS flag)
437 int table_size = (1 << file->page_probes_hash_bits);
438 struct sspt_page *page;
439 struct hlist_node *node, *tmp;
440 struct hlist_head *head;
442 for (i = 0; i < table_size; ++i) {
443 head = &file->page_probes_table[i];
444 swap_hlist_for_each_entry_safe (page, node, tmp, head, hlist) {
445 err = sspt_unregister_page(page, flag, task);
453 if (flag != US_DISARM) {
460 int uninstall_us_proc_probes(struct task_struct *task, struct sspt_procs *procs, enum US_FLAGS flag)
463 struct sspt_file *file;
465 list_for_each_entry_rcu(file, &procs->file_list, list) {
466 err = unregister_us_file_probes(task, file, flag);
476 pid_t find_proc_by_task(const struct task_struct *task, struct dentry *dentry)
478 struct vm_area_struct *vma;
479 struct mm_struct *mm = task->active_mm;
484 for (vma = mm->mmap; vma; vma = vma->vm_next) {
485 if (check_vma(vma)) {
486 if (vma->vm_file->f_dentry == dentry) {
495 void print_vma(struct mm_struct *mm)
497 struct vm_area_struct *vma;
498 printk("### print_vma: START\n");\
499 printk("### print_vma: START\n");
501 for (vma = mm->mmap; vma; vma = vma->vm_next) {
502 char *x = vma->vm_flags & VM_EXEC ? "x" : "-";
503 char *r = vma->vm_flags & VM_READ ? "r" : "-";
504 char *w = vma->vm_flags & VM_WRITE ? "w" : "-";
505 char *name = vma->vm_file ? (char *)vma->vm_file->f_dentry->d_iname : "N/A";
507 printk("### [%8lx..%8lx] %s%s%s pgoff=\'%8lu\' %s\n",
508 vma->vm_start, vma->vm_end, x, r, w, vma->vm_pgoff, name);
510 printk("### print_vma: END\n");
513 static DEFINE_PER_CPU(struct us_ip *, gpCurIp) = NULL;
514 EXPORT_PER_CPU_SYMBOL_GPL(gpCurIp);
515 static DEFINE_PER_CPU(struct pt_regs *, gpUserRegs) = NULL;
516 EXPORT_PER_CPU_SYMBOL_GPL(gpUserRegs);
518 unsigned long ujprobe_event_pre_handler(struct us_ip *ip, struct pt_regs *regs)
520 __get_cpu_var (gpCurIp) = ip;
521 __get_cpu_var (gpUserRegs) = regs;
525 void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
527 struct us_ip *ip = __get_cpu_var(gpCurIp);
528 unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
530 #if defined(CONFIG_ARM)
531 if (ip->offset & 0x01)
533 pack_event_info (US_PROBE_ID, RECORD_ENTRY, "ppppppp", addr | 0x01, arg1, arg2, arg3, arg4, arg5, arg6);
535 pack_event_info (US_PROBE_ID, RECORD_ENTRY, "ppppppp", addr, arg1, arg2, arg3, arg4, arg5, arg6);
538 pack_event_info (US_PROBE_ID, RECORD_ENTRY, "ppppppp", addr, arg1, arg2, arg3, arg4, arg5, arg6);
540 // Mr_Nobody: uncomment for valencia
541 //unregister_usprobe(current, ip, 1);
542 dbi_uprobe_return ();
545 static void send_plt(struct us_ip *ip)
547 unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
548 struct vm_area_struct *vma = find_vma(current->mm, addr);
550 if (vma && check_vma(vma)) {
552 unsigned long real_addr;
553 unsigned long real_got = current->mm->exe_file == vma->vm_file ?
555 ip->got_addr + vma->vm_start;
557 if (!read_proc_vm_atomic(current, real_got, &real_addr, sizeof(real_addr))) {
558 printk("Failed to read got %lx at memory address %lx!\n", ip->got_addr, real_got);
562 vma = find_vma(current->mm, real_addr);
563 if (vma && (vma->vm_start <= real_addr) && (vma->vm_end > real_addr)) {
564 name = vma->vm_file ? vma->vm_file->f_dentry->d_iname : NULL;
566 printk("Failed to get vma, includes %lx address\n", real_addr);
571 pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp", addr, real_addr, name, real_addr - vma->vm_start);
573 pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp", addr, real_addr, real_addr - vma->vm_start);
578 int uretprobe_event_handler(struct uretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip)
580 int retval = regs_return_value(regs);
581 unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
583 if (ip->got_addr && ip->flag_got == 0) {
588 #if defined(CONFIG_ARM)
589 if (ip->offset & 0x01)
591 pack_event_info (US_PROBE_ID, RECORD_RET, "pd", addr | 0x01, retval);
593 pack_event_info (US_PROBE_ID, RECORD_RET, "pd", addr, retval);
596 pack_event_info (US_PROBE_ID, RECORD_RET, "pd", addr, retval);
598 // Mr_Nobody: uncomment for valencia
599 //unregister_usprobe(current, ip, 1);
603 int register_usprobe(struct task_struct *task, struct us_ip *ip)
607 if (ip->jprobe.entry == NULL) {
608 ip->jprobe.entry = (void *)ujprobe_event_handler;
609 DPRINTF("Set default event handler for %x\n", ip->offset);
612 if (ip->jprobe.pre_entry == NULL) {
613 ip->jprobe.pre_entry = (uprobe_pre_entry_handler_t)ujprobe_event_pre_handler;
614 DPRINTF("Set default pre handler for %x\n", ip->offset);
617 ip->jprobe.priv_arg = ip;
618 ip->jprobe.up.task = task;
619 ip->jprobe.up.sm = ip->page->file->procs->sm;
620 ret = dbi_register_ujprobe(&ip->jprobe);
622 if (ret == -ENOEXEC) {
623 pack_event_info(ERR_MSG_ID, RECORD_ENTRY, "dp",
625 ip->jprobe.up.kp.addr);
627 DPRINTF ("dbi_register_ujprobe() failure %d", ret);
631 if (ip->flag_retprobe) {
632 // Mr_Nobody: comment for valencia
633 if (ip->retprobe.handler == NULL) {
634 ip->retprobe.handler = (uretprobe_handler_t)uretprobe_event_handler;
635 DPRINTF("Set default ret event handler for %x\n", ip->offset);
638 ip->retprobe.priv_arg = ip;
639 ip->retprobe.up.task = task;
640 ip->retprobe.up.sm = ip->page->file->procs->sm;
641 ret = dbi_register_uretprobe(&ip->retprobe);
643 EPRINTF ("dbi_register_uretprobe() failure %d", ret);
651 int unregister_usprobe(struct task_struct *task, struct us_ip *ip)
653 dbi_unregister_ujprobe(&ip->jprobe);
655 if (ip->flag_retprobe) {
656 dbi_unregister_uretprobe(&ip->retprobe);