2 * @file fbiprobe/fbi_probe.c
4 * @author Alexander Aksenov <a.aksenov@samsung.com>
5 * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * Copyright (C) Samsung Electronics, 2014
27 * 2014 Alexander Aksenov : FBI implement
28 * 2014 Vitaliy Cherepanov: FBI implement, portage
30 * @section DESCRIPTION
32 * Function body instrumetation
37 #include "fbi_probe_module.h"
41 #include <us_manager/us_manager.h>
42 #include <us_manager/probes/probes.h>
43 #include <us_manager/probes/register_probes.h>
45 #include <uprobe/swap_uprobes.h>
46 #include <us_manager/sspt/ip.h>
48 #include <kprobe/swap_kprobes_deps.h>
49 #include <linux/module.h>
52 #include <linux/sched.h>
53 #include <linux/dcache.h>
54 #include <linux/mm_types.h>
56 #include <us_manager/sspt/sspt_page.h>
57 #include <us_manager/sspt/sspt_file.h>
59 #define DIRECT_ADDR (0xFF)
60 #define MAX_STRING_LEN (512)
62 /* on fails. return NULL, set size to 0 */
63 /* you shoud free allocated data buffer */
64 static char *fbi_probe_alloc_and_read_from_addr(const struct fbi_var_data *fbid,
70 struct fbi_step *step;
74 /* get final variable address */
76 for (i = 0; i != fbid->steps_count; i++) {
78 for (j = 0; j != step->ptr_order; j++) {
79 unsigned long new_addr;
80 /* equel to: addr = *addr */
81 if (!read_proc_vm_atomic(current, addr, &new_addr,
83 print_warn("p = 0x%lx step #%d ptr_order #%d\n",
88 print_debug("dereference addr = 0x%lx;\n", addr);
92 addr += step->data_offset;
93 print_debug("addr + offset = 0x%lx;\n", addr);
97 /* calculate data size */
98 if (fbid->data_size == 0) {
100 * that mean variable is string and
101 * we need to calculate string length
104 *size = strnlen_user((const char __user *)addr, MAX_STRING_LEN);
106 print_warn("Cannot get string from 0x%lx\n", addr);
110 /* else use size from fbi struct */
111 *size = fbid->data_size;
114 buf = kmalloc(*size, GFP_KERNEL);
116 print_warn("Not enough memory\n");
117 goto exit_fail_size_0;
120 if (!read_proc_vm_atomic(current, addr, buf, *size)) {
121 print_warn("Error reading data at 0x%lx, task %d\n",
123 goto exit_fail_free_buf;
126 if (fbid->data_size == 0) {
128 * that mean variable is string and
129 * we need to add terminate '\0'
131 buf[*size - 1] = '\0';
146 static int fbi_probe_get_data_from_reg(const struct fbi_var_data *fbi_i,
147 struct pt_regs *regs)
149 unsigned long *reg_ptr;
151 reg_ptr = get_ptr_by_num(regs, fbi_i->reg_n);
152 if (reg_ptr == NULL) {
153 print_err("fbi_probe_get_data_from_reg: Wrong register number!\n");
157 fbi_msg(fbi_i->var_id, fbi_i->data_size, (char *)reg_ptr);
162 static int fbi_probe_get_data_from_ptrs(const struct fbi_var_data *fbi_i,
163 struct pt_regs *regs)
165 unsigned long *reg_ptr;
170 reg_ptr = get_ptr_by_num(regs, fbi_i->reg_n);
171 if (reg_ptr == NULL) {
172 print_err("fbi_probe_get_data_from_ptrs: Wrong register number!\n");
176 addr = *reg_ptr + fbi_i->reg_offset;
177 print_warn("reg = %p; off = 0x%llx; addr = 0x%lx!\n", reg_ptr,
178 fbi_i->reg_offset, addr);
180 buf = fbi_probe_alloc_and_read_from_addr(fbi_i, addr, &size);
183 /* If buf is NULL size will be 0.
184 * That mean we cannot get data for this probe.
185 * But we should send probe message with packed data size 0
188 fbi_msg(fbi_i->var_id, size, buf);
193 print_err("cannot get data from ptrs\n");
198 static struct vm_area_struct *find_vma_exe_by_dentry(struct mm_struct *mm,
199 struct dentry *dentry)
201 struct vm_area_struct *vma;
203 /* FIXME: down_write(&mm->mmap_sem); up_write(&mm->mmap_sem); */
204 /* TODO FILTER vma */
205 for (vma = mm->mmap; vma; vma = vma->vm_next) {
207 (vma->vm_file->f_dentry == dentry))
218 static int fbi_probe_get_data_from_direct_addr(const struct fbi_var_data *fbi_i,
220 struct pt_regs *regs)
222 struct vm_area_struct *vma;
227 /* register offset is global address */
228 vma = find_vma_exe_by_dentry(current->mm, ip->page->file->dentry);
230 print_warn("cannot locate dentry\n");
234 addr = vma->vm_start + fbi_i->reg_offset;
236 print_debug("DIRECT_ADDR reg_offset = %llx\n", fbi_i->reg_offset);
237 print_debug("DIRECT_ADDR vm_start = %lx\n", vma->vm_start);
238 print_debug("DIRECT_ADDR res_addr = %lx\n", addr);
240 buf = fbi_probe_alloc_and_read_from_addr(fbi_i, addr, &size);
241 /* If buf is NULL size will be 0.
242 * That mean we cannot get data for this probe.
243 * But we should send probe message with packed data size 0
246 fbi_msg(fbi_i->var_id, size, buf);
251 print_warn("get data by direct addr failed (0x%lx :0x%llx)\n",
252 addr, fbi_i->reg_offset);
258 static int fbi_probe_handler(struct kprobe *p, struct pt_regs *regs)
260 struct uprobe *up = container_of(p, struct uprobe, kp);
261 struct us_ip *ip = container_of(up, struct us_ip, uprobe);
262 struct fbi_info *fbi_i = &ip->info->fbi_i;
263 struct fbi_var_data *fbi_d = NULL;
266 if (ip->info->probe_type != SWAP_FBIPROBE) {
267 /* How this can occure? Doesn't matter, just print and go */
268 print_err("Not FBI probe in FBI handler!\n");
272 for (i = 0; i != fbi_i->var_count; i++) {
273 fbi_d = &fbi_i->vars[i];
274 if (fbi_d->reg_n == DIRECT_ADDR) {
275 if (0 != fbi_probe_get_data_from_direct_addr(fbi_d, ip,
277 print_err("fbi_probe_get_data_from_direct_addr error\n");
278 } else if (fbi_d->steps_count == 0) {
279 if (0 != fbi_probe_get_data_from_reg(fbi_d, regs))
280 print_err("fbi_probe_get_data_from_reg error\n");
282 if (0 != fbi_probe_get_data_from_ptrs(fbi_d, regs))
283 print_err("fbi_probe_get_data_from_ptrs error\n");
290 /* FBI probe interfaces */
291 void fbi_probe_cleanup(struct probe_info *probe_i)
294 struct fbi_info *fbi_i = &(probe_i->fbi_i);
296 for (i = 0; i != fbi_i->var_count; i++) {
297 if (fbi_i->vars[i].steps != NULL) {
298 if (fbi_i->vars[i].steps != NULL)
299 kfree(fbi_i->vars[i].steps);
300 fbi_i->vars[i].steps = NULL;
301 fbi_i->vars[i].steps_count = 0;
309 void fbi_probe_init(struct us_ip *ip)
311 ip->uprobe.kp.pre_handler = (kprobe_pre_handler_t)fbi_probe_handler;
314 void fbi_probe_uninit(struct us_ip *ip)
317 fbi_probe_cleanup(ip->info);
320 static int fbi_probe_register_probe(struct us_ip *ip)
322 return swap_register_uprobe(&ip->uprobe);
325 static void fbi_probe_unregister_probe(struct us_ip *ip, int disarm)
327 __swap_unregister_uprobe(&ip->uprobe, disarm);
330 static struct uprobe *fbi_probe_get_uprobe(struct us_ip *ip)
335 int fbi_probe_copy(struct probe_info *dest, const struct probe_info *source)
340 struct fbi_var_data *vars;
341 struct fbi_step *steps_source;
342 struct fbi_step *steps_dest = NULL;
346 memcpy(dest, source, sizeof(*source));
348 vars_size = source->fbi_i.var_count * sizeof(*source->fbi_i.vars);
349 vars = kmalloc(vars_size, GFP_KERNEL);
353 memcpy(vars, source->fbi_i.vars, vars_size);
355 for (i = 0; i != source->fbi_i.var_count; i++) {
357 steps_count = vars[i].steps_count;
358 steps_size = sizeof(*steps_source) * steps_count;
359 steps_source = vars[i].steps;
361 if (steps_size != 0 && steps_source != NULL) {
362 steps_dest = kmalloc(steps_size, GFP_KERNEL);
363 if (steps_dest == NULL) {
364 print_err("can not alloc data\n");
370 memcpy(steps_dest, steps_source, steps_size);
372 vars[i].steps = steps_dest;
375 dest->fbi_i.vars = vars;
379 for (i = 0; i < n; i++)
380 kfree(vars[i].steps);
386 static struct probe_iface fbi_probe_iface = {
387 .init = fbi_probe_init,
388 .uninit = fbi_probe_uninit,
389 .reg = fbi_probe_register_probe,
390 .unreg = fbi_probe_unregister_probe,
391 .get_uprobe = fbi_probe_get_uprobe,
392 .copy = fbi_probe_copy,
393 .cleanup = fbi_probe_cleanup
396 static int __init fbiprobe_module_init(void)
399 ret = swap_register_probe_type(SWAP_FBIPROBE, &fbi_probe_iface);
400 print_debug("Init done. Result=%d\n", ret);
404 static void __exit fbiprobe_module_exit(void)
406 swap_unregister_probe_type(SWAP_FBIPROBE);
409 module_init(fbiprobe_module_init);
410 module_exit(fbiprobe_module_exit);
412 MODULE_LICENSE("GPL");
413 MODULE_DESCRIPTION("SWAP fbiprobe");
414 MODULE_AUTHOR("Alexander Aksenov <a.aksenov@samsung.com>; Vitaliy Cherepanov <v.cherepanov@samsung.com>");