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"
13 #include "linux/proc_mm.h"
15 #include "asm/ptrace.h"
16 #include "asm/uaccess.h"
17 #include "kern_util.h"
18 #include "ptrace_user.h"
21 * Called by kernel/ptrace.c when detaching..
23 void ptrace_disable(struct task_struct
*child
)
27 int sys_ptrace(long request
, long pid
, long addr
, long data
)
29 struct task_struct
*child
;
34 if (request
== PTRACE_TRACEME
) {
35 /* are we already being traced? */
36 if (current
->ptrace
& PT_PTRACED
)
39 ret
= security_ptrace(current
->parent
, current
);
43 /* set the ptrace bit in the process flags. */
44 current
->ptrace
|= PT_PTRACED
;
49 read_lock(&tasklist_lock
);
50 child
= find_task_by_pid(pid
);
52 get_task_struct(child
);
53 read_unlock(&tasklist_lock
);
58 if (pid
== 1) /* you may not mess with init */
61 if (request
== PTRACE_ATTACH
) {
62 ret
= ptrace_attach(child
);
66 ret
= ptrace_check_attach(child
, request
== PTRACE_KILL
);
71 /* when I and D space are separate, these will need to be fixed. */
72 case PTRACE_PEEKTEXT
: /* read word at location addr. */
73 case PTRACE_PEEKDATA
: {
78 copied
= access_process_vm(child
, addr
, &tmp
, sizeof(tmp
), 0);
79 if (copied
!= sizeof(tmp
))
81 ret
= put_user(tmp
,(unsigned long *) data
);
85 /* read the word at location addr in the USER area. */
86 case PTRACE_PEEKUSR
: {
90 if ((addr
& 3) || addr
< 0)
93 tmp
= 0; /* Default return condition */
94 if(addr
< FRAME_SIZE_OFFSET
){
95 tmp
= getreg(child
, addr
);
97 else if((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
98 (addr
<= offsetof(struct user
, u_debugreg
[7]))){
99 addr
-= offsetof(struct user
, u_debugreg
[0]);
101 tmp
= child
->thread
.arch
.debugregs
[addr
];
103 ret
= put_user(tmp
, (unsigned long *) data
);
107 /* when I and D space are separate, this will have to be fixed. */
108 case PTRACE_POKETEXT
: /* write the word at location addr. */
109 case PTRACE_POKEDATA
:
111 if (access_process_vm(child
, addr
, &data
, sizeof(data
),
117 case PTRACE_POKEUSR
: /* write the word at location addr in the USER area */
119 if ((addr
& 3) || addr
< 0)
122 if (addr
< FRAME_SIZE_OFFSET
) {
123 ret
= putreg(child
, addr
, data
);
126 else if((addr
>= offsetof(struct user
, u_debugreg
[0])) &&
127 (addr
<= offsetof(struct user
, u_debugreg
[7]))){
128 addr
-= offsetof(struct user
, u_debugreg
[0]);
130 if((addr
== 4) || (addr
== 5)) break;
131 child
->thread
.arch
.debugregs
[addr
] = data
;
137 case PTRACE_SYSCALL
: /* continue and stop at next (return from) syscall */
138 case PTRACE_CONT
: { /* restart after signal. */
140 if ((unsigned long) data
> _NSIG
)
142 if (request
== PTRACE_SYSCALL
) {
143 set_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
146 clear_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
148 child
->exit_code
= data
;
149 wake_up_process(child
);
155 * make the child exit. Best I can do is send it a sigkill.
156 * perhaps it should be put in the status that it wants to
161 if (child
->state
== TASK_ZOMBIE
) /* already dead */
163 child
->exit_code
= SIGKILL
;
164 wake_up_process(child
);
168 case PTRACE_SINGLESTEP
: { /* set the trap flag. */
170 if ((unsigned long) data
> _NSIG
)
172 clear_tsk_thread_flag(child
, TIF_SYSCALL_TRACE
);
173 child
->ptrace
|= PT_DTRACE
;
174 child
->exit_code
= data
;
175 /* give it a chance to run. */
176 wake_up_process(child
);
182 /* detach a process that was attached. */
183 ret
= ptrace_detach(child
, data
);
186 #ifdef PTRACE_GETREGS
187 case PTRACE_GETREGS
: { /* Get all gp regs from the child. */
188 if (!access_ok(VERIFY_WRITE
, (unsigned long *)data
,
189 FRAME_SIZE_OFFSET
)) {
193 for ( i
= 0; i
< FRAME_SIZE_OFFSET
; i
+= sizeof(long) ) {
194 __put_user(getreg(child
, i
), (unsigned long *) data
);
195 data
+= sizeof(long);
201 #ifdef PTRACE_SETREGS
202 case PTRACE_SETREGS
: { /* Set all gp regs in the child. */
203 unsigned long tmp
= 0;
204 if (!access_ok(VERIFY_READ
, (unsigned *)data
,
205 FRAME_SIZE_OFFSET
)) {
209 for ( i
= 0; i
< FRAME_SIZE_OFFSET
; i
+= sizeof(long) ) {
210 __get_user(tmp
, (unsigned long *) data
);
211 putreg(child
, i
, tmp
);
212 data
+= sizeof(long);
218 #ifdef PTRACE_GETFPREGS
219 case PTRACE_GETFPREGS
: /* Get the child FPU state. */
220 ret
= get_fpregs(data
, child
);
223 #ifdef PTRACE_SETFPREGS
224 case PTRACE_SETFPREGS
: /* Set the child FPU state. */
225 ret
= set_fpregs(data
, child
);
228 #ifdef PTRACE_GETFPXREGS
229 case PTRACE_GETFPXREGS
: /* Get the child FPU state. */
230 ret
= get_fpxregs(data
, child
);
233 #ifdef PTRACE_SETFPXREGS
234 case PTRACE_SETFPXREGS
: /* Set the child FPU state. */
235 ret
= set_fpxregs(data
, child
);
238 case PTRACE_FAULTINFO
: {
239 struct ptrace_faultinfo fault
;
241 fault
= ((struct ptrace_faultinfo
)
242 { .is_write
= child
->thread
.err
,
243 .addr
= child
->thread
.cr2
});
244 ret
= copy_to_user((unsigned long *) data
, &fault
,
250 case PTRACE_SIGPENDING
:
251 ret
= copy_to_user((unsigned long *) data
,
252 &child
->pending
.signal
,
253 sizeof(child
->pending
.signal
));
257 struct ptrace_ldt ldt
;
259 if(copy_from_user(&ldt
, (unsigned long *) data
,
265 /* This one is confusing, so just punt and return -EIO for
271 #ifdef CONFIG_PROC_MM
272 case PTRACE_SWITCH_MM
: {
273 struct mm_struct
*old
= child
->mm
;
274 struct mm_struct
*new = proc_mm_get_mm(data
);
281 atomic_inc(&new->mm_users
);
283 child
->active_mm
= new;
290 ret
= ptrace_request(child
, request
, addr
, data
);
294 put_task_struct(child
);
300 void syscall_trace(union uml_pt_regs
*regs
, int entryexit
)
302 if (unlikely(current
->audit_context
)) {
304 audit_syscall_entry(current
, regs
->orig_eax
,
305 regs
->ebx
, regs
->ecx
,
306 regs
->edx
, regs
->esi
);
308 audit_syscall_exit(current
, regs
->eax
);
311 if (!test_thread_flag(TIF_SYSCALL_TRACE
))
313 if (!(current
->ptrace
& PT_PTRACED
))
316 /* the 0x80 provides a way for the tracing parent to distinguish
317 between a syscall stop and SIGTRAP delivery */
318 ptrace_notify(SIGTRAP
| ((current
->ptrace
& PT_TRACESYSGOOD
)
322 * this isn't the same as continuing with a signal, but it will do
323 * for normal use. strace only continues with a signal if the
324 * stopping signal is not SIGTRAP. -brl
326 if (current
->exit_code
) {
327 send_sig(current
->exit_code
, current
, 1);
328 current
->exit_code
= 0;
333 * Overrides for Emacs so that we follow Linus's tabbing style.
334 * Emacs will notice this stuff at the end of the file and automatically
335 * adjust the settings for this buffer only. This must remain at the end
337 * ---------------------------------------------------------------------------
339 * c-file-style: "linux"