2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL
6 #include "linux/audit.h"
7 #include "linux/ptrace.h"
8 #include "linux/sched.h"
9 #include "asm/uaccess.h"
13 #include "skas_ptrace.h"
17 void user_enable_single_step(struct task_struct
*child
)
19 child
->ptrace
|= PT_DTRACE
;
20 child
->thread
.singlestep_syscall
= 0;
22 #ifdef SUBARCH_SET_SINGLESTEPPING
23 SUBARCH_SET_SINGLESTEPPING(child
, 1);
27 void user_disable_single_step(struct task_struct
*child
)
29 child
->ptrace
&= ~PT_DTRACE
;
30 child
->thread
.singlestep_syscall
= 0;
32 #ifdef SUBARCH_SET_SINGLESTEPPING
33 SUBARCH_SET_SINGLESTEPPING(child
, 0);
38 * Called by kernel/ptrace.c when detaching..
40 void ptrace_disable(struct task_struct
*child
)
42 user_disable_single_step(child
);
45 extern int peek_user(struct task_struct
* child
, long addr
, long data
);
46 extern int poke_user(struct task_struct
* child
, long addr
, long data
);
48 long arch_ptrace(struct task_struct
*child
, long request
, long addr
, long data
)
51 unsigned long __user
*p
= (void __user
*)(unsigned long)data
;
54 /* read word at location addr. */
57 ret
= generic_ptrace_peekdata(child
, addr
, data
);
60 /* read the word at location addr in the USER area. */
62 ret
= peek_user(child
, addr
, data
);
65 /* write the word at location addr. */
68 ret
= generic_ptrace_pokedata(child
, addr
, data
);
71 /* write the word at location addr in the USER area */
73 ret
= poke_user(child
, addr
, data
);
77 case PTRACE_SYSEMU_SINGLESTEP
:
82 case PTRACE_GETREGS
: { /* Get all gp regs from the child. */
83 if (!access_ok(VERIFY_WRITE
, p
, MAX_REG_OFFSET
)) {
87 for ( i
= 0; i
< MAX_REG_OFFSET
; i
+= sizeof(long) ) {
88 __put_user(getreg(child
, i
), p
);
96 case PTRACE_SETREGS
: { /* Set all gp regs in the child. */
97 unsigned long tmp
= 0;
98 if (!access_ok(VERIFY_READ
, p
, MAX_REG_OFFSET
)) {
102 for ( i
= 0; i
< MAX_REG_OFFSET
; i
+= sizeof(long) ) {
104 putreg(child
, i
, tmp
);
111 #ifdef PTRACE_GETFPREGS
112 case PTRACE_GETFPREGS
: /* Get the child FPU state. */
113 ret
= get_fpregs((struct user_i387_struct __user
*) data
,
117 #ifdef PTRACE_SETFPREGS
118 case PTRACE_SETFPREGS
: /* Set the child FPU state. */
119 ret
= set_fpregs((struct user_i387_struct __user
*) data
,
123 case PTRACE_GET_THREAD_AREA
:
124 ret
= ptrace_get_thread_area(child
, addr
,
125 (struct user_desc __user
*) data
);
128 case PTRACE_SET_THREAD_AREA
:
129 ret
= ptrace_set_thread_area(child
, addr
,
130 (struct user_desc __user
*) data
);
133 case PTRACE_FAULTINFO
: {
135 * Take the info from thread->arch->faultinfo,
136 * but transfer max. sizeof(struct ptrace_faultinfo).
137 * On i386, ptrace_faultinfo is smaller!
139 ret
= copy_to_user(p
, &child
->thread
.arch
.faultinfo
,
140 sizeof(struct ptrace_faultinfo
));
146 struct ptrace_ldt ldt
;
148 if (copy_from_user(&ldt
, p
, sizeof(ldt
))) {
154 * This one is confusing, so just punt and return -EIO for
161 #ifdef CONFIG_PROC_MM
162 case PTRACE_SWITCH_MM
: {
163 struct mm_struct
*old
= child
->mm
;
164 struct mm_struct
*new = proc_mm_get_mm(data
);
171 atomic_inc(&new->mm_users
);
173 child
->active_mm
= new;
179 #ifdef PTRACE_ARCH_PRCTL
180 case PTRACE_ARCH_PRCTL
:
181 /* XXX Calls ptrace on the host - needs some SMP thinking */
182 ret
= arch_prctl(child
, data
, (void *) addr
);
186 ret
= ptrace_request(child
, request
, addr
, data
);
188 ret
= subarch_ptrace(child
, request
, addr
, data
);
195 static void send_sigtrap(struct task_struct
*tsk
, struct uml_pt_regs
*regs
,
200 memset(&info
, 0, sizeof(info
));
201 info
.si_signo
= SIGTRAP
;
202 info
.si_code
= TRAP_BRKPT
;
205 info
.si_addr
= UPT_IS_USER(regs
) ? (void __user
*) UPT_IP(regs
) : NULL
;
207 /* Send us the fake SIGTRAP */
208 force_sig_info(SIGTRAP
, &info
, tsk
);
212 * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
213 * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
215 void syscall_trace(struct uml_pt_regs
*regs
, int entryexit
)
217 int is_singlestep
= (current
->ptrace
& PT_DTRACE
) && entryexit
;
220 if (unlikely(current
->audit_context
)) {
222 audit_syscall_entry(HOST_AUDIT_ARCH
,
223 UPT_SYSCALL_NR(regs
),
224 UPT_SYSCALL_ARG1(regs
),
225 UPT_SYSCALL_ARG2(regs
),
226 UPT_SYSCALL_ARG3(regs
),
227 UPT_SYSCALL_ARG4(regs
));
228 else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs
)),
229 UPT_SYSCALL_RET(regs
));
232 /* Fake a debug trap */
234 send_sigtrap(current
, regs
, 0);
236 if (!test_thread_flag(TIF_SYSCALL_TRACE
))
239 if (!(current
->ptrace
& PT_PTRACED
))
243 * the 0x80 provides a way for the tracing parent to distinguish
244 * between a syscall stop and SIGTRAP delivery
246 tracesysgood
= (current
->ptrace
& PT_TRACESYSGOOD
);
247 ptrace_notify(SIGTRAP
| (tracesysgood
? 0x80 : 0));
249 if (entryexit
) /* force do_signal() --> is_syscall() */
250 set_thread_flag(TIF_SIGPENDING
);
253 * this isn't the same as continuing with a signal, but it will do
254 * for normal use. strace only continues with a signal if the
255 * stopping signal is not SIGTRAP. -brl
257 if (current
->exit_code
) {
258 send_sig(current
->exit_code
, current
, 1);
259 current
->exit_code
= 0;