--- /dev/null
+#ifndef __NEW_DPF__
+#define __NEW_DPF__
+
+#include <linux/hash.h>
+#include "storage.h"
+
+enum US_FLAGS {
+ US_UNREGS_PROBE,
+ US_NOT_RP2,
+ US_DISARM
+};
+
+struct ip_data {
+ unsigned long offset;
+ unsigned long got_addr;
+
+ kprobe_pre_entry_handler_t pre_handler;
+ unsigned long jp_handler;
+ kretprobe_handler_t rp_handler;
+
+ unsigned flag_retprobe:1;
+};
+
+struct page_probes {
+ struct list_head ip_list;
+ unsigned long offset;
+ int install;
+ spinlock_t lock;
+
+ struct hlist_node hlist; // for file_probes
+};
+
+struct file_probes {
+ struct list_head list; // for proc_probes
+ struct dentry *dentry;
+ char *path;
+ int loaded;
+ unsigned long vm_start;
+ unsigned long vm_end;
+
+ unsigned long page_probes_hash_bits;
+ struct hlist_head *page_probes_table; // for page_probes
+};
+
+struct proc_probes {
+ struct list_head list;
+ pid_t tgid;
+ struct dentry *dentry;
+ struct list_head file_list;
+};
+
+
+// ==================== us_ip ====================
+
+static struct us_ip *create_ip(unsigned long offset)
+{
+ struct us_ip *ip = kmalloc(sizeof(*ip), GFP_ATOMIC);
+ memset(ip, 0, sizeof(*ip));
+
+ INIT_LIST_HEAD(&ip->list);
+ ip->offset = offset;
+
+ return ip;
+}
+
+static void free_ip(struct us_ip *ip)
+{
+ kfree(ip);
+}
+
+static void set_ip_jp_handler(struct us_ip *ip, kprobe_pre_entry_handler_t per_entry, void *entry)
+{
+ ip->jprobe.pre_entry = per_entry;
+ ip->jprobe.entry = entry;
+}
+
+static void set_ip_rp_handler(struct us_ip *ip, kretprobe_handler_t handler)
+{
+ ip->flag_retprobe = 1;
+ ip->retprobe.handler = handler;
+}
+
+static void set_ip_got_addr(struct us_ip *ip, unsigned long got_addr)
+{
+ ip->got_addr = got_addr;
+}
+
+struct us_ip *us_proc_ip_copy(const struct us_ip *ip)
+{
+ // FIXME: one malloc us_ip
+ struct us_ip *ip_out = kmalloc(sizeof(*ip_out), GFP_ATOMIC);
+ if (ip_out == NULL) {
+ DPRINTF ("us_proc_ip_copy: No enough memory");
+ return NULL;
+ }
+
+ memcpy(ip_out, ip, sizeof(*ip_out));
+
+ // jprobe
+ memset(&ip_out->jprobe, 0, sizeof(struct jprobe));
+ ip_out->jprobe.entry = ip->jprobe.entry;
+ ip_out->jprobe.pre_entry = ip->jprobe.pre_entry;
+
+ // retprobe
+ retprobe_init(&ip_out->retprobe, ip->retprobe.handler);
+
+ ip_out->flag_got = 0;
+
+ INIT_LIST_HEAD(&ip_out->list);
+
+ return ip_out;
+}
+
+static struct us_ip *create_ip_by_ip_data(struct ip_data *ip_d)
+{
+ struct us_ip *ip = create_ip(ip_d->offset);
+ set_ip_jp_handler(ip, ip_d->pre_handler, ip_d->jp_handler);
+
+ if (ip_d->flag_retprobe) {
+ set_ip_rp_handler(ip, ip_d->rp_handler);
+ }
+
+ set_ip_got_addr(ip, ip_d->got_addr);
+
+ return ip;
+}
+
+// ==================== us_ip ====================
+
+
+// page_probes
+static struct page_probes *page_p_new(unsigned long offset)
+{
+ struct page_probes *obj = kmalloc(sizeof(*obj), GFP_ATOMIC);
+ if (obj) {
+ INIT_LIST_HEAD(&obj->ip_list);
+ obj->offset = offset;
+ obj->install = 0;
+ spin_lock_init(&obj->lock);
+ INIT_HLIST_NODE(&obj->hlist);
+ }
+
+ return obj;
+}
+
+static void page_p_del(struct page_probes *page_p)
+{
+ // TODO: del
+}
+
+static struct page_probes *page_p_copy(const struct page_probes *page_p)
+{
+ struct us_ip *ip_in, *ip_out;
+ struct page_probes *page_p_out = kmalloc(sizeof(*page_p), GFP_ATOMIC);
+
+ if (page_p_out) {
+ INIT_LIST_HEAD(&page_p_out->ip_list);
+ list_for_each_entry(ip_in, &page_p->ip_list, list) {
+ ip_out = us_proc_ip_copy(ip_in);
+ if (ip_out == NULL) {
+ // FIXME: free ip_list in page_p_out
+ kfree(page_p_out);
+ return NULL;
+ }
+
+ list_add(&ip_out->list, &page_p_out->ip_list);
+ }
+
+ page_p_out->offset = page_p->offset;
+ page_p_out->install = 0;
+ spin_lock_init(&page_p_out->lock);
+ INIT_HLIST_NODE(&page_p_out->hlist);
+ }
+
+ return page_p_out;
+}
+
+static void page_p_add_ip(struct page_probes *page_p, struct us_ip *ip)
+{
+ ip->offset &= ~PAGE_MASK;
+ INIT_LIST_HEAD(&ip->list);
+ list_add(&ip->list, &page_p->ip_list);
+}
+
+static struct us_ip *page_p_find_ip(struct page_probes *page_p, unsigned long offset)
+{
+ struct us_ip *ip;
+
+ list_for_each_entry(ip, &page_p->ip_list, list) {
+ if (ip->offset == offset) {
+ return ip;
+ }
+ }
+
+ return NULL;
+}
+
+static void page_p_assert_install(const struct page_probes *page_p)
+{
+ if (page_p->install != 0) {
+ panic("already installed page %x\n", page_p->offset);
+ }
+}
+
+static int page_p_is_install(struct page_probes *page_p)
+{
+ return page_p->install;
+}
+
+static void page_p_installed(struct page_probes *page_p)
+{
+ page_p->install = 1;
+}
+
+static void page_p_uninstalled(struct page_probes *page_p)
+{
+ page_p->install = 0;
+}
+// page_probes
+
+static void set_ip_kp_addr(struct us_ip *ip, struct page_probes *page_p, const struct file_probes *file_p)
+{
+ unsigned long addr = file_p->vm_start + page_p->offset + ip->offset;
+ ip->retprobe.kp.addr = ip->jprobe.kp.addr = addr;
+}
+
+static void page_p_set_all_kp_addr(struct page_probes *page_p, const struct file_probes *file_p)
+{
+ struct us_ip *ip;
+ unsigned long addr;
+
+ list_for_each_entry(ip, &page_p->ip_list, list) {
+ addr = file_p->vm_start + page_p->offset + ip->offset;
+ ip->retprobe.kp.addr = ip->jprobe.kp.addr = addr;
+// printk("### pp_set_all_kp_addr: start=%x, page_offset=%x, ip_offset=%x, addr=%x\n",
+// file_p->vm_start, page_p->offset, ip->offset, addr);
+ }
+}
+
+static int calculation_hash_bits(int cnt)
+{
+ int bits;
+ for (bits = 1; cnt >>= 1; ++bits);
+
+ return bits;
+}
+
+// file_probes
+static struct file_probes *file_p_new(const char *path, struct dentry *dentry, int page_cnt)
+{
+ struct file_probes *obj = kmalloc(sizeof(*obj), GFP_ATOMIC);
+
+ if (obj) {
+ int i, table_size;
+ obj->path = path;
+ obj->dentry = dentry;
+ obj->loaded = 0;
+ obj->vm_start = 0;
+ obj->vm_end = 0;
+
+ obj->page_probes_hash_bits = calculation_hash_bits(page_cnt);//PAGE_PROBES_HASH_BITS;
+ table_size = (1 << obj->page_probes_hash_bits);
+
+ obj->page_probes_table = kmalloc(sizeof(*obj->page_probes_table)*table_size, GFP_ATOMIC);
+
+ for (i = 0; i < table_size; ++i) {
+ INIT_HLIST_HEAD(&obj->page_probes_table[i]);
+ }
+ }
+
+ return obj;
+}
+
+static void file_p_del(struct file_probes *file_p)
+{
+ // TODO: del
+}
+
+static void file_p_add_page_p(struct file_probes *file_p, struct page_probes *page_p)
+{
+ hlist_add_head_rcu(&page_p->hlist, &file_p->page_probes_table[hash_ptr(page_p->offset, file_p->page_probes_hash_bits)]);
+}
+
+static struct file_probes *file_p_copy(const struct file_probes *file_p)
+{
+ struct file_probes *file_p_out;
+
+ if (file_p == NULL) {
+ printk("### WARNING: file_p == NULL\n");
+ return NULL;
+ }
+
+ file_p_out = kmalloc(sizeof(*file_p_out), GFP_ATOMIC);
+ if (file_p_out) {
+ struct page_probes *page_p = NULL;
+ struct hlist_node *node = NULL;
+ struct hlist_head *head = NULL;
+ int i, table_size;
+ INIT_LIST_HEAD(&file_p_out->list);
+ file_p_out->dentry = file_p->dentry;
+ file_p_out->path = file_p->path;
+ file_p_out->loaded = 0;
+ file_p_out->vm_start = 0;
+ file_p_out->vm_end = 0;
+
+ file_p_out->page_probes_hash_bits = file_p->page_probes_hash_bits;
+ table_size = (1 << file_p_out->page_probes_hash_bits);
+
+ file_p_out->page_probes_table =
+ kmalloc(sizeof(*file_p_out->page_probes_table)*table_size, GFP_ATOMIC);
+
+ for (i = 0; i < table_size; ++i) {
+ INIT_HLIST_HEAD(&file_p_out->page_probes_table[i]);
+ }
+
+ // copy pages
+ for (i = 0; i < table_size; ++i) {
+ head = &file_p->page_probes_table[i];
+ hlist_for_each_entry_rcu(page_p, node, head, hlist) {
+ file_p_add_page_p(file_p_out, page_p_copy(page_p));
+ }
+ }
+ }
+
+ return file_p_out;
+}
+
+static struct page_probes *file_p_find_page_p(struct file_probes *file_p, unsigned long offset)
+{
+ struct hlist_node *node;
+ struct hlist_head *head;
+ struct page_probes *page_p;
+
+ head = &file_p->page_probes_table[hash_ptr(offset, file_p->page_probes_hash_bits)];
+ hlist_for_each_entry_rcu(page_p, node, head, hlist) {
+ if (page_p->offset == offset) {
+ return page_p;
+ }
+ }
+
+ return NULL;
+}
+
+static struct page_probes *file_p_find_page_p_or_new(struct file_probes *file_p, unsigned long offset)
+{
+ struct page_probes *page_p = file_p_find_page_p(file_p, offset);
+
+ if (page_p == NULL) {
+ page_p = page_p_new(offset);
+ file_p_add_page_p(file_p, page_p);
+ }
+
+ return page_p;
+}
+
+static struct page_probes *file_p_find_page_p_mapped(struct file_probes *file_p, unsigned long page)
+{
+ unsigned long offset;
+
+ if (file_p->vm_start > page || file_p->vm_end < page) {
+ // TODO: or panic?!
+ printk("ERROR: file_p[vm_start..vm_end] <> page: file_p[vm_start=%x, vm_end=%x, path=%s, d_iname=%s] page=%x\n",
+ file_p->vm_start, file_p->vm_end, file_p->path, file_p->dentry->d_iname, page);
+ return NULL;
+ }
+
+ offset = page - file_p->vm_start;
+
+ return file_p_find_page_p(file_p, offset);
+}
+
+static void file_p_add_probe(struct file_probes *file_p, struct ip_data *ip_d)
+{
+ unsigned long offset = ip_d->offset & PAGE_MASK;
+ struct page_probes *page_p = file_p_find_page_p_or_new(file_p, offset);
+
+ // FIXME: delete ip
+ struct us_ip *ip = create_ip_by_ip_data(ip_d);
+
+ page_p_add_ip(page_p, ip);
+}
+
+static struct page_probes *get_page_p(struct file_probes *file_p, unsigned long offset_addr)
+{
+ unsigned long offset = offset_addr & PAGE_MASK;
+ struct page_probes *page_p = file_p_find_page_p_or_new(file_p, offset);
+
+ spin_lock(&page_p->lock);
+
+ return page_p;
+}
+
+static void put_page_p(struct page_probes *page_p)
+{
+ spin_unlock(&page_p->lock);
+}
+// file_probes
+
+// proc_probes
+static void proc_p_init(struct proc_probes *proc_p, struct dentry* dentry, pid_t tgid)
+{
+ INIT_LIST_HEAD(&proc_p->list);
+ proc_p->tgid = tgid;
+ proc_p->dentry = dentry;
+ INIT_LIST_HEAD(&proc_p->file_list);
+}
+
+static void proc_p_add_file_p(struct proc_probes *proc_p, struct file_probes *file_p)
+{
+ list_add(&file_p->list, &proc_p->file_list);
+}
+
+static struct file_probes *proc_p_find_file_p_by_dentry(struct proc_probes *proc_p,
+ const char *pach, struct dentry *dentry)
+{
+ struct file_probes *file_p;
+
+ list_for_each_entry(file_p, &proc_p->file_list, list) {
+ if (file_p->dentry == dentry) {
+ return file_p;
+ }
+ }
+
+ file_p = file_p_new(pach, dentry, 10);
+ proc_p_add_file_p(proc_p, file_p);
+
+ return file_p;
+}
+
+static void proc_p_add_dentry_probes(struct proc_probes *proc_p, const char *pach,
+ struct dentry* dentry, struct ip_data *ip_d, int cnt)
+{
+ int i;
+ struct file_probes *file_p = proc_p_find_file_p_by_dentry(proc_p, pach, dentry);
+
+ for (i = 0; i < cnt; ++i) {
+ file_p_add_probe(file_p, &ip_d[i]);
+ }
+}
+
+static struct proc_probes *proc_p_copy(struct proc_probes *proc_p, struct task_struct *task)
+{
+ struct file_probes *file_p;
+ struct proc_probes *proc_p_out = kmalloc(sizeof(*proc_p_out), GFP_ATOMIC);
+
+ proc_p_init(proc_p_out, proc_p->dentry, task->tgid);
+
+ list_for_each_entry(file_p, &proc_p->file_list, list) {
+ proc_p_add_file_p(proc_p_out, file_p_copy(file_p));
+ }
+
+ return proc_p_out;
+}
+
+static struct file_probes *proc_p_find_file_p(struct proc_probes *proc_p, struct vm_area_struct *vma)
+{
+ struct file_probes *file_p;
+
+ list_for_each_entry(file_p, &proc_p->file_list, list) {
+ if (vma->vm_file->f_dentry == file_p->dentry) {
+ return file_p;
+ }
+ }
+
+ return NULL;
+}
+// proc_probes
+
+#include "storage.h"
+
+static void print_proc_probes(const struct proc_probes *proc_p);
+
+struct proc_probes *get_file_probes(const inst_us_proc_t *task_inst_info)
+{
+ struct proc_probes *proc_p = kmalloc(sizeof(*proc_p), GFP_ATOMIC);
+
+ printk("####### get START #######\n");
+
+ if (proc_p) {
+ int i;
+ proc_p_init(proc_p, task_inst_info->m_f_dentry, 0);
+
+ printk("#2# get_file_probes: proc_p[dentry=%p]\n", proc_p->dentry);
+
+ for (i = 0; i < task_inst_info->libs_count; ++i) {
+ int k, j;
+ us_proc_lib_t *p_libs = &task_inst_info->p_libs[i];
+ struct dentry *dentry = p_libs->m_f_dentry;
+ const char *pach = p_libs->path;
+
+ for (k = 0; k < p_libs->ips_count; ++k) {
+ struct ip_data pd;
+ us_proc_ip_t *ip = &p_libs->p_ips[k];
+ unsigned long got_addr = 0;
+
+ for (j = 0; j < p_libs->plt_count; ++j) {
+ if (ip->offset == p_libs->p_plt[j].func_addr) {
+ got_addr = p_libs->p_plt[j].got_addr;
+ break;
+ }
+ }
+
+ pd.flag_retprobe = 1;
+ pd.offset = ip->offset;
+ pd.got_addr = got_addr;
+ pd.pre_handler = ip->jprobe.pre_entry;
+ pd.jp_handler = ip->jprobe.entry;
+ pd.rp_handler = ip->retprobe.handler;
+
+ proc_p_add_dentry_probes(proc_p, pach, dentry, &pd, 1);
+ }
+ }
+ }
+
+ print_proc_probes(proc_p);
+
+ printk("####### get END #######\n");
+
+ return proc_p;
+}
+
+static int register_usprobe_my(struct task_struct *task, struct us_ip *ip)
+{
+ return register_usprobe(task, ip, 1);
+}
+
+static int unregister_usprobe_my(struct task_struct *task, struct us_ip *ip, enum US_FLAGS flag)
+{
+ int err = 0;
+
+ switch (flag) {
+ case US_UNREGS_PROBE:
+ err = unregister_usprobe(task, ip, 1, 0);
+ break;
+ case US_NOT_RP2:
+ err = unregister_usprobe(task, ip, 1, 1);
+ break;
+ case US_DISARM:
+ arch_disarm_uprobe(&ip->jprobe.kp, task);
+ break;
+ default:
+ panic("incorrect value flag=%d", flag);
+ }
+
+ return err;
+}
+
+// debug
+static void print_jprobe(struct jprobe *jp)
+{
+ printk("### JP: entry=%x, pre_entry=%x\n",
+ jp->entry, jp->pre_entry);
+}
+
+static void print_retprobe(struct kretprobe *rp)
+{
+ printk("### RP: handler=%x\n",
+ rp->handler);
+}
+
+static void print_page_probes(const struct page_probes *page_p)
+{
+ int i = 0;
+ struct us_ip *ip;
+
+ printk("### offset=%x\n", page_p->offset);
+ list_for_each_entry(ip, &page_p->ip_list, list) {
+
+ printk("### addr[%2d]=%x, J_addr=%x, R_addr=%x\n",
+ i, ip->offset, ip->jprobe.kp.addr, ip->retprobe.kp.addr);
+ print_jprobe(&ip->jprobe);
+ print_retprobe(&ip->retprobe);
+ ++i;
+ }
+}
+
+static const char *NA = "N/A";
+
+static void print_file_probes(const struct file_probes *file_p)
+{
+ int i, table_size;
+ struct page_probes *page_p = NULL;
+ struct hlist_node *node = NULL;
+ struct hlist_head *head = NULL;
+
+ if (file_p == NULL) {
+ printk("### file_p == NULL\n");
+ return;
+ }
+
+ table_size = (1 << file_p->page_probes_hash_bits);
+ const char *name = (file_p->dentry) ? file_p->dentry->d_iname : NA;
+
+ printk("### print_file_probes: path=%s, d_iname=%s, table_size=%d, vm_start=%x\n",
+ file_p->path, name, table_size, file_p->vm_start);
+
+ for (i = 0; i < table_size; ++i) {
+ head = &file_p->page_probes_table[i];
+ hlist_for_each_entry_rcu(page_p, node, head, hlist) {
+ print_page_probes(page_p);
+ }
+ }
+}
+
+static void print_proc_probes(const struct proc_probes *proc_p)
+{
+ struct file_probes *file_p;
+
+ printk("### print_proc_probes\n");
+ list_for_each_entry(file_p, &proc_p->file_list, list) {
+ print_file_probes(file_p);
+ }
+ printk("### print_proc_probes\n");
+}
+
+void print_inst_us_proc(const inst_us_proc_t *task_inst_info)
+{
+ int i;
+ int cnt = task_inst_info->libs_count;
+ printk( "### BUNDLE PRINT START ###\n");
+ printk("\n### BUNDLE PRINT START ###\n");
+ printk("### task_inst_info.libs_count=%d\n", cnt);
+
+ for (i = 0; i < cnt; ++i) {
+ int j;
+
+ us_proc_lib_t *lib = &task_inst_info->p_libs[i];
+ int cnt_j = lib->ips_count;
+ char *path = lib->path;
+ printk("### path=%s, cnt_j=%d\n", path, cnt_j);
+
+ for (j = 0; j < cnt_j; ++j) {
+ struct us_ip *ips = &lib->p_ips[j];
+ unsigned long offset = ips->offset;
+ printk("### offset=%x\n", offset);
+ }
+ }
+ printk("### BUNDLE PRINT END ###\n");
+}
+
+#endif /* __NEW_DPF__ */
#include "../kprobe/dbi_kprobes_deps.h"
#include "../kprobe/dbi_uprobes.h"
+#define mm_read_lock(task, mm, atomic, lock) \
+ mm = atomic ? task->active_mm : get_task_mm(task); \
+ if (mm == NULL) { \
+ /* FIXME: */ \
+ panic("ERRR mm_read_lock: mm == NULL\n"); \
+ } \
+ \
+ if (atomic) { \
+ lock = down_read_trylock(&mm->mmap_sem); \
+ } else { \
+ lock = 1; \
+ down_read(&mm->mmap_sem); \
+ }
+
+#define mm_read_unlock(mm, atomic, lock) \
+ if (lock) { \
+ up_read(&mm->mmap_sem); \
+ } \
+ \
+ if (!atomic) { \
+ mmput(mm); \
+ }
+
DEFINE_PER_CPU (us_proc_vtp_t *, gpVtp) = NULL;
DEFINE_PER_CPU (struct pt_regs *, gpCurVtpRegs) = NULL;
# warning ARCH_REG_VAL is not implemented for this architecture. FBI will work improperly or even crash!!!
#endif // ARCH
-unsigned long (*dbi_ujprobe_event_pre_handler_custom_p)
-(us_proc_ip_t *, struct pt_regs *) = NULL;
-EXPORT_SYMBOL(dbi_ujprobe_event_pre_handler_custom_p);
-void (*dbi_ujprobe_event_handler_custom_p)(void) = NULL;
-EXPORT_SYMBOL(dbi_ujprobe_event_handler_custom_p);
-int (*dbi_uretprobe_event_handler_custom_p)
-(struct kretprobe_instance *, struct pt_regs *, us_proc_ip_t *) = NULL;
-EXPORT_SYMBOL(dbi_uretprobe_event_handler_custom_p);
-
-unsigned long ujprobe_event_pre_handler (us_proc_ip_t * ip, struct pt_regs *regs);
+unsigned long ujprobe_event_pre_handler (struct us_ip *ip, struct pt_regs *regs);
void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6);
-int uretprobe_event_handler (struct kretprobe_instance *probe, struct pt_regs *regs, us_proc_ip_t * ip);
+int uretprobe_event_handler (struct kretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip);
+
+static int register_usprobe(struct task_struct *task, struct us_ip *ip, int atomic);
+static int unregister_usprobe(struct task_struct *task, struct us_ip *ip, int atomic, int no_rp2);
-static int register_usprobe (struct task_struct *task, struct mm_struct *mm, us_proc_ip_t * ip, int atomic, kprobe_opcode_t * islot);
-static int unregister_usprobe (struct task_struct *task, us_proc_ip_t * ip, int atomic);
+#include "new_dpf.h"
int us_proc_probes;
-struct task_inst_info_node {
- struct list_head plist;
- inst_us_proc_t * task_inst_info;
- int tgid;
-};
-LIST_HEAD(task_inst_info_list);
+LIST_HEAD(proc_probes_list);
#ifdef SLP_APP
struct dentry *launchpad_daemon_dentry = NULL;
#define LIBDVM_RETURN 0x30bdc
#endif /* __ANDROID */
-us_proc_otg_ip_t *find_otg_probe(unsigned long addr)
-{
- us_proc_otg_ip_t *p;
- list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
- if (p->ip.offset == addr) {
- return p;
- }
- }
- return NULL;
+#define print_event(fmt, args...) \
+{ \
+ char *buf[1024]; \
+ sprintf(buf, fmt, ##args); \
+ pack_event_info(US_PROBE_ID, RECORD_ENTRY, "ds", 0x0badc0de, buf); \
}
-int add_otg_probe_to_list(unsigned long addr, us_proc_otg_ip_t **pprobe)
+static inline int is_libonly(void)
{
- us_proc_otg_ip_t *new_probe;
- us_proc_otg_ip_t *probe;
-
- if (pprobe) {
- *pprobe = NULL;
- }
- /* check if such probe does already exist */
- probe = find_otg_probe(addr);
- if (probe) {
- return 1;
- }
-
- new_probe = kmalloc(sizeof(us_proc_otg_ip_t), GFP_KERNEL);
- if (!new_probe) {
- EPRINTF ("no memory for new probe!");
- return -ENOMEM;
- }
- memset(new_probe,0, sizeof(us_proc_otg_ip_t));
-
- new_probe->ip.offset = addr;
- new_probe->ip.jprobe.kp.addr =
- new_probe->ip.retprobe.kp.addr = (kprobe_opcode_t *)addr;
- new_probe->ip.jprobe.priv_arg =
- new_probe->ip.retprobe.priv_arg = new_probe;
-
- INIT_LIST_HEAD(&new_probe->list);
- list_add_rcu(&new_probe->list, &otg_us_proc_info);
-
- if (pprobe) {
- *pprobe = new_probe;
- }
- return 0;
+ return !strcmp(us_proc_info.path,"*");
}
-int remove_otg_probe_from_list(unsigned long addr)
+// is user-space instrumentation
+static inline int is_us_instrumentation(void)
{
- us_proc_otg_ip_t *p;
-
- //check if such probe does exist
- p = find_otg_probe(addr);
- if (!p) {
- /* We do not care about it. Nothing bad. */
- return 0;
- }
-
- list_del_rcu(&p->list);
-
- kfree (p);
-
- return 0;
+ return !!us_proc_info.path;
}
-/**
- * Prepare copy of instrumentation data for task
- * in case of library only instrumentation
- */
-
-inst_us_proc_t* copy_task_inst_info (struct task_struct *task, inst_us_proc_t * task_inst_info)
+struct proc_probes *get_proc_probes_by_task(struct task_struct *task)
{
- int i, j;
- kprobe_opcode_t *entry_save;
- kprobe_pre_entry_handler_t pre_entry_save;
- kretprobe_handler_t handler_save;
-
- inst_us_proc_t* copy_info = 0;
-
- int unres_ips_count = 0, unres_vtps_count = 0;
-
- copy_info = kmalloc (sizeof (inst_us_proc_t), GFP_ATOMIC);
- memset ((void *) copy_info, 0, sizeof (inst_us_proc_t));
+ struct proc_probes *proc_p, *tmp;
- copy_info->path = task_inst_info->path;
- copy_info->m_f_dentry = NULL;
-
- copy_info->libs_count = task_inst_info->libs_count;
- copy_info->p_libs =
- kmalloc (task_inst_info->libs_count * sizeof (us_proc_lib_t), GFP_ATOMIC);
-
- if (!copy_info->p_libs) {
- DPRINTF ("No enough memory for copy_info->p_libs");
- return NULL;
- }
- memcpy (copy_info->p_libs, task_inst_info->p_libs,
- copy_info->libs_count * sizeof (us_proc_lib_t));
-
- for (i = 0; i < copy_info->libs_count; i++) {
- if (copy_info->p_libs[i].ips_count > 0)
- {
- unres_ips_count += copy_info->p_libs[i].ips_count;
-
- copy_info->p_libs[i].p_ips =
- kmalloc (copy_info->p_libs[i].ips_count * sizeof (us_proc_ip_t), GFP_ATOMIC);
-
- if (!copy_info->p_libs[i].p_ips) {
- DPRINTF ("No enough memory for copy_info->p_libs[i].p_ips");
- return NULL;
- }
-
- memcpy (copy_info->p_libs[i].p_ips, task_inst_info->p_libs[i].p_ips,
- copy_info->p_libs[i].ips_count * sizeof (us_proc_ip_t));
- for (j = 0; j < copy_info->p_libs[i].ips_count; j++) {
- // save handlers
- entry_save = copy_info->p_libs[i].p_ips[j].jprobe.entry;
- pre_entry_save = copy_info->p_libs[i].p_ips[j].jprobe.pre_entry;
- handler_save = copy_info->p_libs[i].p_ips[j].retprobe.handler;
-
- copy_info->p_libs[i].p_ips[j].installed = 0;
- memset(©_info->p_libs[i].p_ips[j].jprobe, 0, sizeof(struct jprobe));
- memset(©_info->p_libs[i].p_ips[j].retprobe, 0, sizeof(struct kretprobe));
-
- // restore handlers
- copy_info->p_libs[i].p_ips[j].jprobe.entry = entry_save;
- copy_info->p_libs[i].p_ips[j].jprobe.pre_entry = pre_entry_save;
- copy_info->p_libs[i].p_ips[j].retprobe.handler = handler_save;
- }
-
- unres_ips_count += copy_info->p_libs[i].ips_count;
- }
-
- for (j = 0; j < copy_info->p_libs[i].plt_count; j++)
- {
- copy_info->p_libs[i].p_plt[j].real_func_addr = 0;
+ if (!is_libonly()) {
+ if (task != current) {
+ printk("ERROR get_proc_probes_by_task: \'task != current\'\n");
+ return NULL;
}
- if (copy_info->p_libs[i].vtps_count > 0) {
- unres_vtps_count += copy_info->p_libs[i].vtps_count;
-
- copy_info->p_libs[i].p_vtps =
- kmalloc (copy_info->p_libs[i].vtps_count * sizeof (us_proc_vtp_t), GFP_ATOMIC);
-
- if (!copy_info->p_libs[i].p_vtps) {
- DPRINTF ("No enough memory for copy_info->p_libs[i].p_vtps");
- return NULL;
- }
-
- memcpy (copy_info->p_libs[i].p_vtps, task_inst_info->p_libs[i].p_vtps,
- copy_info->p_libs[i].vtps_count * sizeof (us_proc_vtp_t));
- for (j = 0; j < copy_info->p_libs[i].vtps_count; j++) {
- copy_info->p_libs[i].p_vtps[j].installed = 0;
- memset (©_info->p_libs[i].p_vtps[j].jprobe, 0, sizeof(struct jprobe));
- }
- unres_vtps_count = copy_info->p_libs[i].vtps_count;
- }
-
- copy_info->p_libs[i].m_f_dentry = task_inst_info->p_libs[i].m_f_dentry;
- copy_info->p_libs[i].loaded = 0;
-
- copy_info->p_libs[i].vma_start = 0;
- copy_info->p_libs[i].vma_end = 0;
+ return us_proc_info.pp;
}
- copy_info->unres_ips_count = unres_ips_count;
- copy_info->unres_vtps_count = unres_vtps_count;
-
- return copy_info;
-}
-inst_us_proc_t* get_task_inst_node(struct task_struct *task)
-{
- struct task_inst_info_node *node, *tnode;
-
- list_for_each_entry_safe(node, tnode, &task_inst_info_list, plist)
- {
- if (node && task && node->tgid == task->tgid) {
- return node->task_inst_info;
+ list_for_each_entry_safe(proc_p, tmp, &proc_probes_list, list) {
+ if (proc_p->tgid == task->tgid) {
+ return proc_p;
}
}
+
return NULL;
}
-void put_task_inst_node(struct task_struct *task, inst_us_proc_t *task_inst_info)
+void add_proc_probes(struct task_struct *task, struct proc_probes *proc_p)
{
- struct task_inst_info_node * node;
-
- node = kmalloc (sizeof(struct task_inst_info_node), GFP_ATOMIC);
-
- node->tgid = task->tgid;
- node->task_inst_info = task_inst_info;
-
- list_add_tail (&(node->plist), &task_inst_info_list);
+ list_add_tail(&proc_p->list, &proc_probes_list);
}
-
-void clear_task_inst_info(void)
+struct proc_probes *get_proc_probes_by_task_or_new(struct task_struct *task)
{
- struct list_head *node, *tmp;
+ struct proc_probes *proc_p = get_proc_probes_by_task(task);
+ if (proc_p == NULL) {
+ proc_p = proc_p_copy(us_proc_info.pp, task);
+ add_proc_probes(task, proc_p);
+ }
- list_for_each_safe(node, tmp, &task_inst_info_list)
- list_del(node);
+ return proc_p;
}
#ifdef SLP_APP
int i, k, err;
unsigned long addr;
unsigned int old_ips_count, old_vtps_count;
- us_proc_otg_ip_t *p;
struct task_struct *t;
struct mm_struct *mm;
task_inst_info->p_libs[i].p_ips[k].offset, addr);
task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr = (kprobe_opcode_t *) addr;
task_inst_info->p_libs[i].p_ips[k].retprobe.kp.addr = (kprobe_opcode_t *) addr;
- task_inst_info->p_libs[i].p_ips[k].installed = 1;
task_inst_info->unres_ips_count--;
- err = register_usprobe (task, mm, &task_inst_info->p_libs[i].p_ips[k], atomic, 0);
+ err = register_usprobe(task, &task_inst_info->p_libs[i].p_ips[k], atomic);
if (err != 0) {
DPRINTF ("failed to install IP at %lx/%p. Error %d!",
task_inst_info->p_libs[i].p_ips[k].offset,
task_inst_info->p_libs[i].p_vtps[k].jprobe.priv_arg = &task_inst_info->p_libs[i].p_vtps[k];
task_inst_info->p_libs[i].p_vtps[k].installed = 1;
task_inst_info->unres_vtps_count--;
- err = dbi_register_ujprobe (task, mm, &task_inst_info->p_libs[i].p_vtps[k].jprobe, atomic);
+ err = dbi_register_ujprobe(task, &task_inst_info->p_libs[i].p_vtps[k].jprobe, atomic);
if ( err != 0 ) {
EPRINTF ("failed to install VTP at %p. Error %d!",
task_inst_info->p_libs[i].p_vtps[k].jprobe.kp.addr, err);
#endif /* __ANDROID */
vma = vma->vm_next;
}
- list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
- if (p->ip.installed) {
- continue;
- }
- if (!page_present(mm, p->ip.offset)) {
- DPRINTF("Page isn't present for %p.",
- p->ip.offset);
- continue;
- }
- p->ip.installed = 1;
- err = register_usprobe(task, mm, &p->ip, atomic, 0);
- if (err != 0) {
- DPRINTF("failed to install IP at %lx/%p. Error %d!",
- p->ip.offset,
- p->ip.jprobe.kp.addr, err);
- continue;
- }
- task_inst_info->unres_otg_ips_count--;
- }
if (!atomic) {
up_read (&mm->mmap_sem);
mmput (mm);
return task_inst_info->unres_ips_count + task_inst_info->unres_vtps_count;
}
-static int install_otg_ip(unsigned long addr,
- unsigned long pre_handler,
- unsigned long jp_handler,
- unsigned long rp_handler)
+static void set_mapping_file(struct file_probes *file_p,
+ const struct proc_probes *proc_p,
+ const struct task_struct *task,
+ const struct vm_area_struct *vma);
+
+int install_otg_ip(unsigned long addr,
+ kprobe_pre_entry_handler_t pre_handler,
+ unsigned long jp_handler,
+ kretprobe_handler_t rp_handler)
{
- int err;
- us_proc_otg_ip_t *pprobe;
+ int ret = 0;
struct task_struct *task = current->group_leader;
struct mm_struct *mm = task->mm;
- /* Probe preparing */
- err = add_otg_probe_to_list(addr, &pprobe);
- if (err) {
- if (err == 1) {
- DPRINTF("OTG probe %p already installed.", addr);
- return 0;
- } else {
- DPRINTF("Failed to add new OTG probe, err=%d",err);
- return err;
- }
- }
- if (pre_handler) {
- pprobe->ip.jprobe.pre_entry =
- (kprobe_pre_entry_handler_t)pre_handler;
- } else {
- pprobe->ip.jprobe.pre_entry =
- (kprobe_pre_entry_handler_t)
- dbi_ujprobe_event_pre_handler_custom_p;
+ if (mm) {
+ struct vm_area_struct *vma = find_vma(mm, addr);
+ if (vma && (vma->vm_flags & VM_EXEC) &&
+ vma->vm_file && vma->vm_file->f_dentry) {
+ unsigned long offset_addr = addr - vma->vm_start;
+ struct dentry *dentry = vma->vm_file->f_dentry;
+ char *name = dentry->d_iname;
+ struct proc_probes *proc_p = get_proc_probes_by_task(task);
+ struct ip_data pd = {
+ .offset = offset_addr,
+ .pre_handler = pre_handler,
+ .jp_handler = jp_handler,
+ .rp_handler = rp_handler,
+ .flag_retprobe = 1
+ };
+
+ struct file_probes *file_p = proc_p_find_file_p_by_dentry(proc_p, name, dentry);
+ struct page_probes *page_p = get_page_p(file_p, offset_addr);
+ struct us_ip *ip = page_p_find_ip(page_p, offset_addr & ~PAGE_MASK);
+
+ if (!file_p->loaded) {
+ set_mapping_file(file_p, proc_p, task, vma);
+ file_p->loaded = 1;
+ }
- }
- if (jp_handler) {
- pprobe->ip.jprobe.entry =
- (kprobe_opcode_t *)jp_handler;
- } else {
- pprobe->ip.jprobe.entry =
- (kprobe_opcode_t *)
- dbi_ujprobe_event_handler_custom_p;
- }
- if (rp_handler) {
- pprobe->ip.retprobe.handler =
- (kretprobe_handler_t)rp_handler;
- } else {
- pprobe->ip.retprobe.handler =
- (kretprobe_handler_t)
- dbi_uretprobe_event_handler_custom_p;
- }
+ if (ip == NULL) {
+ struct file_probes *file_p = proc_p_find_file_p_by_dentry(proc_p, name, dentry);
+ file_p_add_probe(file_p, &pd);
- pprobe->tgid = task->tgid;
- if (!page_present(mm, addr)) {
- DPRINTF("Page isn't present for %p.", addr);
+ /* if addr mapping, that probe install, else it be installed in do_page_fault handler */
+ if (page_present(mm, addr)) {
+ ip = page_p_find_ip(page_p, offset_addr & ~PAGE_MASK);
+ set_ip_kp_addr(ip, page_p, file_p);
- us_proc_info.unres_otg_ips_count++;
- /* Probe will be installed in do_page_fault handler */
- return 0;
- }
- DPRINTF("Page present for %p.", addr);
+ // TODO: error
+ ret = register_usprobe_my(task, ip);
+ if (ret == 0) {
+ page_p_installed(page_p);
+ } else {
+ printk("ERROR install_otg_ip: ret=%d\n", ret);
+ }
+ }
+ }
- /* Probe installing */
- pprobe->ip.installed = 1;
- err = register_usprobe(current, mm, &pprobe->ip, 1, 0);
- if (err != 0) {
- DPRINTF("failed to install IP at %lx/%p. Error %d!",
- addr, pprobe->ip.jprobe.kp.addr, err);
- return err;
+ put_page_p(page_p);
+ }
}
- return 0;
+
+ return ret;
}
EXPORT_SYMBOL_GPL(install_otg_ip);
static int uninstall_mapped_ips (struct task_struct *task, inst_us_proc_t* task_inst_info, int atomic)
{
int i, k, err;
- us_proc_otg_ip_t *p;
for (i = 0; i < task_inst_info->libs_count; i++)
{
if (task_inst_info->p_libs[i].p_ips[k].installed)
{
DPRINTF ("remove IP at %p.", task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr);
- err = unregister_usprobe (task, &task_inst_info->p_libs[i].p_ips[k], atomic);
+ err = unregister_usprobe (task, &task_inst_info->p_libs[i].p_ips[k], atomic, 0);
if (err != 0)
{
EPRINTF ("failed to uninstall IP at %p. Error %d!", task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr, err);
continue;
}
task_inst_info->unres_ips_count++;
- task_inst_info->p_libs[i].p_ips[k].installed = 0;
}
}
for (k = 0; k < task_inst_info->p_libs[i].vtps_count; k++)
}
}
#endif /* __ANDROID */
- list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
- if (!p->ip.installed) {
- continue;
- }
- DPRINTF("remove OTG IP at %p.", p->ip.offset);
- err = unregister_usprobe(task, &p->ip, atomic);
- if (err != 0) {
- EPRINTF("failed to uninstall IP at %p. Error %d!",
- p->ip.jprobe.kp.addr, err);
- continue;
- }
- p->ip.installed = 0;
- }
DPRINTF ("Ures IPs %d.", task_inst_info->unres_ips_count);
DPRINTF ("Ures VTPs %d.", task_inst_info->unres_vtps_count);
return 0;
}
-void send_sig_jprobe_event_handler (int sig, struct siginfo *info, struct task_struct *t, struct sigpending *signals)
-{
- int iRet, del = 0;
- struct task_struct *task;
- inst_us_proc_t *task_inst_info = NULL;
-
- //if user-space instrumentation is not set
- if (!us_proc_info.path)
- return;
-
- if (sig != SIGKILL)
- return;
-
- if (!strcmp(us_proc_info.path,"*"))
- {
- task_inst_info = get_task_inst_node(t);
- if (task_inst_info)
- {
- iRet = uninstall_mapped_ips (t, task_inst_info, 1);
- if (iRet != 0)
- EPRINTF ("failed to uninstall IPs (%d)!", iRet);
- dbi_unregister_all_uprobes(t, 1);
- return;
- }
- }
- else
- {
- if (current->tgid != us_proc_info.tgid)
- return;
- del = 1;
-
- // look for another process with the same tgid
- rcu_read_lock ();
- for_each_process (task)
- {
- if ((task->pid != t->pid) && (task->tgid == us_proc_info.tgid))
- {
- del = 0;
- break;
- }
- }
- rcu_read_unlock ();
- if (del)
- {
- DPRINTF ("%s(%d) send_signal SIGKILL for the last target proc %s(%d)",
- current->comm, current->pid, t->comm, t->pid);
- iRet = uninstall_mapped_ips (t, &us_proc_info, 1);
- if (iRet != 0)
- EPRINTF ("failed to uninstall IPs (%d)!", iRet);
- }
- }
-}
static int uninstall_kernel_probe (unsigned long addr, int uflag, int kflag, kernel_probe_t ** pprobe)
{
kernel_probe_t *probe = NULL;
return iRet;
}
+static int uninstall_us_proc_probes(struct task_struct *task, struct proc_probes *proc_p, enum US_FLAGS flag);
+
int deinst_usr_space_proc (void)
{
int iRet = 0, found = 0;
struct task_struct *task = 0;
inst_us_proc_t *task_inst_info = NULL;
- //if user-space instrumentation is not set
- if (!us_proc_info.path)
+ if (!is_us_instrumentation()) {
return 0;
+ }
iRet = uninstall_kernel_probe (pf_addr, US_PROC_PF_INSTLD,
0, &pf_probe);
if (iRet)
EPRINTF ("uninstall_kernel_probe(do_munmap) result=%d!", iRet);
- if (!strcmp(us_proc_info.path,"*"))
- {
- for_each_process (task)
- {
- task_inst_info = get_task_inst_node(task);
- if (task_inst_info)
- {
- iRet = uninstall_mapped_ips (task, task_inst_info, 1);
- if (iRet != 0)
- EPRINTF ("failed to uninstall IPs (%d)!", iRet);
+ if (is_libonly()) {
+ struct proc_probes *proc_p;
+
+ for_each_process(task) {
+ proc_p = get_proc_probes_by_task(task);
+ if (proc_p) {
+ int ret = uninstall_us_proc_probes(task, proc_p, US_UNREGS_PROBE);
+ if (ret) {
+ EPRINTF ("failed to uninstall IPs (%d)!", ret);
+ }
+
dbi_unregister_all_uprobes(task, 1);
}
}
rcu_read_unlock ();
if (found)
{
- int i;
+ int i, ret;
// uninstall IPs
- iRet = uninstall_mapped_ips (task, &us_proc_info, 0);
- if (iRet != 0)
- EPRINTF ("failed to uninstall IPs %d!", iRet);
+ ret = uninstall_us_proc_probes(task, us_proc_info.pp, US_UNREGS_PROBE);
+ if (ret != 0) {
+ EPRINTF ("failed to uninstall IPs %d!", ret);
+ }
+
put_task_struct (task);
+
+ printk("### 1 ### dbi_unregister_all_uprobes:\n");
dbi_unregister_all_uprobes(task, 1);
us_proc_info.tgid = 0;
for(i = 0; i < us_proc_info.libs_count; i++)
return 0;
}
+static void install_proc_probes(struct task_struct *task, struct proc_probes *proc_p, int atomic);
+
int inst_usr_space_proc (void)
{
int ret, i;
struct task_struct *task = 0;
- inst_us_proc_t *task_inst_info = NULL;
- //if user-space instrumentation is not set
- if (!us_proc_info.path)
+ if (!is_us_instrumentation()) {
return 0;
+ }
DPRINTF("User space instr");
* 2) if process is not running - make sure that do_page_fault handler is installed
* */
- if (!strcmp(us_proc_info.path,"*"))
+ if (is_libonly())
{
- clear_task_inst_info();
+ // FIXME: clear_task_inst_info();
for_each_process (task) {
+ struct proc_probes *proc_p;
+
if (task->flags & PF_KTHREAD){
DPRINTF("ignored kernel thread %d\n",
task->pid);
continue;
}
- task_inst_info = get_task_inst_node(task);
- if (!task_inst_info) {
- task_inst_info =
- copy_task_inst_info(task,
- &us_proc_info);
- put_task_inst_node(task, task_inst_info);
- }
+ proc_p = get_proc_probes_by_task_or_new(task);
DPRINTF("trying process");
#ifdef __ANDROID
if (is_java_inst_enabled()) {
find_libdvm_for_task(task, task_inst_info);
}
#endif /* __ANDROID */
- install_mapped_ips (task, task_inst_info, 1);
+ install_proc_probes(task, proc_p, 1);
//put_task_struct (task);
- task_inst_info = NULL;
}
}
else
find_libdvm_for_task(task, &us_proc_info);
}
#endif /* __ANDROID */
- install_mapped_ips (task, &us_proc_info, 0);
+ install_proc_probes(task, us_proc_info.pp, 0);
put_task_struct (task);
}
}
return 0;
}
-void do_page_fault_ret_pre_code (void)
+#include "../../tools/gpmu/probes/entry_data.h"
+
+extern storage_arg_t sa_dpf;
+
+void do_page_fault_j_pre_code(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
+ struct task_struct *task = current->group_leader;
+
+ if (task->flags & PF_KTHREAD) {
+ DPRINTF("ignored kernel thread %d\n", task->pid);
+ return;
+ }
+
+ if (is_us_instrumentation()) {
+ swap_put_entry_data((void *)addr, &sa_dpf);
+ }
+}
+EXPORT_SYMBOL_GPL(do_page_fault_j_pre_code);
+
+
+unsigned long imi_sum_time = 0;
+unsigned long imi_sum_hit = 0;
+EXPORT_SYMBOL_GPL (imi_sum_time);
+EXPORT_SYMBOL_GPL (imi_sum_hit);
+
+static void set_mapping_file(struct file_probes *file_p,
+ const struct proc_probes *proc_p,
+ const struct task_struct *task,
+ const struct vm_area_struct *vma)
+{
+ int app_flag = (vma->vm_file->f_dentry == proc_p->dentry);
+ char *p;
+ // if we installed something, post library info for those IPs
+ p = strrchr(file_p->path, '/');
+ if(!p) {
+ p = file_p->path;
+ } else {
+ p++;
+ }
+
+ file_p->vm_start = vma->vm_start;
+ file_p->vm_end = vma->vm_end;
+
+ pack_event_info(DYN_LIB_PROBE_ID, RECORD_ENTRY, "dspdd",
+ task->tgid, p, vma->vm_start,
+ vma->vm_end - vma->vm_start, app_flag);
+}
+
+void print_vma(struct mm_struct *mm);
+
+static int register_us_page_probe(struct page_probes *page_p,
+ const struct file_probes *file_p,
+ const struct task_struct *task)
+{
+ int err = 0;
+ struct us_ip *ip;
+
+ spin_lock(&page_p->lock);
+
+ if (page_p_is_install(page_p)) {
+ printk("page %x in %s task[tgid=%u, pid=%u] already installed\n",
+ page_p->offset, file_p->dentry->d_iname, task->tgid, task->pid);
+ print_vma(task->mm);
+ return 0;
+ }
+
+ page_p_assert_install(page_p);
+ page_p_set_all_kp_addr(page_p, file_p);
+
+ list_for_each_entry(ip, &page_p->ip_list, list) {
+ err = register_usprobe_my(task, ip);
+ if (err != 0) {
+ //TODO: ERROR
+ return err;
+ }
+ }
+
+ page_p_installed(page_p);
+
+ spin_unlock(&page_p->lock);
+
+ return 0;
+}
+
+static int unregister_us_page_probe(const struct task_struct *task,
+ struct page_probes *page_p, enum US_FLAGS flag)
+{
+ int err = 0;
+ struct us_ip *ip;
+
+ spin_lock(&page_p->lock);
+ if (!page_p_is_install(page_p)) {
+ spin_unlock(&page_p->lock);
+ return 0;
+ }
+
+ list_for_each_entry(ip, &page_p->ip_list, list) {
+ err = unregister_usprobe_my(task, ip, flag);
+ if (err != 0) {
+ //TODO: ERROR
+ break;
+ }
+ }
+
+ if (flag != US_DISARM) {
+ page_p_uninstalled(page_p);
+ }
+ spin_unlock(&page_p->lock);
+
+ return err;
+}
+
+static int check_vma(struct vm_area_struct *vma)
+{
+#ifndef __ANDROID
+ return vma->vm_file && !(vma->vm_pgoff != 0 || !(vma->vm_flags & VM_EXEC) || (vma->vm_flags & VM_ACCOUNT) ||
+ !(vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) ||
+ !(vma->vm_flags & (VM_READ | VM_MAYREAD)));
+#else // __ANDROID
+ return vma->vm_file && !(vma->vm_pgoff != 0 || !(vma->vm_flags & VM_EXEC));
+#endif // __ANDROID
+}
+
+
+static void install_page_probes(unsigned long page, struct task_struct *task, struct proc_probes *proc_p, int atomic)
+{
+ int lock;
struct mm_struct *mm;
+ struct vm_area_struct *vma;
+
+ mm_read_lock(task, mm, atomic, lock);
+
+ vma = find_vma(mm, page);
+ if (vma && check_vma(vma)) {
+ struct file_probes *file_p = proc_p_find_file_p(proc_p, vma);
+ if (file_p) {
+ struct page_probes *page_p;
+ if (!file_p->loaded) {
+ set_mapping_file(file_p, proc_p, task, vma);
+ file_p->loaded = 1;
+ }
+
+ page_p = file_p_find_page_p_mapped(file_p, page);
+ if (page_p) {
+ register_us_page_probe(page_p, file_p, task);
+ }
+ }
+ }
+
+ mm_read_unlock(mm, atomic, lock);
+}
+
+static void install_file_probes(struct task_struct *task, struct mm_struct *mm, struct file_probes *file_p)
+{
+ struct page_probes *page_p = NULL;
+ struct hlist_node *node = NULL;
+ struct hlist_head *head = NULL;
+ int i, table_size = (1 << file_p->page_probes_hash_bits);
+
+ for (i = 0; i < table_size; ++i) {
+ head = &file_p->page_probes_table[i];
+ hlist_for_each_entry_rcu(page_p, node, head, hlist) {
+ if (page_present(mm, page_p->offset)) {
+ register_us_page_probe(page_p, file_p, task);
+ }
+ }
+ }
+}
+
+static void install_proc_probes(struct task_struct *task, struct proc_probes *proc_p, int atomic)
+{
+ int lock;
+ struct vm_area_struct *vma;
+ struct mm_struct *mm;
+
+ mm_read_lock(task, mm, atomic, lock);
+
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ if (check_vma(vma)) {
+ struct file_probes *file_p = proc_p_find_file_p(proc_p, vma);
+ if (file_p) {
+ if (!file_p->loaded) {
+ set_mapping_file(file_p, proc_p, task, vma);
+ file_p->loaded = 1;
+ }
+
+ install_file_probes(task, mm, file_p);
+ }
+ }
+ }
+
+ mm_read_unlock(mm, atomic, lock);
+}
+
+static int check_install_pages_in_file(struct task_struct *task, struct file_probes *file_p)
+{
+ int i;
+ int table_size = (1 << file_p->page_probes_hash_bits);
+ struct page_probes *page_p;
+ struct hlist_node *node, *tmp;
+ struct hlist_head *head;
+
+ for (i = 0; i < table_size; ++i) {
+ head = &file_p->page_probes_table[i];
+ hlist_for_each_entry_safe (page_p, node, tmp, head, hlist) {
+ if (page_p->install) {
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int unregister_us_file_probes(struct task_struct *task, struct file_probes *file_p, enum US_FLAGS flag)
+{
+ int i, err = 0;
+ int table_size = (1 << file_p->page_probes_hash_bits);
+ struct page_probes *page_p;
+ struct hlist_node *node, *tmp;
+ struct hlist_head *head;
+
+ for (i = 0; i < table_size; ++i) {
+ head = &file_p->page_probes_table[i];
+ hlist_for_each_entry_safe (page_p, node, tmp, head, hlist) {
+ err = unregister_us_page_probe(task, page_p, flag);
+ if (err != 0) {
+ // TODO: ERROR
+ return err;
+ }
+ }
+ }
+
+ if (flag != US_DISARM) {
+ file_p->loaded = 0;
+ }
+
+ return err;
+}
+
+static int uninstall_us_proc_probes(struct task_struct *task, struct proc_probes *proc_p, enum US_FLAGS flag)
+{
+ int err;
+ struct file_probes *file_p;
+
+ list_for_each_entry_rcu(file_p, &proc_p->file_list, list) {
+ err = unregister_us_file_probes(task, file_p, flag);
+ if (err != 0) {
+ // TODO:
+ return err;
+ }
+ }
+
+ return err;
+}
+
+static pid_t find_proc_by_task(const struct task_struct *task, const struct dentry *dentry)
+{
+ struct vm_area_struct *vma;
+ struct mm_struct *mm = task->active_mm;
+ if (mm == NULL) {
+ return 0;
+ }
+
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
+ if (vma->vm_file->f_dentry == dentry) {
+ return task->tgid;
+ }
+#ifdef SLP_APP
+ if (is_slp_app_with_dentry(vma, dentry)) {
+ return task->tgid;
+ }
+#endif /* SLP_APP */
+#ifdef ANDROID_APP
+ if (is_android_app_with_dentry(vma, dentry)) {
+ return task->tgid;
+ }
+#endif /* ANDROID_APP */
+ }
+ }
+
+ return 0;
+}
+
+void do_page_fault_ret_pre_code (void)
+{
+ struct task_struct *task = current->group_leader;
+ struct mm_struct *mm = task->mm;
struct vm_area_struct *vma = 0;
- inst_us_proc_t *task_inst_info = NULL;
+ struct proc_probes *proc_p = NULL;
/*
* Because process threads have same address space
* we instrument only group_leader of all this threads
*/
- struct task_struct *task = current->group_leader;
+ unsigned long addr = 0;
+ int valid_addr;
- //if user-space instrumentation is not set
- if (!us_proc_info.path)
- return;
+ // overhead
+ struct timeval imi_tv1;
+ struct timeval imi_tv2;
+#define USEC_IN_SEC_NUM 1000000
if (task->flags & PF_KTHREAD) {
DPRINTF("ignored kernel thread %d\n", task->pid);
return;
}
+ if (!is_us_instrumentation()) {
+ return;
+ }
- if (!strcmp(us_proc_info.path,"*"))
- {
- task_inst_info = get_task_inst_node(task);
- if (!task_inst_info)
- {
- task_inst_info = copy_task_inst_info(task,
- &us_proc_info);
- put_task_inst_node(task, task_inst_info);
-#ifdef __ANDROID
- if (is_java_inst_enabled()) {
- find_libdvm_for_task(task, task_inst_info);
- }
-#endif /* __ANDROID */
- }
- install_mapped_ips (task, task_inst_info, 1);
+ addr = (unsigned long)swap_get_entry_data(&sa_dpf);
+
+ if (addr == 0) {
+ printk("WARNING: do_page_fault_ret_pre_code addr = 0\n");
return;
}
- task_inst_info = &us_proc_info;
- //DPRINTF("do_page_fault from proc %d-%d-%d", current->pid, task_inst_info->tgid, task_inst_info->unres_ips_count);
- if (!is_java_inst_enabled()
- && (task_inst_info->unres_ips_count + task_inst_info->unres_vtps_count
- + task_inst_info->unres_otg_ips_count) == 0)
- {
- //DPRINTF("do_page_fault: there no unresolved IPs");
+
+
+
+ valid_addr = mm && page_present(mm, addr);
+ if (!valid_addr) {
return;
}
- if (task_inst_info->tgid == 0)
- {
- mm = task->active_mm;
- if (mm)
- {
-// down_read (&mm->mmap_sem);
- vma = mm->mmap;
- while (vma)
- {
- if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
- {
- if (vma->vm_file->f_dentry == task_inst_info->m_f_dentry)
- {
- break;
- }
-#ifdef SLP_APP
- if (is_slp_app_with_dentry(vma, task_inst_info->m_f_dentry)) {
- break;
- }
-#endif /* SLP_APP */
-#ifdef ANDROID_APP
- if (is_android_app_with_dentry(vma, task_inst_info->m_f_dentry)) {
- break;
- }
-#endif /* ANDROID_APP */
- }
- vma = vma->vm_next;
+ if (is_libonly()) {
+ proc_p = get_proc_probes_by_task_or_new(task);
+ } else {
+ // find task
+ if (us_proc_info.tgid == 0) {
+ pid_t tgid = find_proc_by_task(task, us_proc_info.m_f_dentry);
+ if (tgid) {
+ us_proc_info.tgid = gl_nNotifyTgid = tgid;
}
-// up_read (&mm->mmap_sem);
-// mmput (mm);
- } else {
- // DPRINTF ("proc %s/%d has no mm", current->comm, current->pid);
}
- if (vma)
- {
- DPRINTF ("do_page_fault found target proc %s(%d)", task->comm, task->pid);
- task_inst_info->tgid = task->pid;
- gl_nNotifyTgid = task->tgid;
+
+ if (us_proc_info.tgid == task->tgid) {
+ proc_p = us_proc_info.pp;
}
}
- if (task_inst_info->tgid == task->tgid)
- {
- //DPRINTF("do_page_fault from target proc %d", task_inst_info->tgid);
+
+ if (proc_p) {
+ unsigned long page = addr & PAGE_MASK;
+
#ifdef __ANDROID
if (is_java_inst_enabled()) {
find_libdvm_for_task(task, &us_proc_info);
}
#endif /* __ANDROID */
- install_mapped_ips (task, &us_proc_info, 1);
+
+ // overhead
+ do_gettimeofday(&imi_tv1);
+ install_page_probes(page, task, proc_p, 1);
+ do_gettimeofday(&imi_tv2);
+ imi_sum_hit++;
+ imi_sum_time += ((imi_tv2.tv_sec - imi_tv1.tv_sec) * USEC_IN_SEC_NUM +
+ (imi_tv2.tv_usec - imi_tv1.tv_usec));
}
- //DPRINTF("do_page_fault from proc %d-%d exit", task->pid, task_inst_info->pid);
}
EXPORT_SYMBOL_GPL(do_page_fault_ret_pre_code);
}
EXPORT_SYMBOL_GPL(do_exit_probe_pre_code);
-static int check_addr(unsigned long addr, unsigned long start, size_t len)
+int check_vma_area(struct vm_area_struct *vma, unsigned long start, unsigned long end)
{
- if ((addr >= start) && (addr < start + (unsigned long)len)) {
- return 1;
- }
-
- return 0;
+ return (vma->vm_start >= start && vma->vm_end <= end);
}
-static int remove_unmap_probes(struct task_struct *task, inst_us_proc_t* task_inst_info, unsigned long start, size_t len)
+void print_vma(struct mm_struct *mm)
{
- int i, k, err;
- us_proc_otg_ip_t *p;
- unsigned long addr;
- const int atomic = 1;
-
- for (i = 0; i < task_inst_info->libs_count; ++i) {
- for (k = 0; k < task_inst_info->p_libs[i].ips_count; ++k) {
- if (task_inst_info->p_libs[i].p_ips[k].installed) {
- addr = task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr;
- if (check_addr(addr, start, len)) {
- err = unregister_usprobe(task, &task_inst_info->p_libs[i].p_ips[k], atomic);
- if (err != 0) {
- EPRINTF("failed to uninstall IP at %p. Error %d!", task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr, err);
- continue;
- }
- task_inst_info->unres_ips_count++;
- task_inst_info->p_libs[i].p_ips[k].installed = 0;
- }
- }
- }
- for (k = 0; k < task_inst_info->p_libs[i].vtps_count; ++k) {
- if (task_inst_info->p_libs[i].p_vtps[k].installed) {
- addr = task_inst_info->p_libs[i].p_vtps[k].jprobe.kp.addr;
- if (check_addr(addr, start, len)) {
- dbi_unregister_ujprobe(task, &task_inst_info->p_libs[i].p_vtps[k].jprobe, atomic);
- task_inst_info->unres_vtps_count++;
- task_inst_info->p_libs[i].p_vtps[k].installed = 0;
- }
- }
- }
+ struct vm_area_struct *vma;
+ printk("### print_vma: START\n");\
+ printk("### print_vma: START\n");
+
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ char *x = vma->vm_flags & VM_EXEC ? "x" : "-";
+ char *r = vma->vm_flags & VM_READ ? "r" : "-";
+ char *w = vma->vm_flags & VM_WRITE ? "w" : "-";
+ char *name = vma->vm_file ? vma->vm_file->f_dentry->d_iname : "N/A";
+
+ printk("### [%8x..%8x] %s%s%s pgoff=\'%8u\' %s\n",
+ vma->vm_start, vma->vm_end, x, r, w, vma->vm_pgoff, name);
}
-#ifdef __ANDROID
- if (is_java_inst_enabled()) {
- us_proc_ip_t *entp = &task_inst_info->libdvm_entry_ip;
- if (entp->installed) {
- addr = entp->jprobe.kp.addr;
- if (check_addr(addr, start, len)) {
- unregister_usprobe(task, entp, atomic);
- entp->installed = 0;
- }
- }
- us_proc_ip_t *retp = &task_inst_info->libdvm_return_ip;
- if (retp->installed) {
- addr = retp->jprobe.kp.addr;
- if (check_addr(addr, start, len)) {
- unregister_usprobe(task, retp, atomic);
- retp->installed = 0;
- }
- }
+ printk("### print_vma: END\n");
+}
+
+static int remove_unmap_probes(struct task_struct *task, struct proc_probes *proc_p, unsigned long start, size_t len)
+{
+ struct mm_struct *mm = task->mm;
+ struct vm_area_struct *vma;
+ unsigned long end, pointer, step;
+
+ if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE - start) {
+ return -EINVAL;
}
-#endif /* __ANDROID */
- // remove OTG-probes
- list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
- if (!p->ip.installed) {
- continue;
- }
+ if ((len = PAGE_ALIGN(len)) == 0) {
+ return -EINVAL;
+ }
- addr = p->ip.jprobe.kp.addr;
- if (check_addr(addr, start, len) == 0) {
- continue;
- }
+ vma = find_vma(mm, start);
+ if (vma && check_vma(vma)) {
+ struct file_probes *file_p;
+ unsigned long end = start + len;
+
+ file_p = proc_p_find_file_p(proc_p, vma);
+ if (file_p) {
+ if (vma->vm_start == start || vma->vm_end == end) {
+ unregister_us_file_probes(task, file_p, US_NOT_RP2);
+ file_p->loaded = 0;
+ } else {
+ unsigned long page;
+ struct page_probes *page_p;
+
+ for (page = vma->vm_start; page < vma->vm_end; page += PAGE_SIZE) {
+ page_p = file_p_find_page_p_mapped(file_p, page);
+ if (page_p) {
+ unregister_us_page_probe(task, page_p, US_NOT_RP2);
+ }
+ }
- err = unregister_usprobe(task, &p->ip, atomic);
- if (err != 0) {
- EPRINTF("failed to uninstall IP at %p. Error %d!",
- p->ip.jprobe.kp.addr, err);
- continue;
+ if (check_install_pages_in_file(task, file_p)) {
+ file_p->loaded = 0;
+ }
+ }
}
- p->ip.installed = 0;
- remove_otg_probe_from_list(p->ip.offset);
}
return 0;
void do_munmap_probe_pre_code(struct mm_struct *mm, unsigned long start, size_t len)
{
- inst_us_proc_t *task_inst_info = NULL;
+ struct proc_probes *proc_p = NULL;
struct task_struct *task = current;
//if user-space instrumentation is not set
- if (!us_proc_info.path || task->tgid != task->pid)
+ if (!is_us_instrumentation()) {
return;
+ }
- if (!strcmp(us_proc_info.path,"*")) {
- task_inst_info = get_task_inst_node(task);
+ if (is_libonly()) {
+ proc_p = get_proc_probes_by_task(task);
} else {
if (task->tgid == us_proc_info.tgid) {
- task_inst_info = &us_proc_info;
+ proc_p = us_proc_info.pp;
}
}
- if (task_inst_info) {
- remove_unmap_probes(task, task_inst_info, start, len);
+ if (proc_p) {
+ if (remove_unmap_probes(task, proc_p, start, len)) {
+ printk("ERROR do_munmap: start=%x, len=%x\n", start, len);
+ }
}
}
EXPORT_SYMBOL_GPL(do_munmap_probe_pre_code);
void mm_release_probe_pre_code(void)
{
- int iRet, del = 0;
- struct task_struct *task;
- inst_us_proc_t *task_inst_info = NULL;
+ struct task_struct *task = current;
+ struct proc_probes *proc_p = NULL;
- //if user-space instrumentation is not set
- if (!us_proc_info.path || current->tgid != current->pid)
+ if (!is_us_instrumentation() || task->tgid != task->pid) {
return;
+ }
- if (!strcmp(us_proc_info.path,"*"))
- {
- task_inst_info = get_task_inst_node(current);
- if (task_inst_info)
- {
- iRet = uninstall_mapped_ips (current, task_inst_info, 1);
- if (iRet != 0)
- EPRINTF ("failed to uninstall IPs (%d)!", iRet);
- dbi_unregister_all_uprobes(current, 1);
+ if (is_libonly()) {
+ proc_p = get_proc_probes_by_task(task);
+ } else {
+ if (task->tgid == us_proc_info.tgid) {
+ proc_p = get_proc_probes_by_task(task);
+ us_proc_info.tgid = 0;
}
}
- else
- {
- if (current->tgid != us_proc_info.tgid)
- return;
- del = 1;
- // look for another process with the same tgid
- rcu_read_lock ();
- for_each_process (task)
- {
- if ((task->pid != current->pid) && (task->tgid == us_proc_info.tgid))
- {
- del = 0;
- break;
- }
- }
- rcu_read_unlock ();
- if (del)
- {
- int i;
- iRet = uninstall_mapped_ips (current, &us_proc_info, 1);
- if (iRet != 0)
- EPRINTF ("failed to uninstall IPs (%d)!", iRet);
- dbi_unregister_all_uprobes(current, 1);
- us_proc_info.tgid = 0;
- for(i = 0; i < us_proc_info.libs_count; i++)
- us_proc_info.p_libs[i].loaded = 0;
+
+ if (proc_p) {
+ int ret = uninstall_us_proc_probes(task, proc_p, US_NOT_RP2);
+ if (ret != 0) {
+ EPRINTF ("failed to uninstall IPs (%d)!", ret);
}
+
+ dbi_unregister_all_uprobes(task, 1);
}
}
EXPORT_SYMBOL_GPL(mm_release_probe_pre_code);
-static void recover_child(struct task_struct *child_task, inst_us_proc_t *parent_iup)
+static void recover_child(struct task_struct *child_task, struct proc_probes *proc_p)
{
- int i, k;
- for(i = 0; i < parent_iup->libs_count; ++i)
- {
- for(k = 0; k < parent_iup->p_libs[i].ips_count; ++k)
- if(parent_iup->p_libs[i].p_ips[k].installed)
- arch_disarm_uprobe(&parent_iup->p_libs[i].p_ips[k].jprobe.kp, child_task);
-
- for(k = 0; k < parent_iup->p_libs[i].vtps_count; ++k)
- if(parent_iup->p_libs[i].p_vtps[k].installed)
- arch_disarm_uprobe(&parent_iup->p_libs[i].p_vtps[k].jprobe.kp, child_task);
- }
+ uninstall_us_proc_probes(child_task, proc_p, US_DISARM);
}
static void rm_uprobes_child(struct task_struct *new_task)
{
- if(!strcmp(us_proc_info.path, "*")) {
- inst_us_proc_t *task_inst_info = get_task_inst_node(current);
- if(task_inst_info)
- recover_child(new_task, task_inst_info);
+ if (is_libonly()) {
+ struct proc_probes *proc_p = get_proc_probes_by_task(current);
+ if(proc_p) {
+ recover_child(new_task, proc_p);
+ }
} else {
if(us_proc_info.tgid == current->tgid) {
- recover_child(new_task, &us_proc_info);
+ recover_child(new_task, us_proc_info.pp);
}
}
}
}
-DEFINE_PER_CPU (us_proc_ip_t *, gpCurIp) = NULL;
+DEFINE_PER_CPU(struct us_ip *, gpCurIp) = NULL;
EXPORT_PER_CPU_SYMBOL_GPL(gpCurIp);
DEFINE_PER_CPU(struct pt_regs *, gpUserRegs) = NULL;
EXPORT_PER_CPU_SYMBOL_GPL(gpUserRegs);
-unsigned long ujprobe_event_pre_handler (us_proc_ip_t * ip, struct pt_regs *regs)
+unsigned long ujprobe_event_pre_handler(struct us_ip *ip, struct pt_regs *regs)
{
__get_cpu_var (gpCurIp) = ip;
__get_cpu_var (gpUserRegs) = regs;
unsigned long start = 0;
struct pt_regs *regs = __get_cpu_var(gpUserRegs);
- if (!strcmp(us_proc_info.path, "*")) {
+ if (is_libonly()) {
/* TODO: some stuff here */
} else {
start = us_proc_info.libdvm_start;
void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
{
- us_proc_ip_t *ip = __get_cpu_var (gpCurIp);
+ struct us_ip *ip = __get_cpu_var(gpCurIp);
unsigned long addr = (unsigned long)ip->jprobe.kp.addr;
#ifdef __ANDROID
dbi_uprobe_return ();
}
-void find_plt_address(unsigned long addr)
+void send_plt(struct us_ip *ip)
{
- inst_us_proc_t *task_inst_info = NULL;
- int i;
- unsigned real_addr;
- struct vm_area_struct *vma;
- us_proc_lib_t *p_lib = NULL;
- char *szLibPath = NULL;
+ unsigned long addr = (unsigned long)ip->jprobe.kp.addr;
+ struct vm_area_struct *vma = find_vma(current->mm, addr);
- // Search for library structure to check whether this function plt or not
- if (strcmp(us_proc_info.path, "*")){
- // If app lib instrumentation
- task_inst_info = &us_proc_info;
- } else {
- // If lib only instrumentation
- task_inst_info = get_task_inst_node(current);
- }
- if ((task_inst_info != NULL) && (task_inst_info->is_plt != 0)) {
- for (i = 0; i < task_inst_info->libs_count; i++)
- {
- if ((task_inst_info->p_libs[i].loaded)
- && (task_inst_info->p_libs[i].plt_count > 0)
- && (addr > task_inst_info->p_libs[i].vma_start)
- && (addr < task_inst_info->p_libs[i].vma_end))
- {
- p_lib = &(task_inst_info->p_libs[i]);
- break;
- }
+ if (vma && check_vma(vma)) {
+ char *name = NULL;
+ unsigned long real_addr;
+ unsigned long real_got = vma->vm_flags & VM_EXECUTABLE ?
+ ip->got_addr :
+ ip->got_addr + vma->vm_start;
+
+ if (!read_proc_vm_atomic(current, real_got, &real_addr, sizeof(real_addr))) {
+ printk("Failed to read got %p at memory address %p!\n", ip->got_addr, real_got);
+ return;
}
- if (p_lib != NULL) {
- for (i = 0; i < p_lib->plt_count; i++)
- {
- if (addr == p_lib->p_plt[i].func_addr + p_lib->vma_start) {
- unsigned long real_got;
- if (p_lib->vma_flag & VM_EXECUTABLE) {
- real_got = p_lib->p_plt[i].got_addr;
- } else {
- real_got = p_lib->p_plt[i].got_addr + p_lib->vma_start;
- }
- if (!read_proc_vm_atomic(current, (unsigned long)(real_got), &real_addr, sizeof(unsigned long))) {
- printk("Failed to read got %p at memory address %p!\n", p_lib->p_plt[i].got_addr, real_got);
- return;
- }
- if (real_addr != p_lib->p_plt[i].real_func_addr) {
- p_lib->p_plt[i].real_func_addr = real_addr;
- vma = find_vma(current->mm, real_addr);
- if ((vma != NULL) && (vma->vm_start <= real_addr) && (vma->vm_end > real_addr)) {
- if (vma->vm_file != NULL) {
- szLibPath = &(vma->vm_file->f_dentry->d_iname);
- }
- } else {
- printk("Failed to get vma, includes %x address\n", real_addr);
- return;
- }
- if (szLibPath) {
- pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp", addr, real_addr, szLibPath, real_addr - vma->vm_start);
- return;
- } else {
- pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp", addr, real_addr, real_addr - vma->vm_start);
- return;
- }
- } else {
- return;
- }
- }
- }
+
+ vma = find_vma(current->mm, real_addr);
+ if (vma && (vma->vm_start <= real_addr) && (vma->vm_end > real_addr)) {
+ name = vma->vm_file ? vma->vm_file->f_dentry->d_iname : NULL;
+ } else {
+ printk("Failed to get vma, includes %x address\n", real_addr);
+ return;
+ }
+
+ if (name) {
+ pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp", addr, real_addr, name, real_addr - vma->vm_start);
+ } else {
+ pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp", addr, real_addr, real_addr - vma->vm_start);
}
}
}
-int uretprobe_event_handler (struct kretprobe_instance *probe, struct pt_regs *regs, us_proc_ip_t * ip)
+int uretprobe_event_handler(struct kretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip)
{
int retval = regs_return_value(regs);
unsigned long addr = (unsigned long)ip->jprobe.kp.addr;
- find_plt_address(addr);
+ if (ip->got_addr && ip->flag_got == 0) {
+ send_plt(ip);
+ ip->flag_got = 1;
+ }
#if defined(CONFIG_ARM)
if (ip->offset & 0x01)
return 0;
}
-static int register_usprobe (struct task_struct *task, struct mm_struct *mm, us_proc_ip_t * ip, int atomic, kprobe_opcode_t * islot)
+static int register_usprobe(struct task_struct *task, struct us_ip *ip, int atomic)
{
int ret = 0;
ip->jprobe.kp.tgid = task->tgid;
- //ip->jprobe.kp.addr = (kprobe_opcode_t *) addr;
- if(!ip->jprobe.entry) {
- if (dbi_ujprobe_event_handler_custom_p != NULL)
- {
- ip->jprobe.entry = (kprobe_opcode_t *) dbi_ujprobe_event_handler_custom_p;
- DPRINTF("Set custom event handler for %x\n", ip->offset);
- }
- else
- {
- ip->jprobe.entry = (kprobe_opcode_t *) ujprobe_event_handler;
- DPRINTF("Set default event handler for %x\n", ip->offset);
- }
+
+ if (ip->jprobe.entry == NULL) {
+ ip->jprobe.entry = (kprobe_opcode_t *)ujprobe_event_handler;
+ DPRINTF("Set default event handler for %x\n", ip->offset);
}
- if(!ip->jprobe.pre_entry) {
- if (dbi_ujprobe_event_pre_handler_custom_p != NULL)
- {
- ip->jprobe.pre_entry = (kprobe_pre_entry_handler_t) dbi_ujprobe_event_pre_handler_custom_p;
- DPRINTF("Set custom pre handler for %x\n", ip->offset);
- }
- else
- {
- ip->jprobe.pre_entry = (kprobe_pre_entry_handler_t) ujprobe_event_pre_handler;
- DPRINTF("Set default pre handler for %x\n", ip->offset);
- }
+
+ if (ip->jprobe.pre_entry == NULL) {
+ ip->jprobe.pre_entry = (kprobe_pre_entry_handler_t)ujprobe_event_pre_handler;
+ DPRINTF("Set default pre handler for %x\n", ip->offset);
}
+
ip->jprobe.priv_arg = ip;
- ret = dbi_register_ujprobe (task, mm, &ip->jprobe, atomic);
- if (ret)
- {
+ ret = dbi_register_ujprobe(task, &ip->jprobe, atomic);
+ if (ret) {
DPRINTF ("dbi_register_ujprobe() failure %d", ret);
return ret;
}
- // Mr_Nobody: comment for valencia
- ip->retprobe.kp.tgid = task->tgid;
- //ip->retprobe.kp.addr = (kprobe_opcode_t *) addr;
- if(!ip->retprobe.handler) {
- if (dbi_uretprobe_event_handler_custom_p != NULL)
- ip->retprobe.handler = (kretprobe_handler_t) dbi_uretprobe_event_handler_custom_p;
- else {
- ip->retprobe.handler = (kretprobe_handler_t) uretprobe_event_handler;
- //DPRINTF("Failed custom dbi_uretprobe_event_handler_custom_p");
+ if (ip->flag_retprobe) {
+ // Mr_Nobody: comment for valencia
+ ip->retprobe.kp.tgid = task->tgid;
+ if (ip->retprobe.handler == NULL) {
+ ip->retprobe.handler = (kretprobe_handler_t)uretprobe_event_handler;
+ DPRINTF("Set default ret event handler for %x\n", ip->offset);
+ }
+
+ ip->retprobe.priv_arg = ip;
+ ret = dbi_register_uretprobe(task, &ip->retprobe, atomic);
+ if (ret) {
+ EPRINTF ("dbi_register_uretprobe() failure %d", ret);
+ return ret;
}
}
- ip->retprobe.priv_arg = ip;
- ret = dbi_register_uretprobe (task, mm, &ip->retprobe, atomic);
- if (ret)
- {
- EPRINTF ("dbi_register_uretprobe() failure %d", ret);
- return ret;
- }
+
return 0;
}
-static int unregister_usprobe (struct task_struct *task, us_proc_ip_t * ip, int atomic)
+static int unregister_usprobe(struct task_struct *task, struct us_ip *ip, int atomic, int not_rp2)
{
- dbi_unregister_ujprobe (task, &ip->jprobe, atomic);
- dbi_unregister_uretprobe (task, &ip->retprobe, atomic);
+ dbi_unregister_ujprobe(task, &ip->jprobe, atomic);
+
+ if (ip->flag_retprobe) {
+ dbi_unregister_uretprobe(task, &ip->retprobe, atomic, not_rp2);
+ }
+
return 0;
}
}
EXPORT_SYMBOL_GPL(dump_backtrace);
-unsigned long get_ret_addr(struct task_struct *task, us_proc_ip_t *ip)
+unsigned long get_ret_addr(struct task_struct *task, struct us_ip *ip)
{
unsigned long retaddr = 0;
struct hlist_node *item, *tmp_node;
struct hlist_head uprobe_insn_slot_table[KPROBE_TABLE_SIZE];
-static
-int __register_uprobe (struct kprobe *p, struct task_struct *task, int atomic, unsigned long called_from)
+
+#define DEBUG_PRINT_HASH_TABLE 0
+
+#if DEBUG_PRINT_HASH_TABLE
+void print_kprobe_hash_table(void)
+{
+ int i;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct kprobe *p;
+
+ // print uprobe table
+ for (i = 0; i < KPROBE_TABLE_SIZE; ++i) {
+ head = &kprobe_table[i];
+ hlist_for_each_entry_rcu (p, node, head, is_hlist_arm) {
+ printk("####### find K tgid=%u, addr=%x\n",
+ p->tgid, p->addr);
+ }
+ }
+}
+
+void print_kretprobe_hash_table(void)
+{
+ int i;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct kprobe *p;
+
+ // print uprobe table
+ for (i = 0; i < KPROBE_TABLE_SIZE; ++i) {
+ head = &kretprobe_inst_table[i];
+ hlist_for_each_entry_rcu (p, node, head, is_hlist_arm) {
+ printk("####### find KR tgid=%u, addr=%x\n",
+ p->tgid, p->addr);
+ }
+ }
+}
+
+void print_uprobe_hash_table(void)
+{
+ int i;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct kprobe *p;
+
+ // print uprobe table
+ for (i = 0; i < KPROBE_TABLE_SIZE; ++i) {
+ head = &uprobe_insn_slot_table[i];
+ hlist_for_each_entry_rcu (p, node, head, is_hlist_arm) {
+ printk("####### find U tgid=%u, addr=%x\n",
+ p->tgid, p->addr);
+ }
+ }
+}
+#endif
+
+
+static void add_uprobe_table(struct kprobe *p)
+{
+#ifdef CONFIG_ARM
+ INIT_HLIST_NODE(&p->is_hlist_arm);
+ hlist_add_head_rcu(&p->is_hlist_arm, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn_arm, KPROBE_HASH_BITS)]);
+ INIT_HLIST_NODE(&p->is_hlist_thumb);
+ hlist_add_head_rcu(&p->is_hlist_thumb, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn_thumb, KPROBE_HASH_BITS)]);
+#else /* CONFIG_ARM */
+ INIT_HLIST_NODE(&p->is_hlist);
+ hlist_add_head_rcu(&p->is_hlist, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn, KPROBE_HASH_BITS)]);
+#endif /* CONFIG_ARM */
+}
+
+
+static int __register_uprobe(struct kprobe *p, struct task_struct *task, int atomic)
{
int ret = 0;
struct kprobe *old_p;
-// printk (">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> %s %d\n", __FUNCTION__, __LINE__);
-
- if (!p->addr)
+ if (!p->addr) {
return -EINVAL;
+ }
- DBPRINTF ("p->addr = 0x%p p = 0x%p\n", p->addr, p);
+ DBPRINTF("p->addr = 0x%p p = 0x%p\n", p->addr, p);
// thumb address = address-1;
#if defined(CONFIG_ARM)
- if ((unsigned long) p->addr & 0x01)
- {
+ // TODO: must be corrected in 'bundle'
+ if ((unsigned long) p->addr & 0x01) {
p->addr = (kprobe_opcode_t *)((unsigned long)p->addr & 0xfffffffe);
}
#endif
// get the first item
old_p = get_kprobe(p->addr, p->tgid);
- if (old_p)
- {
+ if (old_p) {
#ifdef CONFIG_ARM
p->safe_arm = old_p->safe_arm;
p->safe_thumb = old_p->safe_thumb;
#endif
- ret = register_aggr_kprobe (old_p, p);
+ ret = register_aggr_kprobe(old_p, p);
if (!ret) {
- atomic_inc (&kprobe_count);
-#ifdef CONFIG_ARM
- INIT_HLIST_NODE (&p->is_hlist_arm);
- hlist_add_head_rcu (&p->is_hlist_arm, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn_arm, KPROBE_HASH_BITS)]);
- INIT_HLIST_NODE (&p->is_hlist_thumb);
- hlist_add_head_rcu (&p->is_hlist_thumb, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn_thumb, KPROBE_HASH_BITS)]);
-#else /* CONFIG_ARM */
- INIT_HLIST_NODE (&p->is_hlist);
- hlist_add_head_rcu (&p->is_hlist, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn, KPROBE_HASH_BITS)]);
-#endif /* CONFIG_ARM */
+ atomic_inc(&kprobe_count);
+ add_uprobe_table(p);
}
- DBPRINTF ("goto out\n", ret);
+ DBPRINTF("goto out\n", ret);
goto out;
}
-// printk ("================================ %s %d\n", __FUNCTION__, __LINE__);
- if ((ret = arch_prepare_uprobe (p, task, atomic)) != 0)
- {
-// printk ("================================ %s %d\n", __FUNCTION__, __LINE__);
- DBPRINTF ("goto out\n", ret);
+ ret = arch_prepare_uprobe(p, task, atomic);
+ if (ret) {
+ DBPRINTF("goto out\n", ret);
goto out;
}
-// printk ("================================ %s %d\n", __FUNCTION__, __LINE__);
DBPRINTF ("before out ret = 0x%x\n", ret);
- INIT_HLIST_NODE (&p->hlist);
-// printk ("================================ %s %d\n", __FUNCTION__, __LINE__);
- hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr, KPROBE_HASH_BITS)]);
-
-#ifdef CONFIG_ARM
- INIT_HLIST_NODE (&p->is_hlist_arm);
- INIT_HLIST_NODE (&p->is_hlist_thumb);
-// printk ("================================ %s %d\n", __FUNCTION__, __LINE__);
- hlist_add_head_rcu (&p->is_hlist_arm, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn_arm, KPROBE_HASH_BITS)]);
- hlist_add_head_rcu (&p->is_hlist_thumb, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn_thumb, KPROBE_HASH_BITS)]);
-#else /* CONFIG_ARM */
- INIT_HLIST_NODE (&p->is_hlist);
- // printk ("================================ %s %d\n", __FUNCTION__, __LINE__);
- hlist_add_head_rcu (&p->is_hlist, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn, KPROBE_HASH_BITS)]);
-#endif /* CONFIG_ARM */
-
-// printk ("================================ %s %d\n", __FUNCTION__, __LINE__);
- arch_arm_uprobe (p, task);
-// printk ("================================ %s %d\n", __FUNCTION__, __LINE__);
+ // TODO: add uprobe (must be in function)
+ INIT_HLIST_NODE(&p->hlist);
+ hlist_add_head_rcu(&p->hlist, &kprobe_table[hash_ptr (p->addr, KPROBE_HASH_BITS)]);
+ add_uprobe_table(p);
+ arch_arm_uprobe(p, task);
out:
- DBPRINTF ("out ret = 0x%x\n", ret);
-
-// printk ("<<<<<<<<<<<<<<<<<<<<<<<<<<<<< %s %d\n", __FUNCTION__, __LINE__);
+ DBPRINTF("out ret = 0x%x\n", ret);
return ret;
}
-void unregister_uprobe (struct kprobe *p, struct task_struct *task, int atomic)
+void unregister_uprobe(struct kprobe *p, struct task_struct *task, int atomic)
{
dbi_unregister_kprobe (p, task);
}
-int dbi_register_ujprobe (struct task_struct *task, struct mm_struct *mm, struct jprobe *jp, int atomic)
+int dbi_register_ujprobe(struct task_struct *task, struct jprobe *jp, int atomic)
{
int ret = 0;
jp->kp.pre_handler = setjmp_pre_handler;
jp->kp.break_handler = longjmp_break_handler;
- ret = __register_uprobe (&jp->kp, task, atomic,
- (unsigned long) __builtin_return_address (0));
+ ret = __register_uprobe(&jp->kp, task, atomic);
return ret;
}
-void dbi_unregister_ujprobe (struct task_struct *task, struct jprobe *jp, int atomic)
+void dbi_unregister_ujprobe(struct task_struct *task, struct jprobe *jp, int atomic)
{
- unregister_uprobe (&jp->kp, task, atomic);
+ unregister_uprobe(&jp->kp, task, atomic);
/*
* Here is an attempt to unregister even those probes that have not been
* installed (hence not added to the hlist).
#endif /* CONFIG_ARM */
}
-int dbi_register_uretprobe (struct task_struct *task, struct mm_struct *mm, struct kretprobe *rp, int atomic)
+int dbi_register_uretprobe(struct task_struct *task, struct kretprobe *rp, int atomic)
{
- int ret = 0;
+ int i, ret = 0;
struct kretprobe_instance *inst;
- int i;
DBPRINTF ("START\n");
rp->disarm = 0;
/* Pre-allocate memory for max kretprobe instances */
- if (rp->maxactive <= 0)
- {
+ if (rp->maxactive <= 0) {
#if 1//def CONFIG_PREEMPT
- rp->maxactive = max (10, 2 * NR_CPUS);
+ rp->maxactive = max(10, 2 * NR_CPUS);
#else
rp->maxactive = NR_CPUS;
#endif
}
- INIT_HLIST_HEAD (&rp->used_instances);
- INIT_HLIST_HEAD (&rp->free_instances);
- for (i = 0; i < rp->maxactive; i++)
- {
- inst = kmalloc (sizeof (struct kretprobe_instance), GFP_KERNEL);
- if (inst == NULL)
- {
+
+ INIT_HLIST_HEAD(&rp->used_instances);
+ INIT_HLIST_HEAD(&rp->free_instances);
+
+ for (i = 0; i < rp->maxactive; i++) {
+ inst = kmalloc(sizeof(*inst), GFP_KERNEL);
+ if (inst == NULL) {
free_rp_inst (rp);
ret = -ENOMEM;
goto out;
}
- INIT_HLIST_NODE (&inst->uflist);
- hlist_add_head (&inst->uflist, &rp->free_instances);
+
+ INIT_HLIST_NODE(&inst->uflist);
+ hlist_add_head(&inst->uflist, &rp->free_instances);
}
rp->nmissed = 0;
/* Establish function exit probe point */
- if ((ret = arch_prepare_uretprobe (rp, task)) != 0)
+ ret = arch_prepare_uretprobe(rp, task);
+ if (ret) {
goto out;
+ }
+
/* Establish function entry probe point */
- if ((ret = __register_uprobe (&rp->kp, task, atomic,
- (unsigned long) __builtin_return_address (0))) != 0)
- {
- free_rp_inst (rp);
+ ret = __register_uprobe(&rp->kp, task, atomic);
+ if (ret) {
+ free_rp_inst(rp);
goto out;
}
- arch_arm_uretprobe (rp, task);//vmas[1], pages[1], kaddrs[1]);
+ arch_arm_uretprobe(rp, task);
out:
return ret;
}
-void dbi_unregister_uretprobe (struct task_struct *task, struct kretprobe *rp, int atomic)
+void dbi_unregister_uretprobe(struct task_struct *task, struct kretprobe *rp, int atomic, int not_rp2)
{
unsigned long flags;
struct kretprobe_instance *ri;
struct kretprobe *rp2 = NULL;
spin_lock_irqsave (&kretprobe_lock, flags);
- if (hlist_empty (&rp->used_instances))
- {
+
+ if (hlist_empty(&rp->used_instances) || not_rp2) {
struct kprobe *p = &rp->kp;
// if there are no used retprobe instances (i.e. function is not entered) - disarm retprobe
- arch_disarm_uretprobe (rp, task);//vmas[1], pages[1], kaddrs[1]);
+ arch_disarm_uretprobe(rp, task);//vmas[1], pages[1], kaddrs[1]);
#ifdef CONFIG_ARM
if (!(hlist_unhashed(&p->is_hlist_arm))) {
hlist_del_rcu(&p->is_hlist_arm);
}
+
if (!(hlist_unhashed(&p->is_hlist_thumb))) {
hlist_del_rcu(&p->is_hlist_thumb);
}
hlist_del_rcu(&p->is_hlist);
}
#endif /* CONFIG_ARM */
- }
- else
- {
+ } else {
struct kprobe *new_p = NULL;
struct kprobe *p = &rp->kp;
- rp2 = clone_kretprobe (rp);
- if (!rp2)
+ rp2 = clone_kretprobe(rp);
+ if (!rp2) {
DBPRINTF ("dbi_unregister_uretprobe addr %p: failed to clone retprobe!", rp->kp.addr);
- else
- {
+ } else {
DBPRINTF ("initiating deferred retprobe deletion addr %p", rp->kp.addr);
printk ("initiating deferred retprobe deletion addr %p\n", rp->kp.addr);
arch_disarm_uprobe(&rp->kp, task);
}
#endif /* CONFIG_ARM */
new_p = &rp2->kp;
-#ifdef CONFIG_ARM
- INIT_HLIST_NODE (&new_p->is_hlist_arm);
- INIT_HLIST_NODE (&new_p->is_hlist_thumb);
- hlist_add_head_rcu (&new_p->is_hlist_arm, &uprobe_insn_slot_table[hash_ptr (new_p->ainsn.insn_arm, KPROBE_HASH_BITS)]);
- hlist_add_head_rcu (&new_p->is_hlist_thumb, &uprobe_insn_slot_table[hash_ptr (new_p->ainsn.insn_thumb, KPROBE_HASH_BITS)]);
-#else /* CONFIG_ARM */
- INIT_HLIST_NODE (&new_p->is_hlist);
- hlist_add_head_rcu (&new_p->is_hlist, &uprobe_insn_slot_table[hash_ptr (new_p->ainsn.insn, KPROBE_HASH_BITS)]);
-#endif /* CONFIG_ARM */
+ add_uprobe_table(new_p);
}
- while ((ri = get_used_rp_inst (rp)) != NULL)
- {
+ while ((ri = get_used_rp_inst(rp)) != NULL) {
ri->rp = NULL;
ri->rp2 = rp2;
- hlist_del (&ri->uflist);
+ hlist_del(&ri->uflist);
}
- spin_unlock_irqrestore (&kretprobe_lock, flags);
- free_rp_inst (rp);
- unregister_uprobe (&rp->kp, task, atomic);
+ spin_unlock_irqrestore(&kretprobe_lock, flags);
+ free_rp_inst(rp);
+
+ unregister_uprobe(&rp->kp, task, atomic);
}
-void dbi_unregister_all_uprobes (struct task_struct *task, int atomic)
+void dbi_unregister_all_uprobes(struct task_struct *task, int atomic)
{
struct hlist_head *head;
struct hlist_node *node, *tnode;
struct kprobe *p;
int i;
- for(i = 0; i < KPROBE_TABLE_SIZE; i++){
+ for (i = 0; i < KPROBE_TABLE_SIZE; ++i) {
head = &kprobe_table[i];
- hlist_for_each_entry_safe (p, node, tnode, head, hlist){
- if(p->tgid == task->tgid){
- printk("dbi_unregister_all_uprobes: delete uprobe at %pf for %s/%d\n", p->addr, task->comm, task->pid);
- unregister_uprobe (p, task, atomic);
+ hlist_for_each_entry_safe(p, node, tnode, head, hlist) {
+ if (p->tgid == task->tgid) {
+ printk("dbi_unregister_all_uprobes: delete uprobe at %p[%x] for %s/%d\n",
+ p->addr, p->opcode, task->comm, task->pid);
+ unregister_uprobe(p, task, atomic);
}
}
}
void init_uprobes_insn_slots(int i)
{
- INIT_HLIST_HEAD (&uprobe_insn_slot_table[i]);
+ INIT_HLIST_HEAD(&uprobe_insn_slot_table[i]);
}
-void dbi_uprobe_return (void)
+void dbi_uprobe_return(void)
{
dbi_arch_uprobe_return();
}
-EXPORT_SYMBOL_GPL (dbi_uprobe_return);
-EXPORT_SYMBOL_GPL (dbi_register_ujprobe);
-EXPORT_SYMBOL_GPL (dbi_unregister_ujprobe);
-EXPORT_SYMBOL_GPL (dbi_register_uretprobe);
-EXPORT_SYMBOL_GPL (dbi_unregister_uretprobe);
-EXPORT_SYMBOL_GPL (dbi_unregister_all_uprobes);
-
+EXPORT_SYMBOL_GPL(dbi_uprobe_return);
+EXPORT_SYMBOL_GPL(dbi_register_ujprobe);
+EXPORT_SYMBOL_GPL(dbi_unregister_ujprobe);
+EXPORT_SYMBOL_GPL(dbi_register_uretprobe);
+EXPORT_SYMBOL_GPL(dbi_unregister_uretprobe);
+EXPORT_SYMBOL_GPL(dbi_unregister_all_uprobes);