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