diff --git a/source/module/monitor_kernel_lib.c b/source/module/monitor_kernel_lib.c index e15e1e9..f203f5c 100644 --- a/source/module/monitor_kernel_lib.c +++ b/source/module/monitor_kernel_lib.c @@ -55,12 +55,14 @@ static int init_buffer(unsigned int buf_size) { return ret; } -void diag_tsk(struct task_struct *p, variable_monitor_task *tsk_info,unsigned long *flags) { +void diag_tsk(struct task_struct *p, variable_monitor_task *tsk_info, + unsigned long *flags) { unsigned int nr_bt; printk(KERN_INFO "diag_tsk\n"); - diag_task_brief(p, &tsk_info->task); // task brief + diag_task_brief(p, &tsk_info->task); // task brief // printk("1\n"); diag_task_user_stack(p, &tsk_info->user_stack); // user stack + diag_task_raw_stack(p, &tsk_info->raw_stack); // raw stack // printk("2\n"); nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack // int i = 0; diff --git a/source/module/monitor_trace.c b/source/module/monitor_trace.c index e79b612..20024d2 100644 --- a/source/module/monitor_trace.c +++ b/source/module/monitor_trace.c @@ -2,10 +2,10 @@ #include #include -#include // for syscall_get_nr +#include // for syscall_get_nr #include #include -#include // for get_task_mm +#include // for get_task_mm #include #include @@ -32,7 +32,8 @@ struct stack_frame_user { }; static inline int diag_get_task_type(struct task_struct *tsk) { - if (orig_get_task_type) return orig_get_task_type(&tsk->se); + if (orig_get_task_type) + return orig_get_task_type(&tsk->se); return 0; } @@ -47,7 +48,8 @@ static inline int orig_diag_cgroup_name(struct cgroup *cgrp, char *buf, static inline mm_info *find_mm_info(mm_tree *mm_tree, struct mm_struct *mm) { mm_info *info; - if (mm == NULL) return NULL; + if (mm == NULL) + return NULL; info = radix_tree_lookup(&mm_tree->mm_tree, (unsigned long)mm); return info; } @@ -80,7 +82,8 @@ static int copy_stack_frame(const void __user *fp, ret = 1; pagefault_disable(); - if (__copy_from_user_inatomic(frame, fp, sizeof(*frame))) ret = 0; + if (__copy_from_user_inatomic(frame, fp, sizeof(*frame))) + ret = 0; pagefault_enable(); return ret; @@ -111,15 +114,13 @@ static inline void save_stack_trace_user_remote(struct task_struct *tsk, const void __user *fp = (const void __user *)regs->bp; int count = 0; - if (in_atomic() ) { - printk("save_stack_trace_user_remote %d in_atomic\n", - tsk->pid); + if (in_atomic()) { + printk("save_stack_trace_user_remote %d in_atomic\n", tsk->pid); return; } if (irqs_disabled()) { - printk("save_stack_trace_user_remote %d irqs_disabled\n", - tsk->pid); + printk("save_stack_trace_user_remote %d irqs_disabled\n", tsk->pid); return; } @@ -141,14 +142,14 @@ static inline void save_stack_trace_user_remote(struct task_struct *tsk, if ((unsigned long)fp < regs->sp) { printk("save_stack_trace_user_remote %d fp < sp count:%d\n", tsk->pid, count); - break; // 如果fp小于sp,说明已经到了栈底,退出 + break; // 如果fp小于sp,说明已经到了栈底,退出 } // 如果返回地址不为0,说明是一个有效的栈帧,保存返回地址 if (frame.ret_addr) { trace->entries[trace->nr_entries++] = frame.ret_addr; printk("save_stack_trace_user_remote %d ret_addr:%lx\n", tsk->pid, frame.ret_addr); - } else{ + } else { printk("save_stack_trace_user_remote %d no ret_addr", tsk->pid); break; // continue; @@ -158,14 +159,15 @@ static inline void save_stack_trace_user_remote(struct task_struct *tsk, if (fp == frame.next_fp) { printk("save_stack_trace_user_remote %d fp == next_fp", tsk->pid); break; - } - fp = frame.next_fp; // 否则,继续向下遍历 + } + fp = frame.next_fp; // 否则,继续向下遍历 count++; /** * 线上环境发现这里有hardlockup,这里强制退出 */ - if (count >= trace->max_entries || count >= 100) break; + if (count >= trace->max_entries || count >= 100) + break; } } @@ -182,18 +184,22 @@ static inline void __save_stack_trace_user(struct stack_trace *trace) { frame.next_fp = NULL; frame.ret_addr = 0; - if (!copy_stack_frame(fp, &frame)) break; - if ((unsigned long)fp < regs->sp) break; + if (!copy_stack_frame(fp, &frame)) + break; + if ((unsigned long)fp < regs->sp) + break; if (frame.ret_addr) { trace->entries[trace->nr_entries++] = frame.ret_addr; } - if (fp == frame.next_fp) break; + if (fp == frame.next_fp) + break; fp = frame.next_fp; count++; /** * 线上环境发现这里有hardlockup,这里强制退出 */ - if (count >= trace->max_entries || count >= 100) break; + if (count >= trace->max_entries || count >= 100) + break; } } @@ -239,64 +245,83 @@ static void diagnose_save_stack_trace_user_remote(struct task_struct *tsk, printk("save_stack_trace_user_remote %d, stack: [", tsk->pid); int i = 0; - for (i = 0; i < BACKTRACE_DEPTH; i++) - { + for (i = 0; i < BACKTRACE_DEPTH; i++) { printk("%lx, ", backtrace[i]); } printk("]\n"); } +static int diagnose_task_raw_stack_remote(struct task_struct *tsk, void *to, + void __user *from, unsigned long n) { + int ret; + struct mm_struct *mm; + + if (in_atomic() || irqs_disabled()) { + return 0; + } + + mm = get_task_mm(tsk); + if (!mm) + return 0; + + ret = orig_access_remote_vm(mm, (unsigned long)from, to, n, 0); + mmput(mm); + + return ret < 0 ? ret : 0; +} + void diag_task_brief(struct task_struct *tsk, task_detail *detail) { struct pid_namespace *ns; struct pt_regs *task_regs; struct task_struct *leader; struct pt_regs *irq_regs; - if (!detail) return; + if (!detail) + return; memset(detail, 0, sizeof(task_detail)); - if (!tsk || tsk->exit_state == EXIT_ZOMBIE) // zombie + if (!tsk || tsk->exit_state == EXIT_ZOMBIE) // zombie return; leader = tsk->group_leader; if (!leader || leader->exit_state == EXIT_ZOMBIE) { return; } - if (tsk != current) { // not current task + if (tsk != current) { // not current task detail->user_mode = -1; detail->syscallno = -1; - } else if (!tsk->mm) { // current task but kernel thread + } else if (!tsk->mm) { // current task but kernel thread detail->user_mode = 0; detail->syscallno = -1; - } else { // current task and user thread - irq_regs = get_irq_regs(); // get current irq regs + } else { // current task and user thread + irq_regs = get_irq_regs(); // get current irq regs task_regs = task_pt_regs(tsk); if ((irq_regs && user_mode(irq_regs)) || (task_regs && user_mode(task_regs))) { - detail->user_mode = 1; // user mode + detail->user_mode = 1; // user mode } else { - detail->user_mode = 0; // kernel mode + detail->user_mode = 0; // kernel mode } if (task_regs) { - detail->syscallno = syscall_get_nr(tsk, task_regs); // get syscall no + detail->syscallno = syscall_get_nr(tsk, task_regs); // get syscall no } } - if (tsk->sched_class == orig_idle_sched_class) // idle task + if (tsk->sched_class == orig_idle_sched_class) // idle task detail->sys_task = 2; - else if (!tsk->mm) // kernel thread + else if (!tsk->mm) // kernel thread detail->sys_task = 1; else detail->sys_task = 0; - detail->pid = tsk->pid; // pid - detail->tgid = tsk->tgid; // tgid - detail->state = tsk->__state; // state - detail->task_type = diag_get_task_type(tsk); // task type - ns = task_active_pid_ns(tsk); // container pid + detail->pid = tsk->pid; // pid + detail->tgid = tsk->tgid; // tgid + detail->state = tsk->__state; // state + detail->task_type = diag_get_task_type(tsk); // task type + ns = task_active_pid_ns(tsk); // container pid if (ns && ns != &init_pid_ns) { detail->container_pid = task_pid_nr_ns(tsk, ns); detail->container_tgid = task_tgid_nr_ns(tsk, ns); @@ -305,12 +330,12 @@ void diag_task_brief(struct task_struct *tsk, task_detail *detail) { detail->container_tgid = tsk->tgid; } strncpy(detail->comm, tsk->comm, TASK_COMM_LEN); - detail->comm[TASK_COMM_LEN - 1] = 0; // comm name + detail->comm[TASK_COMM_LEN - 1] = 0; // comm name diag_cgroup_name(tsk, detail->cgroup_buf, CGROUP_NAME_LEN, 0); diag_cgroup_name(tsk, detail->cgroup_cpuset, CGROUP_NAME_LEN, 1); - detail->cgroup_buf[CGROUP_NAME_LEN - 1] = 0; // cgroup name - detail->cgroup_cpuset[CGROUP_NAME_LEN - 1] = 0; // cgroup cpuset name + detail->cgroup_buf[CGROUP_NAME_LEN - 1] = 0; // cgroup name + detail->cgroup_cpuset[CGROUP_NAME_LEN - 1] = 0; // cgroup cpuset name } void diag_task_user_stack(struct task_struct *tsk, user_stack_detail *detail) { @@ -355,7 +380,8 @@ void diag_task_user_stack(struct task_struct *tsk, user_stack_detail *detail) { } } -unsigned int diag_task_kern_stack(struct task_struct *tsk, kern_stack_detail *detail) { +unsigned int diag_task_kern_stack(struct task_struct *tsk, + kern_stack_detail *detail) { return orig_stack_trace_save_tsk(tsk, detail->stack, BACKTRACE_DEPTH, 0); } @@ -371,13 +397,15 @@ void dump_proc_chains_argv(int style, struct task_struct *tsk, mm_tree *mm_tree, detail->chains[i][0] = 0; detail->tgid[i] = 0; } - if (style == 0) return; + if (style == 0) + return; - if (!tsk || !tsk->mm) return; + if (!tsk || !tsk->mm) + return; leader = tsk->group_leader; if (!leader || !leader->mm || - leader->exit_state == EXIT_ZOMBIE) { // leader is zombie or no mm + leader->exit_state == EXIT_ZOMBIE) { // leader is zombie or no mm return; } @@ -399,16 +427,69 @@ void dump_proc_chains_argv(int style, struct task_struct *tsk, mm_tree *mm_tree, } detail->tgid[cnt] = walker->pid; // if ((detail->tgid[cnt] != 0) | (detail->full_argv[cnt] != 0)) { - // printk("pid: %d,full_argv: %d, chains: %s, cnt:%d\n", detail->tgid[cnt], + // printk("pid: %d,full_argv: %d, chains: %s, cnt:%d\n", + // detail->tgid[cnt], // detail->full_argv[cnt], detail->chains[cnt], cnt); // } walker = rcu_dereference(walker->real_parent); cnt++; - if (cnt >= PROCESS_CHAINS_COUNT) break; + if (cnt >= PROCESS_CHAINS_COUNT) + break; } rcu_read_unlock(); } +/** + * @brief copy task raw stack + * + * @param tsk + * @param detail + */ +void diag_task_raw_stack(struct task_struct *tsk, raw_stack_detail *detail) { + struct pt_regs *regs; + int i; + int ret; + unsigned long sp, ip, bp; + char *stack; + + memset(detail->stack, 0, DIAG_USER_STACK_SIZE); + detail->stack_size = 0; + + if (!tsk || !tsk->mm) + return; + + regs = task_pt_regs(tsk); + if (!regs) + return; + + sp = regs->sp; + ip = regs->ip; + bp = regs->bp; + + detail->regs = *regs; + detail->sp = sp; + detail->ip = ip; + detail->bp = bp; + stack = (char *)&detail->stack[0]; + for (i = 0; i < (DIAG_USER_STACK_SIZE / 1024); i++) { + if (tsk == current) { + pagefault_disable(); + ret = __copy_from_user_inatomic( + stack, (void __user *)sp + detail->stack_size, 1024); + pagefault_enable(); + } else { + ret = diagnose_task_raw_stack_remote( + tsk, stack, (void __user *)sp + detail->stack_size, 1024); + } + if (ret) + break; + else + detail->stack_size += 1024; + + stack += 1024; + } +} + /// @brief print all task stack /// @param // static void print_task_stack(void) { @@ -448,7 +529,8 @@ void dump_proc_chains_argv(int style, struct task_struct *tsk, mm_tree *mm_tree, // } // sym.reset(kern_stack->stack[i]); // if (g_symbol_parser.find_kernel_symbol(sym)) { -// printf("#@ 0x%lx %s ([kernel.kallsyms])\n", kern_stack->stack[i], +// printf("#@ 0x%lx %s ([kernel.kallsyms])\n", +// kern_stack->stack[i], // sym.name.c_str()); // } else { // printf("#@ 0x%lx %s\n", kern_stack->stack[i], "UNKNOWN"); @@ -461,7 +543,8 @@ void dump_proc_chains_argv(int style, struct task_struct *tsk, mm_tree *mm_tree, // } // sym.reset(kern_stack->stack[i]); // if (g_symbol_parser.find_kernel_symbol(sym)) { -// printf("#@ 0x%lx %s ([kernel.kallsyms])\n", kern_stack->stack[i], +// printf("#@ 0x%lx %s ([kernel.kallsyms])\n", +// kern_stack->stack[i], // sym.name.c_str()); // } else { // printf("#@ 0x%lx %s\n", kern_stack->stack[i], "UNKNOWN"); diff --git a/source/module/monitor_trace.h b/source/module/monitor_trace.h index 501add1..6ff3abf 100644 --- a/source/module/monitor_trace.h +++ b/source/module/monitor_trace.h @@ -106,6 +106,7 @@ void diag_task_brief(struct task_struct *tsk, task_detail *detail); // get task brief void diag_task_user_stack(struct task_struct *tsk, user_stack_detail *detail); // get task user stack +void diag_task_raw_stack(struct task_struct *tsk, raw_stack_detail *detail); // get task raw stack unsigned int diag_task_kern_stack(struct task_struct *tsk, kern_stack_detail *detail); // get task kernel stack void dump_proc_chains_argv(