#include "us_proc_inst.h"
#include "../kprobe/dbi_kprobes_deps.h"
-#include "../kprobe/dbi_uprobes.h"
+#include "../uprobe/swap_uprobes.h"
#include "sspt/sspt.h"
#include "java_inst.h"
+#include <dbi_insn_slots.h>
+
#define mm_read_lock(task, mm, atomic, lock) \
mm = atomic ? task->active_mm : get_task_mm(task); \
if (mm == NULL) { \
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, struct us_ip *ip);
+int uretprobe_event_handler(struct uretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip);
int us_proc_probes;
return !!us_proc_info.path;
}
+static unsigned long alloc_user_pages(struct task_struct *task, unsigned long len, unsigned long prot, unsigned long flags)
+{
+ unsigned long ret = 0;
+ struct task_struct *otask = current;
+ struct mm_struct *mm;
+ int atomic = in_atomic();
+
+ mm = atomic ? task->active_mm : get_task_mm (task);
+ if (mm) {
+ if (!atomic) {
+ if (!down_write_trylock(&mm->mmap_sem)) {
+ rcu_read_lock();
+
+ up_read(&mm->mmap_sem);
+ down_write(&mm->mmap_sem);
+
+ rcu_read_unlock();
+ }
+ }
+ // FIXME: its seems to be bad decision to replace 'current' pointer temporarily
+ current_thread_info()->task = task;
+ ret = do_mmap_pgoff(NULL, 0, len, prot, flags, 0);
+ current_thread_info()->task = otask;
+ if (!atomic) {
+ downgrade_write (&mm->mmap_sem);
+ mmput(mm);
+ }
+ } else {
+ printk("proc %d has no mm", task->tgid);
+ }
+
+ return ret;
+}
+
+static void *sm_alloc_us(struct slot_manager *sm)
+{
+ struct task_struct *task = sm->data;
+
+ return (void *)alloc_user_pages(task, PAGE_SIZE,
+ PROT_EXEC|PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE);
+}
+
+static void sm_free_us(struct slot_manager *sm, void *ptr)
+{
+ struct task_struct *task = sm->data;
+
+ /*
+ * E. G.: This code provides kernel dump because of rescheduling while atomic.
+ * As workaround, this code was commented. In this case we will have memory leaks
+ * for instrumented process, but instrumentation process should functionate correctly.
+ * Planned that good solution for this problem will be done during redesigning KProbe
+ * for improving supportability and performance.
+ */
+#if 0
+ mm = get_task_mm(task);
+ if (mm) {
+ down_write(&mm->mmap_sem);
+ do_munmap(mm, (unsigned long)(ptr), PAGE_SIZE);
+ up_write(&mm->mmap_sem);
+ mmput(mm);
+ }
+#endif
+ /* FIXME: implement the removal of memory for task */
+}
+
+struct slot_manager *create_sm_us(struct task_struct *task)
+{
+ struct slot_manager *sm = kmalloc(sizeof(*sm), GFP_ATOMIC);
+ sm->slot_size = UPROBES_TRAMP_LEN;
+ sm->alloc = sm_alloc_us;
+ sm->free = sm_free_us;
+ INIT_HLIST_NODE(&sm->page_list);
+ sm->data = task;
+}
+
+void free_sm_us(struct slot_manager *sm)
+{
+ /* FIXME: free */
+}
+
static struct sspt_procs *get_proc_probes_by_task(struct task_struct *task)
{
struct sspt_procs *procs, *tmp;
struct sspt_procs *procs = get_proc_probes_by_task(task);
if (procs == NULL) {
procs = sspt_procs_copy(us_proc_info.pp, task);
+ procs->sm = create_sm_us(task);
add_proc_probes(task, procs);
}
int install_otg_ip(unsigned long addr,
kprobe_pre_entry_handler_t pre_handler,
unsigned long jp_handler,
- kretprobe_handler_t rp_handler)
+ uretprobe_handler_t rp_handler)
{
int ret = 0;
struct task_struct *task = current->group_leader;
{
DPRINTF("task found. installing probes");
us_proc_info.tgid = task->pid;
+ us_proc_info.pp->sm = create_sm_us(task);
install_proc_probes(task, us_proc_info.pp, 0);
put_task_struct (task);
}
for (i = 0; i < table_size; ++i) {
head = &file->page_probes_table[i];
hlist_for_each_entry_rcu(page, node, head, hlist) {
- if (page_present(mm, page->offset)) {
- register_us_page_probe(page, file, task);
- }
+ register_us_page_probe(page, file, task);
}
}
}
if (tgid) {
us_proc_info.tgid = gl_nNotifyTgid = tgid;
+ us_proc_info.pp->sm = create_sm_us(task);
/* install probes in already mapped memory */
install_proc_probes(task, us_proc_info.pp, 1);
}
file = sspt_procs_find_file(procs, dentry);
if (file) {
if (vma->vm_start == start || vma->vm_end == end) {
- unregister_us_file_probes(task, file, US_NOT_RP2);
+ unregister_us_file_probes(task, file, US_UNREGS_PROBE);
file->loaded = 0;
} else {
unsigned long page_addr;
for (page_addr = vma->vm_start; page_addr < vma->vm_end; page_addr += PAGE_SIZE) {
page = sspt_find_page_mapped(file, page_addr);
if (page) {
- unregister_us_page_probe(task, page, US_NOT_RP2);
+ unregister_us_page_probe(task, page, US_UNREGS_PROBE);
}
}
}
if (procs) {
- int ret = uninstall_us_proc_probes(task, procs, US_NOT_RP2);
+ int ret = uninstall_us_proc_probes(task, procs, US_UNREGS_PROBE);
if (ret != 0) {
EPRINTF ("failed to uninstall IPs (%d)!", ret);
}
void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
{
struct us_ip *ip = __get_cpu_var(gpCurIp);
- unsigned long addr = (unsigned long)ip->jprobe.kp.addr;
+ unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
#ifdef __ANDROID
struct pt_regs *regs = __get_cpu_var(gpUserRegs);
static void send_plt(struct us_ip *ip)
{
- unsigned long addr = (unsigned long)ip->jprobe.kp.addr;
+ unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
struct vm_area_struct *vma = find_vma(current->mm, addr);
if (vma && check_vma(vma)) {
}
}
-int uretprobe_event_handler(struct kretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip)
+int uretprobe_event_handler(struct uretprobe_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;
+ unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
if (ip->got_addr && ip->flag_got == 0) {
send_plt(ip);
int register_usprobe(struct task_struct *task, struct us_ip *ip, int atomic)
{
int ret = 0;
- ip->jprobe.kp.tgid = task->tgid;
if (ip->jprobe.entry == NULL) {
- ip->jprobe.entry = (kprobe_opcode_t *)ujprobe_event_handler;
+ ip->jprobe.entry = (void *)ujprobe_event_handler;
DPRINTF("Set default event 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;
+ ip->jprobe.pre_entry = (uprobe_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, &ip->jprobe, atomic);
+ ip->jprobe.up.task = task;
+ ip->jprobe.up.sm = ip->page->file->procs->sm;
+ ret = dbi_register_ujprobe(&ip->jprobe, atomic);
if (ret) {
if (ret == -ENOEXEC) {
pack_event_info(ERR_MSG_ID, RECORD_ENTRY, "dp",
0x1,
- ip->jprobe.kp.addr);
+ ip->jprobe.up.kp.addr);
}
DPRINTF ("dbi_register_ujprobe() failure %d", ret);
return ret;
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;
+ ip->retprobe.handler = (uretprobe_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);
+ ip->retprobe.up.task = task;
+ ip->retprobe.up.sm = ip->page->file->procs->sm;
+ ret = dbi_register_uretprobe(&ip->retprobe, atomic);
if (ret) {
EPRINTF ("dbi_register_uretprobe() failure %d", ret);
return ret;
return 0;
}
-int unregister_usprobe(struct task_struct *task, struct us_ip *ip, int atomic, int not_rp2)
+int unregister_usprobe(struct task_struct *task, struct us_ip *ip, int atomic)
{
- dbi_unregister_ujprobe(task, &ip->jprobe, atomic);
+ dbi_unregister_ujprobe(&ip->jprobe, atomic);
if (ip->flag_retprobe) {
- dbi_unregister_uretprobe(task, &ip->retprobe, atomic, not_rp2);
+ dbi_unregister_uretprobe(&ip->retprobe, atomic);
}
return 0;
}
EXPORT_SYMBOL_GPL(dump_backtrace);
-struct kretprobe_instance *find_ri(struct task_struct *task, struct us_ip *ip)
+struct uretprobe_instance *find_ri(struct task_struct *task, struct us_ip *ip)
{
struct hlist_node *item, *tmp_node;
- struct kretprobe_instance *ri;
+ struct uretprobe_instance *ri;
if (ip == NULL)
return NULL;
hlist_for_each_safe (item, tmp_node, &ip->retprobe.used_instances) {
- ri = hlist_entry (item, struct kretprobe_instance, uflist);
+ ri = hlist_entry(item, struct uretprobe_instance, uflist);
if (ri->task && ri->task->pid == task->pid &&
ri->task->tgid == task->tgid)
unsigned long get_ret_addr(struct task_struct *task, struct us_ip *ip)
{
- struct kretprobe_instance *ri = find_ri(task, ip);;
+ struct uretprobe_instance *ri = find_ri(task, ip);;
if (ri)
return (unsigned long)ri->ret_addr;
else
unsigned long get_entry_sp(struct task_struct *task, struct us_ip *ip)
{
- struct kretprobe_instance *ri = find_ri(task, ip);
+ struct uretprobe_instance *ri = find_ri(task, ip);
if (ri)
return (unsigned long)ri->sp;
else