Commit 481bed454247538e9f57d4ea37b153ccba24ba7b

Authored by Christoph Hellwig
Committed by Linus Torvalds
1 parent db73e9aa99

[PATCH] consolidate sys_ptrace()

The sys_ptrace boilerplate code (everything outside the big switch
statement for the arch-specific requests) is shared by most architectures.
This patch moves it to kernel/ptrace.c and leaves the arch-specific code as
arch_ptrace.

Some architectures have a too different ptrace so we have to exclude them.
They continue to keep their implementations.  For sh64 I had to add a
sh64_ptrace wrapper because it does some initialization on the first call.
For um I removed an ifdefed SUBARCH_PTRACE_SPECIAL block, but
SUBARCH_PTRACE_SPECIAL isn't defined anywhere in the tree.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: Paul Mackerras <paulus@samba.org>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Acked-By: David Howells <dhowells@redhat.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 27 changed files with 163 additions and 818 deletions Side-by-side Diff

arch/arm/kernel/ptrace.c
... ... @@ -648,7 +648,7 @@
648 648  
649 649 #endif
650 650  
651   -static int do_ptrace(int request, struct task_struct *child, long addr, long data)
  651 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
652 652 {
653 653 unsigned long tmp;
654 654 int ret;
... ... @@ -779,53 +779,6 @@
779 779 break;
780 780 }
781 781  
782   - return ret;
783   -}
784   -
785   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
786   -{
787   - struct task_struct *child;
788   - int ret;
789   -
790   - lock_kernel();
791   - ret = -EPERM;
792   - if (request == PTRACE_TRACEME) {
793   - /* are we already being traced? */
794   - if (current->ptrace & PT_PTRACED)
795   - goto out;
796   - ret = security_ptrace(current->parent, current);
797   - if (ret)
798   - goto out;
799   - /* set the ptrace bit in the process flags. */
800   - current->ptrace |= PT_PTRACED;
801   - ret = 0;
802   - goto out;
803   - }
804   - ret = -ESRCH;
805   - read_lock(&tasklist_lock);
806   - child = find_task_by_pid(pid);
807   - if (child)
808   - get_task_struct(child);
809   - read_unlock(&tasklist_lock);
810   - if (!child)
811   - goto out;
812   -
813   - ret = -EPERM;
814   - if (pid == 1) /* you may not mess with init */
815   - goto out_tsk;
816   -
817   - if (request == PTRACE_ATTACH) {
818   - ret = ptrace_attach(child);
819   - goto out_tsk;
820   - }
821   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
822   - if (ret == 0)
823   - ret = do_ptrace(request, child, addr, data);
824   -
825   -out_tsk:
826   - put_task_struct(child);
827   -out:
828   - unlock_kernel();
829 782 return ret;
830 783 }
831 784  
arch/arm26/kernel/ptrace.c
... ... @@ -546,7 +546,7 @@
546 546 sizeof(struct user_fp)) ? -EFAULT : 0;
547 547 }
548 548  
549   -static int do_ptrace(int request, struct task_struct *child, long addr, long data)
  549 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
550 550 {
551 551 unsigned long tmp;
552 552 int ret;
... ... @@ -662,53 +662,6 @@
662 662 break;
663 663 }
664 664  
665   - return ret;
666   -}
667   -
668   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
669   -{
670   - struct task_struct *child;
671   - int ret;
672   -
673   - lock_kernel();
674   - ret = -EPERM;
675   - if (request == PTRACE_TRACEME) {
676   - /* are we already being traced? */
677   - if (current->ptrace & PT_PTRACED)
678   - goto out;
679   - ret = security_ptrace(current->parent, current);
680   - if (ret)
681   - goto out;
682   - /* set the ptrace bit in the process flags. */
683   - current->ptrace |= PT_PTRACED;
684   - ret = 0;
685   - goto out;
686   - }
687   - ret = -ESRCH;
688   - read_lock(&tasklist_lock);
689   - child = find_task_by_pid(pid);
690   - if (child)
691   - get_task_struct(child);
692   - read_unlock(&tasklist_lock);
693   - if (!child)
694   - goto out;
695   -
696   - ret = -EPERM;
697   - if (pid == 1) /* you may not mess with init */
698   - goto out_tsk;
699   -
700   - if (request == PTRACE_ATTACH) {
701   - ret = ptrace_attach(child);
702   - goto out_tsk;
703   - }
704   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
705   - if (ret == 0)
706   - ret = do_ptrace(request, child, addr, data);
707   -
708   -out_tsk:
709   - put_task_struct(child);
710   -out:
711   - unlock_kernel();
712 665 return ret;
713 666 }
714 667  
arch/cris/arch-v10/kernel/ptrace.c
... ... @@ -76,55 +76,11 @@
76 76 * (in user space) where the result of the ptrace call is written (instead of
77 77 * being returned).
78 78 */
79   -asmlinkage int
80   -sys_ptrace(long request, long pid, long addr, long data)
  79 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
81 80 {
82   - struct task_struct *child;
83 81 int ret;
84 82 unsigned long __user *datap = (unsigned long __user *)data;
85 83  
86   - lock_kernel();
87   - ret = -EPERM;
88   -
89   - if (request == PTRACE_TRACEME) {
90   - /* are we already being traced? */
91   - if (current->ptrace & PT_PTRACED)
92   - goto out;
93   - ret = security_ptrace(current->parent, current);
94   - if (ret)
95   - goto out;
96   - /* set the ptrace bit in the process flags. */
97   - current->ptrace |= PT_PTRACED;
98   - ret = 0;
99   - goto out;
100   - }
101   -
102   - ret = -ESRCH;
103   - read_lock(&tasklist_lock);
104   - child = find_task_by_pid(pid);
105   -
106   - if (child)
107   - get_task_struct(child);
108   -
109   - read_unlock(&tasklist_lock);
110   -
111   - if (!child)
112   - goto out;
113   -
114   - ret = -EPERM;
115   -
116   - if (pid == 1) /* Leave the init process alone! */
117   - goto out_tsk;
118   -
119   - if (request == PTRACE_ATTACH) {
120   - ret = ptrace_attach(child);
121   - goto out_tsk;
122   - }
123   -
124   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
125   - if (ret < 0)
126   - goto out_tsk;
127   -
128 84 switch (request) {
129 85 /* Read word at location address. */
130 86 case PTRACE_PEEKTEXT:
... ... @@ -289,10 +245,7 @@
289 245 ret = ptrace_request(child, request, addr, data);
290 246 break;
291 247 }
292   -out_tsk:
293   - put_task_struct(child);
294   -out:
295   - unlock_kernel();
  248 +
296 249 return ret;
297 250 }
298 251  
arch/cris/arch-v32/kernel/ptrace.c
... ... @@ -99,55 +99,11 @@
99 99 }
100 100  
101 101  
102   -asmlinkage int
103   -sys_ptrace(long request, long pid, long addr, long data)
  102 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
104 103 {
105   - struct task_struct *child;
106 104 int ret;
107 105 unsigned long __user *datap = (unsigned long __user *)data;
108 106  
109   - lock_kernel();
110   - ret = -EPERM;
111   -
112   - if (request == PTRACE_TRACEME) {
113   - /* are we already being traced? */
114   - if (current->ptrace & PT_PTRACED)
115   - goto out;
116   - ret = security_ptrace(current->parent, current);
117   - if (ret)
118   - goto out;
119   - /* set the ptrace bit in the process flags. */
120   - current->ptrace |= PT_PTRACED;
121   - ret = 0;
122   - goto out;
123   - }
124   -
125   - ret = -ESRCH;
126   - read_lock(&tasklist_lock);
127   - child = find_task_by_pid(pid);
128   -
129   - if (child)
130   - get_task_struct(child);
131   -
132   - read_unlock(&tasklist_lock);
133   -
134   - if (!child)
135   - goto out;
136   -
137   - ret = -EPERM;
138   -
139   - if (pid == 1) /* Leave the init process alone! */
140   - goto out_tsk;
141   -
142   - if (request == PTRACE_ATTACH) {
143   - ret = ptrace_attach(child);
144   - goto out_tsk;
145   - }
146   -
147   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
148   - if (ret < 0)
149   - goto out_tsk;
150   -
151 107 switch (request) {
152 108 /* Read word at location address. */
153 109 case PTRACE_PEEKTEXT:
... ... @@ -347,10 +303,7 @@
347 303 ret = ptrace_request(child, request, addr, data);
348 304 break;
349 305 }
350   -out_tsk:
351   - put_task_struct(child);
352   -out:
353   - unlock_kernel();
  306 +
354 307 return ret;
355 308 }
356 309  
arch/frv/kernel/ptrace.c
... ... @@ -106,48 +106,11 @@
106 106 child->thread.frame0->__status |= REG__STATUS_STEP;
107 107 }
108 108  
109   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  109 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
110 110 {
111   - struct task_struct *child;
112 111 unsigned long tmp;
113 112 int ret;
114 113  
115   - lock_kernel();
116   - ret = -EPERM;
117   - if (request == PTRACE_TRACEME) {
118   - /* are we already being traced? */
119   - if (current->ptrace & PT_PTRACED)
120   - goto out;
121   - ret = security_ptrace(current->parent, current);
122   - if (ret)
123   - goto out;
124   - /* set the ptrace bit in the process flags. */
125   - current->ptrace |= PT_PTRACED;
126   - ret = 0;
127   - goto out;
128   - }
129   - ret = -ESRCH;
130   - read_lock(&tasklist_lock);
131   - child = find_task_by_pid(pid);
132   - if (child)
133   - get_task_struct(child);
134   - read_unlock(&tasklist_lock);
135   - if (!child)
136   - goto out;
137   -
138   - ret = -EPERM;
139   - if (pid == 1) /* you may not mess with init */
140   - goto out_tsk;
141   -
142   - if (request == PTRACE_ATTACH) {
143   - ret = ptrace_attach(child);
144   - goto out_tsk;
145   - }
146   -
147   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
148   - if (ret < 0)
149   - goto out_tsk;
150   -
151 114 switch (request) {
152 115 /* when I and D space are separate, these will need to be fixed. */
153 116 case PTRACE_PEEKTEXT: /* read word at location addr. */
... ... @@ -351,10 +314,6 @@
351 314 ret = -EIO;
352 315 break;
353 316 }
354   -out_tsk:
355   - put_task_struct(child);
356   -out:
357   - unlock_kernel();
358 317 return ret;
359 318 }
360 319  
arch/h8300/kernel/ptrace.c
... ... @@ -57,43 +57,10 @@
57 57 h8300_disable_trace(child);
58 58 }
59 59  
60   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  60 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
61 61 {
62   - struct task_struct *child;
63 62 int ret;
64 63  
65   - lock_kernel();
66   - ret = -EPERM;
67   - if (request == PTRACE_TRACEME) {
68   - /* are we already being traced? */
69   - if (current->ptrace & PT_PTRACED)
70   - goto out;
71   - /* set the ptrace bit in the process flags. */
72   - current->ptrace |= PT_PTRACED;
73   - ret = 0;
74   - goto out;
75   - }
76   - ret = -ESRCH;
77   - read_lock(&tasklist_lock);
78   - child = find_task_by_pid(pid);
79   - if (child)
80   - get_task_struct(child);
81   - read_unlock(&tasklist_lock);
82   - if (!child)
83   - goto out;
84   -
85   - ret = -EPERM;
86   - if (pid == 1) /* you may not mess with init */
87   - goto out_tsk;
88   -
89   - if (request == PTRACE_ATTACH) {
90   - ret = ptrace_attach(child);
91   - goto out_tsk;
92   - }
93   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
94   - if (ret < 0)
95   - goto out_tsk;
96   -
97 64 switch (request) {
98 65 case PTRACE_PEEKTEXT: /* read word at location addr. */
99 66 case PTRACE_PEEKDATA: {
... ... @@ -251,10 +218,6 @@
251 218 ret = -EIO;
252 219 break;
253 220 }
254   -out_tsk:
255   - put_task_struct(child);
256   -out:
257   - unlock_kernel();
258 221 return ret;
259 222 }
260 223  
arch/i386/kernel/ptrace.c
... ... @@ -354,49 +354,12 @@
354 354 return 0;
355 355 }
356 356  
357   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  357 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
358 358 {
359   - struct task_struct *child;
360 359 struct user * dummy = NULL;
361 360 int i, ret;
362 361 unsigned long __user *datap = (unsigned long __user *)data;
363 362  
364   - lock_kernel();
365   - ret = -EPERM;
366   - if (request == PTRACE_TRACEME) {
367   - /* are we already being traced? */
368   - if (current->ptrace & PT_PTRACED)
369   - goto out;
370   - ret = security_ptrace(current->parent, current);
371   - if (ret)
372   - goto out;
373   - /* set the ptrace bit in the process flags. */
374   - current->ptrace |= PT_PTRACED;
375   - ret = 0;
376   - goto out;
377   - }
378   - ret = -ESRCH;
379   - read_lock(&tasklist_lock);
380   - child = find_task_by_pid(pid);
381   - if (child)
382   - get_task_struct(child);
383   - read_unlock(&tasklist_lock);
384   - if (!child)
385   - goto out;
386   -
387   - ret = -EPERM;
388   - if (pid == 1) /* you may not mess with init */
389   - goto out_tsk;
390   -
391   - if (request == PTRACE_ATTACH) {
392   - ret = ptrace_attach(child);
393   - goto out_tsk;
394   - }
395   -
396   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
397   - if (ret < 0)
398   - goto out_tsk;
399   -
400 363 switch (request) {
401 364 /* when I and D space are separate, these will need to be fixed. */
402 365 case PTRACE_PEEKTEXT: /* read word at location addr. */
... ... @@ -663,10 +626,7 @@
663 626 ret = ptrace_request(child, request, addr, data);
664 627 break;
665 628 }
666   -out_tsk:
667   - put_task_struct(child);
668   -out:
669   - unlock_kernel();
  629 + out_tsk:
670 630 return ret;
671 631 }
672 632  
arch/m68k/kernel/ptrace.c
... ... @@ -121,48 +121,11 @@
121 121 child->thread.work.syscall_trace = 0;
122 122 }
123 123  
124   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  124 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
125 125 {
126   - struct task_struct *child;
127 126 unsigned long tmp;
128 127 int i, ret = 0;
129 128  
130   - lock_kernel();
131   - if (request == PTRACE_TRACEME) {
132   - /* are we already being traced? */
133   - if (current->ptrace & PT_PTRACED) {
134   - ret = -EPERM;
135   - goto out;
136   - }
137   - /* set the ptrace bit in the process flags. */
138   - current->ptrace |= PT_PTRACED;
139   - goto out;
140   - }
141   - read_lock(&tasklist_lock);
142   - child = find_task_by_pid(pid);
143   - if (child)
144   - get_task_struct(child);
145   - read_unlock(&tasklist_lock);
146   - if (unlikely(!child)) {
147   - ret = -ESRCH;
148   - goto out;
149   - }
150   -
151   - /* you may not mess with init */
152   - if (unlikely(pid == 1)) {
153   - ret = -EPERM;
154   - goto out_tsk;
155   - }
156   -
157   - if (request == PTRACE_ATTACH) {
158   - ret = ptrace_attach(child);
159   - goto out_tsk;
160   - }
161   -
162   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
163   - if (ret)
164   - goto out_tsk;
165   -
166 129 switch (request) {
167 130 /* when I and D space are separate, these will need to be fixed. */
168 131 case PTRACE_PEEKTEXT: /* read word at location addr. */
169 132  
... ... @@ -317,14 +280,10 @@
317 280 ret = ptrace_request(child, request, addr, data);
318 281 break;
319 282 }
320   -out_tsk:
321   - put_task_struct(child);
322   -out:
323   - unlock_kernel();
  283 +
324 284 return ret;
325 285 out_eio:
326   - ret = -EIO;
327   - goto out_tsk;
  286 + return -EIO;
328 287 }
329 288  
330 289 asmlinkage void syscall_trace(void)
arch/m68knommu/kernel/ptrace.c
... ... @@ -101,43 +101,10 @@
101 101 put_reg(child, PT_SR, tmp);
102 102 }
103 103  
104   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  104 +long arch_ptrace(truct task_struct *child, long request, long addr, long data)
105 105 {
106   - struct task_struct *child;
107 106 int ret;
108 107  
109   - lock_kernel();
110   - ret = -EPERM;
111   - if (request == PTRACE_TRACEME) {
112   - /* are we already being traced? */
113   - if (current->ptrace & PT_PTRACED)
114   - goto out;
115   - /* set the ptrace bit in the process flags. */
116   - current->ptrace |= PT_PTRACED;
117   - ret = 0;
118   - goto out;
119   - }
120   - ret = -ESRCH;
121   - read_lock(&tasklist_lock);
122   - child = find_task_by_pid(pid);
123   - if (child)
124   - get_task_struct(child);
125   - read_unlock(&tasklist_lock);
126   - if (!child)
127   - goto out;
128   -
129   - ret = -EPERM;
130   - if (pid == 1) /* you may not mess with init */
131   - goto out_tsk;
132   -
133   - if (request == PTRACE_ATTACH) {
134   - ret = ptrace_attach(child);
135   - goto out_tsk;
136   - }
137   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
138   - if (ret < 0)
139   - goto out_tsk;
140   -
141 108 switch (request) {
142 109 /* when I and D space are separate, these will need to be fixed. */
143 110 case PTRACE_PEEKTEXT: /* read word at location addr. */
... ... @@ -357,10 +324,6 @@
357 324 ret = -EIO;
358 325 break;
359 326 }
360   -out_tsk:
361   - put_task_struct(child);
362   -out:
363   - unlock_kernel();
364 327 return ret;
365 328 }
366 329  
arch/mips/kernel/ptrace.c
... ... @@ -174,51 +174,10 @@
174 174 return 0;
175 175 }
176 176  
177   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  177 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
178 178 {
179   - struct task_struct *child;
180 179 int ret;
181 180  
182   -#if 0
183   - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
184   - (int) request, (int) pid, (unsigned long) addr,
185   - (unsigned long) data);
186   -#endif
187   - lock_kernel();
188   - ret = -EPERM;
189   - if (request == PTRACE_TRACEME) {
190   - /* are we already being traced? */
191   - if (current->ptrace & PT_PTRACED)
192   - goto out;
193   - if ((ret = security_ptrace(current->parent, current)))
194   - goto out;
195   - /* set the ptrace bit in the process flags. */
196   - current->ptrace |= PT_PTRACED;
197   - ret = 0;
198   - goto out;
199   - }
200   - ret = -ESRCH;
201   - read_lock(&tasklist_lock);
202   - child = find_task_by_pid(pid);
203   - if (child)
204   - get_task_struct(child);
205   - read_unlock(&tasklist_lock);
206   - if (!child)
207   - goto out;
208   -
209   - ret = -EPERM;
210   - if (pid == 1) /* you may not mess with init */
211   - goto out_tsk;
212   -
213   - if (request == PTRACE_ATTACH) {
214   - ret = ptrace_attach(child);
215   - goto out_tsk;
216   - }
217   -
218   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
219   - if (ret < 0)
220   - goto out_tsk;
221   -
222 181 switch (request) {
223 182 /* when I and D space are separate, these will need to be fixed. */
224 183 case PTRACE_PEEKTEXT: /* read word at location addr. */
... ... @@ -319,7 +278,7 @@
319 278 if (!cpu_has_dsp) {
320 279 tmp = 0;
321 280 ret = -EIO;
322   - goto out_tsk;
  281 + goto out;
323 282 }
324 283 if (child->thread.dsp.used_dsp) {
325 284 dregs = __get_dsp_regs(child);
326 285  
... ... @@ -333,14 +292,14 @@
333 292 if (!cpu_has_dsp) {
334 293 tmp = 0;
335 294 ret = -EIO;
336   - goto out_tsk;
  295 + goto out;
337 296 }
338 297 tmp = child->thread.dsp.dspcontrol;
339 298 break;
340 299 default:
341 300 tmp = 0;
342 301 ret = -EIO;
343   - goto out_tsk;
  302 + goto out;
344 303 }
345 304 ret = put_user(tmp, (unsigned long __user *) data);
346 305 break;
... ... @@ -495,11 +454,7 @@
495 454 ret = ptrace_request(child, request, addr, data);
496 455 break;
497 456 }
498   -
499   -out_tsk:
500   - put_task_struct(child);
501   -out:
502   - unlock_kernel();
  457 + out:
503 458 return ret;
504 459 }
505 460  
arch/parisc/kernel/ptrace.c
... ... @@ -78,52 +78,13 @@
78 78 pa_psw(child)->l = 0;
79 79 }
80 80  
81   -long sys_ptrace(long request, long pid, long addr, long data)
  81 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
82 82 {
83   - struct task_struct *child;
84 83 long ret;
85 84 #ifdef DEBUG_PTRACE
86 85 long oaddr=addr, odata=data;
87 86 #endif
88 87  
89   - lock_kernel();
90   - ret = -EPERM;
91   - if (request == PTRACE_TRACEME) {
92   - /* are we already being traced? */
93   - if (current->ptrace & PT_PTRACED)
94   - goto out;
95   -
96   - ret = security_ptrace(current->parent, current);
97   - if (ret)
98   - goto out;
99   -
100   - /* set the ptrace bit in the process flags. */
101   - current->ptrace |= PT_PTRACED;
102   - ret = 0;
103   - goto out;
104   - }
105   -
106   - ret = -ESRCH;
107   - read_lock(&tasklist_lock);
108   - child = find_task_by_pid(pid);
109   - if (child)
110   - get_task_struct(child);
111   - read_unlock(&tasklist_lock);
112   - if (!child)
113   - goto out;
114   - ret = -EPERM;
115   - if (pid == 1) /* no messing around with init! */
116   - goto out_tsk;
117   -
118   - if (request == PTRACE_ATTACH) {
119   - ret = ptrace_attach(child);
120   - goto out_tsk;
121   - }
122   -
123   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
124   - if (ret < 0)
125   - goto out_tsk;
126   -
127 88 switch (request) {
128 89 case PTRACE_PEEKTEXT: /* read word at location addr. */
129 90 case PTRACE_PEEKDATA: {
130 91  
... ... @@ -383,11 +344,11 @@
383 344  
384 345 case PTRACE_GETEVENTMSG:
385 346 ret = put_user(child->ptrace_message, (unsigned int __user *) data);
386   - goto out_tsk;
  347 + goto out;
387 348  
388 349 default:
389 350 ret = ptrace_request(child, request, addr, data);
390   - goto out_tsk;
  351 + goto out;
391 352 }
392 353  
393 354 out_wake_notrap:
... ... @@ -396,10 +357,7 @@
396 357 wake_up_process(child);
397 358 ret = 0;
398 359 out_tsk:
399   - put_task_struct(child);
400   -out:
401   - unlock_kernel();
402   - DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
  360 + DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
403 361 request, pid, oaddr, odata, ret);
404 362 return ret;
405 363 }
arch/powerpc/kernel/ptrace.c
... ... @@ -248,46 +248,10 @@
248 248 clear_single_step(child);
249 249 }
250 250  
251   -long sys_ptrace(long request, long pid, long addr, long data)
  251 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
252 252 {
253   - struct task_struct *child;
254 253 int ret = -EPERM;
255 254  
256   - lock_kernel();
257   - if (request == PTRACE_TRACEME) {
258   - /* are we already being traced? */
259   - if (current->ptrace & PT_PTRACED)
260   - goto out;
261   - ret = security_ptrace(current->parent, current);
262   - if (ret)
263   - goto out;
264   - /* set the ptrace bit in the process flags. */
265   - current->ptrace |= PT_PTRACED;
266   - ret = 0;
267   - goto out;
268   - }
269   - ret = -ESRCH;
270   - read_lock(&tasklist_lock);
271   - child = find_task_by_pid(pid);
272   - if (child)
273   - get_task_struct(child);
274   - read_unlock(&tasklist_lock);
275   - if (!child)
276   - goto out;
277   -
278   - ret = -EPERM;
279   - if (pid == 1) /* you may not mess with init */
280   - goto out_tsk;
281   -
282   - if (request == PTRACE_ATTACH) {
283   - ret = ptrace_attach(child);
284   - goto out_tsk;
285   - }
286   -
287   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
288   - if (ret < 0)
289   - goto out_tsk;
290   -
291 255 switch (request) {
292 256 /* when I and D space are separate, these will need to be fixed. */
293 257 case PTRACE_PEEKTEXT: /* read word at location addr. */
... ... @@ -540,10 +504,7 @@
540 504 ret = ptrace_request(child, request, addr, data);
541 505 break;
542 506 }
543   -out_tsk:
544   - put_task_struct(child);
545   -out:
546   - unlock_kernel();
  507 +
547 508 return ret;
548 509 }
549 510  
arch/sh/kernel/ptrace.c
... ... @@ -80,48 +80,11 @@
80 80 /* nothing to do.. */
81 81 }
82 82  
83   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  83 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
84 84 {
85   - struct task_struct *child;
86 85 struct user * dummy = NULL;
87 86 int ret;
88 87  
89   - lock_kernel();
90   - ret = -EPERM;
91   - if (request == PTRACE_TRACEME) {
92   - /* are we already being traced? */
93   - if (current->ptrace & PT_PTRACED)
94   - goto out;
95   - ret = security_ptrace(current->parent, current);
96   - if (ret)
97   - goto out;
98   - /* set the ptrace bit in the process flags. */
99   - current->ptrace |= PT_PTRACED;
100   - ret = 0;
101   - goto out;
102   - }
103   - ret = -ESRCH;
104   - read_lock(&tasklist_lock);
105   - child = find_task_by_pid(pid);
106   - if (child)
107   - get_task_struct(child);
108   - read_unlock(&tasklist_lock);
109   - if (!child)
110   - goto out;
111   -
112   - ret = -EPERM;
113   - if (pid == 1) /* you may not mess with init */
114   - goto out_tsk;
115   -
116   - if (request == PTRACE_ATTACH) {
117   - ret = ptrace_attach(child);
118   - goto out_tsk;
119   - }
120   -
121   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
122   - if (ret < 0)
123   - goto out_tsk;
124   -
125 88 switch (request) {
126 89 /* when I and D space are separate, these will need to be fixed. */
127 90 case PTRACE_PEEKTEXT: /* read word at location addr. */
... ... @@ -289,10 +252,7 @@
289 252 ret = ptrace_request(child, request, addr, data);
290 253 break;
291 254 }
292   -out_tsk:
293   - put_task_struct(child);
294   -out:
295   - unlock_kernel();
  255 +
296 256 return ret;
297 257 }
298 258  
arch/sh64/kernel/ptrace.c
... ... @@ -28,6 +28,7 @@
28 28 #include <linux/ptrace.h>
29 29 #include <linux/user.h>
30 30 #include <linux/signal.h>
  31 +#include <linux/syscalls.h>
31 32  
32 33 #include <asm/io.h>
33 34 #include <asm/uaccess.h>
34 35  
35 36  
... ... @@ -121,61 +122,11 @@
121 122 return 0;
122 123 }
123 124  
124   -asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  125 +
  126 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
125 127 {
126   - struct task_struct *child;
127   - extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
128   -#define WPC_DBRMODE 0x0d104008
129   - static int first_call = 1;
130 128 int ret;
131 129  
132   - lock_kernel();
133   -
134   - if (first_call) {
135   - /* Set WPC.DBRMODE to 0. This makes all debug events get
136   - * delivered through RESVEC, i.e. into the handlers in entry.S.
137   - * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
138   - * would normally be left set to 1, which makes debug events get
139   - * delivered through DBRVEC, i.e. into the remote gdb's
140   - * handlers. This prevents ptrace getting them, and confuses
141   - * the remote gdb.) */
142   - printk("DBRMODE set to 0 to permit native debugging\n");
143   - poke_real_address_q(WPC_DBRMODE, 0);
144   - first_call = 0;
145   - }
146   -
147   - ret = -EPERM;
148   - if (request == PTRACE_TRACEME) {
149   - /* are we already being traced? */
150   - if (current->ptrace & PT_PTRACED)
151   - goto out;
152   - /* set the ptrace bit in the process flags. */
153   - current->ptrace |= PT_PTRACED;
154   - ret = 0;
155   - goto out;
156   - }
157   - ret = -ESRCH;
158   - read_lock(&tasklist_lock);
159   - child = find_task_by_pid(pid);
160   - if (child)
161   - get_task_struct(child);
162   - read_unlock(&tasklist_lock);
163   - if (!child)
164   - goto out;
165   -
166   - ret = -EPERM;
167   - if (pid == 1) /* you may not mess with init */
168   - goto out_tsk;
169   -
170   - if (request == PTRACE_ATTACH) {
171   - ret = ptrace_attach(child);
172   - goto out_tsk;
173   - }
174   -
175   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
176   - if (ret < 0)
177   - goto out_tsk;
178   -
179 130 switch (request) {
180 131 /* when I and D space are separate, these will need to be fixed. */
181 132 case PTRACE_PEEKTEXT: /* read word at location addr. */
182 133  
... ... @@ -313,11 +264,31 @@
313 264 ret = ptrace_request(child, request, addr, data);
314 265 break;
315 266 }
316   -out_tsk:
317   - put_task_struct(child);
318   -out:
319   - unlock_kernel();
320 267 return ret;
  268 +}
  269 +
  270 +asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
  271 +{
  272 + extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
  273 +#define WPC_DBRMODE 0x0d104008
  274 + static int first_call = 1;
  275 +
  276 + lock_kernel();
  277 + if (first_call) {
  278 + /* Set WPC.DBRMODE to 0. This makes all debug events get
  279 + * delivered through RESVEC, i.e. into the handlers in entry.S.
  280 + * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
  281 + * would normally be left set to 1, which makes debug events get
  282 + * delivered through DBRVEC, i.e. into the remote gdb's
  283 + * handlers. This prevents ptrace getting them, and confuses
  284 + * the remote gdb.) */
  285 + printk("DBRMODE set to 0 to permit native debugging\n");
  286 + poke_real_address_q(WPC_DBRMODE, 0);
  287 + first_call = 0;
  288 + }
  289 + unlock_kernel();
  290 +
  291 + return sys_ptrace(request, pid, addr, data);
321 292 }
322 293  
323 294 asmlinkage void syscall_trace(void)
arch/sh64/kernel/syscalls.S
... ... @@ -46,7 +46,7 @@
46 46 .long sys_setuid16
47 47 .long sys_getuid16
48 48 .long sys_stime /* 25 */
49   - .long sys_ptrace
  49 + .long sh64_ptrace
50 50 .long sys_alarm
51 51 .long sys_fstat
52 52 .long sys_pause
arch/um/kernel/ptrace.c
... ... @@ -43,53 +43,10 @@
43 43 extern int peek_user(struct task_struct * child, long addr, long data);
44 44 extern int poke_user(struct task_struct * child, long addr, long data);
45 45  
46   -long sys_ptrace(long request, long pid, long addr, long data)
  46 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
47 47 {
48   - struct task_struct *child;
49 48 int i, ret;
50 49  
51   - lock_kernel();
52   - ret = -EPERM;
53   - if (request == PTRACE_TRACEME) {
54   - /* are we already being traced? */
55   - if (current->ptrace & PT_PTRACED)
56   - goto out;
57   -
58   - ret = security_ptrace(current->parent, current);
59   - if (ret)
60   - goto out;
61   -
62   - /* set the ptrace bit in the process flags. */
63   - current->ptrace |= PT_PTRACED;
64   - ret = 0;
65   - goto out;
66   - }
67   - ret = -ESRCH;
68   - read_lock(&tasklist_lock);
69   - child = find_task_by_pid(pid);
70   - if (child)
71   - get_task_struct(child);
72   - read_unlock(&tasklist_lock);
73   - if (!child)
74   - goto out;
75   -
76   - ret = -EPERM;
77   - if (pid == 1) /* you may not mess with init */
78   - goto out_tsk;
79   -
80   - if (request == PTRACE_ATTACH) {
81   - ret = ptrace_attach(child);
82   - goto out_tsk;
83   - }
84   -
85   -#ifdef SUBACH_PTRACE_SPECIAL
86   - SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
87   -#endif
88   -
89   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
90   - if (ret < 0)
91   - goto out_tsk;
92   -
93 50 switch (request) {
94 51 /* when I and D space are separate, these will need to be fixed. */
95 52 case PTRACE_PEEKTEXT: /* read word at location addr. */
... ... @@ -282,10 +239,7 @@
282 239 ret = ptrace_request(child, request, addr, data);
283 240 break;
284 241 }
285   - out_tsk:
286   - put_task_struct(child);
287   - out:
288   - unlock_kernel();
  242 +
289 243 return ret;
290 244 }
291 245  
arch/v850/kernel/ptrace.c
... ... @@ -113,45 +113,10 @@
113 113 return 1;
114 114 }
115 115  
116   -long sys_ptrace(long request, long pid, long addr, long data)
  116 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
117 117 {
118   - struct task_struct *child;
119 118 int rval;
120 119  
121   - lock_kernel();
122   -
123   - if (request == PTRACE_TRACEME) {
124   - /* are we already being traced? */
125   - if (current->ptrace & PT_PTRACED) {
126   - rval = -EPERM;
127   - goto out;
128   - }
129   - /* set the ptrace bit in the process flags. */
130   - current->ptrace |= PT_PTRACED;
131   - rval = 0;
132   - goto out;
133   - }
134   - rval = -ESRCH;
135   - read_lock(&tasklist_lock);
136   - child = find_task_by_pid(pid);
137   - if (child)
138   - get_task_struct(child);
139   - read_unlock(&tasklist_lock);
140   - if (!child)
141   - goto out;
142   -
143   - rval = -EPERM;
144   - if (pid == 1) /* you may not mess with init */
145   - goto out_tsk;
146   -
147   - if (request == PTRACE_ATTACH) {
148   - rval = ptrace_attach(child);
149   - goto out_tsk;
150   - }
151   - rval = ptrace_check_attach(child, request == PTRACE_KILL);
152   - if (rval < 0)
153   - goto out_tsk;
154   -
155 120 switch (request) {
156 121 unsigned long val, copied;
157 122  
... ... @@ -248,11 +213,7 @@
248 213 rval = -EIO;
249 214 goto out;
250 215 }
251   -
252   -out_tsk:
253   - put_task_struct(child);
254   -out:
255   - unlock_kernel();
  216 + out:
256 217 return rval;
257 218 }
258 219  
arch/x86_64/kernel/ptrace.c
... ... @@ -313,48 +313,11 @@
313 313  
314 314 }
315 315  
316   -asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data)
  316 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
317 317 {
318   - struct task_struct *child;
319 318 long i, ret;
320 319 unsigned ui;
321 320  
322   - /* This lock_kernel fixes a subtle race with suid exec */
323   - lock_kernel();
324   - ret = -EPERM;
325   - if (request == PTRACE_TRACEME) {
326   - /* are we already being traced? */
327   - if (current->ptrace & PT_PTRACED)
328   - goto out;
329   - ret = security_ptrace(current->parent, current);
330   - if (ret)
331   - goto out;
332   - /* set the ptrace bit in the process flags. */
333   - current->ptrace |= PT_PTRACED;
334   - ret = 0;
335   - goto out;
336   - }
337   - ret = -ESRCH;
338   - read_lock(&tasklist_lock);
339   - child = find_task_by_pid(pid);
340   - if (child)
341   - get_task_struct(child);
342   - read_unlock(&tasklist_lock);
343   - if (!child)
344   - goto out;
345   -
346   - ret = -EPERM;
347   - if (pid == 1) /* you may not mess with init */
348   - goto out_tsk;
349   -
350   - if (request == PTRACE_ATTACH) {
351   - ret = ptrace_attach(child);
352   - goto out_tsk;
353   - }
354   - ret = ptrace_check_attach(child, request == PTRACE_KILL);
355   - if (ret < 0)
356   - goto out_tsk;
357   -
358 321 switch (request) {
359 322 /* when I and D space are separate, these will need to be fixed. */
360 323 case PTRACE_PEEKTEXT: /* read word at location addr. */
... ... @@ -608,10 +571,6 @@
608 571 ret = ptrace_request(child, request, addr, data);
609 572 break;
610 573 }
611   -out_tsk:
612   - put_task_struct(child);
613   -out:
614   - unlock_kernel();
615 574 return ret;
616 575 }
617 576  
arch/xtensa/kernel/ptrace.c
... ... @@ -45,58 +45,10 @@
45 45 /* Nothing to do.. */
46 46 }
47 47  
48   -long sys_ptrace(long request, long pid, long addr, long data)
  48 +long arch_ptrace(struct task_struct *child, long request, long addr, long data)
49 49 {
50   - struct task_struct *child;
51 50 int ret = -EPERM;
52 51  
53   - lock_kernel();
54   -
55   -#if 0
56   - if ((int)request != 1)
57   - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
58   - (int) request, (int) pid, (unsigned long) addr,
59   - (unsigned long) data);
60   -#endif
61   -
62   - if (request == PTRACE_TRACEME) {
63   -
64   - /* Are we already being traced? */
65   -
66   - if (current->ptrace & PT_PTRACED)
67   - goto out;
68   -
69   - if ((ret = security_ptrace(current->parent, current)))
70   - goto out;
71   -
72   - /* Set the ptrace bit in the process flags. */
73   -
74   - current->ptrace |= PT_PTRACED;
75   - ret = 0;
76   - goto out;
77   - }
78   -
79   - ret = -ESRCH;
80   - read_lock(&tasklist_lock);
81   - child = find_task_by_pid(pid);
82   - if (child)
83   - get_task_struct(child);
84   - read_unlock(&tasklist_lock);
85   - if (!child)
86   - goto out;
87   -
88   - ret = -EPERM;
89   - if (pid == 1) /* you may not mess with init */
90   - goto out;
91   -
92   - if (request == PTRACE_ATTACH) {
93   - ret = ptrace_attach(child);
94   - goto out_tsk;
95   - }
96   -
97   - if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0)
98   - goto out_tsk;
99   -
100 52 switch (request) {
101 53 case PTRACE_PEEKTEXT: /* read word at location addr. */
102 54 case PTRACE_PEEKDATA:
... ... @@ -375,10 +327,7 @@
375 327 ret = ptrace_request(child, request, addr, data);
376 328 goto out;
377 329 }
378   -out_tsk:
379   - put_task_struct(child);
380   -out:
381   - unlock_kernel();
  330 + out:
382 331 return ret;
383 332 }
384 333  
include/asm-alpha/ptrace.h
... ... @@ -67,6 +67,9 @@
67 67 };
68 68  
69 69 #ifdef __KERNEL__
  70 +
  71 +#define __ARCH_SYS_PTRACE 1
  72 +
70 73 #define user_mode(regs) (((regs)->ps & 8) != 0)
71 74 #define instruction_pointer(regs) ((regs)->pc)
72 75 #define profile_pc(regs) instruction_pointer(regs)
include/asm-ia64/ptrace.h
... ... @@ -229,6 +229,9 @@
229 229 };
230 230  
231 231 #ifdef __KERNEL__
  232 +
  233 +#define __ARCH_SYS_PTRACE 1
  234 +
232 235 /*
233 236 * We use the ia64_psr(regs)->ri to determine which of the three
234 237 * instructions in bundle (16 bytes) took the sample. Generate
include/asm-m32r/ptrace.h
... ... @@ -145,6 +145,9 @@
145 145 #define PTRACE_O_TRACESYSGOOD 0x00000001
146 146  
147 147 #ifdef __KERNEL__
  148 +
  149 +#define __ARCH_SYS_PTRACE 1
  150 +
148 151 #if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2)
149 152 #define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0)
150 153 #elif defined(CONFIG_ISA_M32R)
include/asm-s390/ptrace.h
... ... @@ -468,6 +468,8 @@
468 468 };
469 469  
470 470 #ifdef __KERNEL__
  471 +#define __ARCH_SYS_PTRACE 1
  472 +
471 473 #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
472 474 #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)
473 475 #define profile_pc(regs) instruction_pointer(regs)
include/asm-sparc/ptrace.h
... ... @@ -60,6 +60,9 @@
60 60 #define STACKFRAME_SZ sizeof(struct sparc_stackf)
61 61  
62 62 #ifdef __KERNEL__
  63 +
  64 +#define __ARCH_SYS_PTRACE 1
  65 +
63 66 #define user_mode(regs) (!((regs)->psr & PSR_PS))
64 67 #define instruction_pointer(regs) ((regs)->pc)
65 68 unsigned long profile_pc(struct pt_regs *);
include/asm-sparc64/ptrace.h
... ... @@ -94,6 +94,9 @@
94 94 #define STACKFRAME32_SZ sizeof(struct sparc_stackf32)
95 95  
96 96 #ifdef __KERNEL__
  97 +
  98 +#define __ARCH_SYS_PTRACE 1
  99 +
97 100 #define force_successful_syscall_return() \
98 101 do { current_thread_info()->syscall_noerror = 1; \
99 102 } while (0)
include/linux/ptrace.h
... ... @@ -78,6 +78,8 @@
78 78 #include <linux/compiler.h> /* For unlikely. */
79 79 #include <linux/sched.h> /* For struct task_struct. */
80 80  
  81 +
  82 +extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
81 83 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
82 84 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
83 85 extern int ptrace_attach(struct task_struct *tsk);
... ... @@ -406,4 +406,86 @@
406 406  
407 407 return ret;
408 408 }
  409 +
  410 +#ifndef __ARCH_SYS_PTRACE
  411 +static int ptrace_get_task_struct(long request, long pid,
  412 + struct task_struct **childp)
  413 +{
  414 + struct task_struct *child;
  415 + int ret;
  416 +
  417 + /*
  418 + * Callers use child == NULL as an indication to exit early even
  419 + * when the return value is 0, so make sure it is non-NULL here.
  420 + */
  421 + *childp = NULL;
  422 +
  423 + if (request == PTRACE_TRACEME) {
  424 + /*
  425 + * Are we already being traced?
  426 + */
  427 + if (current->ptrace & PT_PTRACED)
  428 + return -EPERM;
  429 + ret = security_ptrace(current->parent, current);
  430 + if (ret)
  431 + return -EPERM;
  432 + /*
  433 + * Set the ptrace bit in the process ptrace flags.
  434 + */
  435 + current->ptrace |= PT_PTRACED;
  436 + return 0;
  437 + }
  438 +
  439 + /*
  440 + * You may not mess with init
  441 + */
  442 + if (pid == 1)
  443 + return -EPERM;
  444 +
  445 + ret = -ESRCH;
  446 + read_lock(&tasklist_lock);
  447 + child = find_task_by_pid(pid);
  448 + if (child)
  449 + get_task_struct(child);
  450 + read_unlock(&tasklist_lock);
  451 + if (!child)
  452 + return -ESRCH;
  453 +
  454 + *childp = child;
  455 + return 0;
  456 +}
  457 +
  458 +asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
  459 +{
  460 + struct task_struct *child;
  461 + long ret;
  462 +
  463 + /*
  464 + * This lock_kernel fixes a subtle race with suid exec
  465 + */
  466 + lock_kernel();
  467 + ret = ptrace_get_task_struct(request, pid, &child);
  468 + if (!child)
  469 + goto out;
  470 +
  471 + if (request == PTRACE_ATTACH) {
  472 + ret = ptrace_attach(child);
  473 + goto out;
  474 + }
  475 +
  476 + ret = ptrace_check_attach(child, request == PTRACE_KILL);
  477 + if (ret < 0)
  478 + goto out_put_task_struct;
  479 +
  480 + ret = arch_ptrace(child, request, addr, data);
  481 + if (ret < 0)
  482 + goto out_put_task_struct;
  483 +
  484 + out_put_task_struct:
  485 + put_task_struct(child);
  486 + out:
  487 + unlock_kernel();
  488 + return ret;
  489 +}
  490 +#endif /* __ARCH_SYS_PTRACE */