aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-02-07 06:00:17 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-07 06:00:17 -0500
commit9775369ec06bad8edb2fbd8c77316f49b439c225 (patch)
tree14b0cb23d5fad3dbd99da0e21cf1b7e3db92595f /arch
parent190aa9f60f9575d1b7382cd1ee33e2589208c514 (diff)
[SPARC]: Move over to arch_ptrace().
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/kernel/entry.S17
-rw-r--r--arch/sparc/kernel/ptrace.c462
-rw-r--r--arch/sparc64/kernel/entry.S4
-rw-r--r--arch/sparc64/kernel/ptrace.c389
4 files changed, 172 insertions, 700 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 88d2cefd01be..c2eed8f71516 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -1224,23 +1224,6 @@ sys_nis_syscall:
1224 call c_sys_nis_syscall 1224 call c_sys_nis_syscall
1225 mov %l5, %o7 1225 mov %l5, %o7
1226 1226
1227 .align 4
1228 .globl sys_ptrace
1229sys_ptrace:
1230 call do_ptrace
1231 add %sp, STACKFRAME_SZ, %o0
1232
1233 ld [%curptr + TI_FLAGS], %l5
1234 andcc %l5, _TIF_SYSCALL_TRACE, %g0
1235 be 1f
1236 nop
1237
1238 call syscall_trace
1239 nop
1240
12411:
1242 RESTORE_ALL
1243
1244 .align 4 1227 .align 4
1245 .globl sys_execve 1228 .globl sys_execve
1246sys_execve: 1229sys_execve:
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 29fa6e5cb450..1c0d5363f720 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -26,215 +26,6 @@
26#include <asm/system.h> 26#include <asm/system.h>
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28 28
29#define MAGIC_CONSTANT 0x80000000
30
31
32/* Returning from ptrace is a bit tricky because the syscall return
33 * low level code assumes any value returned which is negative and
34 * is a valid errno will mean setting the condition codes to indicate
35 * an error return. This doesn't work, so we have this hook.
36 */
37static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
38{
39 regs->u_regs[UREG_I0] = error;
40 regs->psr |= PSR_C;
41 regs->pc = regs->npc;
42 regs->npc += 4;
43}
44
45static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
46{
47 regs->u_regs[UREG_I0] = value;
48 regs->psr &= ~PSR_C;
49 regs->pc = regs->npc;
50 regs->npc += 4;
51}
52
53static void
54pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long __user *addr)
55{
56 if (put_user(value, addr)) {
57 pt_error_return(regs, EFAULT);
58 return;
59 }
60 regs->u_regs[UREG_I0] = 0;
61 regs->psr &= ~PSR_C;
62 regs->pc = regs->npc;
63 regs->npc += 4;
64}
65
66static void
67pt_os_succ_return (struct pt_regs *regs, unsigned long val, long __user *addr)
68{
69 if (current->personality == PER_SUNOS)
70 pt_succ_return (regs, val);
71 else
72 pt_succ_return_linux (regs, val, addr);
73}
74
75/* Fuck me gently with a chainsaw... */
76static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
77 struct task_struct *tsk, long __user *addr)
78{
79 struct pt_regs *cregs = tsk->thread.kregs;
80 struct thread_info *t = task_thread_info(tsk);
81 int v;
82
83 if(offset >= 1024)
84 offset -= 1024; /* whee... */
85 if(offset & ((sizeof(unsigned long) - 1))) {
86 pt_error_return(regs, EIO);
87 return;
88 }
89 if(offset >= 16 && offset < 784) {
90 offset -= 16; offset >>= 2;
91 pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);
92 return;
93 }
94 if(offset >= 784 && offset < 832) {
95 offset -= 784; offset >>= 2;
96 pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);
97 return;
98 }
99 switch(offset) {
100 case 0:
101 v = t->ksp;
102 break;
103 case 4:
104 v = t->kpc;
105 break;
106 case 8:
107 v = t->kpsr;
108 break;
109 case 12:
110 v = t->uwinmask;
111 break;
112 case 832:
113 v = t->w_saved;
114 break;
115 case 896:
116 v = cregs->u_regs[UREG_I0];
117 break;
118 case 900:
119 v = cregs->u_regs[UREG_I1];
120 break;
121 case 904:
122 v = cregs->u_regs[UREG_I2];
123 break;
124 case 908:
125 v = cregs->u_regs[UREG_I3];
126 break;
127 case 912:
128 v = cregs->u_regs[UREG_I4];
129 break;
130 case 916:
131 v = cregs->u_regs[UREG_I5];
132 break;
133 case 920:
134 v = cregs->u_regs[UREG_I6];
135 break;
136 case 924:
137 if(tsk->thread.flags & MAGIC_CONSTANT)
138 v = cregs->u_regs[UREG_G1];
139 else
140 v = 0;
141 break;
142 case 940:
143 v = cregs->u_regs[UREG_I0];
144 break;
145 case 944:
146 v = cregs->u_regs[UREG_I1];
147 break;
148
149 case 948:
150 /* Isn't binary compatibility _fun_??? */
151 if(cregs->psr & PSR_C)
152 v = cregs->u_regs[UREG_I0] << 24;
153 else
154 v = 0;
155 break;
156
157 /* Rest of them are completely unsupported. */
158 default:
159 printk("%s [%d]: Wants to read user offset %ld\n",
160 current->comm, task_pid_nr(current), offset);
161 pt_error_return(regs, EIO);
162 return;
163 }
164 if (current->personality == PER_SUNOS)
165 pt_succ_return (regs, v);
166 else
167 pt_succ_return_linux (regs, v, addr);
168 return;
169}
170
171static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
172 struct task_struct *tsk)
173{
174 struct pt_regs *cregs = tsk->thread.kregs;
175 struct thread_info *t = task_thread_info(tsk);
176 unsigned long value = regs->u_regs[UREG_I3];
177
178 if(offset >= 1024)
179 offset -= 1024; /* whee... */
180 if(offset & ((sizeof(unsigned long) - 1)))
181 goto failure;
182 if(offset >= 16 && offset < 784) {
183 offset -= 16; offset >>= 2;
184 *(((unsigned long *)(&t->reg_window[0]))+offset) = value;
185 goto success;
186 }
187 if(offset >= 784 && offset < 832) {
188 offset -= 784; offset >>= 2;
189 *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;
190 goto success;
191 }
192 switch(offset) {
193 case 896:
194 cregs->u_regs[UREG_I0] = value;
195 break;
196 case 900:
197 cregs->u_regs[UREG_I1] = value;
198 break;
199 case 904:
200 cregs->u_regs[UREG_I2] = value;
201 break;
202 case 908:
203 cregs->u_regs[UREG_I3] = value;
204 break;
205 case 912:
206 cregs->u_regs[UREG_I4] = value;
207 break;
208 case 916:
209 cregs->u_regs[UREG_I5] = value;
210 break;
211 case 920:
212 cregs->u_regs[UREG_I6] = value;
213 break;
214 case 924:
215 cregs->u_regs[UREG_I7] = value;
216 break;
217 case 940:
218 cregs->u_regs[UREG_I0] = value;
219 break;
220 case 944:
221 cregs->u_regs[UREG_I1] = value;
222 break;
223
224 /* Rest of them are completely unsupported or "no-touch". */
225 default:
226 printk("%s [%d]: Wants to write user offset %ld\n",
227 current->comm, task_pid_nr(current), offset);
228 goto failure;
229 }
230success:
231 pt_succ_return(regs, 0);
232 return;
233failure:
234 pt_error_return(regs, EIO);
235 return;
236}
237
238/* #define ALLOW_INIT_TRACING */ 29/* #define ALLOW_INIT_TRACING */
239 30
240/* 31/*
@@ -528,113 +319,42 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
528 return &user_sparc32_view; 319 return &user_sparc32_view;
529} 320}
530 321
531asmlinkage void do_ptrace(struct pt_regs *regs) 322long arch_ptrace(struct task_struct *child, long request, long addr, long data)
532{ 323{
533 unsigned long request = regs->u_regs[UREG_I0]; 324 unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
534 unsigned long pid = regs->u_regs[UREG_I1]; 325 int i, ret;
535 unsigned long addr = regs->u_regs[UREG_I2];
536 unsigned long data = regs->u_regs[UREG_I3];
537 unsigned long addr2 = regs->u_regs[UREG_I4];
538 struct task_struct *child;
539 int ret;
540
541 lock_kernel();
542
543 if (request == PTRACE_TRACEME) {
544 ret = ptrace_traceme();
545 if (ret < 0)
546 pt_error_return(regs, -ret);
547 else
548 pt_succ_return(regs, 0);
549 goto out;
550 }
551
552 child = ptrace_get_task_struct(pid);
553 if (IS_ERR(child)) {
554 ret = PTR_ERR(child);
555 pt_error_return(regs, -ret);
556 goto out;
557 }
558
559 if (request == PTRACE_ATTACH) {
560 if (ptrace_attach(child)) {
561 pt_error_return(regs, EPERM);
562 goto out_tsk;
563 }
564 pt_succ_return(regs, 0);
565 goto out_tsk;
566 }
567
568 ret = ptrace_check_attach(child, request == PTRACE_KILL);
569 if (ret < 0) {
570 pt_error_return(regs, -ret);
571 goto out_tsk;
572 }
573 326
574 switch(request) { 327 switch(request) {
575 case PTRACE_PEEKTEXT: /* read word at location addr. */
576 case PTRACE_PEEKDATA: {
577 unsigned long tmp;
578
579 if (access_process_vm(child, addr,
580 &tmp, sizeof(tmp), 0) == sizeof(tmp))
581 pt_os_succ_return(regs, tmp, (long __user *)data);
582 else
583 pt_error_return(regs, EIO);
584 goto out_tsk;
585 }
586
587 case PTRACE_PEEKUSR:
588 read_sunos_user(regs, addr, child, (long __user *) data);
589 goto out_tsk;
590
591 case PTRACE_POKEUSR:
592 write_sunos_user(regs, addr, child);
593 goto out_tsk;
594
595 case PTRACE_POKETEXT: /* write the word at location addr. */
596 case PTRACE_POKEDATA: {
597 if (access_process_vm(child, addr,
598 &data, sizeof(data), 1) == sizeof(data))
599 pt_succ_return(regs, 0);
600 else
601 pt_error_return(regs, EIO);
602 goto out_tsk;
603 }
604
605 case PTRACE_GETREGS: { 328 case PTRACE_GETREGS: {
606 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 329 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
607 struct pt_regs *cregs = child->thread.kregs; 330 struct pt_regs *cregs = child->thread.kregs;
608 int rval;
609 331
610 if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) { 332 ret = -EFAULT;
611 rval = -EFAULT; 333 if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs)))
612 pt_error_return(regs, -rval); 334 break;
613 goto out_tsk; 335
614 }
615 __put_user(cregs->psr, (&pregs->psr)); 336 __put_user(cregs->psr, (&pregs->psr));
616 __put_user(cregs->pc, (&pregs->pc)); 337 __put_user(cregs->pc, (&pregs->pc));
617 __put_user(cregs->npc, (&pregs->npc)); 338 __put_user(cregs->npc, (&pregs->npc));
618 __put_user(cregs->y, (&pregs->y)); 339 __put_user(cregs->y, (&pregs->y));
619 for(rval = 1; rval < 16; rval++) 340 for (i = 1; i < 16; i++)
620 __put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1])); 341 __put_user(cregs->u_regs[i], &pregs->u_regs[i - 1]);
621 pt_succ_return(regs, 0); 342 ret = 0;
622 goto out_tsk; 343 break;
623 } 344 }
624 345
625 case PTRACE_SETREGS: { 346 case PTRACE_SETREGS: {
626 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 347 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
627 struct pt_regs *cregs = child->thread.kregs; 348 struct pt_regs *cregs = child->thread.kregs;
628 unsigned long psr, pc, npc, y; 349 unsigned long psr, pc, npc, y;
629 int i;
630 350
631 /* Must be careful, tracing process can only set certain 351 /* Must be careful, tracing process can only set certain
632 * bits in the psr. 352 * bits in the psr.
633 */ 353 */
634 if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) { 354 ret = -EFAULT;
635 pt_error_return(regs, EFAULT); 355 if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs)))
636 goto out_tsk; 356 break;
637 } 357
638 __get_user(psr, (&pregs->psr)); 358 __get_user(psr, (&pregs->psr));
639 __get_user(pc, (&pregs->pc)); 359 __get_user(pc, (&pregs->pc));
640 __get_user(npc, (&pregs->npc)); 360 __get_user(npc, (&pregs->npc));
@@ -647,10 +367,10 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
647 cregs->npc =npc; 367 cregs->npc =npc;
648 } 368 }
649 cregs->y = y; 369 cregs->y = y;
650 for(i = 1; i < 16; i++) 370 for (i = 1; i < 16; i++)
651 __get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])); 371 __get_user(cregs->u_regs[i], &pregs->u_regs[i-1]);
652 pt_succ_return(regs, 0); 372 ret = 0;
653 goto out_tsk; 373 break;
654 } 374 }
655 375
656 case PTRACE_GETFPREGS: { 376 case PTRACE_GETFPREGS: {
@@ -666,26 +386,25 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
666 } fpq[16]; 386 } fpq[16];
667 }; 387 };
668 struct fps __user *fps = (struct fps __user *) addr; 388 struct fps __user *fps = (struct fps __user *) addr;
669 int i;
670 389
671 if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) { 390 ret = -EFAULT;
672 i = -EFAULT; 391 if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps)))
673 pt_error_return(regs, -i); 392 break;
674 goto out_tsk; 393
675 } 394 for (i = 0; i < 32; i++)
676 for(i = 0; i < 32; i++) 395 __put_user(child->thread.float_regs[i], &fps->regs[i]);
677 __put_user(child->thread.float_regs[i], (&fps->regs[i]));
678 __put_user(child->thread.fsr, (&fps->fsr)); 396 __put_user(child->thread.fsr, (&fps->fsr));
679 __put_user(child->thread.fpqdepth, (&fps->fpqd)); 397 __put_user(child->thread.fpqdepth, (&fps->fpqd));
680 __put_user(0, (&fps->flags)); 398 __put_user(0, (&fps->flags));
681 __put_user(0, (&fps->extra)); 399 __put_user(0, (&fps->extra));
682 for(i = 0; i < 16; i++) { 400 for (i = 0; i < 16; i++) {
683 __put_user(child->thread.fpqueue[i].insn_addr, 401 __put_user(child->thread.fpqueue[i].insn_addr,
684 (&fps->fpq[i].insnaddr)); 402 (&fps->fpq[i].insnaddr));
685 __put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn)); 403 __put_user(child->thread.fpqueue[i].insn,
404 &fps->fpq[i].insn);
686 } 405 }
687 pt_succ_return(regs, 0); 406 ret = 0;
688 goto out_tsk; 407 break;
689 } 408 }
690 409
691 case PTRACE_SETFPREGS: { 410 case PTRACE_SETFPREGS: {
@@ -701,107 +420,53 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
701 } fpq[16]; 420 } fpq[16];
702 }; 421 };
703 struct fps __user *fps = (struct fps __user *) addr; 422 struct fps __user *fps = (struct fps __user *) addr;
704 int i;
705 423
706 if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) { 424 ret = -EFAULT;
707 i = -EFAULT; 425 if (!access_ok(VERIFY_READ, fps, sizeof(struct fps)))
708 pt_error_return(regs, -i); 426 break;
709 goto out_tsk; 427
710 } 428 copy_from_user(&child->thread.float_regs[0], &fps->regs[0],
711 copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long))); 429 (32 * sizeof(unsigned long)));
712 __get_user(child->thread.fsr, (&fps->fsr)); 430 __get_user(child->thread.fsr, (&fps->fsr));
713 __get_user(child->thread.fpqdepth, (&fps->fpqd)); 431 __get_user(child->thread.fpqdepth, (&fps->fpqd));
714 for(i = 0; i < 16; i++) { 432 for (i = 0; i < 16; i++) {
715 __get_user(child->thread.fpqueue[i].insn_addr, 433 __get_user(child->thread.fpqueue[i].insn_addr,
716 (&fps->fpq[i].insnaddr)); 434 (&fps->fpq[i].insnaddr));
717 __get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn)); 435 __get_user(child->thread.fpqueue[i].insn,
436 &fps->fpq[i].insn);
718 } 437 }
719 pt_succ_return(regs, 0); 438 ret = 0;
720 goto out_tsk; 439 break;
721 } 440 }
722 441
723 case PTRACE_READTEXT: 442 case PTRACE_READTEXT:
724 case PTRACE_READDATA: { 443 case PTRACE_READDATA:
725 int res = ptrace_readdata(child, addr, 444 ret = ptrace_readdata(child, addr,
726 (void __user *) addr2, data); 445 (void __user *) addr2, data);
727 446
728 if (res == data) { 447 if (ret == data)
729 pt_succ_return(regs, 0); 448 ret = 0;
730 goto out_tsk; 449 else if (ret >= 0)
731 } 450 ret = -EIO;
732 /* Partial read is an IO failure */ 451 break;
733 if (res >= 0)
734 res = -EIO;
735 pt_error_return(regs, -res);
736 goto out_tsk;
737 }
738 452
739 case PTRACE_WRITETEXT: 453 case PTRACE_WRITETEXT:
740 case PTRACE_WRITEDATA: { 454 case PTRACE_WRITEDATA:
741 int res = ptrace_writedata(child, (void __user *) addr2, 455 ret = ptrace_writedata(child, (void __user *) addr2,
742 addr, data); 456 addr, data);
743 457
744 if (res == data) { 458 if (ret == data)
745 pt_succ_return(regs, 0); 459 ret = 0;
746 goto out_tsk; 460 else if (ret >= 0)
747 } 461 ret = -EIO;
748 /* Partial write is an IO failure */ 462 break;
749 if (res >= 0)
750 res = -EIO;
751 pt_error_return(regs, -res);
752 goto out_tsk;
753 }
754
755 case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
756 addr = 1;
757
758 case PTRACE_CONT: { /* restart after signal. */
759 if (!valid_signal(data)) {
760 pt_error_return(regs, EIO);
761 goto out_tsk;
762 }
763
764 if (request == PTRACE_SYSCALL)
765 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
766 else
767 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
768
769 child->exit_code = data;
770 wake_up_process(child);
771 pt_succ_return(regs, 0);
772 goto out_tsk;
773 }
774 463
775/* 464 default:
776 * make the child exit. Best I can do is send it a sigkill. 465 ret = ptrace_request(child, request, addr, data);
777 * perhaps it should be put in the status that it wants to 466 break;
778 * exit.
779 */
780 case PTRACE_KILL: {
781 if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
782 pt_succ_return(regs, 0);
783 goto out_tsk;
784 }
785 wake_up_process(child);
786 child->exit_code = SIGKILL;
787 pt_succ_return(regs, 0);
788 goto out_tsk;
789 } 467 }
790 468
791 default: { 469 return ret;
792 int err = ptrace_request(child, request, addr, data);
793 if (err)
794 pt_error_return(regs, -err);
795 else
796 pt_succ_return(regs, 0);
797 goto out_tsk;
798 }
799 }
800out_tsk:
801 if (child)
802 put_task_struct(child);
803out:
804 unlock_kernel();
805} 470}
806 471
807asmlinkage void syscall_trace(void) 472asmlinkage void syscall_trace(void)
@@ -810,7 +475,6 @@ asmlinkage void syscall_trace(void)
810 return; 475 return;
811 if (!(current->ptrace & PT_PTRACED)) 476 if (!(current->ptrace & PT_PTRACED))
812 return; 477 return;
813 current->thread.flags ^= MAGIC_CONSTANT;
814 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) 478 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
815 ? 0x80 : 0)); 479 ? 0x80 : 0));
816 /* 480 /*
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index ea257e828364..6be4d2d2904e 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1477,10 +1477,6 @@ sys32_rt_sigreturn:
1477 add %o7, 1f-.-4, %o7 1477 add %o7, 1f-.-4, %o7
1478 nop 1478 nop
1479#endif 1479#endif
1480sys_ptrace: add %sp, PTREGS_OFF, %o0
1481 call do_ptrace
1482 add %o7, 1f-.-4, %o7
1483 nop
1484 .align 32 1480 .align 32
14851: ldx [%curptr + TI_FLAGS], %l5 14811: ldx [%curptr + TI_FLAGS], %l5
1486 andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 1482 andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index e881dbbd2c49..c831d426c4ac 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -36,56 +36,6 @@
36#include <asm/page.h> 36#include <asm/page.h>
37#include <asm/cpudata.h> 37#include <asm/cpudata.h>
38 38
39/* Returning from ptrace is a bit tricky because the syscall return
40 * low level code assumes any value returned which is negative and
41 * is a valid errno will mean setting the condition codes to indicate
42 * an error return. This doesn't work, so we have this hook.
43 */
44static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
45{
46 regs->u_regs[UREG_I0] = error;
47 regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY);
48 regs->tpc = regs->tnpc;
49 regs->tnpc += 4;
50}
51
52static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
53{
54 regs->u_regs[UREG_I0] = value;
55 regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
56 regs->tpc = regs->tnpc;
57 regs->tnpc += 4;
58}
59
60static inline void
61pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr)
62{
63 if (test_thread_flag(TIF_32BIT)) {
64 if (put_user(value, (unsigned int __user *) addr)) {
65 pt_error_return(regs, EFAULT);
66 return;
67 }
68 } else {
69 if (put_user(value, (long __user *) addr)) {
70 pt_error_return(regs, EFAULT);
71 return;
72 }
73 }
74 regs->u_regs[UREG_I0] = 0;
75 regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
76 regs->tpc = regs->tnpc;
77 regs->tnpc += 4;
78}
79
80static void
81pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr)
82{
83 if (current->personality == PER_SUNOS)
84 pt_succ_return (regs, val);
85 else
86 pt_succ_return_linux (regs, val, addr);
87}
88
89/* #define ALLOW_INIT_TRACING */ 39/* #define ALLOW_INIT_TRACING */
90 40
91/* 41/*
@@ -734,171 +684,113 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
734 return &user_sparc64_view; 684 return &user_sparc64_view;
735} 685}
736 686
737asmlinkage void do_ptrace(struct pt_regs *regs) 687long arch_ptrace(struct task_struct *child, long request, long addr, long data)
738{ 688{
739 int request = regs->u_regs[UREG_I0]; 689 long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
740 pid_t pid = regs->u_regs[UREG_I1]; 690 int i, ret;
741 unsigned long addr = regs->u_regs[UREG_I2];
742 unsigned long data = regs->u_regs[UREG_I3];
743 unsigned long addr2 = regs->u_regs[UREG_I4];
744 struct task_struct *child;
745 int ret;
746 691
747 if (test_thread_flag(TIF_32BIT)) { 692#if 1
748 addr &= 0xffffffffUL; 693 printk(KERN_INFO
749 data &= 0xffffffffUL; 694 "arch_ptrace: request[%ld] addr[%lx] data[%lx] addr2[%lx]\n",
695 request, addr, data, addr2);
696#endif
697 if (test_thread_flag(TIF_32BIT))
750 addr2 &= 0xffffffffUL; 698 addr2 &= 0xffffffffUL;
751 }
752 lock_kernel();
753 if (request == PTRACE_TRACEME) {
754 ret = ptrace_traceme();
755 if (ret < 0)
756 pt_error_return(regs, -ret);
757 else
758 pt_succ_return(regs, 0);
759 goto out;
760 }
761
762 child = ptrace_get_task_struct(pid);
763 if (IS_ERR(child)) {
764 ret = PTR_ERR(child);
765 pt_error_return(regs, -ret);
766 goto out;
767 }
768
769 if (request == PTRACE_ATTACH) {
770 if (ptrace_attach(child)) {
771 pt_error_return(regs, EPERM);
772 goto out_tsk;
773 }
774 pt_succ_return(regs, 0);
775 goto out_tsk;
776 }
777
778 ret = ptrace_check_attach(child, request == PTRACE_KILL);
779 if (ret < 0) {
780 pt_error_return(regs, -ret);
781 goto out_tsk;
782 }
783
784 if (!(test_thread_flag(TIF_32BIT)) &&
785 ((request == PTRACE_READDATA64) ||
786 (request == PTRACE_WRITEDATA64) ||
787 (request == PTRACE_READTEXT64) ||
788 (request == PTRACE_WRITETEXT64) ||
789 (request == PTRACE_PEEKTEXT64) ||
790 (request == PTRACE_POKETEXT64) ||
791 (request == PTRACE_PEEKDATA64) ||
792 (request == PTRACE_POKEDATA64))) {
793 addr = regs->u_regs[UREG_G2];
794 addr2 = regs->u_regs[UREG_G3];
795 request -= 30; /* wheee... */
796 }
797 699
798 switch(request) { 700 switch(request) {
799 case PTRACE_PEEKUSR: 701 case PTRACE_PEEKUSR:
800 if (addr != 0) 702 ret = (addr != 0) ? -EIO : 0;
801 pt_error_return(regs, EIO); 703 break;
802 else
803 pt_succ_return(regs, 0);
804 goto out_tsk;
805 704
806 case PTRACE_PEEKTEXT: /* read word at location addr. */ 705 case PTRACE_PEEKTEXT: /* read word at location addr. */
807 case PTRACE_PEEKDATA: { 706 case PTRACE_PEEKDATA: {
808 unsigned long tmp64; 707 unsigned long tmp64;
809 unsigned int tmp32; 708 unsigned int tmp32;
810 int res, copied; 709 int copied;
811 710
812 res = -EIO; 711 ret = -EIO;
813 if (test_thread_flag(TIF_32BIT)) { 712 if (test_thread_flag(TIF_32BIT)) {
814 copied = access_process_vm(child, addr, 713 copied = access_process_vm(child, addr,
815 &tmp32, sizeof(tmp32), 0); 714 &tmp32, sizeof(tmp32), 0);
816 tmp64 = (unsigned long) tmp32;
817 if (copied == sizeof(tmp32)) 715 if (copied == sizeof(tmp32))
818 res = 0; 716 ret = put_user(tmp32,
717 (unsigned int __user *) data);
819 } else { 718 } else {
820 copied = access_process_vm(child, addr, 719 copied = access_process_vm(child, addr,
821 &tmp64, sizeof(tmp64), 0); 720 &tmp64, sizeof(tmp64), 0);
822 if (copied == sizeof(tmp64)) 721 if (copied == sizeof(tmp64))
823 res = 0; 722 ret = put_user(tmp64,
723 (unsigned long __user *) data);
824 } 724 }
825 if (res < 0) 725 break;
826 pt_error_return(regs, -res);
827 else
828 pt_os_succ_return(regs, tmp64, (void __user *) data);
829 goto out_tsk;
830 } 726 }
831 727
832 case PTRACE_POKETEXT: /* write the word at location addr. */ 728 case PTRACE_POKETEXT: /* write the word at location addr. */
833 case PTRACE_POKEDATA: { 729 case PTRACE_POKEDATA: {
834 unsigned long tmp64; 730 unsigned long tmp64;
835 unsigned int tmp32; 731 unsigned int tmp32;
836 int copied, res = -EIO; 732 int copied;
837 733
734 ret = -EIO;
838 if (test_thread_flag(TIF_32BIT)) { 735 if (test_thread_flag(TIF_32BIT)) {
839 tmp32 = data; 736 tmp32 = data;
840 copied = access_process_vm(child, addr, 737 copied = access_process_vm(child, addr,
841 &tmp32, sizeof(tmp32), 1); 738 &tmp32, sizeof(tmp32), 1);
842 if (copied == sizeof(tmp32)) 739 if (copied == sizeof(tmp32))
843 res = 0; 740 ret = 0;
844 } else { 741 } else {
845 tmp64 = data; 742 tmp64 = data;
846 copied = access_process_vm(child, addr, 743 copied = access_process_vm(child, addr,
847 &tmp64, sizeof(tmp64), 1); 744 &tmp64, sizeof(tmp64), 1);
848 if (copied == sizeof(tmp64)) 745 if (copied == sizeof(tmp64))
849 res = 0; 746 ret = 0;
850 } 747 }
851 if (res < 0) 748 break;
852 pt_error_return(regs, -res);
853 else
854 pt_succ_return(regs, res);
855 goto out_tsk;
856 } 749 }
857 750
858 case PTRACE_GETREGS: { 751 case PTRACE_GETREGS: {
859 struct pt_regs32 __user *pregs = 752 struct pt_regs32 __user *pregs =
860 (struct pt_regs32 __user *) addr; 753 (struct pt_regs32 __user *) addr;
861 struct pt_regs *cregs = task_pt_regs(child); 754 struct pt_regs *cregs = task_pt_regs(child);
862 int rval;
863 755
756 ret = -EFAULT;
864 if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || 757 if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
865 __put_user(cregs->tpc, (&pregs->pc)) || 758 __put_user(cregs->tpc, (&pregs->pc)) ||
866 __put_user(cregs->tnpc, (&pregs->npc)) || 759 __put_user(cregs->tnpc, (&pregs->npc)) ||
867 __put_user(cregs->y, (&pregs->y))) { 760 __put_user(cregs->y, (&pregs->y)))
868 pt_error_return(regs, EFAULT); 761 break;
869 goto out_tsk; 762 for (i = 1; i < 16; i++) {
763 if (__put_user(cregs->u_regs[i],
764 (&pregs->u_regs[i - 1])))
765 break;
870 } 766 }
871 for (rval = 1; rval < 16; rval++) 767 if (i == 16)
872 if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { 768 ret = 0;
873 pt_error_return(regs, EFAULT); 769 break;
874 goto out_tsk;
875 }
876 pt_succ_return(regs, 0);
877 goto out_tsk;
878 } 770 }
879 771
880 case PTRACE_GETREGS64: { 772 case PTRACE_GETREGS64: {
881 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 773 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
882 struct pt_regs *cregs = task_pt_regs(child); 774 struct pt_regs *cregs = task_pt_regs(child);
883 unsigned long tpc = cregs->tpc; 775 unsigned long tpc = cregs->tpc;
884 int rval;
885 776
886 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) 777 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
887 tpc &= 0xffffffff; 778 tpc &= 0xffffffff;
779
780 ret = -EFAULT;
888 if (__put_user(cregs->tstate, (&pregs->tstate)) || 781 if (__put_user(cregs->tstate, (&pregs->tstate)) ||
889 __put_user(tpc, (&pregs->tpc)) || 782 __put_user(tpc, (&pregs->tpc)) ||
890 __put_user(cregs->tnpc, (&pregs->tnpc)) || 783 __put_user(cregs->tnpc, (&pregs->tnpc)) ||
891 __put_user(cregs->y, (&pregs->y))) { 784 __put_user(cregs->y, (&pregs->y)))
892 pt_error_return(regs, EFAULT); 785 break;
893 goto out_tsk; 786 for (i = 1; i < 16; i++) {
787 if (__put_user(cregs->u_regs[i],
788 (&pregs->u_regs[i - 1])))
789 break;
894 } 790 }
895 for (rval = 1; rval < 16; rval++) 791 if (i == 16)
896 if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { 792 ret = 0;
897 pt_error_return(regs, EFAULT); 793 break;
898 goto out_tsk;
899 }
900 pt_succ_return(regs, 0);
901 goto out_tsk;
902 } 794 }
903 795
904 case PTRACE_SETREGS: { 796 case PTRACE_SETREGS: {
@@ -906,18 +798,16 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
906 (struct pt_regs32 __user *) addr; 798 (struct pt_regs32 __user *) addr;
907 struct pt_regs *cregs = task_pt_regs(child); 799 struct pt_regs *cregs = task_pt_regs(child);
908 unsigned int psr, pc, npc, y; 800 unsigned int psr, pc, npc, y;
909 int i;
910 801
911 /* Must be careful, tracing process can only set certain 802 /* Must be careful, tracing process can only set certain
912 * bits in the psr. 803 * bits in the psr.
913 */ 804 */
805 ret = -EFAULT;
914 if (__get_user(psr, (&pregs->psr)) || 806 if (__get_user(psr, (&pregs->psr)) ||
915 __get_user(pc, (&pregs->pc)) || 807 __get_user(pc, (&pregs->pc)) ||
916 __get_user(npc, (&pregs->npc)) || 808 __get_user(npc, (&pregs->npc)) ||
917 __get_user(y, (&pregs->y))) { 809 __get_user(y, (&pregs->y)))
918 pt_error_return(regs, EFAULT); 810 break;
919 goto out_tsk;
920 }
921 cregs->tstate &= ~(TSTATE_ICC); 811 cregs->tstate &= ~(TSTATE_ICC);
922 cregs->tstate |= psr_to_tstate_icc(psr); 812 cregs->tstate |= psr_to_tstate_icc(psr);
923 if (!((pc | npc) & 3)) { 813 if (!((pc | npc) & 3)) {
@@ -926,31 +816,28 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
926 } 816 }
927 cregs->y = y; 817 cregs->y = y;
928 for (i = 1; i < 16; i++) { 818 for (i = 1; i < 16; i++) {
929 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { 819 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])))
930 pt_error_return(regs, EFAULT); 820 break;
931 goto out_tsk;
932 }
933 } 821 }
934 pt_succ_return(regs, 0); 822 if (i == 16)
935 goto out_tsk; 823 ret = 0;
824 break;
936 } 825 }
937 826
938 case PTRACE_SETREGS64: { 827 case PTRACE_SETREGS64: {
939 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 828 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
940 struct pt_regs *cregs = task_pt_regs(child); 829 struct pt_regs *cregs = task_pt_regs(child);
941 unsigned long tstate, tpc, tnpc, y; 830 unsigned long tstate, tpc, tnpc, y;
942 int i;
943 831
944 /* Must be careful, tracing process can only set certain 832 /* Must be careful, tracing process can only set certain
945 * bits in the psr. 833 * bits in the psr.
946 */ 834 */
835 ret = -EFAULT;
947 if (__get_user(tstate, (&pregs->tstate)) || 836 if (__get_user(tstate, (&pregs->tstate)) ||
948 __get_user(tpc, (&pregs->tpc)) || 837 __get_user(tpc, (&pregs->tpc)) ||
949 __get_user(tnpc, (&pregs->tnpc)) || 838 __get_user(tnpc, (&pregs->tnpc)) ||
950 __get_user(y, (&pregs->y))) { 839 __get_user(y, (&pregs->y)))
951 pt_error_return(regs, EFAULT); 840 break;
952 goto out_tsk;
953 }
954 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) { 841 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
955 tpc &= 0xffffffff; 842 tpc &= 0xffffffff;
956 tnpc &= 0xffffffff; 843 tnpc &= 0xffffffff;
@@ -964,13 +851,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
964 } 851 }
965 cregs->y = y; 852 cregs->y = y;
966 for (i = 1; i < 16; i++) { 853 for (i = 1; i < 16; i++) {
967 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { 854 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])))
968 pt_error_return(regs, EFAULT); 855 break;
969 goto out_tsk;
970 }
971 } 856 }
972 pt_succ_return(regs, 0); 857 if (i == 16)
973 goto out_tsk; 858 ret = 0;
859 break;
974 } 860 }
975 861
976 case PTRACE_GETFPREGS: { 862 case PTRACE_GETFPREGS: {
@@ -988,18 +874,18 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
988 struct fps __user *fps = (struct fps __user *) addr; 874 struct fps __user *fps = (struct fps __user *) addr;
989 unsigned long *fpregs = task_thread_info(child)->fpregs; 875 unsigned long *fpregs = task_thread_info(child)->fpregs;
990 876
877 ret = -EFAULT;
991 if (copy_to_user(&fps->regs[0], fpregs, 878 if (copy_to_user(&fps->regs[0], fpregs,
992 (32 * sizeof(unsigned int))) || 879 (32 * sizeof(unsigned int))) ||
993 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) || 880 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) ||
994 __put_user(0, (&fps->fpqd)) || 881 __put_user(0, (&fps->fpqd)) ||
995 __put_user(0, (&fps->flags)) || 882 __put_user(0, (&fps->flags)) ||
996 __put_user(0, (&fps->extra)) || 883 __put_user(0, (&fps->extra)) ||
997 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) { 884 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
998 pt_error_return(regs, EFAULT); 885 break;
999 goto out_tsk; 886
1000 } 887 ret = 0;
1001 pt_succ_return(regs, 0); 888 break;
1002 goto out_tsk;
1003 } 889 }
1004 890
1005 case PTRACE_GETFPREGS64: { 891 case PTRACE_GETFPREGS64: {
@@ -1010,14 +896,14 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
1010 struct fps __user *fps = (struct fps __user *) addr; 896 struct fps __user *fps = (struct fps __user *) addr;
1011 unsigned long *fpregs = task_thread_info(child)->fpregs; 897 unsigned long *fpregs = task_thread_info(child)->fpregs;
1012 898
899 ret = -EFAULT;
1013 if (copy_to_user(&fps->regs[0], fpregs, 900 if (copy_to_user(&fps->regs[0], fpregs,
1014 (64 * sizeof(unsigned int))) || 901 (64 * sizeof(unsigned int))) ||
1015 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { 902 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)))
1016 pt_error_return(regs, EFAULT); 903 break;
1017 goto out_tsk; 904
1018 } 905 ret = 0;
1019 pt_succ_return(regs, 0); 906 break;
1020 goto out_tsk;
1021 } 907 }
1022 908
1023 case PTRACE_SETFPREGS: { 909 case PTRACE_SETFPREGS: {
@@ -1036,19 +922,19 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
1036 unsigned long *fpregs = task_thread_info(child)->fpregs; 922 unsigned long *fpregs = task_thread_info(child)->fpregs;
1037 unsigned fsr; 923 unsigned fsr;
1038 924
925 ret = -EFAULT;
1039 if (copy_from_user(fpregs, &fps->regs[0], 926 if (copy_from_user(fpregs, &fps->regs[0],
1040 (32 * sizeof(unsigned int))) || 927 (32 * sizeof(unsigned int))) ||
1041 __get_user(fsr, (&fps->fsr))) { 928 __get_user(fsr, (&fps->fsr)))
1042 pt_error_return(regs, EFAULT); 929 break;
1043 goto out_tsk; 930
1044 }
1045 task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL; 931 task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL;
1046 task_thread_info(child)->xfsr[0] |= fsr; 932 task_thread_info(child)->xfsr[0] |= fsr;
1047 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) 933 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
1048 task_thread_info(child)->gsr[0] = 0; 934 task_thread_info(child)->gsr[0] = 0;
1049 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL); 935 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
1050 pt_succ_return(regs, 0); 936 ret = 0;
1051 goto out_tsk; 937 break;
1052 } 938 }
1053 939
1054 case PTRACE_SETFPREGS64: { 940 case PTRACE_SETFPREGS64: {
@@ -1059,113 +945,56 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
1059 struct fps __user *fps = (struct fps __user *) addr; 945 struct fps __user *fps = (struct fps __user *) addr;
1060 unsigned long *fpregs = task_thread_info(child)->fpregs; 946 unsigned long *fpregs = task_thread_info(child)->fpregs;
1061 947
948 ret = -EFAULT;
1062 if (copy_from_user(fpregs, &fps->regs[0], 949 if (copy_from_user(fpregs, &fps->regs[0],
1063 (64 * sizeof(unsigned int))) || 950 (64 * sizeof(unsigned int))) ||
1064 __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { 951 __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr)))
1065 pt_error_return(regs, EFAULT); 952 break;
1066 goto out_tsk; 953
1067 }
1068 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) 954 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
1069 task_thread_info(child)->gsr[0] = 0; 955 task_thread_info(child)->gsr[0] = 0;
1070 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); 956 task_thread_info(child)->fpsaved[0] |=
1071 pt_succ_return(regs, 0); 957 (FPRS_FEF | FPRS_DL | FPRS_DU);
1072 goto out_tsk; 958 ret = 0;
959 break;
1073 } 960 }
1074 961
1075 case PTRACE_READTEXT: 962 case PTRACE_READTEXT:
1076 case PTRACE_READDATA: { 963 case PTRACE_READDATA:
1077 int res = ptrace_readdata(child, addr, 964 ret = ptrace_readdata(child, addr,
1078 (char __user *)addr2, data); 965 (char __user *)addr2, data);
1079 if (res == data) { 966 if (ret == data)
1080 pt_succ_return(regs, 0); 967 ret = 0;
1081 goto out_tsk; 968 else if (ret >= 0)
1082 } 969 ret = -EIO;
1083 if (res >= 0) 970 break;
1084 res = -EIO;
1085 pt_error_return(regs, -res);
1086 goto out_tsk;
1087 }
1088 971
1089 case PTRACE_WRITETEXT: 972 case PTRACE_WRITETEXT:
1090 case PTRACE_WRITEDATA: { 973 case PTRACE_WRITEDATA:
1091 int res = ptrace_writedata(child, (char __user *) addr2, 974 ret = ptrace_writedata(child, (char __user *) addr2,
1092 addr, data); 975 addr, data);
1093 if (res == data) { 976 if (ret == data)
1094 pt_succ_return(regs, 0); 977 ret = 0;
1095 goto out_tsk; 978 else if (ret >= 0)
1096 } 979 ret = -EIO;
1097 if (res >= 0) 980 break;
1098 res = -EIO;
1099 pt_error_return(regs, -res);
1100 goto out_tsk;
1101 }
1102 case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
1103 addr = 1;
1104
1105 case PTRACE_CONT: { /* restart after signal. */
1106 if (!valid_signal(data)) {
1107 pt_error_return(regs, EIO);
1108 goto out_tsk;
1109 }
1110
1111 if (request == PTRACE_SYSCALL) {
1112 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1113 } else {
1114 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1115 }
1116
1117 child->exit_code = data;
1118 wake_up_process(child);
1119 pt_succ_return(regs, 0);
1120 goto out_tsk;
1121 }
1122
1123/*
1124 * make the child exit. Best I can do is send it a sigkill.
1125 * perhaps it should be put in the status that it wants to
1126 * exit.
1127 */
1128 case PTRACE_KILL: {
1129 if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
1130 pt_succ_return(regs, 0);
1131 goto out_tsk;
1132 }
1133 child->exit_code = SIGKILL;
1134 wake_up_process(child);
1135 pt_succ_return(regs, 0);
1136 goto out_tsk;
1137 }
1138 981
1139 case PTRACE_GETEVENTMSG: { 982 case PTRACE_GETEVENTMSG: {
1140 int err;
1141
1142 if (test_thread_flag(TIF_32BIT)) 983 if (test_thread_flag(TIF_32BIT))
1143 err = put_user(child->ptrace_message, 984 ret = put_user(child->ptrace_message,
1144 (unsigned int __user *) data); 985 (unsigned int __user *) data);
1145 else 986 else
1146 err = put_user(child->ptrace_message, 987 ret = put_user(child->ptrace_message,
1147 (unsigned long __user *) data); 988 (unsigned long __user *) data);
1148 if (err)
1149 pt_error_return(regs, -err);
1150 else
1151 pt_succ_return(regs, 0);
1152 break; 989 break;
1153 } 990 }
1154 991
1155 default: { 992 default:
1156 int err = ptrace_request(child, request, addr, data); 993 ret = ptrace_request(child, request, addr, data);
1157 if (err) 994 break;
1158 pt_error_return(regs, -err);
1159 else
1160 pt_succ_return(regs, 0);
1161 goto out_tsk;
1162 }
1163 } 995 }
1164out_tsk: 996
1165 if (child) 997 return ret;
1166 put_task_struct(child);
1167out:
1168 unlock_kernel();
1169} 998}
1170 999
1171asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p) 1000asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)