본문 바로가기

[Debugging] Tips

[리눅스커널] 부팅 과정 유익한 패치

아래 패치도 정말 유용하다.
 
 * 유저 프로세스가 ASSET될 때 콜 스택 출력
 * 부팅 과정에 오픈하는 파일을 출력
 * 실행되는 파일 이름 출력
 
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 9f5d818..4d6df0c 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -37,7 +37,8 @@
 #include <asm/tls.h>
 #include <asm/system_misc.h>
 #include <asm/opcodes.h>
-
+#include <linux/file.h>
+#include <linux/slab.h>
 
 static const char *handler[]= {
  "prefetch abort",
@@ -60,6 +61,48 @@ static int __init user_debug_setup(char *str)
 __setup("user_debug=", user_debug_setup);
 #endif
 
+
+void trace_exe_filename(void)
+{
+ struct file *exe_file;
+ char *pathbuf, *fname;
+
+ printk("[+][trace][%s][%s,%d] caller: %pS  \n",
+ current->comm, __func__,__LINE__,  (void *)__builtin_return_address(0));
+
+ exe_file = get_mm_exe_file(current->mm);
+
+ if (!exe_file)
+ {
+ printk("[-] path unknown: %s \n", current->comm);
+ return;
+ }
+
+ pathbuf = kmalloc(PATH_MAX, GFP_TEMPORARY);
+
+ if (!pathbuf) {
+ printk("[-] memory starved: %s \n", current->comm);
+ goto put_exe_file;
+ }
+
+ fname = d_path(&exe_file->f_path, pathbuf, PATH_MAX);
+
+ if (IS_ERR(fname)) {
+ printk("[-] path error: %s \n", current->comm);
+ goto free_buf;
+ }
+
+ printk("[+][%s]: exe_file: %s \n", current->comm, fname);
+
+free_buf:
+ kfree(pathbuf);
+put_exe_file:
+ fput(exe_file);
+
+ return;
+}
+
+
 static void dump_mem(const char *, const char *, unsigned long, unsigned long);
 
 void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
@@ -409,6 +452,8 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
  siginfo_t info;
  void __user *pc;
 
+ printk("[+][trace][%s][%s,%d]: \n", current->comm, __func__,__LINE__);
+
  pc = (void __user *)instruction_pointer(regs);
 
  if (processor_mode(regs) == SVC_MODE) {
@@ -444,14 +489,11 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
  return;
 
 die_sig:
-#ifdef CONFIG_DEBUG_USER
- if (user_debug & UDBG_UNDEFINED) {
- printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
+    printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
  current->comm, task_pid_nr(current), pc);
- __show_regs(regs);
- dump_instr(KERN_INFO, regs);
- }
-#endif
+ __show_regs(regs);
+ dump_instr(KERN_INFO, regs);
+ trace_exe_filename();
 
  info.si_signo = SIGILL;
  info.si_errno = 0;
@@ -508,19 +550,18 @@ static int bad_syscall(int n, struct pt_regs *regs)
  struct thread_info *thread = current_thread_info();
  siginfo_t info;
 
+ printk("[+][trace][%s][%s,%d]: \n", current->comm, __func__,__LINE__);
+
  if ((current->personality & PER_MASK) != PER_LINUX &&
      thread->exec_domain->handler) {
  thread->exec_domain->handler(n, regs);
  return regs->ARM_r0;
  }
 
-#ifdef CONFIG_DEBUG_USER
- if (user_debug & UDBG_SYSCALL) {
- printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
+ printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
  task_pid_nr(current), current->comm, n);
- dump_instr(KERN_ERR, regs);
- }
-#endif
+ dump_instr(KERN_ERR, regs);
+ trace_exe_filename();
 
  info.si_signo = SIGILL;
  info.si_errno = 0;
@@ -688,21 +729,15 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
  return -ENOSYS;
  break;
  }
-#ifdef CONFIG_DEBUG_USER
- /*
-  * experience shows that these seem to indicate that
-  * something catastrophic has happened
-  */
- if (user_debug & UDBG_SYSCALL) {
- printk("[%d] %s: arm syscall %d\n",
-        task_pid_nr(current), current->comm, no);
- dump_instr("", regs);
- if (user_mode(regs)) {
- __show_regs(regs);
- c_backtrace(frame_pointer(regs), processor_mode(regs));
- }
- }
-#endif
+
+  printk("[%d] %s: arm syscall %d\n",
+  task_pid_nr(current), current->comm, no);
+  dump_instr("", regs);
+  __show_regs(regs);
+  c_backtrace(frame_pointer(regs), processor_mode(regs));
+
+ trace_exe_filename();
+
  info.si_signo = SIGILL;
  info.si_errno = 0;
  info.si_code  = ILL_ILLTRP;
@@ -769,14 +804,11 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
  unsigned long addr = instruction_pointer(regs);
  siginfo_t info;
 
-#ifdef CONFIG_DEBUG_USER
- if (user_debug & UDBG_BADABORT) {
- printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
+ printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
  task_pid_nr(current), current->comm, code, instr);
- dump_instr(KERN_ERR, regs);
- show_pte(current->mm, addr);
- }
-#endif
+ dump_instr(KERN_ERR, regs);
+ show_pte(current->mm, addr);
+ trace_exe_filename();
 
  info.si_signo = SIGILL;
  info.si_errno = 0;
diff --git a/fs/exec.c b/fs/exec.c
index b7a5f46..b6089dc 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1425,6 +1425,34 @@ int search_binary_handler(struct linux_binprm *bprm)
 }
 EXPORT_SYMBOL(search_binary_handler);
 
+#define PROCESS_ARG_BUFF_SIZE 128
+
+void trace_process_exec_profile(const char *fname)
+{
+       char process_arg_buf[PROCESS_ARG_BUFF_SIZE] = {0,};
+       int len = 0;
+
+       len = get_cmdline(current, process_arg_buf, PROCESS_ARG_BUFF_SIZE -1);
+
+       if(len == 0) {
+               pr_info("[-] Error: len: %d \n", len);
+               return;
+       }
+
+       if(!fname) {
+               pr_info("[-] Error: fname null \n");
+               return;
+       }
+
+       if (len > PROCESS_ARG_BUFF_SIZE)
+               len = PROCESS_ARG_BUFF_SIZE;
+
+       process_arg_buf[len] = '\0';
+
+       pr_info("[exec:%s-%d] exec_file: %s, arg: [%s] \n",
+                                       current->comm, current->pid, fname, process_arg_buf);
+}
+
 static int exec_binprm(struct linux_binprm *bprm)
 {
  pid_t old_pid, old_vpid;
@@ -1442,6 +1470,8 @@ static int exec_binprm(struct linux_binprm *bprm)
  trace_sched_process_exec(current, old_pid, bprm);
  ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
  proc_exec_connector(current);
+
+ trace_process_exec_profile(bprm->filename);
  }
 
  return ret;