blob: 23ad839d113fcef60137ac27d4f72799684c6029 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* ptrace.c: Sparc process tracing support.
2 *
3 * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
4 * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 *
6 * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
7 * and David Mosberger.
8 *
9 * Added Linux support -miguel (weird, eh?, the original code was meant
10 * to emulate SunOS).
11 */
12
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/errno.h>
17#include <linux/ptrace.h>
18#include <linux/user.h>
19#include <linux/smp.h>
20#include <linux/smp_lock.h>
21#include <linux/security.h>
David S. Millerf7ceba32005-07-10 19:29:45 -070022#include <linux/seccomp.h>
23#include <linux/audit.h>
Jesper Juhl7ed20e12005-05-01 08:59:14 -070024#include <linux/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025
26#include <asm/asi.h>
27#include <asm/pgtable.h>
28#include <asm/system.h>
29#include <asm/uaccess.h>
30#include <asm/psrcompat.h>
31#include <asm/visasm.h>
32#include <asm/spitfire.h>
33
34/* Returning from ptrace is a bit tricky because the syscall return
35 * low level code assumes any value returned which is negative and
36 * is a valid errno will mean setting the condition codes to indicate
37 * an error return. This doesn't work, so we have this hook.
38 */
39static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
40{
41 regs->u_regs[UREG_I0] = error;
42 regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY);
43 regs->tpc = regs->tnpc;
44 regs->tnpc += 4;
45}
46
47static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
48{
49 regs->u_regs[UREG_I0] = value;
50 regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
51 regs->tpc = regs->tnpc;
52 regs->tnpc += 4;
53}
54
55static inline void
56pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr)
57{
58 if (test_thread_flag(TIF_32BIT)) {
59 if (put_user(value, (unsigned int __user *) addr)) {
60 pt_error_return(regs, EFAULT);
61 return;
62 }
63 } else {
64 if (put_user(value, (long __user *) addr)) {
65 pt_error_return(regs, EFAULT);
66 return;
67 }
68 }
69 regs->u_regs[UREG_I0] = 0;
70 regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
71 regs->tpc = regs->tnpc;
72 regs->tnpc += 4;
73}
74
75static void
76pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr)
77{
78 if (current->personality == PER_SUNOS)
79 pt_succ_return (regs, val);
80 else
81 pt_succ_return_linux (regs, val, addr);
82}
83
84/* #define ALLOW_INIT_TRACING */
85/* #define DEBUG_PTRACE */
86
87#ifdef DEBUG_PTRACE
88char *pt_rq [] = {
89 /* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
90 /* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
91 /* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
92 /* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
93 /* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
94 /* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
95 /* 24 */ "SYSCALL", ""
96};
97#endif
98
99/*
100 * Called by kernel/ptrace.c when detaching..
101 *
102 * Make sure single step bits etc are not set.
103 */
104void ptrace_disable(struct task_struct *child)
105{
106 /* nothing to do */
107}
108
David S. Millerdadeafd2005-04-17 18:03:11 -0700109/* To get the necessary page struct, access_process_vm() first calls
110 * get_user_pages(). This has done a flush_dcache_page() on the
111 * accessed page. Then our caller (copy_{to,from}_user_page()) did
112 * to memcpy to read/write the data from that page.
113 *
114 * Now, the only thing we have to do is:
115 * 1) flush the D-cache if it's possible than an illegal alias
116 * has been created
117 * 2) flush the I-cache if this is pre-cheetah and we did a write
118 */
119void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
120 unsigned long uaddr, void *kaddr,
121 unsigned long len, int write)
122{
123 BUG_ON(len > PAGE_SIZE);
124
125#ifdef DCACHE_ALIASING_POSSIBLE
126 /* If bit 13 of the kernel address we used to access the
127 * user page is the same as the virtual address that page
128 * is mapped to in the user's address space, we can skip the
129 * D-cache flush.
130 */
131 if ((uaddr ^ kaddr) & (1UL << 13)) {
132 unsigned long start = __pa(kaddr);
133 unsigned long end = start + len;
134
135 if (tlb_type == spitfire) {
136 for (; start < end; start += 32)
137 spitfire_put_dcache_tag(va & 0x3fe0, 0x0);
138 } else {
139 for (; start < end; start += 32)
140 __asm__ __volatile__(
141 "stxa %%g0, [%0] %1\n\t"
142 "membar #Sync"
143 : /* no outputs */
144 : "r" (va),
145 "i" (ASI_DCACHE_INVALIDATE));
146 }
147 }
148#endif
149 if (write && tlb_type == spitfire) {
150 unsigned long start = (unsigned long) kaddr;
151 unsigned long end = start + len;
152
153 for (; start < end; start += 32)
154 flushi(start);
155 }
156}
157
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158asmlinkage void do_ptrace(struct pt_regs *regs)
159{
160 int request = regs->u_regs[UREG_I0];
161 pid_t pid = regs->u_regs[UREG_I1];
162 unsigned long addr = regs->u_regs[UREG_I2];
163 unsigned long data = regs->u_regs[UREG_I3];
164 unsigned long addr2 = regs->u_regs[UREG_I4];
165 struct task_struct *child;
166 int ret;
167
168 if (test_thread_flag(TIF_32BIT)) {
169 addr &= 0xffffffffUL;
170 data &= 0xffffffffUL;
171 addr2 &= 0xffffffffUL;
172 }
173 lock_kernel();
174#ifdef DEBUG_PTRACE
175 {
176 char *s;
177
178 if ((request >= 0) && (request <= 24))
179 s = pt_rq [request];
180 else
181 s = "unknown";
182
183 if (request == PTRACE_POKEDATA && data == 0x91d02001){
184 printk ("do_ptrace: breakpoint pid=%d, addr=%016lx addr2=%016lx\n",
185 pid, addr, addr2);
186 } else
187 printk("do_ptrace: rq=%s(%d) pid=%d addr=%016lx data=%016lx addr2=%016lx\n",
188 s, request, pid, addr, data, addr2);
189 }
190#endif
191 if (request == PTRACE_TRACEME) {
192 int ret;
193
194 /* are we already being traced? */
195 if (current->ptrace & PT_PTRACED) {
196 pt_error_return(regs, EPERM);
197 goto out;
198 }
199 ret = security_ptrace(current->parent, current);
200 if (ret) {
201 pt_error_return(regs, -ret);
202 goto out;
203 }
204
205 /* set the ptrace bit in the process flags. */
206 current->ptrace |= PT_PTRACED;
207 pt_succ_return(regs, 0);
208 goto out;
209 }
210#ifndef ALLOW_INIT_TRACING
211 if (pid == 1) {
212 /* Can't dork with init. */
213 pt_error_return(regs, EPERM);
214 goto out;
215 }
216#endif
217 read_lock(&tasklist_lock);
218 child = find_task_by_pid(pid);
219 if (child)
220 get_task_struct(child);
221 read_unlock(&tasklist_lock);
222
223 if (!child) {
224 pt_error_return(regs, ESRCH);
225 goto out;
226 }
227
228 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
229 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
230 if (ptrace_attach(child)) {
231 pt_error_return(regs, EPERM);
232 goto out_tsk;
233 }
234 pt_succ_return(regs, 0);
235 goto out_tsk;
236 }
237
238 ret = ptrace_check_attach(child, request == PTRACE_KILL);
239 if (ret < 0) {
240 pt_error_return(regs, -ret);
241 goto out_tsk;
242 }
243
244 if (!(test_thread_flag(TIF_32BIT)) &&
245 ((request == PTRACE_READDATA64) ||
246 (request == PTRACE_WRITEDATA64) ||
247 (request == PTRACE_READTEXT64) ||
248 (request == PTRACE_WRITETEXT64) ||
249 (request == PTRACE_PEEKTEXT64) ||
250 (request == PTRACE_POKETEXT64) ||
251 (request == PTRACE_PEEKDATA64) ||
252 (request == PTRACE_POKEDATA64))) {
253 addr = regs->u_regs[UREG_G2];
254 addr2 = regs->u_regs[UREG_G3];
255 request -= 30; /* wheee... */
256 }
257
258 switch(request) {
259 case PTRACE_PEEKTEXT: /* read word at location addr. */
260 case PTRACE_PEEKDATA: {
261 unsigned long tmp64;
262 unsigned int tmp32;
263 int res, copied;
264
265 res = -EIO;
266 if (test_thread_flag(TIF_32BIT)) {
267 copied = access_process_vm(child, addr,
268 &tmp32, sizeof(tmp32), 0);
269 tmp64 = (unsigned long) tmp32;
270 if (copied == sizeof(tmp32))
271 res = 0;
272 } else {
273 copied = access_process_vm(child, addr,
274 &tmp64, sizeof(tmp64), 0);
275 if (copied == sizeof(tmp64))
276 res = 0;
277 }
278 if (res < 0)
279 pt_error_return(regs, -res);
280 else
281 pt_os_succ_return(regs, tmp64, (void __user *) data);
David S. Millerdadeafd2005-04-17 18:03:11 -0700282 goto out_tsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 }
284
285 case PTRACE_POKETEXT: /* write the word at location addr. */
286 case PTRACE_POKEDATA: {
287 unsigned long tmp64;
288 unsigned int tmp32;
289 int copied, res = -EIO;
290
291 if (test_thread_flag(TIF_32BIT)) {
292 tmp32 = data;
293 copied = access_process_vm(child, addr,
294 &tmp32, sizeof(tmp32), 1);
295 if (copied == sizeof(tmp32))
296 res = 0;
297 } else {
298 tmp64 = data;
299 copied = access_process_vm(child, addr,
300 &tmp64, sizeof(tmp64), 1);
301 if (copied == sizeof(tmp64))
302 res = 0;
303 }
304 if (res < 0)
305 pt_error_return(regs, -res);
306 else
307 pt_succ_return(regs, res);
David S. Millerdadeafd2005-04-17 18:03:11 -0700308 goto out_tsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 }
310
311 case PTRACE_GETREGS: {
312 struct pt_regs32 __user *pregs =
313 (struct pt_regs32 __user *) addr;
314 struct pt_regs *cregs = child->thread_info->kregs;
315 int rval;
316
317 if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
318 __put_user(cregs->tpc, (&pregs->pc)) ||
319 __put_user(cregs->tnpc, (&pregs->npc)) ||
320 __put_user(cregs->y, (&pregs->y))) {
321 pt_error_return(regs, EFAULT);
322 goto out_tsk;
323 }
324 for (rval = 1; rval < 16; rval++)
325 if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
326 pt_error_return(regs, EFAULT);
327 goto out_tsk;
328 }
329 pt_succ_return(regs, 0);
330#ifdef DEBUG_PTRACE
331 printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
332#endif
333 goto out_tsk;
334 }
335
336 case PTRACE_GETREGS64: {
337 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
338 struct pt_regs *cregs = child->thread_info->kregs;
339 unsigned long tpc = cregs->tpc;
340 int rval;
341
342 if ((child->thread_info->flags & _TIF_32BIT) != 0)
343 tpc &= 0xffffffff;
344 if (__put_user(cregs->tstate, (&pregs->tstate)) ||
345 __put_user(tpc, (&pregs->tpc)) ||
346 __put_user(cregs->tnpc, (&pregs->tnpc)) ||
347 __put_user(cregs->y, (&pregs->y))) {
348 pt_error_return(regs, EFAULT);
349 goto out_tsk;
350 }
351 for (rval = 1; rval < 16; rval++)
352 if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) {
353 pt_error_return(regs, EFAULT);
354 goto out_tsk;
355 }
356 pt_succ_return(regs, 0);
357#ifdef DEBUG_PTRACE
358 printk ("PC=%lx nPC=%lx o7=%lx\n", cregs->tpc, cregs->tnpc, cregs->u_regs [15]);
359#endif
360 goto out_tsk;
361 }
362
363 case PTRACE_SETREGS: {
364 struct pt_regs32 __user *pregs =
365 (struct pt_regs32 __user *) addr;
366 struct pt_regs *cregs = child->thread_info->kregs;
367 unsigned int psr, pc, npc, y;
368 int i;
369
370 /* Must be careful, tracing process can only set certain
371 * bits in the psr.
372 */
373 if (__get_user(psr, (&pregs->psr)) ||
374 __get_user(pc, (&pregs->pc)) ||
375 __get_user(npc, (&pregs->npc)) ||
376 __get_user(y, (&pregs->y))) {
377 pt_error_return(regs, EFAULT);
378 goto out_tsk;
379 }
380 cregs->tstate &= ~(TSTATE_ICC);
381 cregs->tstate |= psr_to_tstate_icc(psr);
382 if (!((pc | npc) & 3)) {
383 cregs->tpc = pc;
384 cregs->tnpc = npc;
385 }
386 cregs->y = y;
387 for (i = 1; i < 16; i++) {
388 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
389 pt_error_return(regs, EFAULT);
390 goto out_tsk;
391 }
392 }
393 pt_succ_return(regs, 0);
394 goto out_tsk;
395 }
396
397 case PTRACE_SETREGS64: {
398 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
399 struct pt_regs *cregs = child->thread_info->kregs;
400 unsigned long tstate, tpc, tnpc, y;
401 int i;
402
403 /* Must be careful, tracing process can only set certain
404 * bits in the psr.
405 */
406 if (__get_user(tstate, (&pregs->tstate)) ||
407 __get_user(tpc, (&pregs->tpc)) ||
408 __get_user(tnpc, (&pregs->tnpc)) ||
409 __get_user(y, (&pregs->y))) {
410 pt_error_return(regs, EFAULT);
411 goto out_tsk;
412 }
413 if ((child->thread_info->flags & _TIF_32BIT) != 0) {
414 tpc &= 0xffffffff;
415 tnpc &= 0xffffffff;
416 }
417 tstate &= (TSTATE_ICC | TSTATE_XCC);
418 cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
419 cregs->tstate |= tstate;
420 if (!((tpc | tnpc) & 3)) {
421 cregs->tpc = tpc;
422 cregs->tnpc = tnpc;
423 }
424 cregs->y = y;
425 for (i = 1; i < 16; i++) {
426 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) {
427 pt_error_return(regs, EFAULT);
428 goto out_tsk;
429 }
430 }
431 pt_succ_return(regs, 0);
432 goto out_tsk;
433 }
434
435 case PTRACE_GETFPREGS: {
436 struct fps {
437 unsigned int regs[32];
438 unsigned int fsr;
439 unsigned int flags;
440 unsigned int extra;
441 unsigned int fpqd;
442 struct fq {
443 unsigned int insnaddr;
444 unsigned int insn;
445 } fpq[16];
446 };
447 struct fps __user *fps = (struct fps __user *) addr;
448 unsigned long *fpregs = child->thread_info->fpregs;
449
450 if (copy_to_user(&fps->regs[0], fpregs,
451 (32 * sizeof(unsigned int))) ||
452 __put_user(child->thread_info->xfsr[0], (&fps->fsr)) ||
453 __put_user(0, (&fps->fpqd)) ||
454 __put_user(0, (&fps->flags)) ||
455 __put_user(0, (&fps->extra)) ||
456 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) {
457 pt_error_return(regs, EFAULT);
458 goto out_tsk;
459 }
460 pt_succ_return(regs, 0);
461 goto out_tsk;
462 }
463
464 case PTRACE_GETFPREGS64: {
465 struct fps {
466 unsigned int regs[64];
467 unsigned long fsr;
468 };
469 struct fps __user *fps = (struct fps __user *) addr;
470 unsigned long *fpregs = child->thread_info->fpregs;
471
472 if (copy_to_user(&fps->regs[0], fpregs,
473 (64 * sizeof(unsigned int))) ||
474 __put_user(child->thread_info->xfsr[0], (&fps->fsr))) {
475 pt_error_return(regs, EFAULT);
476 goto out_tsk;
477 }
478 pt_succ_return(regs, 0);
479 goto out_tsk;
480 }
481
482 case PTRACE_SETFPREGS: {
483 struct fps {
484 unsigned int regs[32];
485 unsigned int fsr;
486 unsigned int flags;
487 unsigned int extra;
488 unsigned int fpqd;
489 struct fq {
490 unsigned int insnaddr;
491 unsigned int insn;
492 } fpq[16];
493 };
494 struct fps __user *fps = (struct fps __user *) addr;
495 unsigned long *fpregs = child->thread_info->fpregs;
496 unsigned fsr;
497
498 if (copy_from_user(fpregs, &fps->regs[0],
499 (32 * sizeof(unsigned int))) ||
500 __get_user(fsr, (&fps->fsr))) {
501 pt_error_return(regs, EFAULT);
502 goto out_tsk;
503 }
504 child->thread_info->xfsr[0] &= 0xffffffff00000000UL;
505 child->thread_info->xfsr[0] |= fsr;
506 if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
507 child->thread_info->gsr[0] = 0;
508 child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
509 pt_succ_return(regs, 0);
510 goto out_tsk;
511 }
512
513 case PTRACE_SETFPREGS64: {
514 struct fps {
515 unsigned int regs[64];
516 unsigned long fsr;
517 };
518 struct fps __user *fps = (struct fps __user *) addr;
519 unsigned long *fpregs = child->thread_info->fpregs;
520
521 if (copy_from_user(fpregs, &fps->regs[0],
522 (64 * sizeof(unsigned int))) ||
523 __get_user(child->thread_info->xfsr[0], (&fps->fsr))) {
524 pt_error_return(regs, EFAULT);
525 goto out_tsk;
526 }
527 if (!(child->thread_info->fpsaved[0] & FPRS_FEF))
528 child->thread_info->gsr[0] = 0;
529 child->thread_info->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU);
530 pt_succ_return(regs, 0);
531 goto out_tsk;
532 }
533
534 case PTRACE_READTEXT:
535 case PTRACE_READDATA: {
536 int res = ptrace_readdata(child, addr,
537 (char __user *)addr2, data);
538 if (res == data) {
539 pt_succ_return(regs, 0);
David S. Millerdadeafd2005-04-17 18:03:11 -0700540 goto out_tsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 }
542 if (res >= 0)
543 res = -EIO;
544 pt_error_return(regs, -res);
David S. Millerdadeafd2005-04-17 18:03:11 -0700545 goto out_tsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 }
547
548 case PTRACE_WRITETEXT:
549 case PTRACE_WRITEDATA: {
550 int res = ptrace_writedata(child, (char __user *) addr2,
551 addr, data);
552 if (res == data) {
553 pt_succ_return(regs, 0);
David S. Millerdadeafd2005-04-17 18:03:11 -0700554 goto out_tsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
556 if (res >= 0)
557 res = -EIO;
558 pt_error_return(regs, -res);
David S. Millerdadeafd2005-04-17 18:03:11 -0700559 goto out_tsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 }
561 case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
562 addr = 1;
563
564 case PTRACE_CONT: { /* restart after signal. */
Jesper Juhl7ed20e12005-05-01 08:59:14 -0700565 if (!valid_signal(data)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 pt_error_return(regs, EIO);
567 goto out_tsk;
568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
570 if (request == PTRACE_SYSCALL) {
571 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
572 } else {
573 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
574 }
575
576 child->exit_code = data;
577#ifdef DEBUG_PTRACE
578 printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", child->comm,
579 child->pid, child->exit_code,
580 child->thread_info->kregs->tpc,
581 child->thread_info->kregs->tnpc);
582
583#endif
584 wake_up_process(child);
585 pt_succ_return(regs, 0);
586 goto out_tsk;
587 }
588
589/*
590 * make the child exit. Best I can do is send it a sigkill.
591 * perhaps it should be put in the status that it wants to
592 * exit.
593 */
594 case PTRACE_KILL: {
595 if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
596 pt_succ_return(regs, 0);
597 goto out_tsk;
598 }
599 child->exit_code = SIGKILL;
600 wake_up_process(child);
601 pt_succ_return(regs, 0);
602 goto out_tsk;
603 }
604
605 case PTRACE_SUNDETACH: { /* detach a process that was attached. */
606 int error = ptrace_detach(child, data);
607 if (error) {
608 pt_error_return(regs, EIO);
609 goto out_tsk;
610 }
611 pt_succ_return(regs, 0);
612 goto out_tsk;
613 }
614
615 /* PTRACE_DUMPCORE unsupported... */
616
617 default: {
618 int err = ptrace_request(child, request, addr, data);
619 if (err)
620 pt_error_return(regs, -err);
621 else
622 pt_succ_return(regs, 0);
623 goto out_tsk;
624 }
625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626out_tsk:
627 if (child)
628 put_task_struct(child);
629out:
630 unlock_kernel();
631}
632
David S. Miller8d8a6472005-07-10 16:55:48 -0700633asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634{
David S. Millerbb49bcd2005-07-10 16:49:28 -0700635 /* do the secure computing check first */
David S. Miller8d8a6472005-07-10 16:55:48 -0700636 secure_computing(regs->u_regs[UREG_G1]);
David S. Millerbb49bcd2005-07-10 16:49:28 -0700637
David S. Millerf7ceba32005-07-10 19:29:45 -0700638 if (unlikely(current->audit_context) && syscall_exit_p) {
639 unsigned long tstate = regs->tstate;
640 int result = AUDITSC_SUCCESS;
641
642 if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
643 result = AUDITSC_FAILURE;
644
645 audit_syscall_exit(current, result, regs->u_regs[UREG_I0]);
646 }
647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 if (!(current->ptrace & PT_PTRACED))
David S. Millerf7ceba32005-07-10 19:29:45 -0700649 goto out;
650
651 if (!test_thread_flag(TIF_SYSCALL_TRACE))
652 goto out;
653
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
655 ? 0x80 : 0));
656
657 /*
658 * this isn't the same as continuing with a signal, but it will do
659 * for normal use. strace only continues with a signal if the
660 * stopping signal is not SIGTRAP. -brl
661 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 if (current->exit_code) {
David S. Millerbb49bcd2005-07-10 16:49:28 -0700663 send_sig(current->exit_code, current, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664 current->exit_code = 0;
665 }
David S. Millerf7ceba32005-07-10 19:29:45 -0700666
667out:
668 if (unlikely(current->audit_context) && !syscall_exit_p)
669 audit_syscall_entry(current,
670 (test_thread_flag(TIF_32BIT) ?
671 AUDIT_ARCH_SPARC :
672 AUDIT_ARCH_SPARC64),
673 regs->u_regs[UREG_G1],
674 regs->u_regs[UREG_I0],
675 regs->u_regs[UREG_I1],
676 regs->u_regs[UREG_I2],
677 regs->u_regs[UREG_I3]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678}