]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - arch/powerpc/kernel/ptrace.c
[POWERPC] ptrace cleanups
[mirror_ubuntu-eoan-kernel.git] / arch / powerpc / kernel / ptrace.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * PowerPC version
3 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4 *
5 * Derived from "arch/m68k/kernel/ptrace.c"
6 * Copyright (C) 1994 by Hamish Macdonald
7 * Taken from linux/kernel/ptrace.c and modified for M680x0.
8 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
9 *
10 * Modified by Cort Dougan (cort@hq.fsmlabs.com)
b123923d 11 * and Paul Mackerras (paulus@samba.org).
1da177e4
LT
12 *
13 * This file is subject to the terms and conditions of the GNU General
14 * Public License. See the file README.legal in the main directory of
15 * this archive for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/sched.h>
20#include <linux/mm.h>
21#include <linux/smp.h>
1da177e4
LT
22#include <linux/errno.h>
23#include <linux/ptrace.h>
24#include <linux/user.h>
25#include <linux/security.h>
7ed20e1a 26#include <linux/signal.h>
ea9c102c
DW
27#include <linux/seccomp.h>
28#include <linux/audit.h>
e8a30302 29#ifdef CONFIG_PPC32
ea9c102c 30#include <linux/module.h>
e8a30302 31#endif
1da177e4
LT
32
33#include <asm/uaccess.h>
34#include <asm/page.h>
35#include <asm/pgtable.h>
36#include <asm/system.h>
21a62902 37
e8a30302 38#ifdef CONFIG_PPC64
acd89828 39#include "ptrace-ppc64.h"
1da177e4 40#else
acd89828 41#include "ptrace-ppc32.h"
1da177e4 42#endif
acd89828
BH
43
44#include "ptrace-common.h"
1da177e4
LT
45
46/*
47 * does not yet catch signals sent when the child dies.
48 * in exit.c or in signal.c.
49 */
50
1da177e4
LT
51/*
52 * Called by kernel/ptrace.c when detaching..
53 *
54 * Make sure single step bits etc are not set.
55 */
56void ptrace_disable(struct task_struct *child)
57{
58 /* make sure the single step bit is not set. */
59 clear_single_step(child);
60}
61
481bed45 62long arch_ptrace(struct task_struct *child, long request, long addr, long data)
1da177e4 63{
1da177e4
LT
64 int ret = -EPERM;
65
1da177e4
LT
66 switch (request) {
67 /* when I and D space are separate, these will need to be fixed. */
68 case PTRACE_PEEKTEXT: /* read word at location addr. */
69 case PTRACE_PEEKDATA: {
70 unsigned long tmp;
71 int copied;
72
73 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
74 ret = -EIO;
75 if (copied != sizeof(tmp))
76 break;
77 ret = put_user(tmp,(unsigned long __user *) data);
78 break;
79 }
80
81 /* read the word at location addr in the USER area. */
1da177e4
LT
82 case PTRACE_PEEKUSR: {
83 unsigned long index, tmp;
84
85 ret = -EIO;
86 /* convert to index and check */
e8a30302 87#ifdef CONFIG_PPC32
1da177e4 88 index = (unsigned long) addr >> 2;
e8a30302
SR
89 if ((addr & 3) || (index > PT_FPSCR)
90 || (child->thread.regs == NULL))
91#else
92 index = (unsigned long) addr >> 3;
93 if ((addr & 7) || (index > PT_FPSCR))
94#endif
1da177e4
LT
95 break;
96
e8a30302 97#ifdef CONFIG_PPC32
1da177e4 98 CHECK_FULL_REGS(child->thread.regs);
e8a30302 99#endif
1da177e4
LT
100 if (index < PT_FPR0) {
101 tmp = get_reg(child, (int) index);
102 } else {
e8a30302 103 flush_fp_to_thread(child);
1da177e4
LT
104 tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
105 }
106 ret = put_user(tmp,(unsigned long __user *) data);
107 break;
108 }
109
110 /* If I and D space are separate, this will have to be fixed. */
111 case PTRACE_POKETEXT: /* write the word at location addr. */
112 case PTRACE_POKEDATA:
113 ret = 0;
e8a30302
SR
114 if (access_process_vm(child, addr, &data, sizeof(data), 1)
115 == sizeof(data))
1da177e4
LT
116 break;
117 ret = -EIO;
118 break;
119
120 /* write the word at location addr in the USER area */
121 case PTRACE_POKEUSR: {
122 unsigned long index;
123
124 ret = -EIO;
125 /* convert to index and check */
e8a30302 126#ifdef CONFIG_PPC32
1da177e4 127 index = (unsigned long) addr >> 2;
e8a30302
SR
128 if ((addr & 3) || (index > PT_FPSCR)
129 || (child->thread.regs == NULL))
130#else
131 index = (unsigned long) addr >> 3;
132 if ((addr & 7) || (index > PT_FPSCR))
133#endif
1da177e4
LT
134 break;
135
e8a30302 136#ifdef CONFIG_PPC32
1da177e4 137 CHECK_FULL_REGS(child->thread.regs);
e8a30302 138#endif
1da177e4
LT
139 if (index == PT_ORIG_R3)
140 break;
141 if (index < PT_FPR0) {
142 ret = put_reg(child, index, data);
143 } else {
e8a30302 144 flush_fp_to_thread(child);
1da177e4
LT
145 ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
146 ret = 0;
147 }
148 break;
149 }
150
151 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
152 case PTRACE_CONT: { /* restart after signal. */
153 ret = -EIO;
7ed20e1a 154 if (!valid_signal(data))
1da177e4 155 break;
e8a30302 156 if (request == PTRACE_SYSCALL)
1da177e4 157 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
e8a30302 158 else
1da177e4 159 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1da177e4
LT
160 child->exit_code = data;
161 /* make sure the single step bit is not set. */
162 clear_single_step(child);
163 wake_up_process(child);
164 ret = 0;
165 break;
166 }
167
168/*
169 * make the child exit. Best I can do is send it a sigkill.
170 * perhaps it should be put in the status that it wants to
171 * exit.
172 */
173 case PTRACE_KILL: {
174 ret = 0;
175 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
176 break;
177 child->exit_code = SIGKILL;
178 /* make sure the single step bit is not set. */
179 clear_single_step(child);
180 wake_up_process(child);
181 break;
182 }
183
184 case PTRACE_SINGLESTEP: { /* set the trap flag. */
185 ret = -EIO;
7ed20e1a 186 if (!valid_signal(data))
1da177e4
LT
187 break;
188 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
189 set_single_step(child);
190 child->exit_code = data;
191 /* give it a chance to run. */
192 wake_up_process(child);
193 ret = 0;
194 break;
195 }
196
e8a30302
SR
197#ifdef CONFIG_PPC64
198 case PTRACE_GET_DEBUGREG: {
199 ret = -EINVAL;
200 /* We only support one DABR and no IABRS at the moment */
201 if (addr > 0)
202 break;
203 ret = put_user(child->thread.dabr,
204 (unsigned long __user *)data);
205 break;
206 }
207
208 case PTRACE_SET_DEBUGREG:
209 ret = ptrace_set_debugreg(child, addr, data);
210 break;
211#endif
212
1da177e4
LT
213 case PTRACE_DETACH:
214 ret = ptrace_detach(child, data);
215 break;
216
e8a30302
SR
217 case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
218 int i;
219 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
220 unsigned long __user *tmp = (unsigned long __user *)addr;
221
222 for (i = 0; i < 32; i++) {
223 ret = put_user(*reg, tmp);
224 if (ret)
225 break;
226 reg++;
227 tmp++;
228 }
229 break;
230 }
231
232 case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
233 int i;
234 unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
235 unsigned long __user *tmp = (unsigned long __user *)addr;
236
237 for (i = 0; i < 32; i++) {
238 ret = get_user(*reg, tmp);
239 if (ret)
240 break;
241 reg++;
242 tmp++;
243 }
244 break;
245 }
246
0b3d5c48 247#ifdef CONFIG_PPC64
e8a30302
SR
248 case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
249 int i;
250 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
251 unsigned long __user *tmp = (unsigned long __user *)addr;
252
253 flush_fp_to_thread(child);
254
255 for (i = 0; i < 32; i++) {
256 ret = put_user(*reg, tmp);
257 if (ret)
258 break;
259 reg++;
260 tmp++;
261 }
262 break;
263 }
264
265 case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
266 int i;
267 unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
268 unsigned long __user *tmp = (unsigned long __user *)addr;
269
270 flush_fp_to_thread(child);
271
272 for (i = 0; i < 32; i++) {
273 ret = get_user(*reg, tmp);
274 if (ret)
275 break;
276 reg++;
277 tmp++;
278 }
279 break;
280 }
0b3d5c48 281#endif /* CONFIG_PPC64 */
e8a30302 282
1da177e4
LT
283#ifdef CONFIG_ALTIVEC
284 case PTRACE_GETVRREGS:
285 /* Get the child altivec register state. */
e8a30302 286 flush_altivec_to_thread(child);
1da177e4
LT
287 ret = get_vrregs((unsigned long __user *)data, child);
288 break;
289
290 case PTRACE_SETVRREGS:
291 /* Set the child altivec register state. */
e8a30302 292 flush_altivec_to_thread(child);
1da177e4
LT
293 ret = set_vrregs(child, (unsigned long __user *)data);
294 break;
295#endif
296#ifdef CONFIG_SPE
297 case PTRACE_GETEVRREGS:
298 /* Get the child spe register state. */
299 if (child->thread.regs->msr & MSR_SPE)
300 giveup_spe(child);
301 ret = get_evrregs((unsigned long __user *)data, child);
302 break;
303
304 case PTRACE_SETEVRREGS:
305 /* Set the child spe register state. */
306 /* this is to clear the MSR_SPE bit to force a reload
307 * of register state from memory */
308 if (child->thread.regs->msr & MSR_SPE)
309 giveup_spe(child);
310 ret = set_evrregs(child, (unsigned long __user *)data);
311 break;
312#endif
313
314 default:
315 ret = ptrace_request(child, request, addr, data);
316 break;
317 }
481bed45 318
1da177e4
LT
319 return ret;
320}
321
ea9c102c 322static void do_syscall_trace(void)
1da177e4 323{
ea9c102c
DW
324 /* the 0x80 provides a way for the tracing parent to distinguish
325 between a syscall stop and SIGTRAP delivery */
1da177e4
LT
326 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
327 ? 0x80 : 0));
328
329 /*
330 * this isn't the same as continuing with a signal, but it will do
331 * for normal use. strace only continues with a signal if the
332 * stopping signal is not SIGTRAP. -brl
333 */
334 if (current->exit_code) {
335 send_sig(current->exit_code, current, 1);
336 current->exit_code = 0;
337 }
338}
ea9c102c
DW
339
340void do_syscall_trace_enter(struct pt_regs *regs)
341{
e8a30302 342 secure_computing(regs->gpr[0]);
e8a30302 343
ea9c102c
DW
344 if (test_thread_flag(TIF_SYSCALL_TRACE)
345 && (current->ptrace & PT_PTRACED))
346 do_syscall_trace();
347
cfcd1705
DW
348 if (unlikely(current->audit_context)) {
349#ifdef CONFIG_PPC64
350 if (!test_thread_flag(TIF_32BIT))
351 audit_syscall_entry(AUDIT_ARCH_PPC64,
352 regs->gpr[0],
353 regs->gpr[3], regs->gpr[4],
354 regs->gpr[5], regs->gpr[6]);
355 else
e8a30302 356#endif
cfcd1705
DW
357 audit_syscall_entry(AUDIT_ARCH_PPC,
358 regs->gpr[0],
359 regs->gpr[3] & 0xffffffff,
360 regs->gpr[4] & 0xffffffff,
361 regs->gpr[5] & 0xffffffff,
362 regs->gpr[6] & 0xffffffff);
363 }
ea9c102c
DW
364}
365
366void do_syscall_trace_leave(struct pt_regs *regs)
367{
ea9c102c 368 if (unlikely(current->audit_context))
4b9c876a 369 audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
ea9c102c
DW
370 regs->result);
371
e8a30302 372 if ((test_thread_flag(TIF_SYSCALL_TRACE)
1bd79336 373 || test_thread_flag(TIF_SINGLESTEP))
ea9c102c
DW
374 && (current->ptrace & PT_PTRACED))
375 do_syscall_trace();
376}