2 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
6 #include "linux/sched.h"
8 #include "linux/errno.h"
9 #include "linux/smp_lock.h"
10 #include "linux/security.h"
11 #include "linux/ptrace.h"
12 #include "linux/audit.h"
14 #include "linux/proc_mm.h"
16 #include "asm/ptrace.h"
17 #include "asm/uaccess.h"
18 #include "kern_util.h"
19 #include "skas_ptrace.h"
20 #include "sysdep/ptrace.h"
22 static inline void set_singlestepping(struct task_struct
*child
, int on
)
25 child
->ptrace
|= PT_DTRACE
;
27 child
->ptrace
&= ~PT_DTRACE
;
28 child
->thread
.singlestep_syscall
= 0;
30 #ifdef SUBARCH_SET_SINGLESTEPPING
31 SUBARCH_SET_SINGLESTEPPING(child
, on
);
36 * Called by kernel/ptrace.c when detaching..
38 void ptrace_disable(struct task_struct
*child
)
40 set_singlestepping(child
,0);
43 extern int peek_user(struct task_struct
* child
, long addr
, long data
);
44 extern int poke_user(struct task_struct
* child
, long addr
, long data
);
46 long sys_ptrace(long request
, long pid
, long addr
, long data
)
48 struct task_struct
*child
;
53 if (request
== PTRACE_TRACEME
) {
54 /* are we already being traced? */
55 if (current
->ptrace
& PT_PTRACED
)
58 ret
= security_ptrace(current
->parent
, current
);
62 /* set the ptrace bit in the process flags. */
63 current
->ptrace
|= PT_PTRACED
;
68 read_lock(&tasklist_lock
);
69 child
= find_task_by_pid(pid
);
71 get_task_struct(child
);
72 read_unlock(&tasklist_lock
);
77 if (pid
== 1) /* you may not mess with init */
80 if (request
== PTRACE_ATTACH
) {
81 ret
= ptrace_attach(child
);
85 #ifdef SUBACH_PTRACE_SPECIAL
86 SUBARCH_PTRACE_SPECIAL(child
,request
,addr
,data
);
89 ret
= ptrace_check_attach(child
, request
== PTRACE_KILL
);
94 /* when I and D space are separate, these will need to be fixed. */
95 case PTRACE_PEEKTEXT
: /* read word at location addr. */
96 case PTRACE_PEEKDATA
: {
101 copied
= access_process_vm(child
, addr
, &tmp
, sizeof(tmp
), 0);
102 if (copied
!= sizeof(tmp
))
104 ret
= put_user(tmp
, (unsigned long __user
*) data
);
108 /* read the word at location addr in the USER area. */
110 ret
= peek_user(child
, addr
, data
);
113 /* when I and D space are separate, this will have to be fixed. */
114 case PTRACE_POKETEXT
: /* write the word at location addr. */
115 case PTRACE_POKEDATA
:
117 if (access_process_vm(child
, addr
, &data
, sizeof(data
),
123 case PTRACE_POKEUSR
: /* write the word at location addr in the USER area */
124 ret
= poke_user(child
, addr
, data
);
127 case PTRACE_SYSCALL
: /* continue and stop at next (return from) syscall */
128 case PTRACE_CONT
: { /* restart after signal. */
130 if (!valid_signal(data
))
133 set_singlestepping(child
, 0);
134 if (request
== PTRACE_SYSCALL
) {
135 set_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
138 clear_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
140 child
->exit_code
= data
;
141 wake_up_process(child
);
147 * make the child exit. Best I can do is send it a sigkill.
148 * perhaps it should be put in the status that it wants to
153 if (child
->exit_state
== EXIT_ZOMBIE
) /* already dead */
156 set_singlestepping(child
, 0);
157 child
->exit_code
= SIGKILL
;
158 wake_up_process(child
);
162 case PTRACE_SINGLESTEP
: { /* set the trap flag. */
164 if (!valid_signal(data
))
166 clear_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
167 set_singlestepping(child
, 1);
168 child
->exit_code
= data
;
169 /* give it a chance to run. */
170 wake_up_process(child
);
176 /* detach a process that was attached. */
177 ret
= ptrace_detach(child
, data
);
180 #ifdef PTRACE_GETREGS
181 case PTRACE_GETREGS
: { /* Get all gp regs from the child. */
182 if (!access_ok(VERIFY_WRITE
, (unsigned long *)data
,
187 for ( i
= 0; i
< MAX_REG_OFFSET
; i
+= sizeof(long) ) {
188 __put_user(getreg(child
, i
),
189 (unsigned long __user
*) data
);
190 data
+= sizeof(long);
196 #ifdef PTRACE_SETREGS
197 case PTRACE_SETREGS
: { /* Set all gp regs in the child. */
198 unsigned long tmp
= 0;
199 if (!access_ok(VERIFY_READ
, (unsigned *)data
,
204 for ( i
= 0; i
< MAX_REG_OFFSET
; i
+= sizeof(long) ) {
205 __get_user(tmp
, (unsigned long __user
*) data
);
206 putreg(child
, i
, tmp
);
207 data
+= sizeof(long);
213 #ifdef PTRACE_GETFPREGS
214 case PTRACE_GETFPREGS
: /* Get the child FPU state. */
215 ret
= get_fpregs(data
, child
);
218 #ifdef PTRACE_SETFPREGS
219 case PTRACE_SETFPREGS
: /* Set the child FPU state. */
220 ret
= set_fpregs(data
, child
);
223 #ifdef PTRACE_GETFPXREGS
224 case PTRACE_GETFPXREGS
: /* Get the child FPU state. */
225 ret
= get_fpxregs(data
, child
);
228 #ifdef PTRACE_SETFPXREGS
229 case PTRACE_SETFPXREGS
: /* Set the child FPU state. */
230 ret
= set_fpxregs(data
, child
);
233 case PTRACE_FAULTINFO
: {
234 /* Take the info from thread->arch->faultinfo,
235 * but transfer max. sizeof(struct ptrace_faultinfo).
236 * On i386, ptrace_faultinfo is smaller!
238 ret
= copy_to_user((unsigned long __user
*) data
,
239 &child
->thread
.arch
.faultinfo
,
240 sizeof(struct ptrace_faultinfo
));
248 struct ptrace_ldt ldt
;
250 if(copy_from_user(&ldt
, (unsigned long __user
*) data
,
256 /* This one is confusing, so just punt and return -EIO for
263 #ifdef CONFIG_PROC_MM
264 case PTRACE_SWITCH_MM
: {
265 struct mm_struct
*old
= child
->mm
;
266 struct mm_struct
*new = proc_mm_get_mm(data
);
273 atomic_inc(&new->mm_users
);
275 child
->active_mm
= new;
282 ret
= ptrace_request(child
, request
, addr
, data
);
286 put_task_struct(child
);
292 void send_sigtrap(struct task_struct
*tsk
, union uml_pt_regs
*regs
,
297 memset(&info
, 0, sizeof(info
));
298 info
.si_signo
= SIGTRAP
;
299 info
.si_code
= TRAP_BRKPT
;
302 info
.si_addr
= UPT_IS_USER(regs
) ? (void __user
*) UPT_IP(regs
) : NULL
;
304 /* Send us the fakey SIGTRAP */
305 force_sig_info(SIGTRAP
, &info
, tsk
);
308 /* XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
309 * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
311 void syscall_trace(union uml_pt_regs
*regs
, int entryexit
)
313 int is_singlestep
= (current
->ptrace
& PT_DTRACE
) && entryexit
;
316 if (unlikely(current
->audit_context
)) {
318 audit_syscall_entry(current
,
320 UPT_SYSCALL_NR(regs
),
321 UPT_SYSCALL_ARG1(regs
),
322 UPT_SYSCALL_ARG2(regs
),
323 UPT_SYSCALL_ARG3(regs
),
324 UPT_SYSCALL_ARG4(regs
));
325 else audit_syscall_exit(current
,
326 AUDITSC_RESULT(UPT_SYSCALL_RET(regs
)),
327 UPT_SYSCALL_RET(regs
));
330 /* Fake a debug trap */
332 send_sigtrap(current
, regs
, 0);
334 if (!test_thread_flag(TIF_SYSCALL_TRACE
))
337 if (!(current
->ptrace
& PT_PTRACED
))
340 /* the 0x80 provides a way for the tracing parent to distinguish
341 between a syscall stop and SIGTRAP delivery */
342 tracesysgood
= (current
->ptrace
& PT_TRACESYSGOOD
);
343 ptrace_notify(SIGTRAP
| (tracesysgood
? 0x80 : 0));
345 if (entryexit
) /* force do_signal() --> is_syscall() */
346 set_thread_flag(TIF_SIGPENDING
);
348 /* this isn't the same as continuing with a signal, but it will do
349 * for normal use. strace only continues with a signal if the
350 * stopping signal is not SIGTRAP. -brl
352 if (current
->exit_code
) {
353 send_sig(current
->exit_code
, current
, 1);
354 current
->exit_code
= 0;