// TODO: del
}
-struct page_probes *page_p_copy(const struct page_probes *page_p)
+static struct page_probes *page_p_copy(const struct page_probes *page_p)
{
us_proc_ip_t *ip_in, *ip_out;
struct page_probes *page_p_out = kmalloc(sizeof(*page_p), GFP_ATOMIC);
return page_p_out;
}
-void page_p_add_ip(struct page_probes *page_p, us_proc_ip_t *ip)
+static void page_p_add_ip(struct page_probes *page_p, us_proc_ip_t *ip)
{
ip->offset &= ~PAGE_MASK;
INIT_LIST_HEAD(&ip->list);
list_add(&ip->list, &page_p->ip_list);
}
+static us_proc_ip_t *page_p_find_ip(struct page_probes *page_p, unsigned long offset)
+{
+ us_proc_ip_t *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) {
}
// page_probes
+static void set_ip_kp_addr(us_proc_ip_t *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)
{
us_proc_ip_t *ip;
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;
void file_p_add_probe(struct file_probes *file_p, struct probe_data *pd)
{
- unsigned long page = pd->offset & PAGE_MASK;
- struct page_probes *page_p = file_p_find_page_p(file_p, page);
-
- if (page_p == NULL) {
- unsigned long hash_bits = file_p->page_probes_hash_bits;
- struct hlist_head *head = &file_p->page_probes_table[hash_ptr(page, hash_bits)];
- page_p = page_p_new(page);
- hlist_add_head(&page_p->hlist, head);
- }
+ unsigned long offset = pd->offset & PAGE_MASK;
+ struct page_probes *page_p = file_p_find_page_p_or_new(file_p, offset);
// FIXME: ip
us_proc_ip_t *ip = kmalloc(sizeof(*ip), GFP_ATOMIC);
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
return task_inst_info->unres_ips_count + task_inst_info->unres_vtps_count;
}
+#include "new_dpf.h"
+
+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 (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 = us_proc_info.pp;
+ struct probe_data pd = {
+ .offset = offset_addr,
+ .pre_handler = pre_handler,
+ .jp_handler = jp_handler,
+ .rp_handler = rp_handler
+ };
+
+ 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);
+ us_proc_ip_t *ip = page_p_find_ip(page_p, offset_addr & ~PAGE_MASK);
- pprobe->ip.jprobe.pre_entry = pre_handler;
- pprobe->ip.jprobe.entry = (kprobe_opcode_t *)jp_handler;
- pprobe->ip.retprobe.handler = rp_handler;
+ if (!file_p->loaded) {
+ set_mapping_file(file_p, proc_p, task, vma);
+ file_p->loaded = 1;
+ }
- pprobe->tgid = task->tgid;
- if (!page_present(mm, addr)) {
- DPRINTF("Page isn't present for %p.", addr);
+ 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);
+ /* 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) {
+ printk("ERROR install_otg_ip: ret=%d\n", ret);
+ }
+ }
- /* Probe installing */
- err = register_usprobe(task, &pprobe->ip, 1);
- 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);
return iRet;
}
-
-#include "new_dpf.h"
-
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)
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;
}
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 (vma->vm_start >= start && vma->vm_end <= end);
+}
- return 0;
+void print_vma(struct mm_struct *mm)
+{
+ 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);
+ }
+ printk("### print_vma: END\n");
}
static int remove_unmap_probes(struct task_struct *task, inst_us_proc_t* task_inst_info, unsigned long start, size_t len)
{
- 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, 1);
- 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++;
- }
- }
- }
- 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 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;
}
-#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, 1);
- 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, 1);
- retp->installed = 0;
- }
- }
+
+ if ((len = PAGE_ALIGN(len)) == 0) {
+ return -EINVAL;
}
-#endif /* __ANDROID */
- // remove OTG-probes
- list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
- if (!p->ip.installed) {
- continue;
- }
+ vma = find_vma(mm, start);
+ if (vma && check_vma(vma)) {
+ struct file_probes *file_p;
+ unsigned long end = start + len;
- addr = p->ip.jprobe.kp.addr;
- if (check_addr(addr, start, len) == 0) {
- continue;
- }
+ file_p = proc_p_find_file_p(task_inst_info->pp, 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, 1);
- 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;
+ }
+ }
}
-
- remove_otg_probe_from_list(p->ip.offset);
}
return 0;
}
if (task_inst_info) {
- remove_unmap_probes(task, task_inst_info, start, len);
+ if (remove_unmap_probes(task, task_inst_info, start, len)) {
+ printk("ERROR do_munmap: start=%x, len=%x\n", start, len);
+ }
}
}
EXPORT_SYMBOL_GPL(do_munmap_probe_pre_code);