linux/kernel/ptrace.c
<<
>>
Prefs
   1/*
   2 * linux/kernel/ptrace.c
   3 *
   4 * (C) Copyright 1999 Linus Torvalds
   5 *
   6 * Common interfaces for "ptrace()" which we do not want
   7 * to continually duplicate across every architecture.
   8 */
   9
  10#include <linux/capability.h>
  11#include <linux/module.h>
  12#include <linux/sched.h>
  13#include <linux/errno.h>
  14#include <linux/mm.h>
  15#include <linux/highmem.h>
  16#include <linux/pagemap.h>
  17#include <linux/ptrace.h>
  18#include <linux/security.h>
  19#include <linux/signal.h>
  20#include <linux/audit.h>
  21#include <linux/pid_namespace.h>
  22#include <linux/syscalls.h>
  23#include <linux/uaccess.h>
  24#include <linux/regset.h>
  25
  26
  27/*
  28 * ptrace a task: make the debugger its new parent and
  29 * move it to the ptrace list.
  30 *
  31 * Must be called with the tasklist lock write-held.
  32 */
  33void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
  34{
  35        BUG_ON(!list_empty(&child->ptrace_entry));
  36        list_add(&child->ptrace_entry, &new_parent->ptraced);
  37        child->parent = new_parent;
  38}
  39
  40/*
  41 * Turn a tracing stop into a normal stop now, since with no tracer there
  42 * would be no way to wake it up with SIGCONT or SIGKILL.  If there was a
  43 * signal sent that would resume the child, but didn't because it was in
  44 * TASK_TRACED, resume it now.
  45 * Requires that irqs be disabled.
  46 */
  47static void ptrace_untrace(struct task_struct *child)
  48{
  49        spin_lock(&child->sighand->siglock);
  50        if (task_is_traced(child)) {
  51                /*
  52                 * If the group stop is completed or in progress,
  53                 * this thread was already counted as stopped.
  54                 */
  55                if (child->signal->flags & SIGNAL_STOP_STOPPED ||
  56                    child->signal->group_stop_count)
  57                        __set_task_state(child, TASK_STOPPED);
  58                else
  59                        signal_wake_up(child, 1);
  60        }
  61        spin_unlock(&child->sighand->siglock);
  62}
  63
  64/*
  65 * unptrace a task: move it back to its original parent and
  66 * remove it from the ptrace list.
  67 *
  68 * Must be called with the tasklist lock write-held.
  69 */
  70void __ptrace_unlink(struct task_struct *child)
  71{
  72        BUG_ON(!child->ptrace);
  73
  74        child->ptrace = 0;
  75        child->parent = child->real_parent;
  76        list_del_init(&child->ptrace_entry);
  77
  78        if (task_is_traced(child))
  79                ptrace_untrace(child);
  80}
  81
  82/*
  83 * Check that we have indeed attached to the thing..
  84 */
  85int ptrace_check_attach(struct task_struct *child, int kill)
  86{
  87        int ret = -ESRCH;
  88
  89        /*
  90         * We take the read lock around doing both checks to close a
  91         * possible race where someone else was tracing our child and
  92         * detached between these two checks.  After this locked check,
  93         * we are sure that this is our traced child and that can only
  94         * be changed by us so it's not changing right after this.
  95         */
  96        read_lock(&tasklist_lock);
  97        if ((child->ptrace & PT_PTRACED) && child->parent == current) {
  98                ret = 0;
  99                /*
 100                 * child->sighand can't be NULL, release_task()
 101                 * does ptrace_unlink() before __exit_signal().
 102                 */
 103                spin_lock_irq(&child->sighand->siglock);
 104                if (task_is_stopped(child))
 105                        child->state = TASK_TRACED;
 106                else if (!task_is_traced(child) && !kill)
 107                        ret = -ESRCH;
 108                spin_unlock_irq(&child->sighand->siglock);
 109        }
 110        read_unlock(&tasklist_lock);
 111
 112        if (!ret && !kill)
 113                ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
 114
 115        /* All systems go.. */
 116        return ret;
 117}
 118
 119int __ptrace_may_access(struct task_struct *task, unsigned int mode)
 120{
 121        const struct cred *cred = current_cred(), *tcred;
 122
 123        /* May we inspect the given task?
 124         * This check is used both for attaching with ptrace
 125         * and for allowing access to sensitive information in /proc.
 126         *
 127         * ptrace_attach denies several cases that /proc allows
 128         * because setting up the necessary parent/child relationship
 129         * or halting the specified task is impossible.
 130         */
 131        int dumpable = 0;
 132        /* Don't let security modules deny introspection */
 133        if (task == current)
 134                return 0;
 135        rcu_read_lock();
 136        tcred = __task_cred(task);
 137        if ((cred->uid != tcred->euid ||
 138             cred->uid != tcred->suid ||
 139             cred->uid != tcred->uid  ||
 140             cred->gid != tcred->egid ||
 141             cred->gid != tcred->sgid ||
 142             cred->gid != tcred->gid) &&
 143            !capable(CAP_SYS_PTRACE)) {
 144                rcu_read_unlock();
 145                return -EPERM;
 146        }
 147        rcu_read_unlock();
 148        smp_rmb();
 149        if (task->mm)
 150                dumpable = get_dumpable(task->mm);
 151        if (!dumpable && !capable(CAP_SYS_PTRACE))
 152                return -EPERM;
 153
 154        return security_ptrace_access_check(task, mode);
 155}
 156
 157bool ptrace_may_access(struct task_struct *task, unsigned int mode)
 158{
 159        int err;
 160        task_lock(task);
 161        err = __ptrace_may_access(task, mode);
 162        task_unlock(task);
 163        return !err;
 164}
 165
 166int ptrace_attach(struct task_struct *task)
 167{
 168        int retval;
 169
 170        audit_ptrace(task);
 171
 172        retval = -EPERM;
 173        if (unlikely(task->flags & PF_KTHREAD))
 174                goto out;
 175        if (same_thread_group(task, current))
 176                goto out;
 177
 178        /*
 179         * Protect exec's credential calculations against our interference;
 180         * interference; SUID, SGID and LSM creds get determined differently
 181         * under ptrace.
 182         */
 183        retval = -ERESTARTNOINTR;
 184        if (mutex_lock_interruptible(&task->cred_guard_mutex))
 185                goto out;
 186
 187        task_lock(task);
 188        retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
 189        task_unlock(task);
 190        if (retval)
 191                goto unlock_creds;
 192
 193        write_lock_irq(&tasklist_lock);
 194        retval = -EPERM;
 195        if (unlikely(task->exit_state))
 196                goto unlock_tasklist;
 197        if (task->ptrace)
 198                goto unlock_tasklist;
 199
 200        task->ptrace = PT_PTRACED;
 201        if (capable(CAP_SYS_PTRACE))
 202                task->ptrace |= PT_PTRACE_CAP;
 203
 204        __ptrace_link(task, current);
 205        send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
 206
 207        retval = 0;
 208unlock_tasklist:
 209        write_unlock_irq(&tasklist_lock);
 210unlock_creds:
 211        mutex_unlock(&task->cred_guard_mutex);
 212out:
 213        return retval;
 214}
 215
 216/**
 217 * ptrace_traceme  --  helper for PTRACE_TRACEME
 218 *
 219 * Performs checks and sets PT_PTRACED.
 220 * Should be used by all ptrace implementations for PTRACE_TRACEME.
 221 */
 222int ptrace_traceme(void)
 223{
 224        int ret = -EPERM;
 225
 226        write_lock_irq(&tasklist_lock);
 227        /* Are we already being traced? */
 228        if (!current->ptrace) {
 229                ret = security_ptrace_traceme(current->parent);
 230                /*
 231                 * Check PF_EXITING to ensure ->real_parent has not passed
 232                 * exit_ptrace(). Otherwise we don't report the error but
 233                 * pretend ->real_parent untraces us right after return.
 234                 */
 235                if (!ret && !(current->real_parent->flags & PF_EXITING)) {
 236                        current->ptrace = PT_PTRACED;
 237                        __ptrace_link(current, current->real_parent);
 238                }
 239        }
 240        write_unlock_irq(&tasklist_lock);
 241
 242        return ret;
 243}
 244
 245/*
 246 * Called with irqs disabled, returns true if childs should reap themselves.
 247 */
 248static int ignoring_children(struct sighand_struct *sigh)
 249{
 250        int ret;
 251        spin_lock(&sigh->siglock);
 252        ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) ||
 253              (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT);
 254        spin_unlock(&sigh->siglock);
 255        return ret;
 256}
 257
 258/*
 259 * Called with tasklist_lock held for writing.
 260 * Unlink a traced task, and clean it up if it was a traced zombie.
 261 * Return true if it needs to be reaped with release_task().
 262 * (We can't call release_task() here because we already hold tasklist_lock.)
 263 *
 264 * If it's a zombie, our attachedness prevented normal parent notification
 265 * or self-reaping.  Do notification now if it would have happened earlier.
 266 * If it should reap itself, return true.
 267 *
 268 * If it's our own child, there is no notification to do. But if our normal
 269 * children self-reap, then this child was prevented by ptrace and we must
 270 * reap it now, in that case we must also wake up sub-threads sleeping in
 271 * do_wait().
 272 */
 273static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
 274{
 275        __ptrace_unlink(p);
 276
 277        if (p->exit_state == EXIT_ZOMBIE) {
 278                if (!task_detached(p) && thread_group_empty(p)) {
 279                        if (!same_thread_group(p->real_parent, tracer))
 280                                do_notify_parent(p, p->exit_signal);
 281                        else if (ignoring_children(tracer->sighand)) {
 282                                __wake_up_parent(p, tracer);
 283                                p->exit_signal = -1;
 284                        }
 285                }
 286                if (task_detached(p)) {
 287                        /* Mark it as in the process of being reaped. */
 288                        p->exit_state = EXIT_DEAD;
 289                        return true;
 290                }
 291        }
 292
 293        return false;
 294}
 295
 296int ptrace_detach(struct task_struct *child, unsigned int data)
 297{
 298        bool dead = false;
 299
 300        if (!valid_signal(data))
 301                return -EIO;
 302
 303        /* Architecture-specific hardware disable .. */
 304        ptrace_disable(child);
 305        clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 306
 307        write_lock_irq(&tasklist_lock);
 308        /*
 309         * This child can be already killed. Make sure de_thread() or
 310         * our sub-thread doing do_wait() didn't do release_task() yet.
 311         */
 312        if (child->ptrace) {
 313                child->exit_code = data;
 314                dead = __ptrace_detach(current, child);
 315                if (!child->exit_state)
 316                        wake_up_process(child);
 317        }
 318        write_unlock_irq(&tasklist_lock);
 319
 320        if (unlikely(dead))
 321                release_task(child);
 322
 323        return 0;
 324}
 325
 326/*
 327 * Detach all tasks we were using ptrace on.
 328 */
 329void exit_ptrace(struct task_struct *tracer)
 330{
 331        struct task_struct *p, *n;
 332        LIST_HEAD(ptrace_dead);
 333
 334        write_lock_irq(&tasklist_lock);
 335        list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) {
 336                if (__ptrace_detach(tracer, p))
 337                        list_add(&p->ptrace_entry, &ptrace_dead);
 338        }
 339        write_unlock_irq(&tasklist_lock);
 340
 341        BUG_ON(!list_empty(&tracer->ptraced));
 342
 343        list_for_each_entry_safe(p, n, &ptrace_dead, ptrace_entry) {
 344                list_del_init(&p->ptrace_entry);
 345                release_task(p);
 346        }
 347}
 348
 349int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
 350{
 351        int copied = 0;
 352
 353        while (len > 0) {
 354                char buf[128];
 355                int this_len, retval;
 356
 357                this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
 358                retval = access_process_vm(tsk, src, buf, this_len, 0);
 359                if (!retval) {
 360                        if (copied)
 361                                break;
 362                        return -EIO;
 363                }
 364                if (copy_to_user(dst, buf, retval))
 365                        return -EFAULT;
 366                copied += retval;
 367                src += retval;
 368                dst += retval;
 369                len -= retval;
 370        }
 371        return copied;
 372}
 373
 374int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len)
 375{
 376        int copied = 0;
 377
 378        while (len > 0) {
 379                char buf[128];
 380                int this_len, retval;
 381
 382                this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
 383                if (copy_from_user(buf, src, this_len))
 384                        return -EFAULT;
 385                retval = access_process_vm(tsk, dst, buf, this_len, 1);
 386                if (!retval) {
 387                        if (copied)
 388                                break;
 389                        return -EIO;
 390                }
 391                copied += retval;
 392                src += retval;
 393                dst += retval;
 394                len -= retval;
 395        }
 396        return copied;
 397}
 398
 399static int ptrace_setoptions(struct task_struct *child, long data)
 400{
 401        child->ptrace &= ~PT_TRACE_MASK;
 402
 403        if (data & PTRACE_O_TRACESYSGOOD)
 404                child->ptrace |= PT_TRACESYSGOOD;
 405
 406        if (data & PTRACE_O_TRACEFORK)
 407                child->ptrace |= PT_TRACE_FORK;
 408
 409        if (data & PTRACE_O_TRACEVFORK)
 410                child->ptrace |= PT_TRACE_VFORK;
 411
 412        if (data & PTRACE_O_TRACECLONE)
 413                child->ptrace |= PT_TRACE_CLONE;
 414
 415        if (data & PTRACE_O_TRACEEXEC)
 416                child->ptrace |= PT_TRACE_EXEC;
 417
 418        if (data & PTRACE_O_TRACEVFORKDONE)
 419                child->ptrace |= PT_TRACE_VFORK_DONE;
 420
 421        if (data & PTRACE_O_TRACEEXIT)
 422                child->ptrace |= PT_TRACE_EXIT;
 423
 424        return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
 425}
 426
 427static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
 428{
 429        unsigned long flags;
 430        int error = -ESRCH;
 431
 432        if (lock_task_sighand(child, &flags)) {
 433                error = -EINVAL;
 434                if (likely(child->last_siginfo != NULL)) {
 435                        *info = *child->last_siginfo;
 436                        error = 0;
 437                }
 438                unlock_task_sighand(child, &flags);
 439        }
 440        return error;
 441}
 442
 443static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
 444{
 445        unsigned long flags;
 446        int error = -ESRCH;
 447
 448        if (lock_task_sighand(child, &flags)) {
 449                error = -EINVAL;
 450                if (likely(child->last_siginfo != NULL)) {
 451                        *child->last_siginfo = *info;
 452                        error = 0;
 453                }
 454                unlock_task_sighand(child, &flags);
 455        }
 456        return error;
 457}
 458
 459
 460#ifdef PTRACE_SINGLESTEP
 461#define is_singlestep(request)          ((request) == PTRACE_SINGLESTEP)
 462#else
 463#define is_singlestep(request)          0
 464#endif
 465
 466#ifdef PTRACE_SINGLEBLOCK
 467#define is_singleblock(request)         ((request) == PTRACE_SINGLEBLOCK)
 468#else
 469#define is_singleblock(request)         0
 470#endif
 471
 472#ifdef PTRACE_SYSEMU
 473#define is_sysemu_singlestep(request)   ((request) == PTRACE_SYSEMU_SINGLESTEP)
 474#else
 475#define is_sysemu_singlestep(request)   0
 476#endif
 477
 478static int ptrace_resume(struct task_struct *child, long request, long data)
 479{
 480        if (!valid_signal(data))
 481                return -EIO;
 482
 483        if (request == PTRACE_SYSCALL)
 484                set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 485        else
 486                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
 487
 488#ifdef TIF_SYSCALL_EMU
 489        if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP)
 490                set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
 491        else
 492                clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
 493#endif
 494
 495        if (is_singleblock(request)) {
 496                if (unlikely(!arch_has_block_step()))
 497                        return -EIO;
 498                user_enable_block_step(child);
 499        } else if (is_singlestep(request) || is_sysemu_singlestep(request)) {
 500                if (unlikely(!arch_has_single_step()))
 501                        return -EIO;
 502                user_enable_single_step(child);
 503        } else {
 504                user_disable_single_step(child);
 505        }
 506
 507        child->exit_code = data;
 508        wake_up_process(child);
 509
 510        return 0;
 511}
 512
 513#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
 514
 515static const struct user_regset *
 516find_regset(const struct user_regset_view *view, unsigned int type)
 517{
 518        const struct user_regset *regset;
 519        int n;
 520
 521        for (n = 0; n < view->n; ++n) {
 522                regset = view->regsets + n;
 523                if (regset->core_note_type == type)
 524                        return regset;
 525        }
 526
 527        return NULL;
 528}
 529
 530static int ptrace_regset(struct task_struct *task, int req, unsigned int type,
 531                         struct iovec *kiov)
 532{
 533        const struct user_regset_view *view = task_user_regset_view(task);
 534        const struct user_regset *regset = find_regset(view, type);
 535        int regset_no;
 536
 537        if (!regset || (kiov->iov_len % regset->size) != 0)
 538                return -EINVAL;
 539
 540        regset_no = regset - view->regsets;
 541        kiov->iov_len = min(kiov->iov_len,
 542                            (__kernel_size_t) (regset->n * regset->size));
 543
 544        if (req == PTRACE_GETREGSET)
 545                return copy_regset_to_user(task, view, regset_no, 0,
 546                                           kiov->iov_len, kiov->iov_base);
 547        else
 548                return copy_regset_from_user(task, view, regset_no, 0,
 549                                             kiov->iov_len, kiov->iov_base);
 550}
 551
 552#endif
 553
 554int ptrace_request(struct task_struct *child, long request,
 555                   long addr, long data)
 556{
 557        int ret = -EIO;
 558        siginfo_t siginfo;
 559
 560        switch (request) {
 561        case PTRACE_PEEKTEXT:
 562        case PTRACE_PEEKDATA:
 563                return generic_ptrace_peekdata(child, addr, data);
 564        case PTRACE_POKETEXT:
 565        case PTRACE_POKEDATA:
 566                return generic_ptrace_pokedata(child, addr, data);
 567
 568#ifdef PTRACE_OLDSETOPTIONS
 569        case PTRACE_OLDSETOPTIONS:
 570#endif
 571        case PTRACE_SETOPTIONS:
 572                ret = ptrace_setoptions(child, data);
 573                break;
 574        case PTRACE_GETEVENTMSG:
 575                ret = put_user(child->ptrace_message, (unsigned long __user *) data);
 576                break;
 577
 578        case PTRACE_GETSIGINFO:
 579                ret = ptrace_getsiginfo(child, &siginfo);
 580                if (!ret)
 581                        ret = copy_siginfo_to_user((siginfo_t __user *) data,
 582                                                   &siginfo);
 583                break;
 584
 585        case PTRACE_SETSIGINFO:
 586                if (copy_from_user(&siginfo, (siginfo_t __user *) data,
 587                                   sizeof siginfo))
 588                        ret = -EFAULT;
 589                else
 590                        ret = ptrace_setsiginfo(child, &siginfo);
 591                break;
 592
 593        case PTRACE_DETACH:      /* detach a process that was attached. */
 594                ret = ptrace_detach(child, data);
 595                break;
 596
 597#ifdef CONFIG_BINFMT_ELF_FDPIC
 598        case PTRACE_GETFDPIC: {
 599                struct mm_struct *mm = get_task_mm(child);
 600                unsigned long tmp = 0;
 601
 602                ret = -ESRCH;
 603                if (!mm)
 604                        break;
 605
 606                switch (addr) {
 607                case PTRACE_GETFDPIC_EXEC:
 608                        tmp = mm->context.exec_fdpic_loadmap;
 609                        break;
 610                case PTRACE_GETFDPIC_INTERP:
 611                        tmp = mm->context.interp_fdpic_loadmap;
 612                        break;
 613                default:
 614                        break;
 615                }
 616                mmput(mm);
 617
 618                ret = put_user(tmp, (unsigned long __user *) data);
 619                break;
 620        }
 621#endif
 622
 623#ifdef PTRACE_SINGLESTEP
 624        case PTRACE_SINGLESTEP:
 625#endif
 626#ifdef PTRACE_SINGLEBLOCK
 627        case PTRACE_SINGLEBLOCK:
 628#endif
 629#ifdef PTRACE_SYSEMU
 630        case PTRACE_SYSEMU:
 631        case PTRACE_SYSEMU_SINGLESTEP:
 632#endif
 633        case PTRACE_SYSCALL:
 634        case PTRACE_CONT:
 635                return ptrace_resume(child, request, data);
 636
 637        case PTRACE_KILL:
 638                if (child->exit_state)  /* already dead */
 639                        return 0;
 640                return ptrace_resume(child, request, SIGKILL);
 641
 642#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
 643        case PTRACE_GETREGSET:
 644        case PTRACE_SETREGSET:
 645        {
 646                struct iovec kiov;
 647                struct iovec __user *uiov = (struct iovec __user *) data;
 648
 649                if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
 650                        return -EFAULT;
 651
 652                if (__get_user(kiov.iov_base, &uiov->iov_base) ||
 653                    __get_user(kiov.iov_len, &uiov->iov_len))
 654                        return -EFAULT;
 655
 656                ret = ptrace_regset(child, request, addr, &kiov);
 657                if (!ret)
 658                        ret = __put_user(kiov.iov_len, &uiov->iov_len);
 659                break;
 660        }
 661#endif
 662        default:
 663                break;
 664        }
 665
 666        return ret;
 667}
 668
 669static struct task_struct *ptrace_get_task_struct(pid_t pid)
 670{
 671        struct task_struct *child;
 672
 673        rcu_read_lock();
 674        child = find_task_by_vpid(pid);
 675        if (child)
 676                get_task_struct(child);
 677        rcu_read_unlock();
 678
 679        if (!child)
 680                return ERR_PTR(-ESRCH);
 681        return child;
 682}
 683
 684#ifndef arch_ptrace_attach
 685#define arch_ptrace_attach(child)       do { } while (0)
 686#endif
 687
 688SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data)
 689{
 690        struct task_struct *child;
 691        long ret;
 692
 693        if (request == PTRACE_TRACEME) {
 694                ret = ptrace_traceme();
 695                if (!ret)
 696                        arch_ptrace_attach(current);
 697                goto out;
 698        }
 699
 700        child = ptrace_get_task_struct(pid);
 701        if (IS_ERR(child)) {
 702                ret = PTR_ERR(child);
 703                goto out;
 704        }
 705
 706        if (request == PTRACE_ATTACH) {
 707                ret = ptrace_attach(child);
 708                /*
 709                 * Some architectures need to do book-keeping after
 710                 * a ptrace attach.
 711                 */
 712                if (!ret)
 713                        arch_ptrace_attach(child);
 714                goto out_put_task_struct;
 715        }
 716
 717        ret = ptrace_check_attach(child, request == PTRACE_KILL);
 718        if (ret < 0)
 719                goto out_put_task_struct;
 720
 721        ret = arch_ptrace(child, request, addr, data);
 722
 723 out_put_task_struct:
 724        put_task_struct(child);
 725 out:
 726        return ret;
 727}
 728
 729int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data)
 730{
 731        unsigned long tmp;
 732        int copied;
 733
 734        copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
 735        if (copied != sizeof(tmp))
 736                return -EIO;
 737        return put_user(tmp, (unsigned long __user *)data);
 738}
 739
 740int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data)
 741{
 742        int copied;
 743
 744        copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
 745        return (copied == sizeof(data)) ? 0 : -EIO;
 746}
 747
 748#if defined CONFIG_COMPAT
 749#include <linux/compat.h>
 750
 751int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 752                          compat_ulong_t addr, compat_ulong_t data)
 753{
 754        compat_ulong_t __user *datap = compat_ptr(data);
 755        compat_ulong_t word;
 756        siginfo_t siginfo;
 757        int ret;
 758
 759        switch (request) {
 760        case PTRACE_PEEKTEXT:
 761        case PTRACE_PEEKDATA:
 762                ret = access_process_vm(child, addr, &word, sizeof(word), 0);
 763                if (ret != sizeof(word))
 764                        ret = -EIO;
 765                else
 766                        ret = put_user(word, datap);
 767                break;
 768
 769        case PTRACE_POKETEXT:
 770        case PTRACE_POKEDATA:
 771                ret = access_process_vm(child, addr, &data, sizeof(data), 1);
 772                ret = (ret != sizeof(data) ? -EIO : 0);
 773                break;
 774
 775        case PTRACE_GETEVENTMSG:
 776                ret = put_user((compat_ulong_t) child->ptrace_message, datap);
 777                break;
 778
 779        case PTRACE_GETSIGINFO:
 780                ret = ptrace_getsiginfo(child, &siginfo);
 781                if (!ret)
 782                        ret = copy_siginfo_to_user32(
 783                                (struct compat_siginfo __user *) datap,
 784                                &siginfo);
 785                break;
 786
 787        case PTRACE_SETSIGINFO:
 788                memset(&siginfo, 0, sizeof siginfo);
 789                if (copy_siginfo_from_user32(
 790                            &siginfo, (struct compat_siginfo __user *) datap))
 791                        ret = -EFAULT;
 792                else
 793                        ret = ptrace_setsiginfo(child, &siginfo);
 794                break;
 795#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
 796        case PTRACE_GETREGSET:
 797        case PTRACE_SETREGSET:
 798        {
 799                struct iovec kiov;
 800                struct compat_iovec __user *uiov =
 801                        (struct compat_iovec __user *) datap;
 802                compat_uptr_t ptr;
 803                compat_size_t len;
 804
 805                if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
 806                        return -EFAULT;
 807
 808                if (__get_user(ptr, &uiov->iov_base) ||
 809                    __get_user(len, &uiov->iov_len))
 810                        return -EFAULT;
 811
 812                kiov.iov_base = compat_ptr(ptr);
 813                kiov.iov_len = len;
 814
 815                ret = ptrace_regset(child, request, addr, &kiov);
 816                if (!ret)
 817                        ret = __put_user(kiov.iov_len, &uiov->iov_len);
 818                break;
 819        }
 820#endif
 821
 822        default:
 823                ret = ptrace_request(child, request, addr, data);
 824        }
 825
 826        return ret;
 827}
 828
 829asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
 830                                  compat_long_t addr, compat_long_t data)
 831{
 832        struct task_struct *child;
 833        long ret;
 834
 835        if (request == PTRACE_TRACEME) {
 836                ret = ptrace_traceme();
 837                goto out;
 838        }
 839
 840        child = ptrace_get_task_struct(pid);
 841        if (IS_ERR(child)) {
 842                ret = PTR_ERR(child);
 843                goto out;
 844        }
 845
 846        if (request == PTRACE_ATTACH) {
 847                ret = ptrace_attach(child);
 848                /*
 849                 * Some architectures need to do book-keeping after
 850                 * a ptrace attach.
 851                 */
 852                if (!ret)
 853                        arch_ptrace_attach(child);
 854                goto out_put_task_struct;
 855        }
 856
 857        ret = ptrace_check_attach(child, request == PTRACE_KILL);
 858        if (!ret)
 859                ret = compat_arch_ptrace(child, request, addr, data);
 860
 861 out_put_task_struct:
 862        put_task_struct(child);
 863 out:
 864        return ret;
 865}
 866#endif  /* CONFIG_COMPAT */
 867
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.