This source file includes following definitions.
- get_user_reg
- put_user_reg
- ptrace_disable
- ptrace_read_user
- ptrace_write_user
- arch_ptrace
- syscall_trace
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 #include <linux/kernel.h>
  12 #include <linux/ptrace.h>
  13 #include <linux/signal.h>
  14 #include <linux/uaccess.h>
  15 #include <linux/sched/task_stack.h>
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 static inline long get_user_reg(struct task_struct *task, int offset)
  24 {
  25         return task_pt_regs(task)->uregs[offset];
  26 }
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 static inline int
  35 put_user_reg(struct task_struct *task, int offset, long data)
  36 {
  37         struct pt_regs newregs, *regs = task_pt_regs(task);
  38         int ret = -EINVAL;
  39 
  40         newregs = *regs;
  41         newregs.uregs[offset] = data;
  42 
  43         if (valid_user_regs(&newregs)) {
  44                 regs->uregs[offset] = data;
  45                 ret = 0;
  46         }
  47 
  48         return ret;
  49 }
  50 
  51 
  52 
  53 
  54 void ptrace_disable(struct task_struct *child)
  55 {
  56 }
  57 
  58 
  59 
  60 
  61 static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
  62                             unsigned long __user *ret)
  63 {
  64         unsigned long tmp;
  65 
  66         tmp = 0;
  67         if (off < sizeof(struct pt_regs))
  68                 tmp = get_user_reg(tsk, off >> 2);
  69 
  70         return put_user(tmp, ret);
  71 }
  72 
  73 
  74 
  75 
  76 static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
  77                              unsigned long val)
  78 {
  79         if (off >= sizeof(struct pt_regs))
  80                 return 0;
  81 
  82         return put_user_reg(tsk, off >> 2, val);
  83 }
  84 
  85 long arch_ptrace(struct task_struct *child, long request,
  86                  unsigned long addr, unsigned long data)
  87 {
  88         int ret;
  89         unsigned long __user *datap = (unsigned long __user *) data;
  90 
  91         switch (request) {
  92         case PTRACE_PEEKUSR:
  93                 ret = ptrace_read_user(child, addr, datap);
  94                 break;
  95 
  96         case PTRACE_POKEUSR:
  97                 ret = ptrace_write_user(child, addr, data);
  98                 break;
  99 
 100         case PTRACE_GET_THREAD_AREA:
 101                 ret = put_user(task_pt_regs(child)->UCreg_16,
 102                                datap);
 103                 break;
 104 
 105         default:
 106                 ret = ptrace_request(child, request, addr, data);
 107                 break;
 108         }
 109 
 110         return ret;
 111 }
 112 
 113 asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
 114 {
 115         unsigned long ip;
 116 
 117         if (!test_thread_flag(TIF_SYSCALL_TRACE))
 118                 return scno;
 119         if (!(current->ptrace & PT_PTRACED))
 120                 return scno;
 121 
 122         
 123 
 124 
 125 
 126         ip = regs->UCreg_ip;
 127         regs->UCreg_ip = why;
 128 
 129         current_thread_info()->syscall = scno;
 130 
 131         
 132 
 133         ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
 134                                  ? 0x80 : 0));
 135         
 136 
 137 
 138 
 139 
 140         if (current->exit_code) {
 141                 send_sig(current->exit_code, current, 1);
 142                 current->exit_code = 0;
 143         }
 144         regs->UCreg_ip = ip;
 145 
 146         return current_thread_info()->syscall;
 147 }