~ubuntu-branches/ubuntu/vivid/kernel-patch-viewos/vivid

« back to all changes in this revision

Viewing changes to patch-linux-2.6.21-ptmulti

  • Committer: Bazaar Package Importer
  • Author(s): Ludovico Gardenghi, Filippo Giunchedi, Ludovico Gardenghi
  • Date: 2008-08-15 18:35:09 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080815183509-w2kt2knta7q2xrbd
Tags: 0.20080616-1
[ Filippo Giunchedi ]
* Switch to cdbs
* Add DM-Upload-Allowed field

[ Ludovico Gardenghi ]
* New upstream version
  + Add support to kernels up to 2.6.26 (Closes: #494759)
* Add ptvm kpatches series (in addition to ptmulti and ptmulti-ptvm) as
  starting from 2.6.25 the two patches are independent

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
diff -Naur linux-2.6.21/include/linux/ptrace.h linux-2.6.21-ptmulti/include/linux/ptrace.h
 
2
--- linux-2.6.21/include/linux/ptrace.h 2007-04-26 05:08:32.000000000 +0200
 
3
+++ linux-2.6.21-ptmulti/include/linux/ptrace.h 2008-03-26 10:37:54.000000000 +0100
 
4
@@ -27,6 +27,18 @@
 
5
 #define PTRACE_GETSIGINFO      0x4202
 
6
 #define PTRACE_SETSIGINFO      0x4203
 
7
 
 
8
+#define PTRACE_MULTI            0x4300
 
9
+#define PTRACE_PEEKCHARDATA     0x4301
 
10
+#define PTRACE_POKECHARDATA     0x4302
 
11
+#define PTRACE_PEEKSTRINGDATA   0x4303
 
12
+
 
13
+struct ptrace_multi {
 
14
+       long request;
 
15
+       long addr;
 
16
+       void *localaddr;
 
17
+       long length;
 
18
+};
 
19
+
 
20
 /* options set using PTRACE_SETOPTIONS */
 
21
 #define PTRACE_O_TRACESYSGOOD  0x00000001
 
22
 #define PTRACE_O_TRACEFORK     0x00000002
 
23
@@ -85,6 +97,7 @@
 
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.21/kernel/ptrace.c linux-2.6.21-ptmulti/kernel/ptrace.c
 
32
--- linux-2.6.21/kernel/ptrace.c        2007-04-26 05:08:32.000000000 +0200
 
33
+++ linux-2.6.21-ptmulti/kernel/ptrace.c        2008-03-26 10:44:41.000000000 +0100
 
34
@@ -2,6 +2,7 @@
 
35
  * linux/kernel/ptrace.c
 
36
  *
 
37
  * (C) Copyright 1999 Linus Torvalds
 
38
+ * PTRACE_MULTI support 2006 Renzo Davoli 
 
39
  *
 
40
  * Common interfaces for "ptrace()" which we do not want
 
41
  * to continually duplicate across every architecture.
 
42
@@ -241,54 +242,90 @@
 
43
        return 0;
 
44
 }
 
45
 
 
46
-int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
 
47
+/*
 
48
+ * Access another process' address space to/from user space
 
49
+ * Do not walk the page table directly, use get_user_pages
 
50
+ */
 
51
+static int access_process_vm_user(struct task_struct *tsk, unsigned long addr, char __user *ubuf, int len, int write, int string)
 
52
 {
 
53
-       int copied = 0;
 
54
+       struct mm_struct *mm;
 
55
+       struct vm_area_struct *vma;
 
56
+       struct page *page;
 
57
+       char *buf;
 
58
+       unsigned long old_addr = addr;
 
59
 
 
60
-       while (len > 0) {
 
61
-               char buf[128];
 
62
-               int this_len, retval;
 
63
-
 
64
-               this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
 
65
-               retval = access_process_vm(tsk, src, buf, this_len, 0);
 
66
-               if (!retval) {
 
67
-                       if (copied)
 
68
-                               break;
 
69
-                       return -EIO;
 
70
+       mm = get_task_mm(tsk);
 
71
+       if (!mm)
 
72
+               return 0;
 
73
+
 
74
+       buf=kmalloc(PAGE_SIZE, GFP_KERNEL);
 
75
+       down_read(&mm->mmap_sem);
 
76
+       /* ignore errors, just check how much was sucessfully transfered */
 
77
+       while (len) {
 
78
+               int bytes, ret, offset;
 
79
+               void *maddr;
 
80
+
 
81
+               ret = get_user_pages(tsk, mm, addr, 1,
 
82
+                               write, 1, &page, &vma);
 
83
+               if (ret <= 0)
 
84
+                       break;
 
85
+
 
86
+               bytes = len;
 
87
+               offset = addr & (PAGE_SIZE-1);
 
88
+               if (bytes > PAGE_SIZE-offset)
 
89
+                       bytes = PAGE_SIZE-offset;
 
90
+
 
91
+               maddr = kmap(page);
 
92
+               if (write) {
 
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);
 
98
+               } else {
 
99
+                       copy_from_user_page(vma, page, addr,
 
100
+                                       buf, maddr + offset, bytes);
 
101
+                       if (string) {
 
102
+                               for (offset=0;offset<bytes;offset++)
 
103
+                                       if (buf[offset]==0)
 
104
+                                               break;
 
105
+                               if (offset < bytes)
 
106
+                                       bytes=len=offset+1;
 
107
+                       }
 
108
+                       __copy_to_user(ubuf,buf,bytes);
 
109
                }
 
110
-               if (copy_to_user(dst, buf, retval))
 
111
-                       return -EFAULT;
 
112
-               copied += retval;
 
113
-               src += retval;
 
114
-               dst += retval;
 
115
-               len -= retval;                  
 
116
+               kunmap(page);
 
117
+               page_cache_release(page);
 
118
+               len -= bytes;
 
119
+               ubuf += bytes;
 
120
+               addr += bytes;
 
121
        }
 
122
-       return copied;
 
123
+       up_read(&mm->mmap_sem);
 
124
+       mmput(mm);
 
125
+
 
126
+       kfree(buf);
 
127
+       return addr - old_addr;
 
128
 }
 
129
 
 
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)
 
132
 {
 
133
-       int copied = 0;
 
134
+       if (!access_ok(VERIFY_WRITE, dst ,len))
 
135
+               return -EIO;
 
136
+       return access_process_vm_user(tsk, src, dst, len, 0, 0);
 
137
+}
 
138
 
 
139
-       while (len > 0) {
 
140
-               char buf[128];
 
141
-               int this_len, retval;
 
142
-
 
143
-               this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
 
144
-               if (copy_from_user(buf, src, this_len))
 
145
-                       return -EFAULT;
 
146
-               retval = access_process_vm(tsk, dst, buf, this_len, 1);
 
147
-               if (!retval) {
 
148
-                       if (copied)
 
149
-                               break;
 
150
-                       return -EIO;
 
151
-               }
 
152
-               copied += retval;
 
153
-               src += retval;
 
154
-               dst += retval;
 
155
-               len -= retval;                  
 
156
-       }
 
157
-       return copied;
 
158
+int ptrace_readstringdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
 
159
+{
 
160
+       if (!access_ok(VERIFY_WRITE, dst ,len))
 
161
+               return -EIO;
 
162
+       return access_process_vm_user(tsk, src, dst, len, 0, 1);
 
163
+}
 
164
+
 
165
+int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len)
 
166
+{
 
167
+       if (!access_ok(VERIFY_READ, dst ,len))
 
168
+               return -EIO;
 
169
+       return access_process_vm_user(tsk, dst, src, len, 1, 0);
 
170
 }
 
171
 
 
172
 static int ptrace_setoptions(struct task_struct *child, long data)
 
173
@@ -447,6 +484,53 @@
 
174
        return child;
 
175
 }
 
176
 
 
177
+static int multi_ptrace(struct task_struct *child, long request, long addr, long size)
 
178
+{
 
179
+       int i, ret;
 
180
+       long j;
 
181
+       ret=0;
 
182
+       if (!access_ok(VERIFY_READ, addr,size*sizeof(struct ptrace_multi))) {
 
183
+               ret = -EIO;
 
184
+               goto out_multi_ptrace;
 
185
+       }
 
186
+       for (i=0; i<size && ret==0; i++, addr+=sizeof(struct ptrace_multi)) {
 
187
+               unsigned long len;
 
188
+               struct ptrace_multi __user pm ;
 
189
+               __copy_from_user(&pm, (struct ptrace_multi __user *)addr, sizeof(struct ptrace_multi));
 
190
+               len = pm.length;
 
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));
 
198
+                               break;
 
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));
 
205
+                               break;
 
206
+                       case PTRACE_PEEKCHARDATA:
 
207
+                               ret = ptrace_readdata(child, pm.addr, pm.localaddr, len);
 
208
+                               break;
 
209
+                       case PTRACE_POKECHARDATA:
 
210
+                               ret = ptrace_writedata(child, pm.localaddr, pm.addr, len);
 
211
+                               break;
 
212
+                       case PTRACE_PEEKSTRINGDATA:
 
213
+                               ret = ptrace_readstringdata(child, pm.addr, pm.localaddr, len);
 
214
+                               break;
 
215
+                       default:
 
216
+                               ret=arch_ptrace(child, pm.request, (long) (pm.addr), (long) (pm.localaddr));
 
217
+                               break;
 
218
+               }
 
219
+       }
 
220
+ out_multi_ptrace:
 
221
+       return ret;
 
222
+}
 
223
+
 
224
 #ifndef __ARCH_SYS_PTRACE
 
225
 asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
 
226
 {
 
227
@@ -477,6 +561,9 @@
 
228
        if (ret < 0)
 
229
                goto out_put_task_struct;
 
230
 
 
231
+       if (request == PTRACE_MULTI) 
 
232
+               ret = multi_ptrace(child, request, addr, data);
 
233
+       else
 
234
        ret = arch_ptrace(child, request, addr, data);
 
235
        if (ret < 0)
 
236
                goto out_put_task_struct;