diff options
| author | Christoph Hellwig <hch@lst.de> | 2005-11-07 03:59:47 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-07 10:53:42 -0500 |
| commit | 481bed454247538e9f57d4ea37b153ccba24ba7b (patch) | |
| tree | bb4198296962c08dbf52e8f377dc27206f621640 | |
| parent | db73e9aa99bf093427b79877f9475392724fd5e5 (diff) | |
[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>
27 files changed, 163 insertions, 818 deletions
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 9bd8609a2926..9a340e790da5 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c | |||
| @@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) | |||
| 648 | 648 | ||
| 649 | #endif | 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 | unsigned long tmp; | 653 | unsigned long tmp; |
| 654 | int ret; | 654 | int ret; |
| @@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat | |||
| 782 | return ret; | 782 | return ret; |
| 783 | } | 783 | } |
| 784 | 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 | return ret; | ||
| 830 | } | ||
| 831 | |||
| 832 | asmlinkage void syscall_trace(int why, struct pt_regs *regs) | 785 | asmlinkage void syscall_trace(int why, struct pt_regs *regs) |
| 833 | { | 786 | { |
| 834 | unsigned long ip; | 787 | unsigned long ip; |
diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index cf7e977d18c8..4e6b7356a722 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c | |||
| @@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) | |||
| 546 | sizeof(struct user_fp)) ? -EFAULT : 0; | 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 | unsigned long tmp; | 551 | unsigned long tmp; |
| 552 | int ret; | 552 | int ret; |
| @@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat | |||
| 665 | return ret; | 665 | return ret; |
| 666 | } | 666 | } |
| 667 | 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 | return ret; | ||
| 713 | } | ||
| 714 | |||
| 715 | asmlinkage void syscall_trace(int why, struct pt_regs *regs) | 668 | asmlinkage void syscall_trace(int why, struct pt_regs *regs) |
| 716 | { | 669 | { |
| 717 | unsigned long ip; | 670 | unsigned long ip; |
diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 130dd214e41d..6cbd34a27b90 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c | |||
| @@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child) | |||
| 76 | * (in user space) where the result of the ptrace call is written (instead of | 76 | * (in user space) where the result of the ptrace call is written (instead of |
| 77 | * being returned). | 77 | * being returned). |
| 78 | */ | 78 | */ |
| 79 | asmlinkage int | 79 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
| 80 | sys_ptrace(long request, long pid, long addr, long data) | ||
| 81 | { | 80 | { |
| 82 | struct task_struct *child; | ||
| 83 | int ret; | 81 | int ret; |
| 84 | unsigned long __user *datap = (unsigned long __user *)data; | 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 | switch (request) { | 84 | switch (request) { |
| 129 | /* Read word at location address. */ | 85 | /* Read word at location address. */ |
| 130 | case PTRACE_PEEKTEXT: | 86 | case PTRACE_PEEKTEXT: |
| @@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data) | |||
| 289 | ret = ptrace_request(child, request, addr, data); | 245 | ret = ptrace_request(child, request, addr, data); |
| 290 | break; | 246 | break; |
| 291 | } | 247 | } |
| 292 | out_tsk: | 248 | |
| 293 | put_task_struct(child); | ||
| 294 | out: | ||
| 295 | unlock_kernel(); | ||
| 296 | return ret; | 249 | return ret; |
| 297 | } | 250 | } |
| 298 | 251 | ||
diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index 208489da2a87..5528b83a622b 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c | |||
| @@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child) | |||
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | 101 | ||
| 102 | asmlinkage int | 102 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
| 103 | sys_ptrace(long request, long pid, long addr, long data) | ||
| 104 | { | 103 | { |
| 105 | struct task_struct *child; | ||
| 106 | int ret; | 104 | int ret; |
| 107 | unsigned long __user *datap = (unsigned long __user *)data; | 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 | switch (request) { | 107 | switch (request) { |
| 152 | /* Read word at location address. */ | 108 | /* Read word at location address. */ |
| 153 | case PTRACE_PEEKTEXT: | 109 | case PTRACE_PEEKTEXT: |
| @@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data) | |||
| 347 | ret = ptrace_request(child, request, addr, data); | 303 | ret = ptrace_request(child, request, addr, data); |
| 348 | break; | 304 | break; |
| 349 | } | 305 | } |
| 350 | out_tsk: | 306 | |
| 351 | put_task_struct(child); | ||
| 352 | out: | ||
| 353 | unlock_kernel(); | ||
| 354 | return ret; | 307 | return ret; |
| 355 | } | 308 | } |
| 356 | 309 | ||
diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index cb335a14a315..f953484e7d59 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c | |||
| @@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child) | |||
| 106 | child->thread.frame0->__status |= REG__STATUS_STEP; | 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 | unsigned long tmp; | 111 | unsigned long tmp; |
| 113 | int ret; | 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 | switch (request) { | 114 | switch (request) { |
| 152 | /* when I and D space are separate, these will need to be fixed. */ | 115 | /* when I and D space are separate, these will need to be fixed. */ |
| 153 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 116 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 351 | ret = -EIO; | 314 | ret = -EIO; |
| 352 | break; | 315 | break; |
| 353 | } | 316 | } |
| 354 | out_tsk: | ||
| 355 | put_task_struct(child); | ||
| 356 | out: | ||
| 357 | unlock_kernel(); | ||
| 358 | return ret; | 317 | return ret; |
| 359 | } | 318 | } |
| 360 | 319 | ||
diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index a569fe4aa284..0ff6f79b0fed 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c | |||
| @@ -57,43 +57,10 @@ void ptrace_disable(struct task_struct *child) | |||
| 57 | h8300_disable_trace(child); | 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 | int ret; | 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 | switch (request) { | 64 | switch (request) { |
| 98 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 65 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| 99 | case PTRACE_PEEKDATA: { | 66 | case PTRACE_PEEKDATA: { |
| @@ -251,10 +218,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 251 | ret = -EIO; | 218 | ret = -EIO; |
| 252 | break; | 219 | break; |
| 253 | } | 220 | } |
| 254 | out_tsk: | ||
| 255 | put_task_struct(child); | ||
| 256 | out: | ||
| 257 | unlock_kernel(); | ||
| 258 | return ret; | 221 | return ret; |
| 259 | } | 222 | } |
| 260 | 223 | ||
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index efd11f09c996..5ffbb4b7ad05 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c | |||
| @@ -354,49 +354,12 @@ ptrace_set_thread_area(struct task_struct *child, | |||
| 354 | return 0; | 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 | struct user * dummy = NULL; | 359 | struct user * dummy = NULL; |
| 361 | int i, ret; | 360 | int i, ret; |
| 362 | unsigned long __user *datap = (unsigned long __user *)data; | 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 | switch (request) { | 363 | switch (request) { |
| 401 | /* when I and D space are separate, these will need to be fixed. */ | 364 | /* when I and D space are separate, these will need to be fixed. */ |
| 402 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 365 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -663,10 +626,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 663 | ret = ptrace_request(child, request, addr, data); | 626 | ret = ptrace_request(child, request, addr, data); |
| 664 | break; | 627 | break; |
| 665 | } | 628 | } |
| 666 | out_tsk: | 629 | out_tsk: |
| 667 | put_task_struct(child); | ||
| 668 | out: | ||
| 669 | unlock_kernel(); | ||
| 670 | return ret; | 630 | return ret; |
| 671 | } | 631 | } |
| 672 | 632 | ||
diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index f7f1d2e5b90b..7e54422685cf 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c | |||
| @@ -121,48 +121,11 @@ void ptrace_disable(struct task_struct *child) | |||
| 121 | child->thread.work.syscall_trace = 0; | 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 | unsigned long tmp; | 126 | unsigned long tmp; |
| 128 | int i, ret = 0; | 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 | switch (request) { | 129 | switch (request) { |
| 167 | /* when I and D space are separate, these will need to be fixed. */ | 130 | /* when I and D space are separate, these will need to be fixed. */ |
| 168 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 131 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -317,14 +280,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 317 | ret = ptrace_request(child, request, addr, data); | 280 | ret = ptrace_request(child, request, addr, data); |
| 318 | break; | 281 | break; |
| 319 | } | 282 | } |
| 320 | out_tsk: | 283 | |
| 321 | put_task_struct(child); | ||
| 322 | out: | ||
| 323 | unlock_kernel(); | ||
| 324 | return ret; | 284 | return ret; |
| 325 | out_eio: | 285 | out_eio: |
| 326 | ret = -EIO; | 286 | return -EIO; |
| 327 | goto out_tsk; | ||
| 328 | } | 287 | } |
| 329 | 288 | ||
| 330 | asmlinkage void syscall_trace(void) | 289 | asmlinkage void syscall_trace(void) |
diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 621d7b91ccfe..262ab8c72e5f 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c | |||
| @@ -101,43 +101,10 @@ void ptrace_disable(struct task_struct *child) | |||
| 101 | put_reg(child, PT_SR, tmp); | 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 | int ret; | 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 | switch (request) { | 108 | switch (request) { |
| 142 | /* when I and D space are separate, these will need to be fixed. */ | 109 | /* when I and D space are separate, these will need to be fixed. */ |
| 143 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 110 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -357,10 +324,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 357 | ret = -EIO; | 324 | ret = -EIO; |
| 358 | break; | 325 | break; |
| 359 | } | 326 | } |
| 360 | out_tsk: | ||
| 361 | put_task_struct(child); | ||
| 362 | out: | ||
| 363 | unlock_kernel(); | ||
| 364 | return ret; | 327 | return ret; |
| 365 | } | 328 | } |
| 366 | 329 | ||
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index f1b0f3e1f95b..510da5fda567 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
| @@ -174,51 +174,10 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data) | |||
| 174 | return 0; | 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 | int ret; | 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 | switch (request) { | 181 | switch (request) { |
| 223 | /* when I and D space are separate, these will need to be fixed. */ | 182 | /* when I and D space are separate, these will need to be fixed. */ |
| 224 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 183 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -319,7 +278,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 319 | if (!cpu_has_dsp) { | 278 | if (!cpu_has_dsp) { |
| 320 | tmp = 0; | 279 | tmp = 0; |
| 321 | ret = -EIO; | 280 | ret = -EIO; |
| 322 | goto out_tsk; | 281 | goto out; |
| 323 | } | 282 | } |
| 324 | if (child->thread.dsp.used_dsp) { | 283 | if (child->thread.dsp.used_dsp) { |
| 325 | dregs = __get_dsp_regs(child); | 284 | dregs = __get_dsp_regs(child); |
| @@ -333,14 +292,14 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 333 | if (!cpu_has_dsp) { | 292 | if (!cpu_has_dsp) { |
| 334 | tmp = 0; | 293 | tmp = 0; |
| 335 | ret = -EIO; | 294 | ret = -EIO; |
| 336 | goto out_tsk; | 295 | goto out; |
| 337 | } | 296 | } |
| 338 | tmp = child->thread.dsp.dspcontrol; | 297 | tmp = child->thread.dsp.dspcontrol; |
| 339 | break; | 298 | break; |
| 340 | default: | 299 | default: |
| 341 | tmp = 0; | 300 | tmp = 0; |
| 342 | ret = -EIO; | 301 | ret = -EIO; |
| 343 | goto out_tsk; | 302 | goto out; |
| 344 | } | 303 | } |
| 345 | ret = put_user(tmp, (unsigned long __user *) data); | 304 | ret = put_user(tmp, (unsigned long __user *) data); |
| 346 | break; | 305 | break; |
| @@ -495,11 +454,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 495 | ret = ptrace_request(child, request, addr, data); | 454 | ret = ptrace_request(child, request, addr, data); |
| 496 | break; | 455 | break; |
| 497 | } | 456 | } |
| 498 | 457 | out: | |
| 499 | out_tsk: | ||
| 500 | put_task_struct(child); | ||
| 501 | out: | ||
| 502 | unlock_kernel(); | ||
| 503 | return ret; | 458 | return ret; |
| 504 | } | 459 | } |
| 505 | 460 | ||
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 18130c3748f3..b6fe202a620d 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c | |||
| @@ -78,52 +78,13 @@ void ptrace_disable(struct task_struct *child) | |||
| 78 | pa_psw(child)->l = 0; | 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 | long ret; | 83 | long ret; |
| 85 | #ifdef DEBUG_PTRACE | 84 | #ifdef DEBUG_PTRACE |
| 86 | long oaddr=addr, odata=data; | 85 | long oaddr=addr, odata=data; |
| 87 | #endif | 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 | switch (request) { | 88 | switch (request) { |
| 128 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 89 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| 129 | case PTRACE_PEEKDATA: { | 90 | case PTRACE_PEEKDATA: { |
| @@ -383,11 +344,11 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 383 | 344 | ||
| 384 | case PTRACE_GETEVENTMSG: | 345 | case PTRACE_GETEVENTMSG: |
| 385 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); | 346 | ret = put_user(child->ptrace_message, (unsigned int __user *) data); |
| 386 | goto out_tsk; | 347 | goto out; |
| 387 | 348 | ||
| 388 | default: | 349 | default: |
| 389 | ret = ptrace_request(child, request, addr, data); | 350 | ret = ptrace_request(child, request, addr, data); |
| 390 | goto out_tsk; | 351 | goto out; |
| 391 | } | 352 | } |
| 392 | 353 | ||
| 393 | out_wake_notrap: | 354 | out_wake_notrap: |
| @@ -396,10 +357,7 @@ out_wake: | |||
| 396 | wake_up_process(child); | 357 | wake_up_process(child); |
| 397 | ret = 0; | 358 | ret = 0; |
| 398 | out_tsk: | 359 | out_tsk: |
| 399 | put_task_struct(child); | 360 | DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n", |
| 400 | out: | ||
| 401 | unlock_kernel(); | ||
| 402 | DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n", | ||
| 403 | request, pid, oaddr, odata, ret); | 361 | request, pid, oaddr, odata, ret); |
| 404 | return ret; | 362 | return ret; |
| 405 | } | 363 | } |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 568ea335d616..3d2abd95c7ae 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
| @@ -248,46 +248,10 @@ void ptrace_disable(struct task_struct *child) | |||
| 248 | clear_single_step(child); | 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 | int ret = -EPERM; | 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 | switch (request) { | 255 | switch (request) { |
| 292 | /* when I and D space are separate, these will need to be fixed. */ | 256 | /* when I and D space are separate, these will need to be fixed. */ |
| 293 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 257 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -540,10 +504,7 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 540 | ret = ptrace_request(child, request, addr, data); | 504 | ret = ptrace_request(child, request, addr, data); |
| 541 | break; | 505 | break; |
| 542 | } | 506 | } |
| 543 | out_tsk: | 507 | |
| 544 | put_task_struct(child); | ||
| 545 | out: | ||
| 546 | unlock_kernel(); | ||
| 547 | return ret; | 508 | return ret; |
| 548 | } | 509 | } |
| 549 | 510 | ||
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 1fbe5a428e31..1a8be06519ec 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c | |||
| @@ -80,48 +80,11 @@ void ptrace_disable(struct task_struct *child) | |||
| 80 | /* nothing to do.. */ | 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 | struct user * dummy = NULL; | 85 | struct user * dummy = NULL; |
| 87 | int ret; | 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 | switch (request) { | 88 | switch (request) { |
| 126 | /* when I and D space are separate, these will need to be fixed. */ | 89 | /* when I and D space are separate, these will need to be fixed. */ |
| 127 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 90 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -289,10 +252,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 289 | ret = ptrace_request(child, request, addr, data); | 252 | ret = ptrace_request(child, request, addr, data); |
| 290 | break; | 253 | break; |
| 291 | } | 254 | } |
| 292 | out_tsk: | 255 | |
| 293 | put_task_struct(child); | ||
| 294 | out: | ||
| 295 | unlock_kernel(); | ||
| 296 | return ret; | 256 | return ret; |
| 297 | } | 257 | } |
| 298 | 258 | ||
diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index 71f2eec00b99..cd22e9471316 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/ptrace.h> | 28 | #include <linux/ptrace.h> |
| 29 | #include <linux/user.h> | 29 | #include <linux/user.h> |
| 30 | #include <linux/signal.h> | 30 | #include <linux/signal.h> |
| 31 | #include <linux/syscalls.h> | ||
| 31 | 32 | ||
| 32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
| 33 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
| @@ -121,61 +122,11 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) | |||
| 121 | return 0; | 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 | int ret; | 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 | switch (request) { | 130 | switch (request) { |
| 180 | /* when I and D space are separate, these will need to be fixed. */ | 131 | /* when I and D space are separate, these will need to be fixed. */ |
| 181 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 132 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -313,13 +264,33 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) | |||
| 313 | ret = ptrace_request(child, request, addr, data); | 264 | ret = ptrace_request(child, request, addr, data); |
| 314 | break; | 265 | break; |
| 315 | } | 266 | } |
| 316 | out_tsk: | ||
| 317 | put_task_struct(child); | ||
| 318 | out: | ||
| 319 | unlock_kernel(); | ||
| 320 | return ret; | 267 | return ret; |
| 321 | } | 268 | } |
| 322 | 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); | ||
| 292 | } | ||
| 293 | |||
| 323 | asmlinkage void syscall_trace(void) | 294 | asmlinkage void syscall_trace(void) |
| 324 | { | 295 | { |
| 325 | struct task_struct *tsk = current; | 296 | struct task_struct *tsk = current; |
diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S index a3d037805f1c..c0079d54c850 100644 --- a/arch/sh64/kernel/syscalls.S +++ b/arch/sh64/kernel/syscalls.S | |||
| @@ -46,7 +46,7 @@ sys_call_table: | |||
| 46 | .long sys_setuid16 | 46 | .long sys_setuid16 |
| 47 | .long sys_getuid16 | 47 | .long sys_getuid16 |
| 48 | .long sys_stime /* 25 */ | 48 | .long sys_stime /* 25 */ |
| 49 | .long sys_ptrace | 49 | .long sh64_ptrace |
| 50 | .long sys_alarm | 50 | .long sys_alarm |
| 51 | .long sys_fstat | 51 | .long sys_fstat |
| 52 | .long sys_pause | 52 | .long sys_pause |
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 71af4d503899..98e09395c093 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
| @@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child) | |||
| 43 | extern int peek_user(struct task_struct * child, long addr, long data); | 43 | extern int peek_user(struct task_struct * child, long addr, long data); |
| 44 | extern int poke_user(struct task_struct * child, long addr, long data); | 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 | int i, ret; | 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 | switch (request) { | 50 | switch (request) { |
| 94 | /* when I and D space are separate, these will need to be fixed. */ | 51 | /* when I and D space are separate, these will need to be fixed. */ |
| 95 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 52 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -282,10 +239,7 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 282 | ret = ptrace_request(child, request, addr, data); | 239 | ret = ptrace_request(child, request, addr, data); |
| 283 | break; | 240 | break; |
| 284 | } | 241 | } |
| 285 | out_tsk: | 242 | |
| 286 | put_task_struct(child); | ||
| 287 | out: | ||
| 288 | unlock_kernel(); | ||
| 289 | return ret; | 243 | return ret; |
| 290 | } | 244 | } |
| 291 | 245 | ||
diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index d6077ff47d22..18492d02aaf6 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c | |||
| @@ -113,45 +113,10 @@ static int set_single_step (struct task_struct *t, int val) | |||
| 113 | return 1; | 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 | int rval; | 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 | switch (request) { | 120 | switch (request) { |
| 156 | unsigned long val, copied; | 121 | unsigned long val, copied; |
| 157 | 122 | ||
| @@ -248,11 +213,7 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 248 | rval = -EIO; | 213 | rval = -EIO; |
| 249 | goto out; | 214 | goto out; |
| 250 | } | 215 | } |
| 251 | 216 | out: | |
| 252 | out_tsk: | ||
| 253 | put_task_struct(child); | ||
| 254 | out: | ||
| 255 | unlock_kernel(); | ||
| 256 | return rval; | 217 | return rval; |
| 257 | } | 218 | } |
| 258 | 219 | ||
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index bbf64b59a21e..a87b6cebe80f 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c | |||
| @@ -313,48 +313,11 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno) | |||
| 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 | long i, ret; | 318 | long i, ret; |
| 320 | unsigned ui; | 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 | switch (request) { | 321 | switch (request) { |
| 359 | /* when I and D space are separate, these will need to be fixed. */ | 322 | /* when I and D space are separate, these will need to be fixed. */ |
| 360 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 323 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| @@ -608,10 +571,6 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data | |||
| 608 | ret = ptrace_request(child, request, addr, data); | 571 | ret = ptrace_request(child, request, addr, data); |
| 609 | break; | 572 | break; |
| 610 | } | 573 | } |
| 611 | out_tsk: | ||
| 612 | put_task_struct(child); | ||
| 613 | out: | ||
| 614 | unlock_kernel(); | ||
| 615 | return ret; | 574 | return ret; |
| 616 | } | 575 | } |
| 617 | 576 | ||
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 14460743de07..ab5c4c65b5c4 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c | |||
| @@ -45,58 +45,10 @@ void ptrace_disable(struct task_struct *child) | |||
| 45 | /* Nothing to do.. */ | 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 | int ret = -EPERM; | 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 | switch (request) { | 52 | switch (request) { |
| 101 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 53 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
| 102 | case PTRACE_PEEKDATA: | 54 | case PTRACE_PEEKDATA: |
| @@ -375,10 +327,7 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 375 | ret = ptrace_request(child, request, addr, data); | 327 | ret = ptrace_request(child, request, addr, data); |
| 376 | goto out; | 328 | goto out; |
| 377 | } | 329 | } |
| 378 | out_tsk: | 330 | out: |
| 379 | put_task_struct(child); | ||
| 380 | out: | ||
| 381 | unlock_kernel(); | ||
| 382 | return ret; | 331 | return ret; |
| 383 | } | 332 | } |
| 384 | 333 | ||
diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h index d462c5e14c13..072375c135b4 100644 --- a/include/asm-alpha/ptrace.h +++ b/include/asm-alpha/ptrace.h | |||
| @@ -67,6 +67,9 @@ struct switch_stack { | |||
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | #ifdef __KERNEL__ | 69 | #ifdef __KERNEL__ |
| 70 | |||
| 71 | #define __ARCH_SYS_PTRACE 1 | ||
| 72 | |||
| 70 | #define user_mode(regs) (((regs)->ps & 8) != 0) | 73 | #define user_mode(regs) (((regs)->ps & 8) != 0) |
| 71 | #define instruction_pointer(regs) ((regs)->pc) | 74 | #define instruction_pointer(regs) ((regs)->pc) |
| 72 | #define profile_pc(regs) instruction_pointer(regs) | 75 | #define profile_pc(regs) instruction_pointer(regs) |
diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h index a79d1a7ecc77..2c703d6e0c86 100644 --- a/include/asm-ia64/ptrace.h +++ b/include/asm-ia64/ptrace.h | |||
| @@ -229,6 +229,9 @@ struct switch_stack { | |||
| 229 | }; | 229 | }; |
| 230 | 230 | ||
| 231 | #ifdef __KERNEL__ | 231 | #ifdef __KERNEL__ |
| 232 | |||
| 233 | #define __ARCH_SYS_PTRACE 1 | ||
| 234 | |||
| 232 | /* | 235 | /* |
| 233 | * We use the ia64_psr(regs)->ri to determine which of the three | 236 | * We use the ia64_psr(regs)->ri to determine which of the three |
| 234 | * instructions in bundle (16 bytes) took the sample. Generate | 237 | * instructions in bundle (16 bytes) took the sample. Generate |
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h index 976417126b2d..55cd7ecfde43 100644 --- a/include/asm-m32r/ptrace.h +++ b/include/asm-m32r/ptrace.h | |||
| @@ -145,6 +145,9 @@ struct pt_regs { | |||
| 145 | #define PTRACE_O_TRACESYSGOOD 0x00000001 | 145 | #define PTRACE_O_TRACESYSGOOD 0x00000001 |
| 146 | 146 | ||
| 147 | #ifdef __KERNEL__ | 147 | #ifdef __KERNEL__ |
| 148 | |||
| 149 | #define __ARCH_SYS_PTRACE 1 | ||
| 150 | |||
| 148 | #if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2) | 151 | #if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2) |
| 149 | #define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0) | 152 | #define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0) |
| 150 | #elif defined(CONFIG_ISA_M32R) | 153 | #elif defined(CONFIG_ISA_M32R) |
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index fc7c96edc697..a949cc077cc7 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h | |||
| @@ -468,6 +468,8 @@ struct user_regs_struct | |||
| 468 | }; | 468 | }; |
| 469 | 469 | ||
| 470 | #ifdef __KERNEL__ | 470 | #ifdef __KERNEL__ |
| 471 | #define __ARCH_SYS_PTRACE 1 | ||
| 472 | |||
| 471 | #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) | 473 | #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) |
| 472 | #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) | 474 | #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) |
| 473 | #define profile_pc(regs) instruction_pointer(regs) | 475 | #define profile_pc(regs) instruction_pointer(regs) |
diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h index a8ecb2d6977a..714497099a42 100644 --- a/include/asm-sparc/ptrace.h +++ b/include/asm-sparc/ptrace.h | |||
| @@ -60,6 +60,9 @@ struct sparc_stackf { | |||
| 60 | #define STACKFRAME_SZ sizeof(struct sparc_stackf) | 60 | #define STACKFRAME_SZ sizeof(struct sparc_stackf) |
| 61 | 61 | ||
| 62 | #ifdef __KERNEL__ | 62 | #ifdef __KERNEL__ |
| 63 | |||
| 64 | #define __ARCH_SYS_PTRACE 1 | ||
| 65 | |||
| 63 | #define user_mode(regs) (!((regs)->psr & PSR_PS)) | 66 | #define user_mode(regs) (!((regs)->psr & PSR_PS)) |
| 64 | #define instruction_pointer(regs) ((regs)->pc) | 67 | #define instruction_pointer(regs) ((regs)->pc) |
| 65 | unsigned long profile_pc(struct pt_regs *); | 68 | unsigned long profile_pc(struct pt_regs *); |
diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index 6194f771e9fc..7eba90c6c753 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h | |||
| @@ -94,6 +94,9 @@ struct sparc_trapf { | |||
| 94 | #define STACKFRAME32_SZ sizeof(struct sparc_stackf32) | 94 | #define STACKFRAME32_SZ sizeof(struct sparc_stackf32) |
| 95 | 95 | ||
| 96 | #ifdef __KERNEL__ | 96 | #ifdef __KERNEL__ |
| 97 | |||
| 98 | #define __ARCH_SYS_PTRACE 1 | ||
| 99 | |||
| 97 | #define force_successful_syscall_return() \ | 100 | #define force_successful_syscall_return() \ |
| 98 | do { current_thread_info()->syscall_noerror = 1; \ | 101 | do { current_thread_info()->syscall_noerror = 1; \ |
| 99 | } while (0) | 102 | } while (0) |
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index dc6f3647bfbc..b2b3dba1298d 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
| @@ -78,6 +78,8 @@ | |||
| 78 | #include <linux/compiler.h> /* For unlikely. */ | 78 | #include <linux/compiler.h> /* For unlikely. */ |
| 79 | #include <linux/sched.h> /* For struct task_struct. */ | 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 | extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); | 83 | extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); |
| 82 | extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); | 84 | extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); |
| 83 | extern int ptrace_attach(struct task_struct *tsk); | 85 | extern int ptrace_attach(struct task_struct *tsk); |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 863eee8bff47..5b8dd98a230e 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -406,3 +406,85 @@ int ptrace_request(struct task_struct *child, long request, | |||
| 406 | 406 | ||
| 407 | return ret; | 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 */ | ||
