From 27f1310b9b48ac47fe464679560b21a00f5917b3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Wed, 10 Jun 2015 15:09:51 +0300 Subject: [PATCH] [FEATURE] native setup profiling implement Change-Id: I1b3cf9934d3e93aae8c03cff4a61073ec159b2d4 Signed-off-by: Vyacheslav Cherkashin --- Kbuild | 3 +- nsp/Kbuild | 9 + nsp/nsp.c | 754 ++++++++++++++++++++++++++++++++++++++++++++ nsp/nsp.h | 53 ++++ nsp/nsp_debugfs.c | 407 ++++++++++++++++++++++++ nsp/nsp_debugfs.h | 30 ++ nsp/nsp_module.c | 33 ++ nsp/nsp_msg.c | 51 +++ nsp/nsp_msg.h | 40 +++ nsp/nsp_print.h | 34 ++ nsp/nsp_tdata.c | 207 ++++++++++++ nsp/nsp_tdata.h | 64 ++++ packaging/swap-modules.spec | 2 + uprobe/swap_uaccess.h | 48 +++ writer/swap_msg.c | 5 +- writer/swap_msg.h | 8 + wsp/wsp.c | 32 +- 17 files changed, 1752 insertions(+), 28 deletions(-) create mode 100644 nsp/Kbuild create mode 100644 nsp/nsp.c create mode 100644 nsp/nsp.h create mode 100644 nsp/nsp_debugfs.c create mode 100644 nsp/nsp_debugfs.h create mode 100644 nsp/nsp_module.c create mode 100644 nsp/nsp_msg.c create mode 100644 nsp/nsp_msg.h create mode 100644 nsp/nsp_print.h create mode 100644 nsp/nsp_tdata.c create mode 100644 nsp/nsp_tdata.h create mode 100644 uprobe/swap_uaccess.h diff --git a/Kbuild b/Kbuild index 66a3c89..7c07db7 100644 --- a/Kbuild +++ b/Kbuild @@ -18,4 +18,5 @@ obj-m := master/ \ task_data/ \ preload/ \ fbiprobe/ \ - wsp/ + wsp/ \ + nsp/ diff --git a/nsp/Kbuild b/nsp/Kbuild new file mode 100644 index 0000000..85c8b90 --- /dev/null +++ b/nsp/Kbuild @@ -0,0 +1,9 @@ +EXTRA_CFLAGS := $(extra_cflags) + +obj-m := swap_nsp.o +swap_nsp-y := \ + nsp_module.o \ + nsp.o \ + nsp_msg.o \ + nsp_tdata.o \ + nsp_debugfs.o diff --git a/nsp/nsp.c b/nsp/nsp.c new file mode 100644 index 0000000..baa8160 --- /dev/null +++ b/nsp/nsp.c @@ -0,0 +1,754 @@ +/* + * 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 + * + */ + + +#include +#include +#include +#include +#include +#include +#include "nsp.h" +#include "nsp_msg.h" +#include "nsp_tdata.h" +#include "nsp_print.h" +#include "nsp_debugfs.h" + + +/* ============================================================================ + * = probes = + * ============================================================================ + */ + +/* dlopen@plt */ +static int dlopen_eh(struct uretprobe_instance *ri, struct pt_regs *regs); +static int dlopen_rh(struct uretprobe_instance *ri, struct pt_regs *regs); +static struct probe_info_new pin_dlopen = MAKE_URPROBE(dlopen_eh, dlopen_rh, 0); +struct probe_new p_dlopen = { + .info = &pin_dlopen +}; + +/* dlsym@plt */ +static int dlsym_eh(struct uretprobe_instance *ri, struct pt_regs *regs); +static int dlsym_rh(struct uretprobe_instance *ri, struct pt_regs *regs); +static struct probe_info_new pin_dlsym = MAKE_URPROBE(dlsym_eh, dlsym_rh, 0); +struct probe_new p_dlsym = { + .info = &pin_dlsym +}; + +/* main */ +static int main_h(struct kprobe *p, struct pt_regs *regs); +static struct probe_info_new pin_main = MAKE_UPROBE(main_h); +static struct probe_info_otg pin_main_otg = { + .data = &pin_main +}; + +/* appcore */ +static int appcore_efl_main_h(struct kprobe *p, struct pt_regs *regs); +static struct probe_info_new pin_appcore = MAKE_UPROBE(appcore_efl_main_h); +struct probe_new p_appcore = { + .info = &pin_appcore +}; + +/* create */ +static int create_eh(struct uretprobe_instance *ri, struct pt_regs *regs); +static int create_rh(struct uretprobe_instance *ri, struct pt_regs *regs); +static struct probe_info_new pin_create = MAKE_URPROBE(create_eh, create_rh, 0); +static struct probe_info_otg pin_create_otg = { + .data = &pin_create +}; + +/* reset */ +static int reset_eh(struct uretprobe_instance *ri, struct pt_regs *regs); +static int reset_rh(struct uretprobe_instance *ri, struct pt_regs *regs); +static struct probe_info_new pin_reset = MAKE_URPROBE(reset_eh, reset_rh, 0); +static struct probe_info_otg pin_reset_otg = { + .data = &pin_reset +}; + + + + + +/* ============================================================================ + * = the variables are initialized by the user = + * ============================================================================ + */ +static const char *lpad_path; +static struct dentry *lpad_dentry; + +static const char *libappcore_path; +static struct dentry *libappcore_dentry; + +static struct { + unsigned long create; + unsigned long reset; + unsigned flag_create:1; + unsigned flag_reset:1; +} cb_offset = {0}; + +static bool is_init(void) +{ + return lpad_dentry && libappcore_dentry && + cb_offset.flag_create && cb_offset.flag_reset; +} + +static int do_set_offset(enum offset_t os, unsigned long offset) +{ + switch (os) { + case OS_CREATE: + cb_offset.create = offset; + cb_offset.flag_create = 1; + return 0; + case OS_RESET: + cb_offset.reset = offset; + cb_offset.flag_reset = 1; + return 0; + default: + return -EINVAL; + } + + return -EINVAL; +} + +static int do_set_lpad_info(const char *path, unsigned long dlopen, + unsigned long dlsym) +{ + struct dentry *dentry; + const char *new_path; + + dentry = dentry_by_path(path); + if (dentry == NULL) { + pr_err("dentry not found (path='%s')\n", path); + return -EINVAL; + } + + new_path = kstrdup(path, GFP_KERNEL); + if (new_path == NULL) { + pr_err("out of memory\n"); + return -ENOMEM; + } + + kfree(lpad_path); + + lpad_path = new_path; + lpad_dentry = dentry; + p_dlopen.offset = dlopen; + p_dlsym.offset = dlsym; + + return 0; +} + +static int do_set_appcore_info(const char *path, + unsigned long appcore_efl_main) +{ + struct dentry *dentry; + const char *new_path; + + dentry = dentry_by_path(path); + if (dentry == NULL) { + pr_err("dentry not found (path='%s')\n", path); + return -EINVAL; + } + + new_path = kstrdup(path, GFP_KERNEL); + if (new_path == NULL) { + pr_err("out of memory\n"); + return -ENOMEM; + } + + kfree(libappcore_path); + + libappcore_path = new_path; + libappcore_dentry = dentry; + p_appcore.offset = appcore_efl_main; + + return 0; +} + + + + + +/* ============================================================================ + * = nsp_data = + * ============================================================================ + */ +struct nsp_data { + struct list_head list; + + const char *app_path; + struct dentry *app_dentry; + + struct pf_group *pfg; +}; + +static LIST_HEAD(nsp_data_list); + +static struct nsp_data *nsp_data_create(const char *app_path) +{ + struct dentry *dentry; + struct nsp_data *data; + + dentry = dentry_by_path(app_path); + if (dentry == NULL) + return ERR_PTR(-ENOENT); + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return ERR_PTR(-ENOMEM); + + data->app_path = kstrdup(app_path, GFP_KERNEL); + if (data->app_dentry == NULL) { + kfree(data); + return ERR_PTR(-ENOMEM); + } + + data->app_dentry = dentry; + data->pfg = NULL; + + return data; +} + +static void nsp_data_destroy(struct nsp_data *data) +{ + kfree(data->app_path); + kfree(data); +} + +static struct nsp_data *nsp_data_find(const struct dentry *dentry) +{ + struct nsp_data *data; + + list_for_each_entry(data, &nsp_data_list, list) { + if (data->app_dentry == dentry) + return data; + } + + return NULL; +} + +static struct nsp_data *nsp_data_find_by_path(const char *path) +{ + struct nsp_data *data; + + list_for_each_entry(data, &nsp_data_list, list) { + if (strcmp(data->app_path, path) == 0) + return data; + } + + return NULL; +} + +static void nsp_data_add(struct nsp_data *data) +{ + list_add(&data->list, &nsp_data_list); +} + +static void nsp_data_rm(struct nsp_data *data) +{ + list_del(&data->list); +} + +static int nsp_data_inst(struct nsp_data *data) +{ + int ret; + struct pf_group *pfg; + + pfg = get_pf_group_by_dentry(lpad_dentry, (void *)data->app_dentry); + if (pfg == NULL) + return -ENOMEM; + + ret = pin_register(&p_dlsym, pfg, lpad_dentry); + if (ret) + goto put_g; + + ret = pin_register(&p_dlopen, pfg, lpad_dentry); + if (ret) + goto ur_dlsym; + + ret = pin_register(&p_appcore, pfg, libappcore_dentry); + if (ret) + goto ur_dlopen; + + data->pfg = pfg; + + return 0; +ur_dlopen: + pin_unregister(&p_dlopen, pfg, lpad_dentry); +ur_dlsym: + pin_unregister(&p_dlsym, pfg, lpad_dentry); +put_g: + put_pf_group(pfg); + return ret; +} + +static void nsp_data_uninst(struct nsp_data *data) +{ + pin_unregister(&p_appcore, data->pfg, libappcore_dentry); + pin_unregister(&p_dlopen, data->pfg, lpad_dentry); + pin_unregister(&p_dlsym, data->pfg, lpad_dentry); + put_pf_group(data->pfg); + data->pfg = NULL; +} + +static int __nsp_add(const char *app_path) +{ + struct nsp_data *data; + + if (nsp_data_find_by_path(app_path)) + return -EEXIST; + + data = nsp_data_create(app_path); + if (IS_ERR(data)) + return PTR_ERR(data); + + nsp_data_add(data); + + return 0; +} + +static int __nsp_rm(const char *path) +{ + struct dentry *dentry; + struct nsp_data *data; + + dentry = dentry_by_path(path); + if (dentry == NULL) + return -ENOENT; + + data = nsp_data_find(dentry); + if (data == NULL) + return -ESRCH; + + nsp_data_rm(data); + nsp_data_destroy(data); + + return 0; +} + +static int __nsp_rm_all(void) +{ + struct nsp_data *data, *n; + + list_for_each_entry_safe(data, n, &nsp_data_list, list) { + nsp_data_rm(data); + nsp_data_destroy(data); + } + + return 0; +} + +static void __nsp_disabel(void) +{ + struct nsp_data *data; + + list_for_each_entry(data, &nsp_data_list, list) { + if (data->pfg) + nsp_data_uninst(data); + } +} + +static int __nsp_enable(void) +{ + int ret; + struct nsp_data *data; + + list_for_each_entry(data, &nsp_data_list, list) { + ret = nsp_data_inst(data); + if (ret) + goto fail; + } + + return 0; + +fail: + __nsp_disabel(); + return ret; +} + + + + + + + +/* ============================================================================ + * = set parameters = + * ============================================================================ + */ +#define F_ARG1(m, t, a) m(t, a) +#define F_ARG2(m, t, a, ...) m(t, a), F_ARG1(m, __VA_ARGS__) +#define F_ARG3(m, t, a, ...) m(t, a), F_ARG2(m, __VA_ARGS__) +#define F_ARG(n, m, ...) F_ARG##n(m, __VA_ARGS__) + +#define M_TYPE_AND_ARG(t, a) t a +#define M_ARG(t, a) a + +#define DECLARE_SAFE_FUNC(n, func_name, do_func, ...) \ +int func_name(F_ARG(n, M_TYPE_AND_ARG, __VA_ARGS__)) \ +{ \ + int ret; \ + mutex_lock(&stat_mutex); \ + if (stat == NS_ON) { \ + ret = -EBUSY; \ + goto unlock; \ + } \ + ret = do_func(F_ARG(n, M_ARG, __VA_ARGS__)); \ +unlock: \ + mutex_unlock(&stat_mutex); \ + return ret; \ +} + +#define DECLARE_SAFE_FUNC0(name, _do) DECLARE_SAFE_FUNC(1, name, _do, void, /* */); +#define DECLARE_SAFE_FUNC1(name, _do, ...) DECLARE_SAFE_FUNC(1, name, _do, __VA_ARGS__); +#define DECLARE_SAFE_FUNC2(name, _do, ...) DECLARE_SAFE_FUNC(2, name, _do, __VA_ARGS__); +#define DECLARE_SAFE_FUNC3(name, _do, ...) DECLARE_SAFE_FUNC(3, name, _do, __VA_ARGS__); + + +static DEFINE_MUTEX(stat_mutex); +static enum nsp_stat stat = NS_OFF; + +DECLARE_SAFE_FUNC1(nsp_add, __nsp_add, const char *, app_path); +DECLARE_SAFE_FUNC1(nsp_rm, __nsp_rm, const char *, app_path); +DECLARE_SAFE_FUNC0(nsp_rm_all, __nsp_rm_all); +DECLARE_SAFE_FUNC2(nsp_set_offset, do_set_offset, + enum offset_t, os, unsigned long, offset); +DECLARE_SAFE_FUNC3(nsp_set_lpad_info, do_set_lpad_info, + const char *, path, unsigned long, dlopen, + unsigned long, dlsym); +DECLARE_SAFE_FUNC2(nsp_set_appcore_info, do_set_appcore_info, + const char *, path, unsigned long, appcore_efl_main); + + + + + +/* ============================================================================ + * = set stat = + * ============================================================================ + */ +static int set_stat_off(void) +{ + if (stat == NS_OFF) + return -EINVAL; + + __nsp_disabel(); + tdata_disable(); + + stat = NS_OFF; + + return 0; +} + +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; + + return 0; +} + +int nsp_set_stat(enum nsp_stat st) +{ + int ret = -EINVAL; + + mutex_lock(&stat_mutex); + switch (st) { + case NS_OFF: + ret = set_stat_off(); + break; + case NS_ON: + ret = set_stat_on(); + break; + } + mutex_unlock(&stat_mutex); + + return ret; +} + +enum nsp_stat nsp_get_stat(void) +{ + return stat; +} + + + + + +/* ============================================================================ + * = handlers = + * ============================================================================ + */ +static int main_h(struct kprobe *p, struct pt_regs *regs) +{ + struct tdata *tdata; + + tdata = tdata_get(current); + if (tdata) { + u64 time = swap_msg_current_time(); + u64 exec_time = tdata->time; + + tdata->time = time; + tdata_put(tdata); + + nsp_msg(NMS_MAPPING, exec_time, time); + } else { + nsp_print("can't find mapping begin time\n"); + } + + return 0; +} + +static int appcore_efl_main_h(struct kprobe *p, struct pt_regs *regs) +{ + unsigned long *ptr; + unsigned long appcore_ops_addr; + unsigned long create_vaddr; + unsigned long reset_vaddr; + struct tdata *tdata; + u64 main_time; + u64 time; + + tdata = tdata_get(current); + if (tdata == NULL) { + nsp_print("can't find 'main' begin time\n"); + return 0; + } + + /* sent time spent in main() */ + main_time = tdata->time; + tdata_put(tdata); + time = swap_msg_current_time(); + nsp_msg(NMS_MAIN, main_time, time); + + + /* pointer to appcore_ops struct */ + appcore_ops_addr = swap_get_uarg(regs, 3); + + /* get address create callback */ + ptr = (unsigned long *)(appcore_ops_addr + cb_offset.create); + if (get_user(create_vaddr, ptr)) { + nsp_print("failed to dereference a pointer, ptr=%p\n", ptr); + return 0; + } + + /* get address reset callback */ + ptr = (unsigned long *)(appcore_ops_addr + cb_offset.reset); + if (get_user(reset_vaddr, ptr)) { + nsp_print("failed to dereference a pointer, ptr=%p\n", ptr); + return 0; + } + + pin_set_probe(&pin_create_otg, create_vaddr); + pin_set_probe(&pin_reset_otg, reset_vaddr); + + return 0; +} + +static int dlopen_eh(struct uretprobe_instance *ri, struct pt_regs *regs) +{ + const char __user *user_s = (const char __user *)swap_get_uarg(regs, 0); + const char *path; + struct nsp_data *nsp_data; + + path = strdup_from_user(user_s, GFP_ATOMIC); + if (path == NULL) + return 0; + + 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; + } + + tdata = tdata_create(task); + if (tdata) { + 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; + + 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); + } + } + + return 0; +} + +static int dlsym_eh(struct uretprobe_instance *ri, struct pt_regs *regs) +{ + struct tdata *tdata; + + tdata = tdata_get(current); + if (tdata) { + const char __user *str = (char __user *)swap_get_uarg(regs, 1); + 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; + + kfree(name); + } + + tdata_put(tdata); + } + + return 0; +} + +static int dlsym_rh(struct uretprobe_instance *ri, struct pt_regs *regs) +{ + struct tdata *tdata; + + tdata = tdata_get(current); + if (tdata) { + if (tdata->stat == NPS_SYM_E) { + unsigned long main_vaddr = regs_return_value(regs); + + tdata->stat = NPS_SYM_R; + pin_set_probe(&pin_main_otg, main_vaddr); + } + + tdata_put(tdata); + } + + return 0; +} + +static void do_eh(const char *name) +{ + struct tdata *tdata; + + tdata = tdata_get(current); + if (tdata) { + tdata->time = swap_msg_current_time(); + tdata_put(tdata); + } else { + nsp_print("can't find tdata for '%s'\n", name); + } +} + +static void do_rh(const char *name, enum nsp_msg_stage st) +{ + struct tdata *tdata; + + tdata = tdata_get(current); + if (tdata) { + u64 b_time = tdata->time; + u64 e_time; + tdata_put(tdata); + + e_time = swap_msg_current_time(); + nsp_msg(st, b_time, e_time); + } else { + nsp_print("can't find tdata for '%s'\n", name); + } +} + +static char create_name[] = "create"; +static int create_eh(struct uretprobe_instance *ri, struct pt_regs *regs) +{ + do_eh(create_name); + + return 0; +} + +static int create_rh(struct uretprobe_instance *ri, struct pt_regs *regs) +{ + do_rh(create_name, NMS_CREATE); + + return 0; +} + +static char reset_name[] = "reset"; +static int reset_eh(struct uretprobe_instance *ri, struct pt_regs *regs) +{ + do_eh(reset_name); + return 0; +} + +static int reset_rh(struct uretprobe_instance *ri, struct pt_regs *regs) +{ + do_rh(reset_name, NMS_RESET); + return 0; +} + + + + + +int nsp_init(void) +{ + return 0; +} + +void nsp_exit(void) +{ + if (stat == NS_ON) + set_stat_off(); +} diff --git a/nsp/nsp.h b/nsp/nsp.h new file mode 100644 index 0000000..4f8c50e --- /dev/null +++ b/nsp/nsp.h @@ -0,0 +1,53 @@ +#ifndef _NSP_H +#define _NSP_H + +/* + * 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 + * + */ + + +enum offset_t { + OS_CREATE, + OS_RESET +}; + +enum nsp_stat { + NS_OFF, + NS_ON +}; + + +int nsp_init(void); +void nsp_exit(void); + +int nsp_set_offset(enum offset_t os, unsigned long offset); +int nsp_set_lpad_info(const char *path, unsigned long dlopen, + unsigned long dlsym); +int nsp_set_appcore_info(const char *path, unsigned long appcore_efl_main); + +int nsp_set_stat(enum nsp_stat st); +enum nsp_stat nsp_get_stat(void); + +int nsp_add(const char *app_path); +int nsp_rm(const char *app_path); +int nsp_rm_all(void); + + +#endif /* _NSP_H */ diff --git a/nsp/nsp_debugfs.c b/nsp/nsp_debugfs.c new file mode 100644 index 0000000..3be7894 --- /dev/null +++ b/nsp/nsp_debugfs.c @@ -0,0 +1,407 @@ +/* + * 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, 2014 + * + * 2014 Vyacheslav Cherkashin + * + */ + + +#include +#include +#include +#include +#include +#include "nsp.h" + + +/* remove end-line symbols */ +static void rm_endline_symbols(char *buf, size_t len) +{ + char *p, *buf_end; + + buf_end = buf + len; + for (p = buf; p != buf_end; ++p) + if (*p == '\n' || *p == '\r') + *p = '\0'; +} + +/* + * format: + * app_path + * + * sample: + * /bin/app_sample + */ +static int do_add(const char *buf, size_t len) +{ + int n, ret; + char *app_path; + const char fmt[] = "/%%%ds"; + char fmt_buf[64]; + + n = snprintf(fmt_buf, sizeof(fmt_buf), fmt, PATH_MAX - 2); + if (n <= 0) + return -EINVAL; + + app_path = kmalloc(PATH_MAX, GFP_KERNEL); + if (app_path == NULL) + return -ENOMEM; + + n = sscanf(buf, fmt_buf, app_path + 1); + if (n != 1) { + ret = -EINVAL; + goto free_app_path; + } + app_path[0] = '/'; + + ret = nsp_add(app_path); + +free_app_path: + kfree(app_path); + return ret; +} + +/* + * format: + * path + * + * sample: + * /tmp/sample + */ +static int do_rm(const char *buf, size_t len) +{ + return nsp_rm(buf); +} + +static int do_rm_all(const char *buf, size_t len) +{ + return nsp_rm_all(); +} + +static int set_param(const char *param, unsigned long val) +{ + if (strcmp(param, "offset_create") == 0) { + return nsp_set_offset(OS_CREATE, val); + } else if (strcmp(param, "offset_reset") == 0) { + return nsp_set_offset(OS_RESET, val); + } + + return -EINVAL; +} + +/* + * format: + * param val + * + * sample: + * offset_create 4 + */ +static int do_set(const char *buf, size_t len_data) +{ + unsigned long val; + char *param; + int n, ret; + + param = kmalloc(len_data, GFP_KERNEL); + if (param == NULL) + return -ENOMEM; + + n = sscanf(buf, "%s %lu", param, &val); + if (n != 2) { + ret = -EINVAL; + goto par_free; + } + + ret = set_param(param, val); + +par_free: + kfree(param); + return ret; +} + +/* + * format: + * dlopen_addr@plt:dlsym_addr@plt:launchpad_path + * + * sample: + * 0x000234:0x000342:/usr/bin/launchpad-loader + */ +static int do_set_lpad_info(const char *data, size_t len) +{ + int n, ret; + unsigned long dlopen_addr; + unsigned long dlsym_addr; + char *lpad_path; + const char fmt[] = "%%lx:%%lx:/%%%ds"; + char fmt_buf[64]; + + n = snprintf(fmt_buf, sizeof(fmt_buf), fmt, PATH_MAX - 2); + if (n <= 0) + return -EINVAL; + + lpad_path = kmalloc(PATH_MAX, GFP_KERNEL); + if (lpad_path == NULL) + return -ENOMEM; + + n = sscanf(data, fmt_buf, &dlopen_addr, &dlsym_addr, lpad_path + 1); + if (n != 3) { + ret = -EINVAL; + goto free_lpad_path; + } + lpad_path[0] = '/'; + + ret = nsp_set_lpad_info(lpad_path, dlopen_addr, dlsym_addr); + +free_lpad_path: + kfree(lpad_path); + return ret; +} + +/* + * format: + * appcore_efl_main:libappcore-efl_path + * + * sample: + * 0x00342e:/usr/lib/libappcore-efl.so.1 + */ +static int do_set_appcore_info(const char *data, size_t len) +{ + int n, ret; + unsigned long appcore_main_addr; + char *lib_path; + const char fmt[] = "%%lx:/%%%ds"; + char fmt_buf[64]; + + n = snprintf(fmt_buf, sizeof(fmt_buf), fmt, PATH_MAX - 2); + if (n <= 0) + return -EINVAL; + + lib_path = kmalloc(PATH_MAX, GFP_KERNEL); + if (lib_path == NULL) + return -ENOMEM; + + n = sscanf(data, fmt_buf, &appcore_main_addr, lib_path + 1); + if (n != 2) { + ret = -EINVAL; + goto free_lib_path; + } + lib_path[0] = '/'; + + ret = nsp_set_appcore_info(lib_path, appcore_main_addr); + +free_lib_path: + kfree(lib_path); + return ret; +} + +/* + * format: + * 0 byte - type + * 1 byte - ' ' + * 2.. bytes - data + */ +static int do_cmd(const char *data, size_t len) +{ + char type; + size_t len_data; + const char *cmd_data; + + if (len) { + if (data[0] == 'c') + return do_rm_all(data + 1, len - 1); + } + /* + * 0 byte - type + * 1 byte - ' ' + */ + if (len < 2 || data[1] != ' ') + return -EINVAL; + + len_data = len - 2; + cmd_data = data + 2; + type = data[0]; + switch (type) { + case 'a': + return do_add(cmd_data, len_data); + case 'b': + return do_set_lpad_info(cmd_data, len_data); + case 'l': + return do_set_appcore_info(cmd_data, len_data); + case 'r': + return do_rm(cmd_data, len_data); + case 's': + return do_set(cmd_data, len_data); + default: + return -EINVAL; + } + + return 0; +} + + + + +/* ============================================================================ + * === DEBUGFS FOR CMD === + * ============================================================================ + */ +static ssize_t write_cmd(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + char *buf; + ssize_t ret = count; + + buf = kmalloc(count + 1, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + if (copy_from_user(buf, user_buf, count)) { + ret = -EFAULT; + goto free_buf; + } + + buf[count] = '\0'; + rm_endline_symbols(buf, count); + + if (do_cmd(buf, count)) + ret = -EINVAL; + +free_buf: + kfree(buf); + + return ret; +} + +static ssize_t read_cmd(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + const char help[] = + "use:\n" + "\ta $app_path - add\n" + "\tr $app_path - remove\n" + "\tc - remove all\n" + "\tb $dlopen_addr@plt:$dlsym_addr@plt:$launchpad_path\n" + "\tl $appcore_efl_main:$libappcore-efl_path\n" + "\ts $param $val - set parameter"; + ssize_t ret; + + ret = simple_read_from_buffer(user_buf, count, ppos, + help, sizeof(help)); + + return ret; +} + +static const struct file_operations fops_cmd = { + .read = read_cmd, + .write = write_cmd, + .llseek = default_llseek +}; + + + + +/* ============================================================================ + * === DEBUGFS FOR ENABLE === + * ============================================================================ + */ +static ssize_t read_enabled(struct file *file, char /*__user*/ *user_buf, + size_t count, loff_t *ppos) +{ + char buf[2]; + + buf[0] = nsp_get_stat() == NS_OFF ? '0' : '1'; + buf[1] = '\n'; + + return simple_read_from_buffer(user_buf, count, ppos, buf, 2); +} + +static ssize_t write_enabled(struct file *file, const char /*__user*/ *user_buf, + size_t count, loff_t *ppos) +{ + int ret = 0; + char buf[32]; + size_t buf_size; + + buf_size = min(count, (sizeof(buf) - 1)); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + + buf[buf_size] = '\0'; + switch (buf[0]) { + case '1': + ret = nsp_set_stat(NS_ON); + break; + case '0': + ret = nsp_set_stat(NS_OFF); + break; + default: + return -EINVAL; + } + + if (ret) + return ret; + + return count; +} + +static const struct file_operations fops_enabled = { + .read = read_enabled, + .write = write_enabled, + .llseek = default_llseek, +}; + + + + +static struct dentry *nsp_dir = NULL; + +void nsp_debugfs_exit(void) +{ + if (nsp_dir) + debugfs_remove_recursive(nsp_dir); + + nsp_dir = NULL; +} + +int nsp_debugfs_init(void) +{ + struct dentry *dentry; + + dentry = swap_debugfs_getdir(); + if (dentry == NULL) + return -ENOENT; + + nsp_dir = debugfs_create_dir("nsp", dentry); + if (nsp_dir == NULL) + return -ENOMEM; + + dentry = debugfs_create_file("cmd", 0600, nsp_dir, NULL, + &fops_cmd); + if (dentry == NULL) + goto fail; + + dentry = debugfs_create_file("enabled", 0600, nsp_dir, NULL, + &fops_enabled); + if (dentry == NULL) + goto fail; + + return 0; + +fail: + nsp_debugfs_exit(); + return -ENOMEM; +} diff --git a/nsp/nsp_debugfs.h b/nsp/nsp_debugfs.h new file mode 100644 index 0000000..62565b7 --- /dev/null +++ b/nsp/nsp_debugfs.h @@ -0,0 +1,30 @@ +#ifndef _NSP_DEBUGFS_H +#define _NSP_DEBUGFS_H + +/* + * 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 + * + */ + + +int nsp_debugfs_init(void); +void nsp_debugfs_exit(void); + + +#endif /* _NSP_DEBUGFS_H */ diff --git a/nsp/nsp_module.c b/nsp/nsp_module.c new file mode 100644 index 0000000..d97ec03 --- /dev/null +++ b/nsp/nsp_module.c @@ -0,0 +1,33 @@ +/* + * 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 + * + */ + + +#include +#include +#include "nsp.h" +#include "nsp_tdata.h" +#include "nsp_debugfs.h" + + +SWAP_LIGHT_INIT_MODULE(tdata_once, nsp_init, nsp_exit, + nsp_debugfs_init, nsp_debugfs_exit); + +MODULE_LICENSE("GPL"); diff --git a/nsp/nsp_msg.c b/nsp/nsp_msg.c new file mode 100644 index 0000000..b48c3a1 --- /dev/null +++ b/nsp/nsp_msg.c @@ -0,0 +1,51 @@ +/* + * 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 + * + */ + + +#include +#include +#include "nsp_msg.h" + + +struct nsp_msg_struct { + u32 pid; + u32 stage; + u64 begin_time; + u64 end_time; +} __packed; + + +void nsp_msg(enum nsp_msg_stage stage, u64 begin_time, u64 end_time) +{ + struct swap_msg *m; + struct nsp_msg_struct *nsp; + + m = swap_msg_get(MSG_NSP); + + nsp = (struct nsp_msg_struct *)swap_msg_payload(m); + nsp->pid = (u32)current->tgid; + nsp->stage = (u32)stage; + nsp->begin_time = begin_time; + nsp->end_time = end_time; + + swap_msg_flush(m, sizeof(*nsp)); + swap_msg_put(m); +} diff --git a/nsp/nsp_msg.h b/nsp/nsp_msg.h new file mode 100644 index 0000000..17d50ba --- /dev/null +++ b/nsp/nsp_msg.h @@ -0,0 +1,40 @@ +/* + * 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 + * + */ + +#ifndef _NSP_MSG_H +#define _NSP_MSG_H + + +#include + + +enum nsp_msg_stage { + NMS_MAPPING = 0x00, + NMS_MAIN = 0x01, + NMS_CREATE = 0x02, + NMS_RESET = 0x03, +}; + + +void nsp_msg(enum nsp_msg_stage stage, u64 begin_time, u64 end_time); + + +#endif /* _NSP_MSG_H */ diff --git a/nsp/nsp_print.h b/nsp/nsp_print.h new file mode 100644 index 0000000..d4d68d4 --- /dev/null +++ b/nsp/nsp_print.h @@ -0,0 +1,34 @@ +/* + * 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 + * + */ + +#ifndef _NSP_PRINT_H +#define _NSP_PRINT_H + + +#include + + +#define NSP_PREFIX "[NSP] " + +#define nsp_print(...) printk(NSP_PREFIX __VA_ARGS__) + + +#endif /* _NSP_PRINT_H */ diff --git a/nsp/nsp_tdata.c b/nsp/nsp_tdata.c new file mode 100644 index 0000000..a1d7eb3 --- /dev/null +++ b/nsp/nsp_tdata.c @@ -0,0 +1,207 @@ +/* + * 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 + * + */ + + +#include +#include +#include +#include +#include +#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 new file mode 100644 index 0000000..ee229ad --- /dev/null +++ b/nsp/nsp_tdata.h @@ -0,0 +1,64 @@ +/* + * 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 + * + */ + +#ifndef _NSP_TDATA_H +#define _NSP_TDATA_H + + +#include +#include + + +enum nsp_proc_stat { + NPS_ERR, + NPS_OPEN_E, + NPS_OPEN_R, + NPS_SYM_E, + NPS_SYM_R +}; + + +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 */ diff --git a/packaging/swap-modules.spec b/packaging/swap-modules.spec index 0f9f7f9..de8c370 100755 --- a/packaging/swap-modules.spec +++ b/packaging/swap-modules.spec @@ -49,6 +49,7 @@ install -m 666 task_data/swap_task_data.ko -t %{buildroot}/opt/swap/sdk install -m 666 preload/swap_preload.ko -t %{buildroot}/opt/swap/sdk install -m 666 fbiprobe/swap_fbiprobe.ko -t %{buildroot}/opt/swap/sdk install -m 666 wsp/swap_wsp.ko -t %{buildroot}/opt/swap/sdk +install -m 666 nsp/swap_nsp.ko -t %{buildroot}/opt/swap/sdk %files %defattr(-,root,root) @@ -71,3 +72,4 @@ install -m 666 wsp/swap_wsp.ko -t %{buildroot}/opt/swap/sdk /opt/swap/sdk/swap_preload.ko /opt/swap/sdk/swap_fbiprobe.ko /opt/swap/sdk/swap_wsp.ko +/opt/swap/sdk/swap_nsp.ko diff --git a/uprobe/swap_uaccess.h b/uprobe/swap_uaccess.h new file mode 100644 index 0000000..7a9215e --- /dev/null +++ b/uprobe/swap_uaccess.h @@ -0,0 +1,48 @@ +/* + * 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 + * + */ + + +#include +#include +#include + + +static const char *strdup_from_user(const char __user *user_s, gfp_t gfp) +{ + enum { max_str_len = 1024 }; + char *str; + int len_s, ret; + + len_s = strnlen_user(user_s, max_str_len - 1); + str = kmalloc(len_s + 1, gfp); + if (str == NULL) + return NULL; + + ret = copy_from_user(str, user_s, len_s); + if (ret < 0) { + kfree(str); + return NULL; + } + + str[len_s] = '\0'; + + return str; +} diff --git a/writer/swap_msg.c b/writer/swap_msg.c index 90a3d53..85a7c60 100644 --- a/writer/swap_msg.c +++ b/writer/swap_msg.c @@ -107,16 +107,13 @@ u64 swap_msg_timespec2time(struct timespec *ts) struct swap_msg *swap_msg_get(enum swap_msg_id id) { - struct timespec ts; struct swap_msg *m; - getnstimeofday(&ts); - m = (struct swap_msg *)cpu_buf[get_cpu()]; m->msg_id = (u32)id; m->seq_num = atomic_inc_return(&seq_num); - m->time = swap_msg_spec2time(&ts); + m->time = swap_msg_current_time(); return m; } diff --git a/writer/swap_msg.h b/writer/swap_msg.h index 24f2c6f..afa6dbd 100644 --- a/writer/swap_msg.h +++ b/writer/swap_msg.h @@ -47,6 +47,7 @@ enum swap_msg_id { MSG_PROC_COMM = 0x0014, MSG_WEB_FUNCTION_ENTRY = 0x0015, MSG_WEB_FUNCTION_EXIT = 0x0016, + MSG_NSP = 0x0019, MSG_WSP = 0x001a, MSG_FBI = 0x0020 }; @@ -66,6 +67,13 @@ static inline u64 swap_msg_spec2time(struct timespec *ts) return ((u64)ts->tv_nsec) << 32 | ts->tv_sec; } +static inline u64 swap_msg_current_time(void) +{ + struct timespec ts; + getnstimeofday(&ts); + return swap_msg_spec2time(&ts); +} + struct swap_msg *swap_msg_get(enum swap_msg_id id); int swap_msg_flush(struct swap_msg *m, size_t size); void swap_msg_put(struct swap_msg *m); diff --git a/wsp/wsp.c b/wsp/wsp.c index 908e303..f25723f 100644 --- a/wsp/wsp.c +++ b/wsp/wsp.c @@ -20,6 +20,7 @@ */ +#include #include #include #include "wsp.h" @@ -51,28 +52,6 @@ static const char ewebkit_path[] = "/usr/lib/libewebkit2.so"; } -static const char *strdup_from_user(const char __user *user_s) -{ - enum { max_str_len = 1024 }; - char *str; - int len_s, ret; - - len_s = strnlen_user(user_s, max_str_len - 1); - str = kmalloc(len_s + 1, GFP_ATOMIC); - if (str == NULL) - return NULL; - - ret = strncpy_from_user(str, user_s, len_s); - if (ret < 0) { - kfree(str); - return NULL; - } - - str[ret] = '\0'; - - return str; -} - static void do_res_processing_begin(void *data, void *ptr, enum wsp_res_t type) { struct wsp_res **save_res = (struct wsp_res **)data; @@ -107,6 +86,7 @@ static void do_res_finish(struct wsp_res *res) static int soup_req_handle(struct kprobe *p, struct pt_regs *regs) { enum { max_str_len = 512 }; + const char __user *user_s; const char *path; struct wsp_res *res; @@ -116,7 +96,13 @@ static int soup_req_handle(struct kprobe *p, struct pt_regs *regs) return 0; } - path = strdup_from_user((const char __user *)swap_get_uarg(regs, 1)); + user_s = (const char __user *)swap_get_uarg(regs, 1); + path = strdup_from_user(user_s, GFP_ATOMIC); + if (path == NULL) { + pr_warn("soup_req_handle: invalid path\n"); + return 0; + } + wsp_msg(WSP_RES_LOAD_BEGIN, res->id, path); wsp_res_stat_set_next(res, WRS_SOUP_REQ); kfree(path); -- 2.7.4