Commit 481bed454247538e9f57d4ea37b153ccba24ba7b
Committed by
Linus Torvalds
1 parent
db73e9aa99
Exists in
master
and in
39 other branches
[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
- arch/arm26/kernel/ptrace.c
- arch/cris/arch-v10/kernel/ptrace.c
- arch/cris/arch-v32/kernel/ptrace.c
- arch/frv/kernel/ptrace.c
- arch/h8300/kernel/ptrace.c
- arch/i386/kernel/ptrace.c
- arch/m68k/kernel/ptrace.c
- arch/m68knommu/kernel/ptrace.c
- arch/mips/kernel/ptrace.c
- arch/parisc/kernel/ptrace.c
- arch/powerpc/kernel/ptrace.c
- arch/sh/kernel/ptrace.c
- arch/sh64/kernel/ptrace.c
- arch/sh64/kernel/syscalls.S
- arch/um/kernel/ptrace.c
- arch/v850/kernel/ptrace.c
- arch/x86_64/kernel/ptrace.c
- arch/xtensa/kernel/ptrace.c
- include/asm-alpha/ptrace.h
- include/asm-ia64/ptrace.h
- include/asm-m32r/ptrace.h
- include/asm-s390/ptrace.h
- include/asm-sparc/ptrace.h
- include/asm-sparc64/ptrace.h
- include/linux/ptrace.h
- kernel/ptrace.c
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
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
include/asm-ia64/ptrace.h
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
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); |
kernel/ptrace.c
... | ... | @@ -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 */ |