static int __preload_cbs_start_h = -1;
static int __preload_cbs_stop_h = -1;
+static struct dentry *handler_dentry = NULL;
+
static inline struct pd_t *__get_process_data(struct uretprobe *rp)
{
struct us_ip *ip = to_us_ip(rp);
}
static inline void print_regs(const char *prefix, struct pt_regs *regs,
- struct uretprobe_instance *ri)
+ struct uretprobe_instance *ri, struct hd_t *hd)
{
+ struct dentry *dentry = preload_pd_get_dentry(hd);
+
#ifdef CONFIG_ARM
- printk(PRELOAD_PREFIX "%s[%d/%d] (%d) %s addr(%08lx), "
+ printk(PRELOAD_PREFIX "%s[%d/%d] %s (%d) %s addr(%08lx), "
"r0(%08lx), r1(%08lx), r2(%08lx), r3(%08lx), "
"r4(%08lx), r5(%08lx), r6(%08lx), r7(%08lx), "
"sp(%08lx), lr(%08lx), pc(%08lx)\n",
current->comm, current->tgid, current->pid,
- (int)preload_pd_get_state(__get_process_data(ri->rp)),
+ dentry != NULL ? (char *)(dentry->d_name.name) :
+ (char *)("NULL"),
+ (int)preload_pd_get_state(hd),
prefix, (unsigned long)ri->rp->up.addr,
regs->ARM_r0, regs->ARM_r1, regs->ARM_r2, regs->ARM_r3,
regs->ARM_r4, regs->ARM_r5, regs->ARM_r6, regs->ARM_r7,
regs->ARM_sp, regs->ARM_lr, regs->ARM_pc);
#else /* !CONFIG_ARM */
- printk(PRELOAD_PREFIX "%s[%d/%d] (%d) %s addr(%08lx), "
+ printk(PRELOAD_PREFIX "%s[%d/%d] %s (%d) %s addr(%08lx), "
"ip(%08lx), arg0(%08lx), arg1(%08lx), raddr(%08lx)\n",
current->comm, current->tgid, current->pid,
- (int)preload_pd_get_state(__get_process_data(ri->rp)),
+ dentry != NULL ? (char *)(dentry->d_name.name) :
+ (char *)("NULL"),
+ (int)preload_pd_get_state(hd),
prefix, (unsigned long)ri->rp->up.addr,
regs->EREG(ip), swap_get_arg(regs, 0), swap_get_arg(regs, 1),
swap_get_ret_addr(regs));
return false;
}
-static inline bool __is_handlers_call(struct vm_area_struct *caller)
+static inline bool __is_handlers_call(struct vm_area_struct *caller,
+ struct pd_t *pd)
{
- /* TODO Optimize using start/stop callbacks */
-
- struct bin_info *hi = preload_storage_get_handlers_info();
- bool res = false;
-
- if (hi == NULL) {
- printk(PRELOAD_PREFIX "Cannot get handlers dentry!\n");
- goto is_handlers_call_out;
- }
+ struct hd_t *hd;
if (caller == NULL || caller->vm_file == NULL ||
- caller->vm_file->f_dentry == NULL) {
- goto is_handlers_call_out;
+ caller->vm_file->f_path.dentry == NULL) {
+ return false;
}
- if (hi->dentry == caller->vm_file->f_dentry)
- res = true;
-
-is_handlers_call_out:
-
- preload_storage_put_handlers_info(hi);
+ hd = preload_pd_get_hd(pd, caller->vm_file->f_path.dentry);
+ if (hd != NULL)
+ return true;
- return res;
+ return false;
}
static inline int __msg_sanitization(char *user_msg, size_t len,
struct file *file = (struct file *)swap_get_karg(regs, 0);
unsigned long prot = swap_get_karg(regs, 3);
struct mmap_priv *priv = (struct mmap_priv *)ri->data;
+ struct task_struct *task = current->group_leader;
struct dentry *dentry, *loader_dentry;
- struct bin_info *hi;
+ struct pd_t *pd;
+ struct hd_t *hd;
+ struct sspt_proc *proc;
priv->dentry = NULL;
if (!check_prot(prot))
if (!file)
return 0;
+
dentry = file->f_dentry;
if (dentry == NULL)
return 0;
- hi = preload_storage_get_handlers_info();
- if (hi == NULL) {
- printk(PRELOAD_PREFIX "Cannot get handlers info [%u %u %s]\n",
- current->tgid, current->pid, current->comm);
+ loader_dentry = preload_debugfs_get_loader_dentry();
+ if (dentry == loader_dentry) {
+ priv->dentry = loader_dentry;
return 0;
}
- loader_dentry = preload_debugfs_get_loader_dentry();
- if (dentry == loader_dentry)
- priv->dentry = loader_dentry;
- else if (hi->dentry != NULL && dentry == hi->dentry)
- priv->dentry = hi->dentry;
+ proc = sspt_proc_get_by_task(task);
+ 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;
+ }
- preload_storage_put_handlers_info(hi);
+ hd = preload_pd_get_hd(pd, dentry);
+ if (hd != NULL)
+ priv->dentry = preload_pd_get_dentry(hd);
return 0;
}
struct mmap_priv *priv = (struct mmap_priv *)ri->data;
struct task_struct *task = current->group_leader;
struct pd_t *pd;
+ struct hd_t *hd;
struct sspt_proc *proc;
struct dentry *loader_dentry;
- struct bin_info *hi;
unsigned long vaddr;
if (!task->mm)
return 0;
}
- hi = preload_storage_get_handlers_info();
- if (hi == NULL) {
- printk(PRELOAD_PREFIX "Cannot get handlers info [%u %u %s]\n",
- current->tgid, current->pid, current->comm);
- return 0;
- }
-
loader_dentry = preload_debugfs_get_loader_dentry();
-
if (priv->dentry == loader_dentry)
preload_pd_set_loader_base(pd, vaddr);
- else if (priv->dentry == hi->dentry)
- preload_pd_set_handlers_base(pd, vaddr);
- preload_storage_put_handlers_info(hi);
+
+ hd = preload_pd_get_hd(pd, priv->dentry);
+ if (hd != NULL)
+ preload_pd_set_handlers_base(hd, vaddr);
return 0;
}
static unsigned long __not_loaded_entry(struct uretprobe_instance *ri,
struct pt_regs *regs,
- struct pd_t *pd)
+ struct pd_t *pd, struct hd_t *hd)
{
char __user *path = NULL;
unsigned long vaddr = 0;
if (vaddr) {
/* save original regs state */
__save_uregs(ri, regs);
- print_regs("PROBE ORIG", regs, ri);
+ print_regs("ORIG", regs, ri, hd);
- path = preload_pd_get_path(pd);
+ path = preload_pd_get_path(pd, hd);
/* set dlopen args: filename, flags */
swap_set_arg(regs, 0, (unsigned long)path/*swap_get_stack_ptr(regs)*/);
/* do the jump to dlopen */
__prepare_ujump(ri, regs, vaddr);
/* set new state */
- preload_pd_set_state(pd, LOADING);
+ preload_pd_set_state(hd, LOADING);
}
return vaddr;
}
-static unsigned long __loaded_entry(struct uretprobe_instance *ri,
- struct pt_regs *regs,
- struct pd_t *pd)
+static void __loading_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+ struct pd_t *pd, struct hd_t *hd)
+{
+ struct us_priv *priv = (struct us_priv *)ri->data;
+ unsigned long vaddr = 0;
+
+ /* check if preloading has been completed */
+ vaddr = preload_pd_get_loader_base(pd) +
+ preload_debugfs_get_loader_offset();
+ if (vaddr && (priv->origin == vaddr)) {
+ preload_pd_set_handle(hd,
+ (void __user *)regs_return_value(regs));
+
+ /* restore original regs state */
+ __restore_uregs(ri, regs);
+ print_regs("REST", regs, ri, hd);
+ /* check if preloading done */
+
+ if (preload_pd_get_handle(hd)) {
+ preload_pd_set_state(hd, LOADED);
+ } else {
+ preload_pd_dec_attempts(hd);
+ preload_pd_set_state(hd, FAILED);
+ }
+ }
+}
+
+static void __failed_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
+ struct pd_t *pd, struct hd_t *hd)
+{
+ if (preload_pd_get_attempts(hd))
+ preload_pd_set_state(hd, NOT_LOADED);
+}
+
+
+
+static unsigned long __do_preload_entry(struct uretprobe_instance *ri,
+ struct pt_regs *regs,
+ struct hd_t *hd)
{
struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
unsigned long offset = ip->desc->info.pl_i.handler;
struct vm_area_struct *cvma;
enum preload_call_type ct;
- base = preload_pd_get_handlers_base(pd);
+ base = preload_pd_get_handlers_base(hd);
if (base == 0)
return 0; /* handlers isn't mapped */
(cvma->vm_file->f_path.dentry != NULL) &&
!preload_control_check_dentry_is_ignored(cvma->vm_file->f_path.dentry)) &&
__check_flag_and_call_type(ip, ct) &&
- !__is_handlers_call(cvma)) {
+ !__is_handlers_call(cvma, preload_pd_get_parent_pd(hd))) {
if (preload_threads_set_data(current, caddr, ct, disable_addr,
__should_drop(ip, ct)) != 0)
printk(PRELOAD_PREFIX "Error! Failed to set caller 0x%lx"
return vaddr;
}
-static void __loading_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
- struct pd_t *pd)
+static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
{
+ struct pd_t *pd = __get_process_data(ri->rp);
+ struct hd_t *hd;
+ unsigned long flags = get_preload_flags(current);
+ struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
struct us_priv *priv = (struct us_priv *)ri->data;
unsigned long vaddr = 0;
- /* check if preloading has been completed */
- vaddr = preload_pd_get_loader_base(pd) + preload_debugfs_get_loader_offset();
- if (vaddr && (priv->origin == vaddr)) {
- preload_pd_set_handle(pd, (void __user *)regs_return_value(regs));
+ if (handler_dentry == NULL)
+ goto out_set_orig;
- /* restore original regs state */
- __restore_uregs(ri, regs);
- print_regs("PROBE REST", regs, ri);
- /* check if preloading done */
+ if ((flags & HANDLER_RUNNING) ||
+ preload_threads_check_disabled_probe(current, ip->orig_addr))
+ goto out_set_orig;
- if (preload_pd_get_handle(pd)) {
- preload_pd_set_state(pd, LOADED);
- } else {
- preload_pd_dec_attempts(pd);
- preload_pd_set_state(pd, FAILED);
- }
- }
+ hd = preload_pd_get_hd(pd, handler_dentry);
+ if (hd == NULL)
+ goto out_set_orig;
+
+ if ((flags & HANDLER_RUNNING) ||
+ preload_threads_check_disabled_probe(current, ip->orig_addr))
+ goto out_set_orig;
+
+ if (preload_pd_get_state(hd) == NOT_LOADED ||
+ preload_pd_get_state(hd) == FAILED)
+ vaddr = __not_loaded_entry(ri, regs, pd, hd);
+ else if (preload_pd_get_state(hd) == LOADED)
+ vaddr =__do_preload_entry(ri, regs, hd);
+
+out_set_orig:
+ priv->origin = vaddr;
+ return 0;
}
-static void __loaded_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
- struct pd_t *pd)
+static void __do_preload_ret(struct uretprobe_instance *ri, struct hd_t *hd)
{
struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
struct us_priv *priv = (struct us_priv *)ri->data;
bool non_blk_probe = __is_probe_non_block(ip);
/* drop the flag if the handler has completed */
- vaddr = preload_pd_get_handlers_base(pd) + offset;
+ vaddr = preload_pd_get_handlers_base(hd) + offset;
if (vaddr && (priv->origin == vaddr)) {
if (preload_threads_put_data(current) != 0)
printk(PRELOAD_PREFIX "Error! Failed to put caller slot"
}
}
-static void __failed_ret(struct uretprobe_instance *ri, struct pt_regs *regs,
- struct pd_t *pd)
-{
- if (preload_pd_get_attempts(pd)) {
- preload_pd_set_state(pd, NOT_LOADED);
- }
-}
-
-static int preload_us_entry(struct uretprobe_instance *ri, struct pt_regs *regs)
+static int preload_us_ret(struct uretprobe_instance *ri, struct pt_regs *regs)
{
struct pd_t *pd = __get_process_data(ri->rp);
- struct us_ip *ip = container_of(ri->rp, struct us_ip, retprobe);
- struct us_priv *priv = (struct us_priv *)ri->data;
- unsigned long flags = get_preload_flags(current);
- unsigned long vaddr = 0;
-
- if ((flags & HANDLER_RUNNING) ||
- preload_threads_check_disabled_probe(current, ip->orig_addr))
- goto out_set_origin;
+ struct hd_t *hd;
- switch (preload_pd_get_state(pd)) {
- case NOT_LOADED:
- vaddr = __not_loaded_entry(ri, regs, pd);
- break;
- case LOADING:
- /* handlers have not yet been loaded... just ignore */
- break;
- case LOADED:
- vaddr = __loaded_entry(ri, regs, pd);
- break;
- case FAILED:
- case ERROR:
- default:
- /* do nothing */
- break;
- }
-
-out_set_origin:
- priv->origin = vaddr;
- return 0;
-}
+ if (handler_dentry == NULL)
+ return 0;
-static int preload_us_ret(struct uretprobe_instance *ri, struct pt_regs *regs)
-{
- struct pd_t *pd = __get_process_data(ri->rp);
+ hd = preload_pd_get_hd(pd, handler_dentry);
+ if (hd == NULL)
+ return 0;
- switch (preload_pd_get_state(pd)) {
+ switch (preload_pd_get_state(hd)) {
case NOT_LOADED:
/* loader has not yet been mapped... just ignore */
break;
case LOADING:
- __loading_ret(ri, regs, pd);
+ __loading_ret(ri, regs, pd, hd);
break;
case LOADED:
- __loaded_ret(ri, regs, pd);
+ __do_preload_ret(ri, hd);
break;
case FAILED:
- __failed_ret(ri, regs, pd);
+ __failed_ret(ri, regs, pd, hd);
break;
case ERROR:
default:
}
+void preload_module_set_handler_dentry(struct dentry *dentry)
+{
+ handler_dentry = dentry;
+}
+
static int preload_module_init(void)
{
int ret;
int preload_module_write_msg_init(struct us_ip *ip);
void preload_module_write_msg_exit(struct us_ip *ip);
+void preload_module_set_handler_dentry(struct dentry *dentry);
+
struct dentry *get_dentry(const char *filepath);
void put_dentry(struct dentry *dentry);
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/hardirq.h>
+#include <linux/list.h>
#include <us_manager/us_manager_common.h>
#include <us_manager/sspt/sspt_proc.h>
#include "preload_pd.h"
#include "preload.h"
struct pd_t {
- enum ps_t state;
unsigned long loader_base;
- unsigned long handlers_base;
unsigned long data_page;
+ struct list_head handlers;
+};
+
+struct hd_t {
+ struct list_head list;
+ struct dentry *dentry;
+ enum ps_t state;
+ struct pd_t *parent;
+ unsigned long base;
+ unsigned long offset;
void __user *handle;
long attempts;
};
-static struct bin_info *handlers_info;
-
-
-
static inline bool check_vma(struct vm_area_struct *vma, struct dentry *dentry)
{
struct file *file = vma->vm_file;
return (file && (vma->vm_flags & VM_EXEC) && (file->f_dentry == dentry));
}
-static inline enum ps_t __get_state(struct pd_t *pd)
+static inline unsigned long __get_loader_base(struct pd_t *pd)
{
- return pd->state;
+ return pd->loader_base;
}
-static inline void __set_state(struct pd_t *pd,
- enum ps_t state)
+static inline void __set_loader_base(struct pd_t *pd,
+ unsigned long addr)
{
- pd->state = state;
+ pd->loader_base = addr;
}
-static inline unsigned long __get_loader_base(struct pd_t *pd)
+static inline unsigned long __get_data_page(struct pd_t *pd)
{
- return pd->loader_base;
+ return pd->data_page;
}
-static inline void __set_loader_base(struct pd_t *pd,
- unsigned long addr)
+static inline void __set_data_page(struct pd_t *pd, unsigned long page)
{
- pd->loader_base = addr;
+ pd->data_page = page;
+}
+
+
+
+static inline enum ps_t __get_state(struct hd_t *hd)
+{
+ return hd->state;
}
-static inline unsigned long __get_handlers_base(struct pd_t *pd)
+static inline void __set_state(struct hd_t *hd, enum ps_t state)
{
- return pd->handlers_base;
+ hd->state = state;
}
-static inline void __set_handlers_base(struct pd_t *pd,
+static inline unsigned long __get_handlers_base(struct hd_t *hd)
+{
+ return hd->base;
+}
+
+static inline void __set_handlers_base(struct hd_t *hd,
unsigned long addr)
{
- pd->handlers_base = addr;
+ hd->base = addr;
}
-static inline char __user *__get_path(struct pd_t *pd)
+static inline unsigned long __get_offset(struct hd_t *hd)
{
- return (char *)pd->data_page;
+ return hd->offset;
}
-static inline unsigned long __get_data_page(struct pd_t *pd)
+static inline void *__get_handle(struct hd_t *hd)
{
- return pd->data_page;
+ return hd->handle;
}
-static inline void __set_data_page(struct pd_t *pd, unsigned long page)
+static inline void __set_handle(struct hd_t *hd, void __user *handle)
{
- pd->data_page = page;
+ hd->handle = handle;
}
-static inline void *__get_handle(struct pd_t *pd)
+static inline long __get_attempts(struct hd_t *hd)
{
- return pd->handle;
+ return hd->attempts;
}
-static inline void __set_handle(struct pd_t *pd, void __user *handle)
+static inline void __set_attempts(struct hd_t *hd, long attempts)
{
- pd->handle = handle;
+ hd->attempts = attempts;
}
-static inline long __get_attempts(struct pd_t *pd)
+
+
+static struct vm_area_struct *find_vma_by_dentry(struct mm_struct *mm,
+ struct dentry *dentry)
{
- return pd->attempts;
+ struct vm_area_struct *vma;
+
+ for (vma = mm->mmap; vma; vma = vma->vm_next)
+ if (check_vma(vma, dentry))
+ return vma;
+
+ return NULL;
}
-static inline void __set_attempts(struct pd_t *pd, long attempts)
+static struct pd_t *__create_pd(void)
{
- pd->attempts = attempts;
+ struct pd_t *pd;
+ unsigned long page;
+
+ pd = kzalloc(sizeof(*pd), GFP_ATOMIC);
+ if (pd == NULL)
+ return NULL;
+
+ down_write(¤t->mm->mmap_sem);
+ page = swap_do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_WRITE,
+ 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 create_pd_fail;
+ }
+
+ __set_data_page(pd, page);
+
+ INIT_LIST_HEAD(&pd->handlers);
+
+ return pd;
+
+create_pd_fail:
+ kfree(pd);
+
+ return NULL;
}
+static size_t __copy_path(char *src, unsigned long page, unsigned long offset)
+{
+ unsigned long dest = page + offset;
+ size_t len = strnlen(src, PATH_MAX);
+ /* set handler path */
+ if (copy_to_user((void __user *)dest, src, len) != 0) {
+ printk(KERN_ERR PRELOAD_PREFIX
+ "Cannot copy string to user!\n");
+ return 0;
+ }
+ return len;
+}
-static int __pd_create_on_demand(void)
+static void __set_ld_mapped(struct pd_t *pd, struct mm_struct *mm)
{
- if (handlers_info == NULL) {
- handlers_info = preload_storage_get_handlers_info();
- if (handlers_info == NULL)
- return -EINVAL;
+ struct vm_area_struct *vma;
+ struct dentry *ld = preload_debugfs_get_loader_dentry();
+
+ down_read(&mm->mmap_sem);
+ if (ld) {
+ vma = find_vma_by_dentry(mm, ld);
+ if (vma)
+ __set_loader_base(pd, vma->vm_start);
}
+ up_read(&mm->mmap_sem);
+}
- return 0;
+static void __set_handler_mapped(struct hd_t *hd, struct mm_struct *mm)
+{
+ struct vm_area_struct *vma;
+ struct dentry *handlers = hd->dentry;
+
+ down_read(&mm->mmap_sem);
+ if (handlers) {
+ vma = find_vma_by_dentry(mm, handlers);
+ if (vma) {
+ __set_handlers_base(hd, vma->vm_start);
+ __set_state(hd, LOADED);
+ goto set_handler_mapped_out;
+ }
+ }
+ __set_state(hd, NOT_LOADED);
+
+set_handler_mapped_out:
+ up_read(&mm->mmap_sem);
+}
+
+
+static int __get_handlers(struct pd_t *pd, struct task_struct *task)
+{
+ struct list_head *handlers = NULL;
+ struct bin_info_el *bin;
+ struct hd_t *hd;
+ unsigned long offset = 0;
+ size_t len;
+ int ret = 0;
+
+ handlers = preload_storage_get_handlers();
+ if (handlers == NULL)
+ return -EINVAL;
+
+ list_for_each_entry(bin, handlers, list) {
+ len = __copy_path(bin->path, pd->data_page, offset);
+ if (len == 0) {
+ ret = -EINVAL;
+ goto get_handlers_out;
+ }
+
+ hd = kzalloc(sizeof(*hd), GFP_ATOMIC);
+ if (hd == NULL) {
+ printk(KERN_ERR PRELOAD_PREFIX "No atomic mem!\n");
+ ret = -ENOMEM;
+ goto get_handlers_out;
+ }
+
+
+ INIT_LIST_HEAD(&hd->list);
+ hd->parent = pd;
+ hd->dentry = bin->dentry;
+ hd->offset = offset;
+ __set_handler_mapped(hd, task->mm);
+ __set_attempts(hd, PRELOAD_MAX_ATTEMPTS);
+ list_add_tail(&hd->list, &pd->handlers);
+
+ /* inc handlers path's on page */
+ offset += len + 1;
+ }
+
+get_handlers_out:
+ /* TODO Cleanup already created */
+ preload_storage_put_handlers();
+
+ return ret;
}
-enum ps_t preload_pd_get_state(struct pd_t *pd)
+enum ps_t preload_pd_get_state(struct hd_t *hd)
{
- if (pd == NULL)
+ if (hd == NULL)
return 0;
- return __get_state(pd);
+ return __get_state(hd);
}
-void preload_pd_set_state(struct pd_t *pd, enum ps_t state)
+void preload_pd_set_state(struct hd_t *hd, enum ps_t state)
{
- if (pd == NULL) {
- printk(PRELOAD_PREFIX "%d: No process data! Current %d %s\n", __LINE__,
- current->tgid, current->comm);
+ if (hd == NULL) {
+ printk(PRELOAD_PREFIX "%d: No handler data! Current %d %s\n",
+ __LINE__, current->tgid, current->comm);
return;
}
- __set_state(pd, state);
+ __set_state(hd, state);
}
unsigned long preload_pd_get_loader_base(struct pd_t *pd)
__set_loader_base(pd, vaddr);
}
-unsigned long preload_pd_get_handlers_base(struct pd_t *pd)
+unsigned long preload_pd_get_handlers_base(struct hd_t *hd)
{
- if (pd == NULL)
+ if (hd == NULL)
return 0;
- return __get_handlers_base(pd);
+ return __get_handlers_base(hd);
}
-void preload_pd_set_handlers_base(struct pd_t *pd, unsigned long vaddr)
+void preload_pd_set_handlers_base(struct hd_t *hd, unsigned long vaddr)
{
- __set_handlers_base(pd, vaddr);
+ __set_handlers_base(hd, vaddr);
}
-char __user *preload_pd_get_path(struct pd_t *pd)
+char __user *preload_pd_get_path(struct pd_t *pd, struct hd_t *hd)
{
- char __user *path = __get_path(pd);
+ unsigned long page = __get_data_page(pd);
+ unsigned long offset = __get_offset(hd);
- return path;
+ return (char __user *)(page + offset);
}
-void *preload_pd_get_handle(struct pd_t *pd)
+void *preload_pd_get_handle(struct hd_t *hd)
{
- if (pd == NULL)
+ if (hd == NULL)
return NULL;
- return __get_handle(pd);
+ return __get_handle(hd);
}
-void preload_pd_set_handle(struct pd_t *pd, void __user *handle)
+void preload_pd_set_handle(struct hd_t *hd, void __user *handle)
{
- if (pd == NULL) {
- printk(PRELOAD_PREFIX "%d: No process data! Current %d %s\n", __LINE__,
- current->tgid, current->comm);
+ if (hd == NULL) {
+ printk(PRELOAD_PREFIX "%d: No handler data! Current %d %s\n",
+ __LINE__, current->tgid, current->comm);
return;
}
- __set_handle(pd, handle);
+ __set_handle(hd, handle);
}
-long preload_pd_get_attempts(struct pd_t *pd)
+long preload_pd_get_attempts(struct hd_t *hd)
{
- if (pd == NULL)
+ if (hd == NULL)
return -EINVAL;
- return __get_attempts(pd);
+ return __get_attempts(hd);
}
-void preload_pd_dec_attempts(struct pd_t *pd)
+void preload_pd_dec_attempts(struct hd_t *hd)
{
long attempts;
- if (pd == NULL) {
- printk(PRELOAD_PREFIX "%d: No process data! Current %d %s\n", __LINE__,
- current->tgid, current->comm);
+ if (hd == NULL) {
+ printk(PRELOAD_PREFIX "%d: No handler data! Current %d %s\n",
+ __LINE__, current->tgid, current->comm);
return;
}
- attempts = __get_attempts(pd);
+ attempts = __get_attempts(hd);
attempts--;
- __set_attempts(pd, attempts);
+ __set_attempts(hd, attempts);
}
-struct pd_t *preload_pd_get(struct sspt_proc *proc)
+struct dentry *preload_pd_get_dentry(struct hd_t *hd)
{
- return (struct pd_t *)proc->private_data;
+ return hd->dentry;
}
-static unsigned long make_preload_path(void)
+struct pd_t *preload_pd_get_parent_pd(struct hd_t *hd)
{
- 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 | PROT_WRITE,
- 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;
+ return hd->parent;
}
-static struct vm_area_struct *find_vma_by_dentry(struct mm_struct *mm,
- struct dentry *dentry)
+struct pd_t *preload_pd_get(struct sspt_proc *proc)
{
- struct vm_area_struct *vma;
-
- for (vma = mm->mmap; vma; vma = vma->vm_next)
- if (check_vma(vma, dentry))
- return vma;
-
- return NULL;
+ return (struct pd_t *)proc->private_data;
}
-static void set_already_mapp(struct pd_t *pd, struct mm_struct *mm)
+struct hd_t *preload_pd_get_hd(struct pd_t *pd, struct dentry *dentry)
{
- struct vm_area_struct *vma;
- struct dentry *ld = preload_debugfs_get_loader_dentry();
- struct dentry *handlers = handlers_info->dentry;
+ struct hd_t *hd;
- down_read(&mm->mmap_sem);
- if (ld) {
- vma = find_vma_by_dentry(mm, ld);
- if (vma)
- __set_loader_base(pd, vma->vm_start);
+ list_for_each_entry(hd, &pd->handlers, list) {
+ if (hd->dentry == dentry)
+ return hd;
}
- if (handlers) {
- vma = find_vma_by_dentry(mm, handlers);
- if (vma) {
- __set_handlers_base(pd, vma->vm_start);
- __set_state(pd, LOADED);
- }
- }
- up_read(&mm->mmap_sem);
+ return NULL;
}
static struct pd_t *do_create_pd(struct task_struct *task)
{
struct pd_t *pd;
- unsigned long page;
int ret;
- ret = __pd_create_on_demand();
- if (ret)
- goto create_pd_exit;
-
- pd = kzalloc(sizeof(*pd), GFP_ATOMIC);
+ pd = __create_pd();
if (pd == NULL) {
ret = -ENOMEM;
goto create_pd_exit;
}
- page = make_preload_path();
- if (IS_ERR_VALUE(page)) {
- ret = (long)page;
+ ret = __get_handlers(pd, task);
+ if (ret)
goto free_pd;
- }
- __set_data_page(pd, page);
- __set_attempts(pd, PRELOAD_MAX_ATTEMPTS);
- set_already_mapp(pd, task->mm);
+ __set_ld_mapped(pd, task->mm);
return pd;
{
sspt_proc_cb_set(NULL);
- if (handlers_info)
- preload_storage_put_handlers_info(handlers_info);
- handlers_info = NULL;
+ /* TODO Cleanup */
}
#define __PRELOAD_PD_H__
struct pd_t;
+struct hd_t;
struct sspt_proc;
+struct dentry;
+struct list_head;
/* process preload states */
enum ps_t {
};
struct pd_t *preload_pd_get(struct sspt_proc *proc);
-
-enum ps_t preload_pd_get_state(struct pd_t *pd);
-void preload_pd_set_state(struct pd_t *pd, enum ps_t state);
unsigned long preload_pd_get_loader_base(struct pd_t *pd);
void preload_pd_set_loader_base(struct pd_t *pd, unsigned long vaddr);
-unsigned long preload_pd_get_handlers_base(struct pd_t *pd);
-void preload_pd_set_handlers_base(struct pd_t *pd, unsigned long vaddr);
-void *preload_pd_get_handle(struct pd_t *pd);
-void preload_pd_set_handle(struct pd_t *pd, void __user *handle);
-
-long preload_pd_get_attempts(struct pd_t *pd);
-void preload_pd_dec_attempts(struct pd_t *pd);
-char __user *preload_pd_get_path(struct pd_t *pd);
+struct hd_t *preload_pd_get_hd(struct pd_t *pd, struct dentry *dentry);
+struct dentry *preload_pd_get_dentry(struct hd_t *hd);
+struct pd_t *preload_pd_get_parent_pd(struct hd_t *hd);
+enum ps_t preload_pd_get_state(struct hd_t *hd);
+void preload_pd_set_state(struct hd_t *hd, enum ps_t state);
+unsigned long preload_pd_get_handlers_base(struct hd_t *hd);
+void preload_pd_set_handlers_base(struct hd_t *hd, unsigned long vaddr);
+void *preload_pd_get_handle(struct hd_t *hd);
+void preload_pd_set_handle(struct hd_t *hd, void __user *handle);
+long preload_pd_get_attempts(struct hd_t *hd);
+void preload_pd_dec_attempts(struct hd_t *hd);
+
+char __user *preload_pd_get_path(struct pd_t *pd, struct hd_t *hd);
int preload_pd_init(void);
void preload_pd_uninit(void);
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <ks_features/ks_map.h>
#include <linux/fs.h>
+#include <linux/list.h>
+#include <ks_features/ks_map.h>
#include "preload.h"
#include "preload_module.h"
#include "preload_storage.h"
static struct bin_info __handlers_info = { NULL, NULL };
static struct bin_info __linker_info = { NULL, NULL };
+static LIST_HEAD(handlers_list);
+
static inline struct bin_info *__get_handlers_info(void)
{
return &__handlers_info;
return (__handlers_info.dentry != NULL); /* TODO */
}
+static inline int __add_handler(char *path)
+{
+ struct dentry *dentry;
+ size_t len = strnlen(path, PATH_MAX);
+ struct bin_info_el *bin;
+ int ret = 0;
+
+ bin = kmalloc(sizeof(*bin), GFP_KERNEL);
+ if (bin == NULL) {
+ ret = -ENOMEM;
+ goto add_handler_fail;
+ }
+
+ bin->path = kmalloc(len + 1, GFP_KERNEL);
+ if (bin->path == NULL) {
+ ret = -ENOMEM;
+ goto add_handler_fail_free_bin;
+ }
+
+ dentry = get_dentry(path);
+ if (!dentry) {
+ ret = -ENOENT;
+ goto add_handler_fail_free_path;
+ }
+
+ INIT_LIST_HEAD(&bin->list);
+ strncpy(bin->path, path, len);
+ bin->path[len] = '\0';
+ bin->dentry = dentry;
+ list_add_tail(&bin->list, &handlers_list);
+
+ return ret;
+
+add_handler_fail_free_path:
+ kfree(bin->path);
+
+add_handler_fail_free_bin:
+ kfree(bin);
+
+add_handler_fail:
+ return ret;
+}
+
+static inline void __remove_handler(struct bin_info_el *bin)
+{
+ list_del(&bin->list);
+ put_dentry(bin->dentry);
+ kfree(bin->path);
+ kfree(bin);
+}
+
+static inline void __remove_handlers(void)
+{
+ struct bin_info_el *bin, *tmp;
+
+ list_for_each_entry_safe(bin, tmp, &handlers_list, list)
+ __remove_handler(bin);
+}
+
static inline int __init_handlers_info(char *path)
{
struct dentry *dentry;
int preload_storage_set_handlers_info(char *path)
{
- return __init_handlers_info(path);
+ int ret;
+
+ ret = __init_handlers_info(path);
+ if (ret != 0)
+ return ret;
+
+ ret = __add_handler(path);
+ if (ret != 0)
+ return ret;
+
+ preload_module_set_handler_dentry(__handlers_info.dentry);
+
+ return ret;
+}
+
+int preload_storage_add_handler(char *path)
+{
+ int ret;
+
+ ret = __add_handler(path);
+ if (ret != 0)
+ return ret;
+
+ return ret;
}
struct bin_info *preload_storage_get_handlers_info(void)
return NULL;
}
+struct list_head *preload_storage_get_handlers(void)
+{
+ /* TODO counter, syncs */
+ return &handlers_list;
+}
+
void preload_storage_put_handlers_info(struct bin_info *info)
{
}
+void preload_storage_put_handlers(void)
+{
+ /* TODO dec counter, release sync */
+}
+
int preload_storage_set_linker_info(char *path)
{
return __init_linker_info(path);
{
__drop_handlers_info();
__drop_linker_info();
+ __remove_handlers();
}
#ifndef __PRELOAD_STORAGE_H__
#define __PRELOAD_STORAGE_H__
+struct list_head;
+struct dentry;
+
struct bin_info {
char *path;
/* ghot */
struct dentry *dentry;
};
+struct bin_info_el {
+ struct list_head list;
+ char *path;
+ /* ghot */
+ struct dentry *dentry;
+};
+
+
int preload_storage_set_handlers_info(char *path);
struct bin_info *preload_storage_get_handlers_info(void);
void preload_storage_put_handlers_info(struct bin_info *info);
+int preload_storage_add_handler(char *path);
+struct list_head *preload_storage_get_handlers(void);
+void preload_storage_put_handlers(void);
+
int preload_storage_set_linker_info(char *path);
struct bin_info *preload_storage_get_linker_info(void);
void preload_storage_put_linker_info(struct bin_info *info);