From e24f6b7ab49ecc3be53047c5333d3d8e4492d004 Mon Sep 17 00:00:00 2001 From: Anatolii Nikulin Date: Tue, 25 Oct 2016 15:59:07 +0300 Subject: [PATCH] Rework webprobe module Implement webprobe probes like probes in NSP module Change-Id: I467f1cb84be43ca21da257b4b601dbe382190ad5 Signed-off-by: Anatolii Nikulin --- webprobe/Kbuild | 1 - webprobe/webprobe.c | 275 ++++++++++++++++++++----------- webprobe/{webprobe_prof.h => webprobe.h} | 18 +- webprobe/webprobe_debugfs.c | 10 +- webprobe/webprobe_prof.c | 255 ---------------------------- 5 files changed, 186 insertions(+), 373 deletions(-) rename webprobe/{webprobe_prof.h => webprobe.h} (74%) delete mode 100644 webprobe/webprobe_prof.c diff --git a/webprobe/Kbuild b/webprobe/Kbuild index b6eef32..fd39693 100644 --- a/webprobe/Kbuild +++ b/webprobe/Kbuild @@ -3,5 +3,4 @@ EXTRA_CFLAGS := $(extra_cflags) obj-m := swap_webprobe.o swap_webprobe-y := webprobe.o \ webprobe_debugfs.o \ - webprobe_prof.o \ web_msg.o diff --git a/webprobe/webprobe.c b/webprobe/webprobe.c index e6d0231..c213184 100644 --- a/webprobe/webprobe.c +++ b/webprobe/webprobe.c @@ -26,150 +26,235 @@ * Web application profiling */ +#include +#include #include -#include -#include -#include +#include +#include #include #include -#include -#include #include +#include "webprobe.h" #include "webprobe_debugfs.h" -#include "webprobe_prof.h" #include "web_msg.h" -static unsigned long inspserver_addr_local; -static unsigned long tick_addr_local; +struct web_prof_data { + struct dentry *app_dentry; + struct dentry *lib_dentry; + struct pf_group *pfg; + u64 inspserver_addr; + u64 tick_addr; + bool enable; +}; -static int webprobe_copy(struct probe_info *dest, - const struct probe_info *source) +static DEFINE_MUTEX(web_mutex); +static const char *CHROMIUM_EWK = "/usr/lib/libchromium-ewk.so"; +static struct web_prof_data *web_data; + +/* function tick handler */ +static int tick_handler(struct uprobe *p, struct pt_regs *regs); +static struct probe_desc pin_tick_handler = MAKE_UPROBE(tick_handler); +static struct probe_new tick_probe = { + .desc = &pin_tick_handler +}; + +/* function inspector port */ +static int insport_rhandler(struct uretprobe_instance *ri, + struct pt_regs *regs); +static struct probe_desc pin_insport_rhandler = + MAKE_URPROBE(NULL, insport_rhandler, 0); +static struct probe_new insport_probe = { + .desc = &pin_insport_rhandler +}; + +static int insport_rhandler(struct uretprobe_instance *ri, + struct pt_regs *regs) { - memcpy(dest, source, sizeof(*source)); + set_wrt_launcher_port((int)regs_return_value(regs)); return 0; } -static void webprobe_cleanup(struct probe_info *probe_i) +static int tick_handler(struct uprobe *p, struct pt_regs *regs) { -} + web_sample_msg(regs); -static struct uprobe *webprobe_get_uprobe(struct sspt_ip *ip) -{ - return &ip->retprobe.up; + return 0; } -static int webprobe_register_probe(struct sspt_ip *ip) +u64 *web_prof_addr_ptr(enum web_prof_addr_t type) { - return swap_register_uretprobe(&ip->retprobe); -} + u64 *addr_ptr; -static void webprobe_unregister_probe(struct sspt_ip *ip, int disarm) -{ - if (ip->orig_addr == inspserver_addr_local) - web_func_inst_remove(INSPSERVER_START); - else if (ip->orig_addr == tick_addr_local) - web_func_inst_remove(TICK_PROBE); + mutex_lock(&web_mutex); + switch (type) { + case INSPSERVER_START: + addr_ptr = &web_data->inspserver_addr; + break; + case TICK_PROBE: + addr_ptr = &web_data->tick_addr; + break; + default: + pr_err("ERROR: WEB_PROF_ADDR_PTR_TYPE=0x%x\n", type); + addr_ptr = NULL; + } + mutex_unlock(&web_mutex); - __swap_unregister_uretprobe(&ip->retprobe, disarm); + return addr_ptr; } -static int web_entry_handler(struct uretprobe_instance *ri, - struct pt_regs *regs) +int web_prof_data_set(char *app_path, char *app_id) { - struct uretprobe *rp = ri->rp; - struct sspt_ip *ip; - unsigned long vaddr, page_vaddr; - struct vm_area_struct *vma; - - if (!rp) - return 0; - - ip = container_of(rp, struct sspt_ip, retprobe); - vaddr = (unsigned long)ip->orig_addr; - page_vaddr = vaddr & PAGE_MASK; - - vma = find_vma_intersection(current->mm, page_vaddr, page_vaddr + 1); - if (vma && check_vma(vma)) { - unsigned long addr = vaddr - vma->vm_start; - struct dentry *d = vma->vm_file->f_path.dentry; - - if (addr == web_prof_addr(TICK_PROBE) && - d == web_prof_lib_dentry()) { - tick_addr_local = ip->orig_addr; - web_sample_msg(regs); - } + int ret = 0; + + mutex_lock(&web_mutex); + web_data->app_dentry = dentry_by_path(app_path); + if (!web_data->app_dentry) { + ret = -EFAULT; + goto out; + } + + web_data->lib_dentry = dentry_by_path(CHROMIUM_EWK); + if (!web_data->lib_dentry) { + ret = -EFAULT; + goto out; + } + + if (web_data->pfg) + put_pf_group(web_data->pfg); + + web_data->pfg = get_pf_group_by_comm(app_id, web_data->app_dentry); + if (!web_data->pfg) { + ret = -EFAULT; + goto out; } +out: + mutex_unlock(&web_mutex); + return 0; } -static int web_ret_handler(struct uretprobe_instance *ri, struct pt_regs *regs) +bool web_prof_enabled(void) { - struct uretprobe *rp = ri->rp; - struct sspt_ip *ip; - unsigned long vaddr, page_vaddr; - struct vm_area_struct *vma; - - if (!rp) - return 0; - - ip = container_of(rp, struct sspt_ip, retprobe); - vaddr = (unsigned long)ip->orig_addr; - page_vaddr = vaddr & PAGE_MASK; - - vma = find_vma_intersection(current->mm, page_vaddr, page_vaddr + 1); - if (vma && check_vma(vma)) { - unsigned long addr = vaddr - vma->vm_start; - struct dentry *d = vma->vm_file->f_path.dentry; - - if (addr == web_prof_addr(INSPSERVER_START) && - d == web_prof_lib_dentry()) { - inspserver_addr_local = ip->orig_addr; - set_wrt_launcher_port((int)regs_return_value(regs)); - } - } + bool ret; - return 0; + mutex_lock(&web_mutex); + ret = web_data->enable; + mutex_unlock(&web_mutex); + + return ret; } -static void webprobe_init(struct sspt_ip *ip) +static void __web_prof_disable(struct web_prof_data *data) { - ip->retprobe.entry_handler = web_entry_handler; - ip->retprobe.handler = web_ret_handler; - ip->retprobe.maxactive = 0; + pin_unregister(&tick_probe, data->pfg, data->lib_dentry); + pin_unregister(&insport_probe, data->pfg, data->lib_dentry); } -static void webprobe_uninit(struct sspt_ip *ip) +static int __web_prof_enable(struct web_prof_data *data) { - webprobe_cleanup(&ip->desc->info); + int ret; + + tick_probe.offset = data->tick_addr; + ret = pin_register(&tick_probe, data->pfg, data->lib_dentry); + if (ret) + goto fail0; + + insport_probe.offset = data->inspserver_addr; + ret = pin_register(&insport_probe, data->pfg, data->lib_dentry); + if (ret) + goto fail1; + + return 0; + +fail1: + pin_unregister(&tick_probe, data->pfg, data->lib_dentry); +fail0: + return ret; } -static struct probe_iface webprobe_iface = { - .init = webprobe_init, - .uninit = webprobe_uninit, - .reg = webprobe_register_probe, - .unreg = webprobe_unregister_probe, - .get_uprobe = webprobe_get_uprobe, - .copy = webprobe_copy, - .cleanup = webprobe_cleanup -}; +int web_prof_enable(void) +{ + int ret = 0; -static int webprobe_module_init(void) + mutex_lock(&web_mutex); + if (web_data->enable) { + pr_err("ERROR: Web profiling is already enabled\n"); + ret = -EBUSY; + goto out; + } + + if (!web_data->inspserver_addr) { + pr_err("bad inspserver addr 0x%llx\n", + web_data->inspserver_addr); + goto out; + } + + if (!web_data->tick_addr) { + pr_err("bad tick addr 0x%llx\n", web_data->tick_addr); + goto out; + } + + ret = __web_prof_enable(web_data); + if (ret) { + pr_err("failed to enable Web profiling\n"); + goto out; + } + + web_data->enable = true; + +out: + mutex_unlock(&web_mutex); + + return ret; +} + +int web_prof_disable(void) { int ret = 0; - ret = swap_register_probe_type(SWAP_WEBPROBE, &webprobe_iface); - if (ret) - pr_err("Cannot register probe type SWAP_WEBPROBE\n"); + mutex_lock(&web_mutex); + if (!web_data->enable) { + pr_err("ERROR: Web profiling is already disabled\n"); + ret = -EBUSY; + goto out; + } + __web_prof_disable(web_data); + web_data->enable = false; + +out: + mutex_unlock(&web_mutex); return ret; } +static int webprobe_module_init(void) +{ + mutex_lock(&web_mutex); + web_data = kzalloc(sizeof(*web_data), GFP_KERNEL); + if (!web_data) + return -ENOMEM; + + web_data->enable = false; + mutex_unlock(&web_mutex); + + return 0; +} + static void webprobe_module_exit(void) { - swap_unregister_probe_type(SWAP_WEBPROBE); + mutex_lock(&web_mutex); + if (web_data->enable) + __web_prof_disable(web_data); + + if (web_data->pfg) + put_pf_group(web_data->pfg); + + kfree(web_data); + web_data = NULL; + mutex_unlock(&web_mutex); } SWAP_LIGHT_INIT_MODULE(NULL, webprobe_module_init, webprobe_module_exit, diff --git a/webprobe/webprobe_prof.h b/webprobe/webprobe.h similarity index 74% rename from webprobe/webprobe_prof.h rename to webprobe/webprobe.h index 99e8fda..003931e 100644 --- a/webprobe/webprobe_prof.h +++ b/webprobe/webprobe.h @@ -1,5 +1,5 @@ -#ifndef _WEBPROBE_PROF_H -#define _WEBPROBE_PROF_H +#ifndef _WEBPROBE_H +#define _WEBPROBE_H /** * @file webprobe/webprobe_prof.h @@ -31,20 +31,10 @@ enum web_prof_addr_t { TICK_PROBE }; -enum web_prof_state_t { - PROF_OFF, - PROF_ON -}; - -int web_prof_init(void); -void web_prof_exit(void); int web_prof_enable(void); int web_prof_disable(void); -enum web_prof_state_t web_prof_enabled(void); -int web_func_inst_remove(enum web_prof_addr_t type); +bool web_prof_enabled(void); u64 *web_prof_addr_ptr(enum web_prof_addr_t type); -unsigned long web_prof_addr(enum web_prof_addr_t type); int web_prof_data_set(char *app_path, char *app_id); -struct dentry *web_prof_lib_dentry(void); -#endif /* _WEBPROBE_PROF_H */ +#endif /* _WEBPROBE_H */ diff --git a/webprobe/webprobe_debugfs.c b/webprobe/webprobe_debugfs.c index f1331f7..a27263b 100644 --- a/webprobe/webprobe_debugfs.c +++ b/webprobe/webprobe_debugfs.c @@ -29,7 +29,7 @@ #include #include "webprobe_debugfs.h" -#include "webprobe_prof.h" +#include "webprobe.h" static const char ENABLED_FILE[] = "enabled"; static const char APP_INFO_FILE[] = "app_info"; @@ -49,7 +49,7 @@ static ssize_t read_enabled(struct file *file, char __user *user_buf, { char buf[2]; - buf[0] = web_prof_enabled() == PROF_ON ? '1' : '0'; + buf[0] = web_prof_enabled() ? '1' : '0'; buf[1] = '\n'; return simple_read_from_buffer(user_buf, count, ppos, buf, 2); @@ -167,10 +167,7 @@ static struct dentry *webprobe_dir; void webprobe_debugfs_exit(void) { - web_prof_exit(); - debugfs_remove_recursive(webprobe_dir); - webprobe_dir = NULL; } @@ -178,9 +175,6 @@ int webprobe_debugfs_init(void) { struct dentry *dentry; - if (web_prof_init()) - goto fail; - dentry = swap_debugfs_getdir(); if (!dentry) return -ENOENT; diff --git a/webprobe/webprobe_prof.c b/webprobe/webprobe_prof.c deleted file mode 100644 index 5c80d74..0000000 --- a/webprobe/webprobe_prof.c +++ /dev/null @@ -1,255 +0,0 @@ -/** - * webprobe/webprobe_prof.c - * - * 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, see . - * - * Copyright (C) Samsung Electronics, 2015 - * - * 2015 Anastasia Lyupa - * - */ - -#include -#include -#include - -#include -#include -#include - -#include "webprobe_prof.h" - -static DEFINE_MUTEX(mutex_enable); - -struct web_prof_data { - struct dentry *app_dentry; - struct dentry *lib_dentry; - struct pf_group *pfg; - u64 inspserver_addr; - struct probe_desc *inspserver; - u64 tick_addr; - struct probe_desc *tick_probe; - enum web_prof_state_t enabled; -}; - -static const char *CHROMIUM_EWK = "/usr/lib/libchromium-ewk.so"; -static struct web_prof_data *web_data; - -u64 *web_prof_addr_ptr(enum web_prof_addr_t type) -{ - u64 *addr_ptr; - - switch (type) { - case INSPSERVER_START: - addr_ptr = &web_data->inspserver_addr; - break; - case TICK_PROBE: - addr_ptr = &web_data->tick_addr; - break; - default: - pr_err("ERROR: WEB_PROF_ADDR_PTR_TYPE=0x%x\n", type); - addr_ptr = NULL; - } - - return addr_ptr; -} - -unsigned long web_prof_addr(enum web_prof_addr_t type) -{ - unsigned long addr; - - switch (type) { - case INSPSERVER_START: - addr = web_data->inspserver_addr; - break; - case TICK_PROBE: - addr = web_data->tick_addr; - break; - default: - pr_err("ERROR: WEB_PROF_ADDR_TYPE=0x%x\n", type); - addr = 0; - } - - return addr; -} - -static struct probe_desc *web_func_inst_add(unsigned long addr) -{ - int ret; - struct probe_desc *probe = NULL; - - probe = kmalloc(sizeof(*probe), GFP_KERNEL); - - if (!probe) - return NULL; - - memset(probe, 0, sizeof(*probe)); - probe->type = SWAP_WEBPROBE; - - ret = pf_register_probe(web_data->pfg, web_data->lib_dentry, - addr, probe); - - return probe; -} - -static int __web_func_inst_remove(unsigned long addr, struct probe_desc *pd) -{ - int ret; - - if (!addr || !pd) - return -EINVAL; - - /* FIXME: check that address needs removing */ - ret = pf_unregister_probe(web_data->pfg, web_data->lib_dentry, - addr, pd); - - return ret; -} - -int web_func_inst_remove(enum web_prof_addr_t type) -{ - unsigned long addr = 0; - struct probe_desc *pd = NULL; - - switch (type) { - case INSPSERVER_START: - addr = web_data->inspserver_addr; - pd = web_data->inspserver; - break; - case TICK_PROBE: - addr = web_data->tick_addr; - pd = web_data->tick_probe; - break; - default: - pr_err("ERROR: WEB_PROF_ADDR_TYPE=0x%x\n", type); - } - - return __web_func_inst_remove(addr, pd); -} - -int web_prof_data_set(char *app_path, char *app_id) -{ - web_data->app_dentry = dentry_by_path(app_path); - if (!web_data->app_dentry) - return -EFAULT; - - web_data->lib_dentry = dentry_by_path(CHROMIUM_EWK); - if (!web_data->lib_dentry) - return -EFAULT; - - if (web_data->pfg) - put_pf_group(web_data->pfg); - - web_data->pfg = get_pf_group_by_comm(app_id, web_data->app_dentry); - if (!web_data->pfg) - return -EFAULT; - - return 0; -} - -struct dentry *web_prof_lib_dentry(void) -{ - return web_data->lib_dentry; -} - -enum web_prof_state_t web_prof_enabled(void) -{ - return web_data->enabled; -} - -int web_prof_enable(void) -{ - int ret = 0; - - mutex_lock(&mutex_enable); - if (web_data->enabled != PROF_OFF) { - pr_err("ERROR: Web profiling is already enabled\n"); - goto out; - } - - web_data->enabled = PROF_ON; - - if (web_data->inspserver_addr) { - web_data->inspserver = - web_func_inst_add(web_data->inspserver_addr); - } - - if (web_data->tick_addr) { - web_data->tick_probe = - web_func_inst_add(web_data->tick_addr); - } - -out: - mutex_unlock(&mutex_enable); - - return ret; -} - -int web_prof_disable(void) -{ - int ret = 0; - - mutex_lock(&mutex_enable); - if (web_data->enabled != PROF_ON) { - pr_err("ERROR: Web profiling is already disabled\n"); - ret = -EBUSY; - goto out; - } - - web_data->enabled = PROF_OFF; - - if (web_data->inspserver_addr) { - if (!__web_func_inst_remove(web_data->inspserver_addr, - web_data->inspserver)) { - kfree(web_data->inspserver); - web_data->inspserver = NULL; - } - } - - if (web_data->tick_addr) { - if (!__web_func_inst_remove(web_data->tick_addr, - web_data->tick_probe)) { - kfree(web_data->tick_probe); - web_data->tick_probe = NULL; - } - } - -out: - mutex_unlock(&mutex_enable); - - return ret; -} - -int web_prof_init(void) -{ - web_data = kmalloc(sizeof(*web_data), GFP_KERNEL); - if (!web_data) - return -ENOMEM; - - memset(web_data, 0, sizeof(struct web_prof_data)); - - web_data->enabled = PROF_OFF; - - return 0; -} - -void web_prof_exit(void) -{ - if (web_data->pfg) - put_pf_group(web_data->pfg); - - kfree(web_data->inspserver); - kfree(web_data->tick_probe); - kfree(web_data); -} -- 2.7.4