From e8f7ca45c9480189f40a0a68db3fbdf87d09825b Mon Sep 17 00:00:00 2001 From: Vasiliy Ulyanov Date: Mon, 13 Jul 2015 17:40:21 +0300 Subject: [PATCH] [FIX] Preload: move dentry lookup out of uprobe handler It was causing a lot of 'scheduling while in atomic' BUGs (and a deadlock at the end) which were masked by oops_in_progress (set in kprobe_trap_handler). Change-Id: I2f0c5f5f3ca58ba07c785ca2b3f73e3e2d04c32c Signed-off-by: Vasiliy Ulyanov --- preload/preload_module.c | 18 ++++++++++++------ preload/preload_storage.c | 26 ++++++++++++++++++++++++++ preload/preload_storage.h | 3 +++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/preload/preload_module.c b/preload/preload_module.c index ddd9cfa..0e02a08 100644 --- a/preload/preload_module.c +++ b/preload/preload_module.c @@ -273,19 +273,25 @@ static struct vm_area_struct *__get_linker_vma(struct task_struct *task) static struct vm_area_struct *__get_libc_vma(struct task_struct *task) { struct vm_area_struct *vma = NULL; - struct dentry *libc_dentry; + struct bin_info *libc_info; - libc_dentry = get_dentry("/lib/libc.so.6"); + libc_info = preload_storage_get_libc_info(); + + if (!libc_info) { + printk(PRELOAD_PREFIX "Cannot get libc info [%u %u %s]!\n", + task->tgid, task->pid, task->comm); + return NULL; + } for (vma = task->mm->mmap; vma; vma = vma->vm_next) { if (vma->vm_file && vma->vm_flags & VM_EXEC - && vma->vm_file->f_dentry == libc_dentry) { - put_dentry(libc_dentry); - return vma; + && vma->vm_file->f_dentry == libc_info->dentry) { + preload_storage_put_libc_info(libc_info); + return vma; } } - put_dentry(libc_dentry); + preload_storage_put_libc_info(libc_info); return NULL; } diff --git a/preload/preload_storage.c b/preload/preload_storage.c index c19853b..524232b 100644 --- a/preload/preload_storage.c +++ b/preload/preload_storage.c @@ -9,6 +9,7 @@ static struct bin_info __handlers_info = { NULL, NULL }; static struct bin_info __linker_info = { NULL, NULL }; +static struct bin_info __libc_info; static inline struct bin_info *__get_handlers_info(void) { @@ -149,17 +150,42 @@ struct bin_info *preload_storage_get_linker_info(void) return NULL; } +static inline void __drop_libc_info(void) +{ + if (__libc_info.dentry) + put_dentry(__libc_info.dentry); + + __libc_info.path = NULL; + __libc_info.dentry = NULL; +} + void preload_storage_put_linker_info(struct bin_info *info) { } +struct bin_info *preload_storage_get_libc_info(void) +{ + return &__libc_info; +} + +void preload_storage_put_libc_info(struct bin_info *info) +{ +} + int preload_storage_init(void) { + __libc_info.path = "/lib/libc.so.6"; + __libc_info.dentry = get_dentry(__libc_info.path); + + if (!__libc_info.dentry) + return -ENOENT; + return 0; } void preload_storage_exit(void) { + __drop_libc_info(); __drop_handlers_info(); __drop_linker_info(); } diff --git a/preload/preload_storage.h b/preload/preload_storage.h index 86c7919..faa9ff6 100644 --- a/preload/preload_storage.h +++ b/preload/preload_storage.h @@ -15,6 +15,9 @@ 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); +struct bin_info *preload_storage_get_libc_info(void); +void preload_storage_put_libc_info(struct bin_info *info); + int preload_storage_init(void); void preload_storage_exit(void); -- 2.7.4