From 1e2f3d59a1c33d4da1cb390ff4e0b33ffdb3139f Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Thu, 27 Jun 2013 17:15:37 +0400 Subject: [PATCH] [FEATURE] add message (protocol SWAP DA 6/26/2013) massages: MSG_PROCESS_INFO, MSG_ERROR, MSG_SAMPLE, MSG_FUNCTION_ENTRY, MSG_FUNCTION_EXIT, MSG_CONTEXT_SWITCH ENTRY, MSG_CONTEXT_SWITCH_EXIT --- driver/msg/swap_msg.c | 555 ++++++++++++++++++++++++++++++++++++++++++++++++ driver/msg/swap_msg.h | 38 ++++ us_manager/Kbuild | 2 +- us_manager/us_manager.c | 5 + 4 files changed, 599 insertions(+), 1 deletion(-) create mode 100644 driver/msg/swap_msg.c create mode 100644 driver/msg/swap_msg.h diff --git a/driver/msg/swap_msg.c b/driver/msg/swap_msg.c new file mode 100644 index 0000000..d43edff --- /dev/null +++ b/driver/msg/swap_msg.c @@ -0,0 +1,555 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "swap_msg.h" + +/* FIXME: "../.." */ +#include "../../buffer/swap_buffer_module.h" + +enum MSG_ID { + MSG_PROC_INFO = 0x2002, + MSG_ERROR = 0x2005, + MSG_SAMPLE = 0x2006, + MSG_FUNCTION_ENTRY = 0x2010, + MSG_FUNCTION_EXIT = 0x2011, + MSG_CONTEXT_SWITCH_ENTRY = 0x2012, + MSG_CONTEXT_SWITCH_EXIT = 0x2013 +}; + +static char *cpu_buf[NR_CPUS]; + +int init_msg(size_t buf_size) +{ + int i; + + for (i = 0; i < NR_CPUS; ++i) + cpu_buf[i] = kmalloc(buf_size, GFP_KERNEL); + + return 0; +} + +void uninit_msg(void) +{ + int i; + + for (i = 0; i < NR_CPUS; ++i) + kfree(cpu_buf[i]); +} + +static char *get_current_buf(void) +{ + return cpu_buf[task_cpu(current)]; +} + +static inline u64 timespec2time(struct timespec *ts) +{ + return ((u64)ts->tv_sec) << 32 | ts->tv_nsec; +} + + + + + +/* ============================================================================ + * = BASIC MESSAGE FORMAT = + * ============================================================================ + */ + +struct basic_msg_fmt { + u32 msg_id; + u32 seq_number; + u64 time; + u32 len; + char payload[0]; +} __attribute__((packed)); + +#if 0 /* debug */ +static void print_hex(char *ptr, int len) +{ + int i; + + printk("print_hex:\n"); + for (i = 0; i < len; ++i) { + printk("[%x] [%3d]=%2x\n", &ptr[i], i, ptr[i]); + } +} +#endif + +static void set_len_msg(char *buf, char *end) +{ + struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf; + bmf->len = end - buf - sizeof(*bmf); + + swap_buffer_write(bmf->len + sizeof(*bmf), buf); +} + +static char* pack_basic_msg_fmt(char *buf, enum MSG_ID id) +{ + struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf; + struct timespec ts; + + getnstimeofday(&ts); + + bmf->msg_id = id; + bmf->time = timespec2time(&ts); + + return bmf->payload; +} + + + + + +/* ============================================================================ + * = PROCESS INFO = + * ============================================================================ + */ + +struct proc_info { + u32 pid; + u64 start_time; + u64 low_addr; + u64 high_addr; + u32 app_type; + u32 bin_type; + char bin_path[0]; +} __attribute__((packed)); + +struct proc_info_part { + u32 lib_cnt; + char libs[0]; +} __attribute__((packed)); + +struct lib_obj { + u64 low_addr; + u64 high_addr; + char lib_path[0]; +} __attribute__((packed)); + +static char *pack_path(char *buf, struct file *file) +{ + enum { TMP_BUF_LEN = 512 }; + char tmp_buf[TMP_BUF_LEN]; + char NA[] = "N/A"; + char *filename; + size_t len; + + if (file == NULL) + return strcpy(buf, NA) + sizeof(NA); + + filename = d_path(&file->f_path, tmp_buf, TMP_BUF_LEN); + if (IS_ERR_OR_NULL(filename)) + return strcpy(buf, NA) + sizeof(NA); + + len = strlen(filename) + 1; + memcpy(buf, filename, len); + + return buf + len; +} + +static char *pack_lib_obj(char *lib_obj, struct vm_area_struct *vma) +{ + struct lib_obj *lo = (struct lib_obj *)lib_obj; + struct file *file; + + lo->low_addr = vma->vm_start; + lo->high_addr = vma->vm_end; + + return pack_path(lo->lib_path, vma->vm_file); +} + +/* FIXME: check_vma()*/ +#include "../../us_manager/sspt/sspt.h" +static char *pack_proc_info_part(char *bin_path, struct mm_struct *mm) +{ + struct proc_info_part *pip; + struct vm_area_struct *vma; + char *lib_obj, *end_path = NULL; + int lib_cnt = 0; + + end_path = pack_path(bin_path, mm->exe_file); + + pip = (struct proc_info_part *)end_path; + lib_obj = pip->libs; + + down_write(&mm->mmap_sem); + for (vma = mm->mmap; vma; vma = vma->vm_next) { + if (check_vma(vma)) { + lib_obj = pack_lib_obj(lib_obj, vma); + ++lib_cnt; + } + } + up_write(&mm->mmap_sem); + + pip->lib_cnt = lib_cnt; + return lib_obj; +} + +static char *pack_proc_info(char *payload, struct task_struct *task) +{ + struct proc_info *pi = (struct proc_info *)payload; + + pi->pid = task->tgid; + + /* FIXME: */ + pi->start_time = timespec2time(&task->start_time); + pi->low_addr = 2; + pi->high_addr = 3; + pi->app_type = 4; + pi->bin_type = 5; + + return pack_proc_info_part(pi->bin_path, task->mm); +} + +void proc_info_msg(struct task_struct *task) +{ + char *buf, *payload, *buf_end; + + buf = get_current_buf(); + payload = pack_basic_msg_fmt(buf, MSG_PROC_INFO); + buf_end = pack_proc_info(payload, task); + + set_len_msg(buf, buf_end); +} + + + + + +/* ============================================================================ + * = SAMPLE = + * ============================================================================ + */ + +struct sample { + u32 pid; + u32 tid; + u64 pc_addr; +} __attribute__((packed)); + +static char *pack_sample(char *payload, struct pt_regs *regs) +{ + struct sample *s = (struct sample *)payload; + struct task_struct *task = current; + + s->pid = task->tgid; + s->tid = task->pid; + s->pc_addr = regs->ARM_pc; + + return payload + sizeof(*s); +} + +void sample_msg(struct pt_regs *regs) +{ + char *buf, *payload, *buf_end; + + buf = get_current_buf(); + payload = pack_basic_msg_fmt(buf, MSG_SAMPLE); + buf_end = pack_sample(payload, regs); + + set_len_msg(buf, buf_end); +} + + + + + +/* ============================================================================ + * = ENTRY = + * ============================================================================ + */ + +struct msg_func_entry { + u64 pc_addr; + u64 caller_pc_addr; + u16 probe_type; + u16 probe_sub_type; + u32 pid; + u32 tid; + u32 cpu_num; + u32 cnt_args; + char args[0]; +} __attribute__((packed)); + +static char *pack_msg_func_entry(char *payload, const char *fmt, struct pt_regs *regs, + enum PROBE_TYPE pt, enum PROBE_SUB_TYPE pst) +{ + struct msg_func_entry *mfe = (struct msg_func_entry *)payload; + struct task_struct *task = current; + + mfe->pid = task->tgid; + mfe->tid = task->pid; + mfe->cpu_num = task_cpu(task); + mfe->pc_addr = regs->ARM_pc; + mfe->caller_pc_addr = regs->ARM_lr; + mfe->probe_type = pt; + mfe->probe_sub_type = pst; + mfe->cnt_args = strlen(fmt); + + return payload + sizeof(*mfe); +} + +static int get_args(unsigned long args[], int cnt, struct pt_regs *regs) +{ + int i, arg_in_regs; + + arg_in_regs = cnt < 3 ? cnt : 3; + switch (arg_in_regs) { + case 3: + args[3] = regs->ARM_r3; + case 2: + args[2] = regs->ARM_r2; + case 1: + args[1] = regs->ARM_r1; + case 0: + args[0] = regs->ARM_r0; + } + + /* FIXME: cnt > 4 */ + for (i = 4; i < cnt; ++i) { + args[i] = 0; + } + + return 0; +} + +static int pack_args(char *buf, int len, const char *fmt, struct pt_regs *regs) +{ + enum { args_cnt = 16 }; + char *buf_old = buf; + unsigned long arg, args[args_cnt]; + u32 *tmp_u32; + u64 *tmp_u64; + int i, cnt; + + cnt = strlen(fmt); + + /* FIXME: when the number of arguments is greater than args_cnt */ + cnt = cnt < args_cnt ? cnt : args_cnt; + get_args(args, cnt, regs); + + for (i = 0; i < cnt; ++i) { + if (len < 2) + return -ENOMEM; + + arg = args[i]; + *buf = fmt[i]; + buf += 1; + len -= 1; + + switch (fmt[i]) { + case 'c': /* 1 byte(char) */ + if (len < 1) + return -ENOMEM; + *buf = (char)arg; + buf += 1; + len -= 1; + break; + + case 'd': /* 4 byte(int) */ + if (len < 4) + return -ENOMEM; + tmp_u32 = buf; + *tmp_u32 = arg; + buf += 4; + len -= 4; + break; + + case 'x': /* 8 byte(long) */ + case 'p': /* 8 byte(pointer) */ + if (len < 8) + return -ENOMEM; + tmp_u64 = buf; + *tmp_u64 = (u64)arg; + buf += 8; + len -= 8; + break; +// case 'f': /* 4 byte(float) */ +// break; +// case 'w': /* 8 byte(double) */ +// break; + case 's': /* string end with '\0' */ + { + enum { max_str_len = 512 }; + const char __user *user_s; + int len_s, ret; + + user_s = (const char __user *)arg; + len_s = strnlen_user(user_s, max_str_len); + if (len < len_s) + return -ENOMEM; + + ret = strncpy_from_user(buf, user_s, len_s); + if (ret < 0) + return -EFAULT; + + buf += ret; + len -= ret; + } + break; + default: + return -EINVAL; + } + } + + return buf - buf_old; +} + +void entry_event(const char *fmt, struct pt_regs *regs, + enum PROBE_TYPE pt, enum PROBE_SUB_TYPE pst) +{ + char *buf, *payload, *args, *buf_end; + int ret; + + buf = get_current_buf(); + payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY); + args = pack_msg_func_entry(payload, fmt, regs, pt, pst); + + /* FIXME: len = 1024 */ + ret = pack_args(args, 1024, fmt, regs); + if (ret < 0) { + printk("ERROR: !!!!!\n"); + return; + } + + buf_end = args + ret; + + set_len_msg(buf, buf_end); +} + + + + + +/* ============================================================================ + * = EXIT = + * ============================================================================ + */ + +struct msg_func_exit { + u32 pid; + u32 tid; + u64 pc_addr; + u32 cpu_num; + u64 ret_val; +} __attribute__((packed)); + +static char *pack_msg_func_exit(char *payload, struct pt_regs *regs) +{ + struct msg_func_exit *mfe = (struct msg_func_exit *)payload; + struct task_struct *task = current; + + mfe->pid = task->tgid; + mfe->tid = task->pid; + mfe->cpu_num = task_cpu(task); + mfe->pc_addr = regs->ARM_pc; + mfe->ret_val = regs->ARM_r0; + + return payload + sizeof(*mfe); +} + +void exit_event(struct pt_regs *regs) +{ + char *buf, *payload, *buf_end; + + buf = get_current_buf(); + payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT); + buf_end = pack_msg_func_exit(payload, regs); + set_len_msg(buf, buf_end); +} + + + + + +/* ============================================================================ + * = CONTEXT SWITCH = + * ============================================================================ + */ + +struct msg_context_switch { + u64 pc_addr; + u32 pid; + u32 tid; + u32 cpu_num; +} __attribute__((packed)); + +static char *pack_msg_context_switch(char *payload, struct pt_regs *regs) +{ + struct msg_context_switch *mcs = (struct msg_context_switch *)payload; + struct task_struct *task = current; + + mcs->pc_addr = regs->ARM_pc; + mcs->pid = task->tgid; + mcs->tid = task->pid; + mcs->cpu_num = task_cpu(task); + + return payload + sizeof(*mcs); +} + +static void context_switch(struct pt_regs *regs, enum MSG_ID id) +{ + char *buf, *payload, *buf_end; + + buf = get_current_buf(); + payload = pack_basic_msg_fmt(buf, id); + buf_end = pack_msg_context_switch(payload, regs); + set_len_msg(buf, buf_end); +} + +void switch_entry(struct pt_regs *regs) +{ + context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY); +} + +void switch_exit(struct pt_regs *regs) +{ + context_switch(regs, MSG_CONTEXT_SWITCH_EXIT); +} + + + + + +/* ============================================================================ + * = ERROR = + * ============================================================================ + */ + +struct msg_err { + char msg[0]; +} __attribute__((packed)); + +static char *pack_msg_err(char *payload, const char *fmt, va_list args) +{ + struct msg_err *me = (struct msg_err *)payload; + int ret; + + ret = vsprintf(me->msg, fmt, args); + if (ret < 0) + return payload; + + return payload + sizeof(*me) + ret + 1; +} + +void error_msg(const char *fmt, ...) +{ + char *buf, *payload, *buf_end; + va_list args; + + buf = get_current_buf(); + payload = pack_basic_msg_fmt(buf, MSG_ERROR); + + va_start(args, fmt); + buf_end = pack_msg_err(payload, fmt, args); + va_end(args); + + set_len_msg(buf, buf_end); +} diff --git a/driver/msg/swap_msg.h b/driver/msg/swap_msg.h new file mode 100644 index 0000000..a8a427e --- /dev/null +++ b/driver/msg/swap_msg.h @@ -0,0 +1,38 @@ +#ifndef _SWAP_MSG_H +#define _SWAP_MSG_H + +#include + +enum PROBE_TYPE { + PT_US = 1, + PT_KS = 2 +}; + +enum PROBE_SUB_TYPE { + PST_NONE = 0, + PST_KS_FILE = 1, + PST_KS_IPC = 2, + PST_KS_PROCESS = 3, + PST_KS_SIGNAL = 4, + PST_KS_NETWORK = 5, + PST_KS_DESK = 6 +}; + +struct pt_regs; + +int init_msg(size_t buf_size); +void uninit_msg(void); + +void proc_info_msg(struct task_struct *task); +void sample_msg(struct pt_regs *regs); + +void entry_event(const char *fmt, struct pt_regs *regs, + enum PROBE_TYPE pt, enum PROBE_SUB_TYPE pst); +void exit_event(struct pt_regs *regs); + +void switch_entry(struct pt_regs *regs); +void switch_exit(struct pt_regs *regs); + +void error_msg(const char *fmt, ...); + +#endif /* _SWAP_MSG_H */ diff --git a/us_manager/Kbuild b/us_manager/Kbuild index b2addfc..9b7948c 100644 --- a/us_manager/Kbuild +++ b/us_manager/Kbuild @@ -5,4 +5,4 @@ swap_us_manager-y := us_manager.o us_slot_manager.o helper.o \ sspt/ip.o sspt/sspt_page.o sspt/sspt_file.o sspt/sspt_proc.o \ pf/proc_filters.o pf/pf_group.o \ img/img_proc.o img/img_file.o img/img_ip.o \ - ../driver/us_def_handler.o + ../driver/us_def_handler.o ../driver/msg/swap_msg.o diff --git a/us_manager/us_manager.c b/us_manager/us_manager.c index 526149e..9eead9e 100644 --- a/us_manager/us_manager.c +++ b/us_manager/us_manager.c @@ -5,6 +5,8 @@ #include #include "pf/proc_filters.h" +#include "../driver/msg/swap_msg.h" + struct proc_filter *pf; void (*ptr_pack_task_event_info)(struct task_struct *task, @@ -159,6 +161,8 @@ static int __init init_us_manager(void) { int ret; + init_msg(32*1024); + ret = init_helper(); if (ret) return ret; @@ -168,6 +172,7 @@ static int __init init_us_manager(void) static void __exit exit_us_manager(void) { + uninit_msg(); uninit_helper(); } -- 2.7.4