1
diff -Naur linux-2.6.24/include/linux/ptrace.h linux-2.6.24-ptmulti/include/linux/ptrace.h
2
--- linux-2.6.24/include/linux/ptrace.h 2008-01-24 23:58:37.000000000 +0100
3
+++ linux-2.6.24-ptmulti/include/linux/ptrace.h 2008-03-25 22:27:36.000000000 +0100
5
#define PTRACE_GETSIGINFO 0x4202
6
#define PTRACE_SETSIGINFO 0x4203
8
+#define PTRACE_MULTI 0x4300
9
+#define PTRACE_PEEKCHARDATA 0x4301
10
+#define PTRACE_POKECHARDATA 0x4302
11
+#define PTRACE_PEEKSTRINGDATA 0x4303
13
+struct ptrace_multi {
20
/* options set using PTRACE_SETOPTIONS */
21
#define PTRACE_O_TRACESYSGOOD 0x00000001
22
#define PTRACE_O_TRACEFORK 0x00000002
24
extern struct task_struct *ptrace_get_task_struct(pid_t pid);
25
extern int ptrace_traceme(void);
26
extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
27
+extern int ptrace_readstringdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
28
extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
29
extern int ptrace_attach(struct task_struct *tsk);
30
extern int ptrace_detach(struct task_struct *, unsigned int);
31
diff -Naur linux-2.6.24/kernel/ptrace.c linux-2.6.24-ptmulti/kernel/ptrace.c
32
--- linux-2.6.24/kernel/ptrace.c 2008-01-24 23:58:37.000000000 +0100
33
+++ linux-2.6.24-ptmulti/kernel/ptrace.c 2008-03-25 22:43:05.000000000 +0100
35
* linux/kernel/ptrace.c
37
* (C) Copyright 1999 Linus Torvalds
38
+ * PTRACE_MULTI support 2006 Renzo Davoli
40
* Common interfaces for "ptrace()" which we do not want
41
* to continually duplicate across every architecture.
46
-int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
48
+ * Access another process' address space to/from user space
49
+ * Do not walk the page table directly, use get_user_pages
51
+static int access_process_vm_user(struct task_struct *tsk, unsigned long addr, char __user *ubuf, int len, int write, int string)
54
+ struct mm_struct *mm;
55
+ struct vm_area_struct *vma;
58
+ unsigned long old_addr = addr;
62
- int this_len, retval;
64
- this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
65
- retval = access_process_vm(tsk, src, buf, this_len, 0);
70
+ mm = get_task_mm(tsk);
74
+ buf=kmalloc(PAGE_SIZE, GFP_KERNEL);
75
+ down_read(&mm->mmap_sem);
76
+ /* ignore errors, just check how much was sucessfully transfered */
78
+ int bytes, ret, offset;
81
+ ret = get_user_pages(tsk, mm, addr, 1,
82
+ write, 1, &page, &vma);
87
+ offset = addr & (PAGE_SIZE-1);
88
+ if (bytes > PAGE_SIZE-offset)
89
+ bytes = PAGE_SIZE-offset;
93
+ __copy_from_user(buf,ubuf,bytes);
94
+ copy_to_user_page(vma, page, addr,
95
+ maddr + offset, buf, bytes);
96
+ if (!PageCompound(page))
97
+ set_page_dirty_lock(page);
99
+ copy_from_user_page(vma, page, addr,
100
+ buf, maddr + offset, bytes);
102
+ for (offset=0;offset<bytes;offset++)
103
+ if (buf[offset]==0)
105
+ if (offset < bytes)
106
+ bytes=len=offset+1;
108
+ __copy_to_user(ubuf,buf,bytes);
110
- if (copy_to_user(dst, buf, retval))
117
+ page_cache_release(page);
123
+ up_read(&mm->mmap_sem);
127
+ return addr - old_addr;
130
-int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len)
131
+int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
134
+ if (!access_ok(VERIFY_WRITE, dst ,len))
136
+ return access_process_vm_user(tsk, src, dst, len, 0, 0);
141
- int this_len, retval;
143
- this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
144
- if (copy_from_user(buf, src, this_len))
146
- retval = access_process_vm(tsk, dst, buf, this_len, 1);
158
+int ptrace_readstringdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
160
+ if (!access_ok(VERIFY_WRITE, dst ,len))
162
+ return access_process_vm_user(tsk, src, dst, len, 0, 1);
165
+int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len)
167
+ if (!access_ok(VERIFY_READ, dst ,len))
169
+ return access_process_vm_user(tsk, dst, src, len, 1, 0);
172
static int ptrace_setoptions(struct task_struct *child, long data)
177
+static int multi_ptrace(struct task_struct *child, long request, long addr, long size)
182
+ if (!access_ok(VERIFY_READ, addr,size*sizeof(struct ptrace_multi))) {
184
+ goto out_multi_ptrace;
186
+ for (i=0; i<size && ret==0; i++, addr+=sizeof(struct ptrace_multi)) {
188
+ struct ptrace_multi __user pm ;
189
+ __copy_from_user(&pm, (struct ptrace_multi __user *)addr, sizeof(struct ptrace_multi));
191
+ switch (pm.request) {
192
+ case PTRACE_PEEKTEXT:
193
+ case PTRACE_PEEKDATA:
194
+ case PTRACE_PEEKUSR:
195
+ if (len <= 0) len=1;
196
+ for (j=0; j<len && ret==0; j++)
197
+ ret=arch_ptrace(child, pm.request, (long) (pm.addr) + j*sizeof(long), (long) (pm.localaddr) + j*sizeof(long));
199
+ case PTRACE_POKETEXT:
200
+ case PTRACE_POKEDATA:
201
+ case PTRACE_POKEUSR:
202
+ if (len <= 0) len=1;
203
+ for (j=0; j<len && ret==0; j++)
204
+ ret=arch_ptrace(child, pm.request, (long) (pm.addr) + j*sizeof(long), *(((long *) (pm.localaddr)) + j));
206
+ case PTRACE_PEEKCHARDATA:
207
+ ret = ptrace_readdata(child, pm.addr, pm.localaddr, len);
209
+ case PTRACE_POKECHARDATA:
210
+ ret = ptrace_writedata(child, pm.localaddr, pm.addr, len);
212
+ case PTRACE_PEEKSTRINGDATA:
213
+ ret = ptrace_readstringdata(child, pm.addr, pm.localaddr, len);
216
+ ret=arch_ptrace(child, pm.request, (long) (pm.addr), (long) (pm.localaddr));
224
#ifndef arch_ptrace_attach
225
#define arch_ptrace_attach(child) do { } while (0)
229
goto out_put_task_struct;
231
+ if (request == PTRACE_MULTI)
232
+ ret = multi_ptrace(child, request, addr, data);
234
ret = arch_ptrace(child, request, addr, data);
236
goto out_put_task_struct;