static inline struct process_data *__get_process_data(struct uretprobe *rp)
{
- struct process_data *pd;
- struct us_ip *ip = to_us_ip(rp);
-
- pd = ip_to_proc(ip)->private_data;
+ struct us_ip *ip = to_us_ip(rp);
+ struct sspt_proc *proc = ip_to_proc(ip);
- return pd;
+ return preload_pd_get(proc);
}
static struct dentry *__get_dentry(struct dentry *dentry)
{
struct mmap_priv *priv = (struct mmap_priv *)ri->data;
struct task_struct *task = current->group_leader;
+ struct process_data *pd;
struct sspt_proc *proc;
unsigned long vaddr;
if (!proc)
return 0;
+ pd = preload_pd_get(proc);
+ if (pd == NULL) {
+ printk(PRELOAD_PREFIX "%d: No process data! Current %d %s\n",
+ __LINE__, current->tgid, current->comm);
+ return 0;
+ }
+
switch (priv->type) {
case MMAP_LOADER:
- preload_pd_set_loader_base(proc->private_data, vaddr);
+ preload_pd_set_loader_base(pd, vaddr);
break;
case MMAP_HANDLERS:
- preload_pd_set_handlers_base(proc->private_data, vaddr);
+ preload_pd_set_handlers_base(pd, vaddr);
break;
case MMAP_SKIP:
default:
unsigned long flags = get_preload_flags(current);
unsigned long offset = ip->info->pl_i.handler;
unsigned long vaddr = 0;
+ unsigned long base;
char __user *path = NULL;
if ((flags & HANDLER_RUNNING) ||
if (!__should_we_preload_handlers(current, regs))
goto out_set_origin;
+ base = preload_pd_get_loader_base(pd);
+ if (base == 0)
+ break; /* loader isn't mapped */
+
/* jump to loader code if ready */
- vaddr = preload_pd_get_loader_base(pd) + preload_debugfs_get_loader_offset();
+ vaddr = base + preload_debugfs_get_loader_offset();
if (vaddr) {
/* save original regs state */
__save_uregs(ri, regs);
/* handlers have not yet been loaded... just ignore */
break;
case LOADED:
+ base = preload_pd_get_handlers_base(pd);
+ if (base == 0)
+ break; /* handlers isn't mapped */
+
/* jump to preloaded handler */
- vaddr = preload_pd_get_handlers_base(pd) + offset;
+ vaddr = base + offset;
if (vaddr) {
unsigned long disable_addr;
unsigned long caddr = get_regs_ret_func(regs);
int preload_module_uprobe_init(struct us_ip *ip)
{
struct uretprobe *rp = &ip->retprobe;
- struct sspt_proc *proc = page_to_proc(ip->page);
- int ret;
-
- if (proc->private_data == NULL) {
- ret = preload_pd_create_pd(&(proc->private_data), proc->task);
- if (ret != 0)
- return ret;
- }
rp->entry_handler = preload_us_entry;
rp->handler = preload_us_ret;
* to dlopen */
rp->data_size = sizeof(struct us_priv);
- preload_pd_inc_refs(proc->private_data);
-
return 0;
}
void preload_module_uprobe_exit(struct us_ip *ip)
{
- struct sspt_proc *proc = ip_to_proc(ip);
-
- preload_pd_dec_refs(proc->private_data);
}
int preload_set(void)
#include <linux/mman.h>
#include <linux/hardirq.h>
#include <us_manager/us_manager_common.h>
+#include <us_manager/sspt/sspt_proc.h>
#include "preload_pd.h"
#include "preload_threads.h"
#include "preload_debugfs.h"
#include "preload_storage.h"
-#include "preload_patcher.h"
#include "preload.h"
struct process_data {
- char is_mapped;
enum preload_state_t state;
unsigned long loader_base;
unsigned long handlers_base;
-static unsigned long __find_dentry_base(struct mm_struct *mm,
- struct dentry *dentry)
-{
- struct vm_area_struct *vma;
-
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- if (check_vma(vma, dentry))
- return vma->vm_start;
- }
-
- return 0;
-}
-
-static unsigned long find_dentry_base(struct task_struct *task,
- struct dentry *dentry)
-{
- struct mm_struct *mm = task->mm;
- unsigned long addr;
-
-#ifdef CONFIG_ARM
- down_read(&mm->mmap_sem);
-#endif /* CONFIG_ARM */
- addr = __find_dentry_base(mm, dentry);
-#ifdef CONFIG_ARM
- up_read(&mm->mmap_sem);
-#endif /* CONFIG_ARM */
-
- return addr;
-}
-
static int __pd_create_on_demand(void)
{
if (handlers_info == NULL) {
unsigned long preload_pd_get_loader_base(struct process_data *pd)
{
if (pd == NULL)
- return ERROR;
+ return 0;
return __get_loader_base(pd);
}
void preload_pd_set_loader_base(struct process_data *pd, unsigned long vaddr)
{
- if (pd == NULL) {
- printk(PRELOAD_PREFIX "%d: No process data! Current %d %s\n", __LINE__,
- current->tgid, current->comm);
- return;
- }
-
__set_loader_base(pd, vaddr);
}
void preload_pd_set_handlers_base(struct process_data *pd, unsigned long vaddr)
{
- if (pd == NULL) {
- printk(PRELOAD_PREFIX "%d: No process data! Current %d %s\n", __LINE__,
- current->tgid, current->comm);
- return;
- }
-
__set_handlers_base(pd, vaddr);
}
char __user *preload_pd_get_path(struct process_data *pd)
{
- /* This function should be called only for current */
-
- struct task_struct *task = current;
- unsigned long page = 0;
- int ret;
-
- if (pd == NULL)
- return NULL;
-
- page = __get_data_page(pd);
+ char __user *path = __get_path(pd);
- if (page == 0)
- return NULL;
-
- if (pd->is_mapped == 1)
- return __get_path(pd);
-
- ret = preload_patcher_write_string((void *)page, handlers_info->path,
- strnlen(handlers_info->path, PATH_MAX),
- task);
- if (ret <= 0) {
- printk(KERN_ERR PRELOAD_PREFIX "Cannot copy string to user!\n");
- goto get_path_failed;
- }
-
- pd->is_mapped = 1;
-
- return __get_path(pd);
-
-get_path_failed:
-
- return NULL;
+ return path;
}
return __get_refcount(pd);
}
-int preload_pd_create_pd(void **target_place, struct task_struct *task)
+struct process_data *preload_pd_get(struct sspt_proc *proc)
+{
+ return (struct process_data *)proc->private_data;
+}
+
+static unsigned long make_preload_path(void)
+{
+ unsigned long page = -EINVAL;
+
+ if (handlers_info) {
+ const char *path = handlers_info->path;
+ size_t len = strnlen(path, PATH_MAX);
+
+ down_write(¤t->mm->mmap_sem);
+ page = swap_do_mmap(NULL, 0, PAGE_SIZE, PROT_READ,
+ MAP_ANONYMOUS | MAP_PRIVATE, 0);
+ up_write(¤t->mm->mmap_sem);
+
+ if (IS_ERR_VALUE(page)) {
+ printk(KERN_ERR PRELOAD_PREFIX
+ "Cannot alloc page for %u\n", current->tgid);
+ goto out;
+ }
+
+ /* set preload_library path */
+ if (copy_to_user((void __user *)page, path, len) <= 0)
+ printk(KERN_ERR PRELOAD_PREFIX
+ "Cannot copy string to user!\n");
+ }
+
+out:
+ return page;
+}
+
+static struct process_data *do_create_pd(struct task_struct *task)
{
struct process_data *pd;
- unsigned long page = 0;
- unsigned long base;
- struct dentry *dentry;
- int ret = 0;
+ unsigned long page;
+ int ret;
ret = __pd_create_on_demand();
if (ret)
- return ret;
+ goto create_pd_exit;
pd = kzalloc(sizeof(*pd), GFP_ATOMIC);
- if (pd == NULL)
- return -ENOMEM;
-
- /* 1. check if loader is already mapped */
- dentry = preload_debugfs_get_loader_dentry();
- base = find_dentry_base(task, dentry);
- if (base)
- __set_loader_base(pd, base);
-
- /* 2. check if handlers are already mapped */
- base = find_dentry_base(task, handlers_info->dentry);
- if (base) {
- __set_handlers_base(pd, base);
- __set_state(pd, LOADED);
- }
-
- /* 3. map page to store path */
-#ifdef CONFIG_ARM
- down_write(¤t->mm->mmap_sem);
-#endif
-
- page = swap_do_mmap(NULL, 0, PAGE_SIZE, PROT_READ,
- MAP_ANONYMOUS | MAP_PRIVATE, 0);
-#ifdef CONFIG_ARM
- up_write(¤t->mm->mmap_sem);
-#endif
- if (IS_ERR((void *)page)) {
- printk(KERN_ERR PRELOAD_PREFIX "Cannot alloc page for %u\n", task->tgid);
+ if (pd == NULL) {
ret = -ENOMEM;
goto create_pd_exit;
}
- pd->is_mapped = 0;
+ page = make_preload_path();
+ if (IS_ERR_VALUE(page)) {
+ ret = (long)page;
+ goto free_pd;
+ }
__set_data_page(pd, page);
__set_attempts(pd, PRELOAD_MAX_ATTEMPTS);
- *target_place = pd;
+ return pd;
- return ret;
+free_pd:
+ kfree(pd);
create_pd_exit:
- kfree(pd);
- return ret;
+ printk(KERN_ERR PRELOAD_PREFIX "do_pd_create_pd: error=%d\n", ret);
+ return NULL;
+}
+
+static void *pd_create(struct sspt_proc *proc)
+{
+ struct process_data *pd;
+
+ pd = do_create_pd(proc->task);
+
+ return (void *)pd;
+}
+
+static void pd_destroy(struct sspt_proc *proc, void *data)
+{
+ /* FIXME: to be implemented */
}
+struct sspt_proc_cb pd_cb = {
+ .priv_create = pd_create,
+ .priv_destroy = pd_destroy
+};
+
int preload_pd_init(void)
{
- return 0;
+ int ret;
+
+ ret = sspt_proc_cb_set(&pd_cb);
+
+ return ret;
}
void preload_pd_uninit(void)
{
+ sspt_proc_cb_set(NULL);
+
if (handlers_info)
preload_storage_put_handlers_info(handlers_info);
handlers_info = NULL;