1
2
3
4
5
6
7
8
9
10#include <linux/module.h>
11#include <linux/sched.h>
12#include <linux/errno.h>
13#include <linux/mm.h>
14#include <linux/highmem.h>
15#include <linux/pagemap.h>
16#include <linux/smp_lock.h>
17#include <linux/ptrace.h>
18#include <linux/security.h>
19
20#include <asm/pgtable.h>
21#include <asm/uaccess.h>
22
23
24
25
26
27
28
29void __ptrace_link(task_t *child, task_t *new_parent)
30{
31 if (!list_empty(&child->ptrace_list))
32 BUG();
33 if (child->parent == new_parent)
34 return;
35 list_add(&child->ptrace_list, &child->parent->ptrace_children);
36 REMOVE_LINKS(child);
37 child->parent = new_parent;
38 SET_LINKS(child);
39}
40
41static inline int pending_resume_signal(struct sigpending *pending)
42{
43#define M(sig) (1UL << ((sig)-1))
44 return sigtestsetmask(&pending->signal, M(SIGCONT) | M(SIGKILL));
45}
46
47
48
49
50
51
52
53void ptrace_untrace(task_t *child)
54{
55 spin_lock(&child->sighand->siglock);
56 if (child->state == TASK_TRACED) {
57 if (pending_resume_signal(&child->pending) ||
58 pending_resume_signal(&child->signal->shared_pending)) {
59 signal_wake_up(child, 1);
60 } else {
61 child->state = TASK_STOPPED;
62 }
63 }
64 spin_unlock(&child->sighand->siglock);
65}
66
67
68
69
70
71
72
73void __ptrace_unlink(task_t *child)
74{
75 if (!child->ptrace)
76 BUG();
77 child->ptrace = 0;
78 if (!list_empty(&child->ptrace_list)) {
79 list_del_init(&child->ptrace_list);
80 REMOVE_LINKS(child);
81 child->parent = child->real_parent;
82 SET_LINKS(child);
83 }
84
85 if (child->state == TASK_TRACED)
86 ptrace_untrace(child);
87}
88
89
90
91
92int ptrace_check_attach(struct task_struct *child, int kill)
93{
94 int ret = -ESRCH;
95
96
97
98
99
100
101
102
103 read_lock(&tasklist_lock);
104 if ((child->ptrace & PT_PTRACED) && child->parent == current &&
105 (!(child->ptrace & PT_ATTACHED) || child->real_parent != current)
106 && child->signal != NULL) {
107 ret = 0;
108 spin_lock_irq(&child->sighand->siglock);
109 if (child->state == TASK_STOPPED) {
110 child->state = TASK_TRACED;
111 } else if (child->state != TASK_TRACED && !kill) {
112 ret = -ESRCH;
113 }
114 spin_unlock_irq(&child->sighand->siglock);
115 }
116 read_unlock(&tasklist_lock);
117
118 if (!ret && !kill) {
119 wait_task_inactive(child);
120 }
121
122
123 return ret;
124}
125
126int ptrace_attach(struct task_struct *task)
127{
128 int retval;
129
130 retval = -EPERM;
131 if (task->pid <= 1)
132 goto out;
133 if (task == current)
134 goto out;
135
136repeat:
137
138
139
140
141
142
143
144
145
146 task_lock(task);
147 local_irq_disable();
148 if (!write_trylock(&tasklist_lock)) {
149 local_irq_enable();
150 task_unlock(task);
151 do {
152 cpu_relax();
153 } while (rwlock_is_locked(&tasklist_lock));
154 goto repeat;
155 }
156
157 if (!task->mm)
158 goto bad;
159 if(((current->uid != task->euid) ||
160 (current->uid != task->suid) ||
161 (current->uid != task->uid) ||
162 (current->gid != task->egid) ||
163 (current->gid != task->sgid) ||
164 (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
165 goto bad;
166 rmb();
167 if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
168 goto bad;
169
170 if (task->ptrace & PT_PTRACED)
171 goto bad;
172 retval = security_ptrace(current, task);
173 if (retval)
174 goto bad;
175
176
177 task->ptrace |= PT_PTRACED | ((task->real_parent != current)
178 ? PT_ATTACHED : 0);
179 if (capable(CAP_SYS_PTRACE))
180 task->ptrace |= PT_PTRACE_CAP;
181
182 __ptrace_link(task, current);
183
184 force_sig_specific(SIGSTOP, task);
185
186bad:
187 write_unlock_irq(&tasklist_lock);
188 task_unlock(task);
189out:
190 return retval;
191}
192
193void __ptrace_detach(struct task_struct *child, unsigned int data)
194{
195
196 child->exit_code = data;
197 __ptrace_unlink(child);
198
199 if (child->exit_state != EXIT_ZOMBIE)
200 wake_up_process(child);
201}
202
203int ptrace_detach(struct task_struct *child, unsigned int data)
204{
205 if ((unsigned long) data > _NSIG)
206 return -EIO;
207
208
209 ptrace_disable(child);
210 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
211
212 write_lock_irq(&tasklist_lock);
213
214 if (child->ptrace)
215 __ptrace_detach(child, data);
216 write_unlock_irq(&tasklist_lock);
217
218 return 0;
219}
220
221
222
223
224
225
226
227int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
228{
229 struct mm_struct *mm;
230 struct vm_area_struct *vma;
231 struct page *page;
232 void *old_buf = buf;
233
234 mm = get_task_mm(tsk);
235 if (!mm)
236 return 0;
237
238 down_read(&mm->mmap_sem);
239
240 while (len) {
241 int bytes, ret, offset;
242 void *maddr;
243
244 ret = get_user_pages(tsk, mm, addr, 1,
245 write, 1, &page, &vma);
246 if (ret <= 0)
247 break;
248
249 bytes = len;
250 offset = addr & (PAGE_SIZE-1);
251 if (bytes > PAGE_SIZE-offset)
252 bytes = PAGE_SIZE-offset;
253
254 maddr = kmap(page);
255 if (write) {
256 copy_to_user_page(vma, page, addr,
257 maddr + offset, buf, bytes);
258 if (!PageCompound(page))
259 set_page_dirty_lock(page);
260 } else {
261 copy_from_user_page(vma, page, addr,
262 buf, maddr + offset, bytes);
263 }
264 kunmap(page);
265 page_cache_release(page);
266 len -= bytes;
267 buf += bytes;
268 addr += bytes;
269 }
270 up_read(&mm->mmap_sem);
271 mmput(mm);
272
273 return buf - old_buf;
274}
275
276int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
277{
278 int copied = 0;
279
280 while (len > 0) {
281 char buf[128];
282 int this_len, retval;
283
284 this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
285 retval = access_process_vm(tsk, src, buf, this_len, 0);
286 if (!retval) {
287 if (copied)
288 break;
289 return -EIO;
290 }
291 if (copy_to_user(dst, buf, retval))
292 return -EFAULT;
293 copied += retval;
294 src += retval;
295 dst += retval;
296 len -= retval;
297 }
298 return copied;
299}
300
301int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len)
302{
303 int copied = 0;
304
305 while (len > 0) {
306 char buf[128];
307 int this_len, retval;
308
309 this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
310 if (copy_from_user(buf, src, this_len))
311 return -EFAULT;
312 retval = access_process_vm(tsk, dst, buf, this_len, 1);
313 if (!retval) {
314 if (copied)
315 break;
316 return -EIO;
317 }
318 copied += retval;
319 src += retval;
320 dst += retval;
321 len -= retval;
322 }
323 return copied;
324}
325
326static int ptrace_setoptions(struct task_struct *child, long data)
327{
328 child->ptrace &= ~PT_TRACE_MASK;
329
330 if (data & PTRACE_O_TRACESYSGOOD)
331 child->ptrace |= PT_TRACESYSGOOD;
332
333 if (data & PTRACE_O_TRACEFORK)
334 child->ptrace |= PT_TRACE_FORK;
335
336 if (data & PTRACE_O_TRACEVFORK)
337 child->ptrace |= PT_TRACE_VFORK;
338
339 if (data & PTRACE_O_TRACECLONE)
340 child->ptrace |= PT_TRACE_CLONE;
341
342 if (data & PTRACE_O_TRACEEXEC)
343 child->ptrace |= PT_TRACE_EXEC;
344
345 if (data & PTRACE_O_TRACEVFORKDONE)
346 child->ptrace |= PT_TRACE_VFORK_DONE;
347
348 if (data & PTRACE_O_TRACEEXIT)
349 child->ptrace |= PT_TRACE_EXIT;
350
351 return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
352}
353
354static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
355{
356 siginfo_t lastinfo;
357 int error = -ESRCH;
358
359 read_lock(&tasklist_lock);
360 if (likely(child->sighand != NULL)) {
361 error = -EINVAL;
362 spin_lock_irq(&child->sighand->siglock);
363 if (likely(child->last_siginfo != NULL)) {
364 lastinfo = *child->last_siginfo;
365 error = 0;
366 }
367 spin_unlock_irq(&child->sighand->siglock);
368 }
369 read_unlock(&tasklist_lock);
370 if (!error)
371 return copy_siginfo_to_user(data, &lastinfo);
372 return error;
373}
374
375static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
376{
377 siginfo_t newinfo;
378 int error = -ESRCH;
379
380 if (copy_from_user(&newinfo, data, sizeof (siginfo_t)))
381 return -EFAULT;
382
383 read_lock(&tasklist_lock);
384 if (likely(child->sighand != NULL)) {
385 error = -EINVAL;
386 spin_lock_irq(&child->sighand->siglock);
387 if (likely(child->last_siginfo != NULL)) {
388 *child->last_siginfo = newinfo;
389 error = 0;
390 }
391 spin_unlock_irq(&child->sighand->siglock);
392 }
393 read_unlock(&tasklist_lock);
394 return error;
395}
396
397int ptrace_request(struct task_struct *child, long request,
398 long addr, long data)
399{
400 int ret = -EIO;
401
402 switch (request) {
403#ifdef PTRACE_OLDSETOPTIONS
404 case PTRACE_OLDSETOPTIONS:
405#endif
406 case PTRACE_SETOPTIONS:
407 ret = ptrace_setoptions(child, data);
408 break;
409 case PTRACE_GETEVENTMSG:
410 ret = put_user(child->ptrace_message, (unsigned long __user *) data);
411 break;
412 case PTRACE_GETSIGINFO:
413 ret = ptrace_getsiginfo(child, (siginfo_t __user *) data);
414 break;
415 case PTRACE_SETSIGINFO:
416 ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
417 break;
418 default:
419 break;
420 }
421
422 return ret;
423}
424