From 948188db55a1b8b4008d81524c9dbb561c466e4a Mon Sep 17 00:00:00 2001 From: Vitaliy Cherepanov Date: Tue, 2 Dec 2014 17:40:59 +0300 Subject: [PATCH] [FEATURE] FBI multi probing Change-Id: I27186afb057ad97724225c93e6a1f596d2df6ff3 Signed-off-by: Vitaliy Cherepanov --- fbiprobe/fbiprobe.c | 87 ++++++++++++++++++++++++++++++++++++----------------- fbiprobe/fbiprobe.h | 10 ++++-- parser/msg_parser.c | 58 ++++++++++++++++++++++++++++------- 3 files changed, 115 insertions(+), 40 deletions(-) diff --git a/fbiprobe/fbiprobe.c b/fbiprobe/fbiprobe.c index d37e4c0..1eba7d8 100644 --- a/fbiprobe/fbiprobe.c +++ b/fbiprobe/fbiprobe.c @@ -60,7 +60,7 @@ #define MAX_STRING_LEN (512) /* you shoud free allocated data buffer */ -static char *fbi_probe_alloc_and_read_from_addr(const struct fbi_info *fbi_i, +static char *fbi_probe_alloc_and_read_from_addr(const struct fbi_var_data *fbi_i, unsigned long addr, uint32_t *size) { @@ -139,7 +139,7 @@ fail_exit: } -static int fbi_probe_get_data_from_reg(const struct fbi_info *fbi_i, +static int fbi_probe_get_data_from_reg(const struct fbi_var_data *fbi_i, struct pt_regs *regs) { unsigned long *reg_ptr; @@ -155,7 +155,7 @@ static int fbi_probe_get_data_from_reg(const struct fbi_info *fbi_i, return 0; } -static int fbi_probe_get_data_from_ptrs(const struct fbi_info *fbi_i, +static int fbi_probe_get_data_from_ptrs(const struct fbi_var_data *fbi_i, struct pt_regs *regs) { unsigned long *reg_ptr; @@ -200,7 +200,7 @@ exit: return vma; } -static int fbi_probe_get_data_from_direct_addr(const struct fbi_info *fbi_i, +static int fbi_probe_get_data_from_direct_addr(const struct fbi_var_data *fbi_i, struct us_ip *ip, struct pt_regs *regs) { @@ -239,6 +239,8 @@ static int fbi_probe_handler(struct kprobe *p, struct pt_regs *regs) struct uprobe *up = container_of(p, struct uprobe, kp); struct us_ip *ip = container_of(up, struct us_ip, uprobe); struct fbi_info *fbi_i = &ip->probe_i.fbi_i; + struct fbi_var_data *fbi_d = NULL; + uint8_t i; if (ip->probe_i.probe_type != SWAP_FBIPROBE) { /* How this can occure? Doesn't matter, just print and go */ @@ -246,12 +248,19 @@ static int fbi_probe_handler(struct kprobe *p, struct pt_regs *regs) return 0; } - if (fbi_i->reg_n == DIRECT_ADDR) - return fbi_probe_get_data_from_direct_addr(fbi_i, ip, regs); - else if (fbi_i->steps_count == 0) - return fbi_probe_get_data_from_reg(fbi_i, regs); - else - return fbi_probe_get_data_from_ptrs(fbi_i, regs); + for (i = 0; i != fbi_i->var_count; i++) { + fbi_d = &fbi_i->vars[i]; + if (fbi_d->reg_n == DIRECT_ADDR) { + if (0 != fbi_probe_get_data_from_direct_addr(fbi_d, ip, regs)) + print_err("fbi_probe_get_data_from_direct_addr error\n"); + } else if (fbi_d->steps_count == 0) { + if (0 != fbi_probe_get_data_from_reg(fbi_d, regs)) + print_err("fbi_probe_get_data_from_reg error\n"); + } else { + if (0 != fbi_probe_get_data_from_ptrs(fbi_d, regs)) + print_err("fbi_probe_get_data_from_ptrs error\n"); + } + } return 0; } @@ -259,12 +268,21 @@ static int fbi_probe_handler(struct kprobe *p, struct pt_regs *regs) /* FBI probe interfaces */ void fbi_probe_cleanup(struct probe_info *probe_i) { - struct fbi_step *steps; - steps = probe_i->fbi_i.steps; - if (steps != NULL) { - kfree(steps); - probe_i->fbi_i.steps = NULL; - probe_i->fbi_i.steps_count = 0; + uint8_t i; + struct fbi_info *fbi_i = &(probe_i->fbi_i); + + for (i = 0; i != fbi_i->var_count; i++) { + if (fbi_i->vars[i].steps != NULL) { + if (fbi_i->vars[i].steps != NULL) + kfree(fbi_i->vars[i].steps); + fbi_i->vars[i].steps = NULL; + fbi_i->vars[i].steps_count = 0; + } + } + + if (fbi_i->vars) { + kfree(fbi_i->vars); + fbi_i->vars = NULL; } } @@ -298,24 +316,39 @@ int fbi_probe_copy(struct probe_info *dest, const struct probe_info *source) { uint8_t steps_count; size_t steps_size; + size_t vars_size; + struct fbi_var_data *vars; struct fbi_step *steps_source; struct fbi_step *steps_dest = NULL; + uint8_t i; - steps_source = source->fbi_i.steps; - steps_count = source->fbi_i.steps_count; - steps_size = sizeof(*steps_source) * steps_count; memcpy(dest, source, sizeof(*source)); - if (steps_size != 0 && steps_source != NULL) { - steps_dest = kmalloc(steps_size, GFP_KERNEL); - if (steps_dest == NULL) { - print_err("can not alloc data\n"); - return -ENOMEM; - } - memcpy(steps_dest, steps_source, steps_size); + vars_size = source->fbi_i.var_count * sizeof(*source->fbi_i.vars); + vars = kmalloc(vars_size, GFP_KERNEL); + memcpy(vars, source->fbi_i.vars, vars_size); + + for (i = 0; i != source->fbi_i.var_count; i++) { + steps_dest = NULL; + steps_count = vars[i].steps_count; + steps_size = sizeof(*steps_source) * steps_count; + steps_source = vars[i].steps; + + if (steps_size != 0 && steps_source != NULL) { + steps_dest = kmalloc(steps_size, GFP_KERNEL); + if (steps_dest == NULL) { + print_err("can not alloc data\n"); + return -ENOMEM; + } + + memcpy(steps_dest, steps_source, steps_size); + } + vars[i].steps = steps_dest; } - dest->fbi_i.steps = steps_dest; + + dest->fbi_i.vars = vars; + return 0; } diff --git a/fbiprobe/fbiprobe.h b/fbiprobe/fbiprobe.h index fbd8359..125995d 100644 --- a/fbiprobe/fbiprobe.h +++ b/fbiprobe/fbiprobe.h @@ -47,8 +47,8 @@ struct fbi_step { uint64_t data_offset; } __packed; -/* FBI info */ -struct fbi_info { +/* FBI var data */ +struct fbi_var_data { /* Variable position is evaluated by the following rule: * var_position = *(pointer_to_register) - reg_offset * It is expected that the offset is not null only when we're taking @@ -65,4 +65,10 @@ struct fbi_info { struct fbi_step *steps; /* extract steps */ }; +/* FBI info */ +struct fbi_info { + uint8_t var_count; + struct fbi_var_data *vars; +}; + #endif /* __FBI_PROBE_H__ */ diff --git a/parser/msg_parser.c b/parser/msg_parser.c index 4f0108f..4c327ba 100644 --- a/parser/msg_parser.c +++ b/parser/msg_parser.c @@ -432,7 +432,7 @@ void put_get_call_type_probe(struct probe_info *pi) * @param pi Pointer to the probe_info struct. * @return 0 on success, error code on error. */ -int get_fbi_probe(struct msg_buf *mb, struct probe_info *pi) +int get_fbi_data(struct msg_buf *mb, struct fbi_var_data *vd) { u64 var_id; u64 reg_offset; @@ -472,10 +472,12 @@ int get_fbi_probe(struct msg_buf *mb, struct probe_info *pi) } if (steps_count > 0) { - steps = kmalloc(steps_count * sizeof(pi->fbi_i.steps[0]), + steps = kmalloc(steps_count * sizeof(*vd->steps), GFP_KERNEL); - if (steps == NULL) + if (steps == NULL) { + print_err("MALLOC FAIL\n"); return -ENOMEM; + } for (i = 0; i != steps_count; i++) { print_parse_debug("steps #%d ptr_order:", i); @@ -493,14 +495,12 @@ int get_fbi_probe(struct msg_buf *mb, struct probe_info *pi) } } - pi->probe_type = SWAP_FBIPROBE; - pi->fbi_i.reg_n = reg_n; - pi->fbi_i.reg_offset = reg_offset; - pi->fbi_i.data_size = data_size; - pi->fbi_i.var_id = var_id; - pi->fbi_i.steps_count = steps_count; - pi->fbi_i.steps = steps; - pi->size = 0; + vd->reg_n = reg_n; + vd->reg_offset = reg_offset; + vd->data_size = data_size; + vd->var_id = var_id; + vd->steps_count = steps_count; + vd->steps = steps; return 0; @@ -509,6 +509,42 @@ free_steps: return -EINVAL; } +int get_fbi_probe(struct msg_buf *mb, struct probe_info *pi) +{ + uint8_t var_count, i; + struct fbi_var_data *vars; + + print_parse_debug("var count:"); + if (get_u8(mb, &var_count)) { + print_err("failed to read var ID\n"); + return -EINVAL; + } + + vars = kmalloc(var_count * sizeof(*vars), GFP_KERNEL); + if (vars == NULL) { + print_err("alloc vars error\n"); + goto err; + } + + for (i = 0; i != var_count; i++) { + if (get_fbi_data(mb, &vars[i]) != 0) + goto free_vars; + } + + pi->probe_type = SWAP_FBIPROBE; + pi->fbi_i.var_count = var_count; + pi->fbi_i.vars = vars; + pi->size =0 ; + return 0; + +free_vars: + kfree(vars); + +err: + return -EINVAL; + +} + /** * @brief FBI probe data cleanup. * -- 2.7.4