2 * linux/kernel/ptrace.c
4 * (C) Copyright 1999 Linus Torvalds
6 * Common interfaces for "ptrace()" which we do not want
7 * to continually duplicate across every architecture.
10 #include <linux/sched.h>
11 #include <linux/errno.h>
13 #include <linux/highmem.h>
14 #include <linux/pagemap.h>
15 #include <linux/smp_lock.h>
16 #include <linux/ptrace.h>
18 #include <asm/pgtable.h>
19 #include <asm/uaccess.h>
22 * ptrace a task: make the debugger its new parent and
23 * move it to the ptrace list.
25 * Must be called with the tasklist lock write-held.
27 void __ptrace_link(task_t
*child
, task_t
*new_parent
)
29 if (!list_empty(&child
->ptrace_list
))
31 if (child
->parent
== new_parent
)
33 list_add(&child
->ptrace_list
, &child
->parent
->ptrace_children
);
35 child
->parent
= new_parent
;
40 * unptrace a task: move it back to its original parent and
41 * remove it from the ptrace list.
43 * Must be called with the tasklist lock write-held.
45 void __ptrace_unlink(task_t
*child
)
50 if (list_empty(&child
->ptrace_list
))
52 list_del_init(&child
->ptrace_list
);
54 child
->parent
= child
->real_parent
;
59 * Check that we have indeed attached to the thing..
61 int ptrace_check_attach(struct task_struct
*child
, int kill
)
63 if (!(child
->ptrace
& PT_PTRACED
))
66 if (child
->parent
!= current
)
70 if (child
->state
!= TASK_STOPPED
)
72 wait_task_inactive(child
);
75 /* All systems go.. */
79 int ptrace_attach(struct task_struct
*task
)
90 if(((current
->uid
!= task
->euid
) ||
91 (current
->uid
!= task
->suid
) ||
92 (current
->uid
!= task
->uid
) ||
93 (current
->gid
!= task
->egid
) ||
94 (current
->gid
!= task
->sgid
) ||
95 (current
->gid
!= task
->gid
)) && !capable(CAP_SYS_PTRACE
))
98 if (!task
->mm
->dumpable
&& !capable(CAP_SYS_PTRACE
))
100 /* the same process cannot be attached many times */
101 if (task
->ptrace
& PT_PTRACED
)
103 retval
= security_ops
->ptrace(current
, task
);
108 task
->ptrace
|= PT_PTRACED
;
109 if (capable(CAP_SYS_PTRACE
))
110 task
->ptrace
|= PT_PTRACE_CAP
;
113 write_lock_irq(&tasklist_lock
);
114 __ptrace_link(task
, current
);
115 write_unlock_irq(&tasklist_lock
);
117 send_sig(SIGSTOP
, task
, 1);
125 int ptrace_detach(struct task_struct
*child
, unsigned int data
)
127 if ((unsigned long) data
> _NSIG
)
130 /* Architecture-specific hardware disable .. */
131 ptrace_disable(child
);
133 /* .. re-parent .. */
134 child
->exit_code
= data
;
136 write_lock_irq(&tasklist_lock
);
137 __ptrace_unlink(child
);
138 /* .. and wake it up. */
139 if (child
->state
!= TASK_ZOMBIE
)
140 wake_up_process(child
);
141 write_unlock_irq(&tasklist_lock
);
147 * Access another process' address space.
148 * Source/target buffer must be kernel space,
149 * Do not walk the page table directly, use get_user_pages
152 int access_process_vm(struct task_struct
*tsk
, unsigned long addr
, void *buf
, int len
, int write
)
154 struct mm_struct
*mm
;
155 struct vm_area_struct
*vma
;
159 mm
= get_task_mm(tsk
);
163 down_read(&mm
->mmap_sem
);
164 /* ignore errors, just check how much was sucessfully transfered */
166 int bytes
, ret
, offset
;
169 ret
= get_user_pages(current
, mm
, addr
, 1,
170 write
, 1, &page
, &vma
);
175 offset
= addr
& (PAGE_SIZE
-1);
176 if (bytes
> PAGE_SIZE
-offset
)
177 bytes
= PAGE_SIZE
-offset
;
179 flush_cache_page(vma
, addr
);
183 memcpy(maddr
+ offset
, buf
, bytes
);
184 flush_page_to_ram(page
);
185 flush_icache_user_range(vma
, page
, addr
, bytes
);
187 memcpy(buf
, maddr
+ offset
, bytes
);
188 flush_page_to_ram(page
);
191 page_cache_release(page
);
196 up_read(&mm
->mmap_sem
);
199 return buf
- old_buf
;
202 int ptrace_readdata(struct task_struct
*tsk
, unsigned long src
, char *dst
, int len
)
208 int this_len
, retval
;
210 this_len
= (len
> sizeof(buf
)) ? sizeof(buf
) : len
;
211 retval
= access_process_vm(tsk
, src
, buf
, this_len
, 0);
217 if (copy_to_user(dst
, buf
, retval
))
227 int ptrace_writedata(struct task_struct
*tsk
, char * src
, unsigned long dst
, int len
)
233 int this_len
, retval
;
235 this_len
= (len
> sizeof(buf
)) ? sizeof(buf
) : len
;
236 if (copy_from_user(buf
, src
, this_len
))
238 retval
= access_process_vm(tsk
, dst
, buf
, this_len
, 1);