Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ptrace.c
Go to the documentation of this file.
1 /*
2  * `ptrace' system call
3  *
4  * Copyright (C) 2008-2009 Michal Simek <[email protected]>
5  * Copyright (C) 2007-2009 PetaLogix
6  * Copyright (C) 2004-2007 John Williams <[email protected]>
7  *
8  * derived from arch/v850/kernel/ptrace.c
9  *
10  * Copyright (C) 2002,03 NEC Electronics Corporation
11  * Copyright (C) 2002,03 Miles Bader <[email protected]>
12  *
13  * Derived from arch/mips/kernel/ptrace.c:
14  *
15  * Copyright (C) 1992 Ross Biro
16  * Copyright (C) Linus Torvalds
17  * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
18  * Copyright (C) 1996 David S. Miller
19  * Kevin D. Kissell, [email protected] and Carsten Langgaard, [email protected]
20  * Copyright (C) 1999 MIPS Technologies, Inc.
21  *
22  * This file is subject to the terms and conditions of the GNU General
23  * Public License. See the file COPYING in the main directory of this
24  * archive for more details.
25  */
26 
27 #include <linux/kernel.h>
28 #include <linux/mm.h>
29 #include <linux/sched.h>
30 #include <linux/ptrace.h>
31 #include <linux/signal.h>
32 #include <linux/elf.h>
33 #include <linux/audit.h>
34 #include <linux/seccomp.h>
35 #include <linux/tracehook.h>
36 
37 #include <linux/errno.h>
38 #include <asm/processor.h>
39 #include <linux/uaccess.h>
40 #include <asm/asm-offsets.h>
41 #include <asm/cacheflush.h>
42 #include <asm/syscall.h>
43 #include <asm/io.h>
44 
45 /* Returns the address where the register at REG_OFFS in P is stashed away. */
46 static microblaze_reg_t *reg_save_addr(unsigned reg_offs,
47  struct task_struct *t)
48 {
49  struct pt_regs *regs;
50 
51  /*
52  * Three basic cases:
53  *
54  * (1) A register normally saved before calling the scheduler, is
55  * available in the kernel entry pt_regs structure at the top
56  * of the kernel stack. The kernel trap/irq exit path takes
57  * care to save/restore almost all registers for ptrace'd
58  * processes.
59  *
60  * (2) A call-clobbered register, where the process P entered the
61  * kernel via [syscall] trap, is not stored anywhere; that's
62  * OK, because such registers are not expected to be preserved
63  * when the trap returns anyway (so we don't actually bother to
64  * test for this case).
65  *
66  * (3) A few registers not used at all by the kernel, and so
67  * normally never saved except by context-switches, are in the
68  * context switch state.
69  */
70 
71  /* Register saved during kernel entry (or not available). */
72  regs = task_pt_regs(t);
73 
74  return (microblaze_reg_t *)((char *)regs + reg_offs);
75 }
76 
77 long arch_ptrace(struct task_struct *child, long request,
78  unsigned long addr, unsigned long data)
79 {
80  int rval;
81  unsigned long val = 0;
82 
83  switch (request) {
84  /* Read/write the word at location ADDR in the registers. */
85  case PTRACE_PEEKUSR:
86  case PTRACE_POKEUSR:
87  pr_debug("PEEKUSR/POKEUSR : 0x%08lx\n", addr);
88  rval = 0;
89  if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) {
90  /*
91  * Special requests that don't actually correspond
92  * to offsets in struct pt_regs.
93  */
94  if (addr == PT_TEXT_ADDR) {
95  val = child->mm->start_code;
96  } else if (addr == PT_DATA_ADDR) {
97  val = child->mm->start_data;
98  } else if (addr == PT_TEXT_LEN) {
99  val = child->mm->end_code
100  - child->mm->start_code;
101  } else {
102  rval = -EIO;
103  }
104  } else if (addr < PT_SIZE && (addr & 0x3) == 0) {
105  microblaze_reg_t *reg_addr = reg_save_addr(addr, child);
106  if (request == PTRACE_PEEKUSR)
107  val = *reg_addr;
108  else {
109 #if 1
110  *reg_addr = data;
111 #else
112  /* MS potential problem on WB system
113  * Be aware that reg_addr is virtual address
114  * virt_to_phys conversion is necessary.
115  * This could be sensible solution.
116  */
117  u32 paddr = virt_to_phys((u32)reg_addr);
118  invalidate_icache_range(paddr, paddr + 4);
119  *reg_addr = data;
120  flush_dcache_range(paddr, paddr + 4);
121 #endif
122  }
123  } else
124  rval = -EIO;
125 
126  if (rval == 0 && request == PTRACE_PEEKUSR)
127  rval = put_user(val, (unsigned long __user *)data);
128  break;
129  default:
130  rval = ptrace_request(child, request, addr, data);
131  }
132  return rval;
133 }
134 
136 {
137  long ret = 0;
138 
139  secure_computing_strict(regs->r12);
140 
141  if (test_thread_flag(TIF_SYSCALL_TRACE) &&
142  tracehook_report_syscall_entry(regs))
143  /*
144  * Tracing decided this syscall should not happen.
145  * We'll return a bogus call number to get an ENOSYS
146  * error, but leave the original number in regs->regs[0].
147  */
148  ret = -1L;
149 
150  audit_syscall_entry(EM_MICROBLAZE, regs->r12, regs->r5, regs->r6,
151  regs->r7, regs->r8);
152 
153  return ret ?: regs->r12;
154 }
155 
157 {
158  int step;
159 
160  audit_syscall_exit(regs);
161 
162  step = test_thread_flag(TIF_SINGLESTEP);
163  if (step || test_thread_flag(TIF_SYSCALL_TRACE))
164  tracehook_report_syscall_exit(regs, step);
165 }
166 
167 #if 0
168 static asmlinkage void syscall_trace(void)
169 {
170  if (!test_thread_flag(TIF_SYSCALL_TRACE))
171  return;
172  if (!(current->ptrace & PT_PTRACED))
173  return;
174  /* The 0x80 provides a way for the tracing parent to distinguish
175  between a syscall stop and SIGTRAP delivery */
177  ? 0x80 : 0));
178  /*
179  * this isn't the same as continuing with a signal, but it will do
180  * for normal use. strace only continues with a signal if the
181  * stopping signal is not SIGTRAP. -brl
182  */
183  if (current->exit_code) {
184  send_sig(current->exit_code, current, 1);
185  current->exit_code = 0;
186  }
187 }
188 #endif
189 
191 {
192  /* nothing to do */
193 }