From: Vasiliy Ulyanov Date: Wed, 26 Aug 2015 09:15:21 +0000 (+0300) Subject: [FIX] Workaround to skip page faults from Preload X-Git-Tag: submit/tizen_2.4/20150912.103527~23 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2b54b37c9a190cb48477fd68a0e004efaf64b163;p=kernel%2Fswap-modules.git [FIX] Workaround to skip page faults from Preload Attempts to read userspace stuff from probe handlers (e.g. like we do in Preload) may lead to crashes. Change-Id: I00009bb9dc19ba003740d078b9a36dee2f75c3f5 Signed-off-by: Vyacheslav Cherkashin --- diff --git a/preload/preload_module.c b/preload/preload_module.c index 547edf9..580c066 100644 --- a/preload/preload_module.c +++ b/preload/preload_module.c @@ -374,6 +374,7 @@ static inline int __msg_sanitization(char *user_msg, size_t len, static bool __is_proc_mmap_mappable(struct task_struct *task) { struct vm_area_struct *linker_vma = __get_linker_vma(task); + struct sspt_proc *proc; unsigned long r_debug_addr; unsigned int state; enum { r_state_offset = sizeof(int) + sizeof(void *) + sizeof(long) }; @@ -386,6 +387,10 @@ static bool __is_proc_mmap_mappable(struct task_struct *task) return false; r_debug_addr += r_state_offset; + proc = sspt_proc_get_by_task(task); + if (proc) + proc->r_state_addr = r_debug_addr; + if (get_user(state, (unsigned long *)r_debug_addr)) return false; diff --git a/us_manager/helper.c b/us_manager/helper.c index d71adf4..3ba5c4f 100644 --- a/us_manager/helper.c +++ b/us_manager/helper.c @@ -68,6 +68,14 @@ static int entry_handler_pf(struct kretprobe_instance *ri, struct pt_regs *regs) #error "this architecture is not supported" #endif /* CONFIG_arch */ + if (data->addr) { + struct sspt_proc * proc = sspt_proc_get_by_task(current); + + if (proc && (proc->r_state_addr == data->addr)) + /* skip ret_handler_pf() for current task */ + return 1; + } + return 0; } diff --git a/us_manager/sspt/sspt_proc.c b/us_manager/sspt/sspt_proc.c index 01f0353..85d24f4 100644 --- a/us_manager/sspt/sspt_proc.c +++ b/us_manager/sspt/sspt_proc.c @@ -88,7 +88,7 @@ void sspt_proc_write_unlock(void) */ struct sspt_proc *sspt_proc_create(struct task_struct *task) { - struct sspt_proc *proc = kmalloc(sizeof(*proc), GFP_ATOMIC); + struct sspt_proc *proc = kzalloc(sizeof(*proc), GFP_ATOMIC); if (proc) { proc->feature = sspt_create_feature(); @@ -101,8 +101,6 @@ struct sspt_proc *sspt_proc_create(struct task_struct *task) proc->tgid = task->tgid; proc->task = task->group_leader; proc->sm = create_sm_us(task); - proc->first_install = 0; - proc->private_data = NULL; INIT_LIST_HEAD(&proc->file_list); INIT_LIST_HEAD(&proc->filter_list); atomic_set(&proc->usage, 1); diff --git a/us_manager/sspt/sspt_proc.h b/us_manager/sspt/sspt_proc.h index 534f150..d82a271 100644 --- a/us_manager/sspt/sspt_proc.h +++ b/us_manager/sspt/sspt_proc.h @@ -48,6 +48,7 @@ struct sspt_proc { struct list_head list; /**< For global process list */ pid_t tgid; /**< Thread group ID */ struct task_struct *task; /**< Ptr to the task */ + unsigned long r_state_addr; /**< address of r_state */ struct slot_manager *sm; /**< Ptr to the manager slot */ struct list_head file_list; /**< For sspt_file */ struct list_head filter_list; /**< Filter list */