[FIX] nsp: sleeping function called from atomic context
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 30 Mar 2016 11:12:03 +0000 (14:12 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 30 Mar 2016 11:18:06 +0000 (14:18 +0300)
Change-Id: I47cef6151729ed39456999424e47e7037153a67d
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
nsp/Kbuild
nsp/nsp.c
nsp/nsp_module.c
nsp/nsp_tdata.c [deleted file]
nsp/nsp_tdata.h [deleted file]

index 85c8b90..86ea819 100644 (file)
@@ -5,5 +5,4 @@ swap_nsp-y := \
        nsp_module.o \
        nsp.o \
        nsp_msg.o \
-       nsp_tdata.o \
        nsp_debugfs.o
index 8c10cd9..8fee92b 100644 (file)
--- a/nsp/nsp.c
+++ b/nsp/nsp.c
 
 #include <linux/module.h>
 #include <writer/swap_msg.h>
+#include <kprobe/swap_ktd.h>
 #include <uprobe/swap_uaccess.h>
 #include <us_manager/pf/pf_group.h>
 #include <us_manager/sspt/sspt_proc.h>
 #include <us_manager/probes/probe_info_new.h>
 #include "nsp.h"
 #include "nsp_msg.h"
-#include "nsp_tdata.h"
 #include "nsp_print.h"
 #include "nsp_debugfs.h"
 
@@ -478,7 +478,6 @@ static int set_stat_off(void)
                return -EINVAL;
 
        __nsp_disabel();
-       tdata_disable();
 
        stat = NS_OFF;
 
@@ -487,18 +486,12 @@ static int set_stat_off(void)
 
 static int set_stat_on(void)
 {
-       int ret;
-
        if (is_init() == false)
                return -EPERM;
 
        if (stat == NS_ON)
                return -EINVAL;
 
-       ret = tdata_enable();
-       if (ret)
-               return ret;
-
        __nsp_enable();
 
        stat = NS_ON;
@@ -534,6 +527,53 @@ enum nsp_stat nsp_get_stat(void)
 
 
 /* ============================================================================
+ * =                                 tdata                                    =
+ * ============================================================================
+ */
+enum nsp_proc_stat {
+       NPS_OPEN_E,             /* mapping begin */
+       NPS_OPEN_R,
+       NPS_SYM_E,
+       NPS_SYM_R,              /* mapping end   */
+       NPS_MAIN_E,             /* main begin    */
+       NPS_AC_EFL_MAIN_E,      /* main end      */
+       NPS_AC_INIT_R,          /* create begin  */
+       NPS_ELM_RUN_E,          /* create end    */
+       NPS_DO_APP_E,           /* reset begin   */
+       NPS_DO_APP_R            /* reset end     */
+};
+
+struct tdata {
+       enum nsp_proc_stat stat;
+       struct nsp_data *nsp_data;
+       u64 time;
+       void __user *handle;
+       struct probe_new p_main;
+};
+
+
+static void ktd_init(struct task_struct *task, void *data)
+{
+       struct tdata *tdata = (struct tdata *)data;
+
+       tdata->nsp_data = NULL;
+}
+
+struct ktask_data ktd = {
+       .init = ktd_init,
+       .size = sizeof(struct tdata),
+};
+
+static struct tdata *tdata_get(struct task_struct *task)
+{
+       return (struct tdata *)swap_ktd(&ktd, task);
+}
+
+
+
+
+
+/* ============================================================================
  * =                                handlers                                  =
  * ============================================================================
  */
@@ -549,48 +589,30 @@ static int dlopen_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
 
        nsp_data = nsp_data_find_by_path(path);
        if (nsp_data) {
-               struct task_struct *task = current;
-               struct tdata *tdata;
-
-               tdata = tdata_get(task);
-               if (tdata) {
-                       nsp_print("ERROR: dlopen already cal for '%s'\n", path);
-                       tdata_put(tdata);
-                       goto free_path;
-               }
+               struct tdata *tdata = tdata_get(current);
 
-               tdata = tdata_create(task);
-               if (tdata) {
+               /* init tdata */
+               if (tdata->nsp_data == NULL) {
                        tdata->stat = NPS_OPEN_E;
                        tdata->time = swap_msg_current_time();
                        tdata->nsp_data = nsp_data;
-                       tdata_put(tdata);
-               } else {
-                       nsp_print("ERROR: out of memory\n");
                }
        }
 
-free_path:
        kfree(path);
        return 0;
 }
 
 static int dlopen_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
-       struct tdata *tdata;
+       struct tdata *tdata = tdata_get(current);
+       void *handle = (void *)regs_return_value(regs);
 
-       tdata = tdata_get(current);
-       if (tdata) {
-               void *handle;
-
-               handle = (void *)regs_return_value(regs);
-               if ((tdata->stat == NPS_OPEN_E) && handle) {
-                       tdata->stat = NPS_OPEN_R;
-                       tdata->handle = handle;
-                       tdata_put(tdata);
-               } else {
-                       tdata_destroy(tdata);
-               }
+       if ((tdata->stat == NPS_OPEN_E) && handle) {
+               tdata->stat = NPS_OPEN_R;
+               tdata->handle = handle;
+       } else {
+               tdata->handle = NULL;
        }
 
        return 0;
@@ -598,24 +620,18 @@ static int dlopen_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
 
 static int dlsym_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
-       struct tdata *tdata;
+       struct tdata *tdata = tdata_get(current);
+       void __user *handle = (void __user *)swap_get_uarg(regs, 0);
+       const char __user *str = (const char __user *)swap_get_uarg(regs, 1);
 
-       tdata = tdata_get(current);
-       if (tdata) {
-               const char __user *str = (char __user *)swap_get_uarg(regs, 1);
+       if (handle == tdata->handle && tdata->stat == NPS_OPEN_R) {
                const char *name;
-               void *handle;
 
-               handle = (void *)swap_get_uarg(regs, 0);
-               if (handle == tdata->handle && tdata->stat == NPS_OPEN_R) {
-                       name = strdup_from_user(str, GFP_ATOMIC);
-                       if (name && (strcmp(name, "main") == 0))
-                               tdata->stat = NPS_SYM_E;
+               name = strdup_from_user(str, GFP_ATOMIC);
+               if (name && (strcmp(name, "main") == 0))
+                       tdata->stat = NPS_SYM_E;
 
-                       kfree(name);
-               }
-
-               tdata_put(tdata);
+               kfree(name);
        }
 
        return 0;
@@ -623,50 +639,34 @@ static int dlsym_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
 
 static int dlsym_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
-       struct tdata *tdata;
+       struct tdata *tdata = tdata_get(current);
 
-       tdata = tdata_get(current);
-       if (tdata) {
-               if (tdata->stat == NPS_SYM_E)
-                       tdata->stat = NPS_SYM_R;
-               tdata_put(tdata);
-       }
+       if (tdata->handle && tdata->stat == NPS_SYM_E)
+               tdata->stat = NPS_SYM_R;
 
        return 0;
 }
 
 static void stage_begin(enum nsp_proc_stat priv, enum nsp_proc_stat cur)
 {
-       struct tdata *tdata;
+       struct tdata *tdata = tdata_get(current);
 
-       tdata = tdata_get(current);
-       if (tdata) {
-               if (tdata->stat == priv) {
-                       tdata->stat = cur;
-                       tdata->time = swap_msg_current_time();
-               }
-
-               tdata_put(tdata);
+       if (tdata->handle && tdata->stat == priv) {
+               tdata->stat = cur;
+               tdata->time = swap_msg_current_time();
        }
 }
 
 static void stage_end(enum nsp_proc_stat priv, enum nsp_proc_stat cur,
                      enum nsp_msg_stage st)
 {
-       struct tdata *tdata;
+       struct tdata *tdata = tdata_get(current);
        u64 time_start;
        u64 time_end;
 
-       tdata = tdata_get(current);
-       if (tdata) {
-               if (tdata->stat != priv) {
-                       tdata_put(tdata);
-                       return;
-               }
-
+       if (tdata->handle && tdata->stat == priv) {
                tdata->stat = cur;
                time_start = tdata->time;
-               tdata_put(tdata);
 
                time_end = swap_msg_current_time();
                nsp_msg(st, time_start, time_end);
@@ -675,24 +675,16 @@ static void stage_end(enum nsp_proc_stat priv, enum nsp_proc_stat cur,
 
 static int main_h(struct uprobe *p, struct pt_regs *regs)
 {
-       struct tdata *tdata;
+       struct tdata *tdata = tdata_get(current);
        u64 time_start;
        u64 time_end;
 
-       tdata = tdata_get(current);
-       if (tdata) {
-               if (tdata->stat != NPS_SYM_R) {
-                       tdata_put(tdata);
-                       return 0;
-               }
-
+       if (tdata->handle && tdata->stat == NPS_SYM_R) {
                tdata->stat = NPS_MAIN_E;
                time_start = tdata->time;
                time_end = swap_msg_current_time();
                tdata->time = time_end;
 
-               tdata_put(tdata);
-
                nsp_msg(NMS_MAPPING, time_start, time_end);
        }
 
@@ -729,14 +721,12 @@ static int main_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
 
        if (rp && get_quiet() == QT_OFF) {
                struct us_ip *ip;
-               char ret_type;
                unsigned long func_addr;
                unsigned long ret_addr;
 
                ip = container_of(rp, struct us_ip, retprobe);
                func_addr = (unsigned long)ip->orig_addr;
                ret_addr = (unsigned long)ri->ret_addr;
-               ret_type = ip->desc->info.rp_i.ret_type;
                rp_msg_exit(regs, func_addr, 'n', ret_addr);
        }
 
@@ -784,7 +774,7 @@ static int do_app_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
 
 int nsp_init(void)
 {
-       return 0;
+       return swap_ktd_reg(&ktd);
 }
 
 void nsp_exit(void)
@@ -793,4 +783,5 @@ void nsp_exit(void)
                set_stat_off();
 
        uninit_variables();
+       swap_ktd_unreg(&ktd);
 }
index d97ec03..e40f8ee 100644 (file)
 #include <linux/module.h>
 #include <master/swap_initializer.h>
 #include "nsp.h"
-#include "nsp_tdata.h"
 #include "nsp_debugfs.h"
 
 
-SWAP_LIGHT_INIT_MODULE(tdata_once, nsp_init, nsp_exit,
+SWAP_LIGHT_INIT_MODULE(NULL, nsp_init, nsp_exit,
                       nsp_debugfs_init, nsp_debugfs_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/nsp/nsp_tdata.c b/nsp/nsp_tdata.c
deleted file mode 100644 (file)
index d8e6f4f..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) Samsung Electronics, 2015
- *
- * 2015         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
- *
- */
-
-
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <writer/swap_msg.h>
-#include <kprobe/swap_kprobes.h>
-#include <ksyms/ksyms.h>
-#include "nsp_tdata.h"
-#include "nsp_print.h"
-
-
-/* ============================================================================
- * =                                priv_tdata                                =
- * ============================================================================
- */
-struct priv_tdata {
-       struct list_head list;
-       struct task_struct *task;
-
-       struct tdata tdata;
-};
-
-
-static LIST_HEAD(task_list);
-static DEFINE_SPINLOCK(task_list_lock);
-
-
-/* called with task_list_lock held */
-static struct priv_tdata *priv_tdata_create(struct task_struct *task)
-{
-       struct priv_tdata *p_tdata;
-
-       p_tdata = kmalloc(sizeof(*p_tdata), GFP_ATOMIC);
-       if (p_tdata) {
-               INIT_LIST_HEAD(&p_tdata->list);
-               p_tdata->task = task;
-
-               /* add to list */
-               list_add(&p_tdata->list, &task_list);
-       }
-
-       return p_tdata;
-}
-
-/* called with task_list_lock held */
-static void priv_tdata_destroy(struct priv_tdata *p_tdata)
-{
-       /* delete from list */
-       list_del(&p_tdata->list);
-
-       kfree(p_tdata);
-}
-
-/* called with task_list_lock held */
-static void __priv_tdata_destroy(struct tdata *tdata)
-{
-       struct priv_tdata *p_tdata;
-
-       p_tdata = container_of(tdata, struct priv_tdata, tdata);
-       priv_tdata_destroy(p_tdata);
-}
-
-/* called with task_list_lock held */
-static void priv_tdata_destroy_all(void)
-{
-       struct priv_tdata *p_tdata, *n;
-
-       list_for_each_entry_safe(p_tdata, n, &task_list, list)
-               priv_tdata_destroy(p_tdata);
-}
-
-
-
-
-
-/* ============================================================================
- * =                                  tdata                                   =
- * ============================================================================
- */
-struct tdata *tdata_create(struct task_struct *task)
-{
-       struct priv_tdata *p_tdata;
-
-       spin_lock(&task_list_lock);
-       p_tdata = priv_tdata_create(task);
-       if (p_tdata)
-               return &p_tdata->tdata;
-       spin_unlock(&task_list_lock);
-
-       return NULL;
-
-}
-
-void tdata_destroy(struct tdata *tdata)
-{
-       __priv_tdata_destroy(tdata);
-       spin_unlock(&task_list_lock);
-}
-
-struct tdata *tdata_find(struct task_struct *task)
-{
-       struct priv_tdata *p_tdata;
-
-       list_for_each_entry(p_tdata, &task_list, list) {
-               if (p_tdata->task == task)
-                       return &p_tdata->tdata;
-       }
-
-       return NULL;
-}
-
-struct tdata *tdata_get(struct task_struct *task)
-{
-       struct tdata *tdata;
-
-       spin_lock(&task_list_lock);
-       tdata = tdata_find(task);
-       if (tdata)
-               return tdata;
-       spin_unlock(&task_list_lock);
-
-       return NULL;
-}
-
-void tdata_put(struct tdata *tdata)
-{
-       spin_unlock(&task_list_lock);
-}
-
-
-
-
-
-/* ============================================================================
- * =                                 do_exit                                  =
- * ============================================================================
- */
-static int do_exit_handler(struct kprobe *p, struct pt_regs *regs)
-{
-       struct tdata *tdata;
-
-       tdata = tdata_get(current);
-       if (tdata)
-               tdata_destroy(tdata);
-
-       return 0;
-}
-
-struct kprobe do_exit_kp = {
-       .pre_handler = do_exit_handler,
-};
-
-int tdata_enable(void)
-{
-       int ret;
-
-       ret = swap_register_kprobe(&do_exit_kp);
-       if (ret)
-               return ret;
-
-       return ret;
-}
-
-void tdata_disable(void)
-{
-       swap_unregister_kprobe(&do_exit_kp);
-
-       spin_lock(&task_list_lock);
-       priv_tdata_destroy_all();
-       spin_unlock(&task_list_lock);
-}
-
-int tdata_once(void)
-{
-       const char *sym;
-
-       sym = "do_exit";
-       do_exit_kp.addr = (void *)swap_ksyms(sym);
-       if (do_exit_kp.addr == NULL)
-               goto not_found;
-
-       return 0;
-
-not_found:
-       nsp_print("ERROR: symbol '%s' not found\n", sym);
-       return -ESRCH;
-}
diff --git a/nsp/nsp_tdata.h b/nsp/nsp_tdata.h
deleted file mode 100644 (file)
index 1eb0c7f..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright (C) Samsung Electronics, 2015
- *
- * 2015         Vyacheslav Cherkashin <v.cherkashin@samsung.com>
- *
- */
-
-#ifndef _NSP_TDATA_H
-#define _NSP_TDATA_H
-
-
-#include <linux/types.h>
-#include <us_manager/probes/probe_info_new.h>
-
-
-enum nsp_proc_stat {
-       NPS_OPEN_E,             /* mapping begin */
-       NPS_OPEN_R,
-       NPS_SYM_E,
-       NPS_SYM_R,              /* mapping end   */
-       NPS_MAIN_E,             /* main begin    */
-       NPS_AC_EFL_MAIN_E,      /* main end      */
-       NPS_AC_INIT_R,          /* create begin  */
-       NPS_ELM_RUN_E,          /* create end    */
-       NPS_DO_APP_E,           /* reset begin   */
-       NPS_DO_APP_R            /* reset end     */
-};
-
-
-struct nsp_data;
-struct task_struct;
-
-
-struct tdata {
-       enum nsp_proc_stat stat;
-       struct nsp_data *nsp_data;
-       u64 time;
-       void *handle;
-       struct probe_new p_main;
-};
-
-
-struct tdata *tdata_create(struct task_struct *task);
-void tdata_destroy(struct tdata *tdata);
-
-struct tdata *tdata_get(struct task_struct *task);
-void tdata_put(struct tdata *tdata);
-
-int tdata_enable(void);
-void tdata_disable(void);
-
-int tdata_once(void);
-
-
-#endif /* _NSP_TDATA_H */