linux/arch/arm64/kernel/ptrace.c
<<
>>
Prefs
   1/*
   2 * Based on arch/arm/kernel/ptrace.c
   3 *
   4 * By Ross Biro 1/23/92
   5 * edited by Linus Torvalds
   6 * ARM modifications Copyright (C) 2000 Russell King
   7 * Copyright (C) 2012 ARM Ltd.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21
  22#include <linux/audit.h>
  23#include <linux/compat.h>
  24#include <linux/kernel.h>
  25#include <linux/sched.h>
  26#include <linux/mm.h>
  27#include <linux/smp.h>
  28#include <linux/ptrace.h>
  29#include <linux/user.h>
  30#include <linux/security.h>
  31#include <linux/init.h>
  32#include <linux/signal.h>
  33#include <linux/uaccess.h>
  34#include <linux/perf_event.h>
  35#include <linux/hw_breakpoint.h>
  36#include <linux/regset.h>
  37#include <linux/tracehook.h>
  38#include <linux/elf.h>
  39
  40#include <asm/compat.h>
  41#include <asm/debug-monitors.h>
  42#include <asm/pgtable.h>
  43#include <asm/syscall.h>
  44#include <asm/traps.h>
  45#include <asm/system_misc.h>
  46
  47#define CREATE_TRACE_POINTS
  48#include <trace/events/syscalls.h>
  49
  50/*
  51 * TODO: does not yet catch signals sent when the child dies.
  52 * in exit.c or in signal.c.
  53 */
  54
  55/*
  56 * Called by kernel/ptrace.c when detaching..
  57 */
  58void ptrace_disable(struct task_struct *child)
  59{
  60}
  61
  62#ifdef CONFIG_HAVE_HW_BREAKPOINT
  63/*
  64 * Handle hitting a HW-breakpoint.
  65 */
  66static void ptrace_hbptriggered(struct perf_event *bp,
  67                                struct perf_sample_data *data,
  68                                struct pt_regs *regs)
  69{
  70        struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
  71        siginfo_t info = {
  72                .si_signo       = SIGTRAP,
  73                .si_errno       = 0,
  74                .si_code        = TRAP_HWBKPT,
  75                .si_addr        = (void __user *)(bkpt->trigger),
  76        };
  77
  78#ifdef CONFIG_COMPAT
  79        int i;
  80
  81        if (!is_compat_task())
  82                goto send_sig;
  83
  84        for (i = 0; i < ARM_MAX_BRP; ++i) {
  85                if (current->thread.debug.hbp_break[i] == bp) {
  86                        info.si_errno = (i << 1) + 1;
  87                        break;
  88                }
  89        }
  90
  91        for (i = 0; i < ARM_MAX_WRP; ++i) {
  92                if (current->thread.debug.hbp_watch[i] == bp) {
  93                        info.si_errno = -((i << 1) + 1);
  94                        break;
  95                }
  96        }
  97
  98send_sig:
  99#endif
 100        force_sig_info(SIGTRAP, &info, current);
 101}
 102
 103/*
 104 * Unregister breakpoints from this task and reset the pointers in
 105 * the thread_struct.
 106 */
 107void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
 108{
 109        int i;
 110        struct thread_struct *t = &tsk->thread;
 111
 112        for (i = 0; i < ARM_MAX_BRP; i++) {
 113                if (t->debug.hbp_break[i]) {
 114                        unregister_hw_breakpoint(t->debug.hbp_break[i]);
 115                        t->debug.hbp_break[i] = NULL;
 116                }
 117        }
 118
 119        for (i = 0; i < ARM_MAX_WRP; i++) {
 120                if (t->debug.hbp_watch[i]) {
 121                        unregister_hw_breakpoint(t->debug.hbp_watch[i]);
 122                        t->debug.hbp_watch[i] = NULL;
 123                }
 124        }
 125}
 126
 127void ptrace_hw_copy_thread(struct task_struct *tsk)
 128{
 129        memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
 130}
 131
 132static struct perf_event *ptrace_hbp_get_event(unsigned int note_type,
 133                                               struct task_struct *tsk,
 134                                               unsigned long idx)
 135{
 136        struct perf_event *bp = ERR_PTR(-EINVAL);
 137
 138        switch (note_type) {
 139        case NT_ARM_HW_BREAK:
 140                if (idx < ARM_MAX_BRP)
 141                        bp = tsk->thread.debug.hbp_break[idx];
 142                break;
 143        case NT_ARM_HW_WATCH:
 144                if (idx < ARM_MAX_WRP)
 145                        bp = tsk->thread.debug.hbp_watch[idx];
 146                break;
 147        }
 148
 149        return bp;
 150}
 151
 152static int ptrace_hbp_set_event(unsigned int note_type,
 153                                struct task_struct *tsk,
 154                                unsigned long idx,
 155                                struct perf_event *bp)
 156{
 157        int err = -EINVAL;
 158
 159        switch (note_type) {
 160        case NT_ARM_HW_BREAK:
 161                if (idx < ARM_MAX_BRP) {
 162                        tsk->thread.debug.hbp_break[idx] = bp;
 163                        err = 0;
 164                }
 165                break;
 166        case NT_ARM_HW_WATCH:
 167                if (idx < ARM_MAX_WRP) {
 168                        tsk->thread.debug.hbp_watch[idx] = bp;
 169                        err = 0;
 170                }
 171                break;
 172        }
 173
 174        return err;
 175}
 176
 177static struct perf_event *ptrace_hbp_create(unsigned int note_type,
 178                                            struct task_struct *tsk,
 179                                            unsigned long idx)
 180{
 181        struct perf_event *bp;
 182        struct perf_event_attr attr;
 183        int err, type;
 184
 185        switch (note_type) {
 186        case NT_ARM_HW_BREAK:
 187                type = HW_BREAKPOINT_X;
 188                break;
 189        case NT_ARM_HW_WATCH:
 190                type = HW_BREAKPOINT_RW;
 191                break;
 192        default:
 193                return ERR_PTR(-EINVAL);
 194        }
 195
 196        ptrace_breakpoint_init(&attr);
 197
 198        /*
 199         * Initialise fields to sane defaults
 200         * (i.e. values that will pass validation).
 201         */
 202        attr.bp_addr    = 0;
 203        attr.bp_len     = HW_BREAKPOINT_LEN_4;
 204        attr.bp_type    = type;
 205        attr.disabled   = 1;
 206
 207        bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, tsk);
 208        if (IS_ERR(bp))
 209                return bp;
 210
 211        err = ptrace_hbp_set_event(note_type, tsk, idx, bp);
 212        if (err)
 213                return ERR_PTR(err);
 214
 215        return bp;
 216}
 217
 218static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
 219                                     struct arch_hw_breakpoint_ctrl ctrl,
 220                                     struct perf_event_attr *attr)
 221{
 222        int err, len, type, disabled = !ctrl.enabled;
 223
 224        attr->disabled = disabled;
 225        if (disabled)
 226                return 0;
 227
 228        err = arch_bp_generic_fields(ctrl, &len, &type);
 229        if (err)
 230                return err;
 231
 232        switch (note_type) {
 233        case NT_ARM_HW_BREAK:
 234                if ((type & HW_BREAKPOINT_X) != type)
 235                        return -EINVAL;
 236                break;
 237        case NT_ARM_HW_WATCH:
 238                if ((type & HW_BREAKPOINT_RW) != type)
 239                        return -EINVAL;
 240                break;
 241        default:
 242                return -EINVAL;
 243        }
 244
 245        attr->bp_len    = len;
 246        attr->bp_type   = type;
 247
 248        return 0;
 249}
 250
 251static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info)
 252{
 253        u8 num;
 254        u32 reg = 0;
 255
 256        switch (note_type) {
 257        case NT_ARM_HW_BREAK:
 258                num = hw_breakpoint_slots(TYPE_INST);
 259                break;
 260        case NT_ARM_HW_WATCH:
 261                num = hw_breakpoint_slots(TYPE_DATA);
 262                break;
 263        default:
 264                return -EINVAL;
 265        }
 266
 267        reg |= debug_monitors_arch();
 268        reg <<= 8;
 269        reg |= num;
 270
 271        *info = reg;
 272        return 0;
 273}
 274
 275static int ptrace_hbp_get_ctrl(unsigned int note_type,
 276                               struct task_struct *tsk,
 277                               unsigned long idx,
 278                               u32 *ctrl)
 279{
 280        struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
 281
 282        if (IS_ERR(bp))
 283                return PTR_ERR(bp);
 284
 285        *ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0;
 286        return 0;
 287}
 288
 289static int ptrace_hbp_get_addr(unsigned int note_type,
 290                               struct task_struct *tsk,
 291                               unsigned long idx,
 292                               u64 *addr)
 293{
 294        struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
 295
 296        if (IS_ERR(bp))
 297                return PTR_ERR(bp);
 298
 299        *addr = bp ? bp->attr.bp_addr : 0;
 300        return 0;
 301}
 302
 303static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type,
 304                                                        struct task_struct *tsk,
 305                                                        unsigned long idx)
 306{
 307        struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
 308
 309        if (!bp)
 310                bp = ptrace_hbp_create(note_type, tsk, idx);
 311
 312        return bp;
 313}
 314
 315static int ptrace_hbp_set_ctrl(unsigned int note_type,
 316                               struct task_struct *tsk,
 317                               unsigned long idx,
 318                               u32 uctrl)
 319{
 320        int err;
 321        struct perf_event *bp;
 322        struct perf_event_attr attr;
 323        struct arch_hw_breakpoint_ctrl ctrl;
 324
 325        bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
 326        if (IS_ERR(bp)) {
 327                err = PTR_ERR(bp);
 328                return err;
 329        }
 330
 331        attr = bp->attr;
 332        decode_ctrl_reg(uctrl, &ctrl);
 333        err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr);
 334        if (err)
 335                return err;
 336
 337        return modify_user_hw_breakpoint(bp, &attr);
 338}
 339
 340static int ptrace_hbp_set_addr(unsigned int note_type,
 341                               struct task_struct *tsk,
 342                               unsigned long idx,
 343                               u64 addr)
 344{
 345        int err;
 346        struct perf_event *bp;
 347        struct perf_event_attr attr;
 348
 349        bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
 350        if (IS_ERR(bp)) {
 351                err = PTR_ERR(bp);
 352                return err;
 353        }
 354
 355        attr = bp->attr;
 356        attr.bp_addr = addr;
 357        err = modify_user_hw_breakpoint(bp, &attr);
 358        return err;
 359}
 360
 361#define PTRACE_HBP_ADDR_SZ      sizeof(u64)
 362#define PTRACE_HBP_CTRL_SZ      sizeof(u32)
 363#define PTRACE_HBP_PAD_SZ       sizeof(u32)
 364
 365static int hw_break_get(struct task_struct *target,
 366                        const struct user_regset *regset,
 367                        unsigned int pos, unsigned int count,
 368                        void *kbuf, void __user *ubuf)
 369{
 370        unsigned int note_type = regset->core_note_type;
 371        int ret, idx = 0, offset, limit;
 372        u32 info, ctrl;
 373        u64 addr;
 374
 375        /* Resource info */
 376        ret = ptrace_hbp_get_resource_info(note_type, &info);
 377        if (ret)
 378                return ret;
 379
 380        ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0,
 381                                  sizeof(info));
 382        if (ret)
 383                return ret;
 384
 385        /* Pad */
 386        offset = offsetof(struct user_hwdebug_state, pad);
 387        ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset,
 388                                       offset + PTRACE_HBP_PAD_SZ);
 389        if (ret)
 390                return ret;
 391
 392        /* (address, ctrl) registers */
 393        offset = offsetof(struct user_hwdebug_state, dbg_regs);
 394        limit = regset->n * regset->size;
 395        while (count && offset < limit) {
 396                ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
 397                if (ret)
 398                        return ret;
 399                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr,
 400                                          offset, offset + PTRACE_HBP_ADDR_SZ);
 401                if (ret)
 402                        return ret;
 403                offset += PTRACE_HBP_ADDR_SZ;
 404
 405                ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl);
 406                if (ret)
 407                        return ret;
 408                ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl,
 409                                          offset, offset + PTRACE_HBP_CTRL_SZ);
 410                if (ret)
 411                        return ret;
 412                offset += PTRACE_HBP_CTRL_SZ;
 413
 414                ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
 415                                               offset,
 416                                               offset + PTRACE_HBP_PAD_SZ);
 417                if (ret)
 418                        return ret;
 419                offset += PTRACE_HBP_PAD_SZ;
 420                idx++;
 421        }
 422
 423        return 0;
 424}
 425
 426static int hw_break_set(struct task_struct *target,
 427                        const struct user_regset *regset,
 428                        unsigned int pos, unsigned int count,
 429                        const void *kbuf, const void __user *ubuf)
 430{
 431        unsigned int note_type = regset->core_note_type;
 432        int ret, idx = 0, offset, limit;
 433        u32 ctrl;
 434        u64 addr;
 435
 436        /* Resource info and pad */
 437        offset = offsetof(struct user_hwdebug_state, dbg_regs);
 438        ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
 439        if (ret)
 440                return ret;
 441
 442        /* (address, ctrl) registers */
 443        limit = regset->n * regset->size;
 444        while (count && offset < limit) {
 445                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
 446                                         offset, offset + PTRACE_HBP_ADDR_SZ);
 447                if (ret)
 448                        return ret;
 449                ret = ptrace_hbp_set_addr(note_type, target, idx, addr);
 450                if (ret)
 451                        return ret;
 452                offset += PTRACE_HBP_ADDR_SZ;
 453
 454                ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
 455                                         offset, offset + PTRACE_HBP_CTRL_SZ);
 456                if (ret)
 457                        return ret;
 458                ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl);
 459                if (ret)
 460                        return ret;
 461                offset += PTRACE_HBP_CTRL_SZ;
 462
 463                ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
 464                                                offset,
 465                                                offset + PTRACE_HBP_PAD_SZ);
 466                if (ret)
 467                        return ret;
 468                offset += PTRACE_HBP_PAD_SZ;
 469                idx++;
 470        }
 471
 472        return 0;
 473}
 474#endif  /* CONFIG_HAVE_HW_BREAKPOINT */
 475
 476static int gpr_get(struct task_struct *target,
 477                   const struct user_regset *regset,
 478                   unsigned int pos, unsigned int count,
 479                   void *kbuf, void __user *ubuf)
 480{
 481        struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs;
 482        return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
 483}
 484
 485static int gpr_set(struct task_struct *target, const struct user_regset *regset,
 486                   unsigned int pos, unsigned int count,
 487                   const void *kbuf, const void __user *ubuf)
 488{
 489        int ret;
 490        struct user_pt_regs newregs;
 491
 492        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
 493        if (ret)
 494                return ret;
 495
 496        if (!valid_user_regs(&newregs))
 497                return -EINVAL;
 498
 499        task_pt_regs(target)->user_regs = newregs;
 500        return 0;
 501}
 502
 503/*
 504 * TODO: update fp accessors for lazy context switching (sync/flush hwstate)
 505 */
 506static int fpr_get(struct task_struct *target, const struct user_regset *regset,
 507                   unsigned int pos, unsigned int count,
 508                   void *kbuf, void __user *ubuf)
 509{
 510        struct user_fpsimd_state *uregs;
 511        uregs = &target->thread.fpsimd_state.user_fpsimd;
 512        return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
 513}
 514
 515static int fpr_set(struct task_struct *target, const struct user_regset *regset,
 516                   unsigned int pos, unsigned int count,
 517                   const void *kbuf, const void __user *ubuf)
 518{
 519        int ret;
 520        struct user_fpsimd_state newstate;
 521
 522        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
 523        if (ret)
 524                return ret;
 525
 526        target->thread.fpsimd_state.user_fpsimd = newstate;
 527        fpsimd_flush_task_state(target);
 528        return ret;
 529}
 530
 531static int tls_get(struct task_struct *target, const struct user_regset *regset,
 532                   unsigned int pos, unsigned int count,
 533                   void *kbuf, void __user *ubuf)
 534{
 535        unsigned long *tls = &target->thread.tp_value;
 536        return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1);
 537}
 538
 539static int tls_set(struct task_struct *target, const struct user_regset *regset,
 540                   unsigned int pos, unsigned int count,
 541                   const void *kbuf, const void __user *ubuf)
 542{
 543        int ret;
 544        unsigned long tls;
 545
 546        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
 547        if (ret)
 548                return ret;
 549
 550        target->thread.tp_value = tls;
 551        return ret;
 552}
 553
 554enum aarch64_regset {
 555        REGSET_GPR,
 556        REGSET_FPR,
 557        REGSET_TLS,
 558#ifdef CONFIG_HAVE_HW_BREAKPOINT
 559        REGSET_HW_BREAK,
 560        REGSET_HW_WATCH,
 561#endif
 562};
 563
 564static const struct user_regset aarch64_regsets[] = {
 565        [REGSET_GPR] = {
 566                .core_note_type = NT_PRSTATUS,
 567                .n = sizeof(struct user_pt_regs) / sizeof(u64),
 568                .size = sizeof(u64),
 569                .align = sizeof(u64),
 570                .get = gpr_get,
 571                .set = gpr_set
 572        },
 573        [REGSET_FPR] = {
 574                .core_note_type = NT_PRFPREG,
 575                .n = sizeof(struct user_fpsimd_state) / sizeof(u32),
 576                /*
 577                 * We pretend we have 32-bit registers because the fpsr and
 578                 * fpcr are 32-bits wide.
 579                 */
 580                .size = sizeof(u32),
 581                .align = sizeof(u32),
 582                .get = fpr_get,
 583                .set = fpr_set
 584        },
 585        [REGSET_TLS] = {
 586                .core_note_type = NT_ARM_TLS,
 587                .n = 1,
 588                .size = sizeof(void *),
 589                .align = sizeof(void *),
 590                .get = tls_get,
 591                .set = tls_set,
 592        },
 593#ifdef CONFIG_HAVE_HW_BREAKPOINT
 594        [REGSET_HW_BREAK] = {
 595                .core_note_type = NT_ARM_HW_BREAK,
 596                .n = sizeof(struct user_hwdebug_state) / sizeof(u32),
 597                .size = sizeof(u32),
 598                .align = sizeof(u32),
 599                .get = hw_break_get,
 600                .set = hw_break_set,
 601        },
 602        [REGSET_HW_WATCH] = {
 603                .core_note_type = NT_ARM_HW_WATCH,
 604                .n = sizeof(struct user_hwdebug_state) / sizeof(u32),
 605                .size = sizeof(u32),
 606                .align = sizeof(u32),
 607                .get = hw_break_get,
 608                .set = hw_break_set,
 609        },
 610#endif
 611};
 612
 613static const struct user_regset_view user_aarch64_view = {
 614        .name = "aarch64", .e_machine = EM_AARCH64,
 615        .regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets)
 616};
 617
 618#ifdef CONFIG_COMPAT
 619#include <linux/compat.h>
 620
 621enum compat_regset {
 622        REGSET_COMPAT_GPR,
 623        REGSET_COMPAT_VFP,
 624};
 625
 626static int compat_gpr_get(struct task_struct *target,
 627                          const struct user_regset *regset,
 628                          unsigned int pos, unsigned int count,
 629                          void *kbuf, void __user *ubuf)
 630{
 631        int ret = 0;
 632        unsigned int i, start, num_regs;
 633
 634        /* Calculate the number of AArch32 registers contained in count */
 635        num_regs = count / regset->size;
 636
 637        /* Convert pos into an register number */
 638        start = pos / regset->size;
 639
 640        if (start + num_regs > regset->n)
 641                return -EIO;
 642
 643        for (i = 0; i < num_regs; ++i) {
 644                unsigned int idx = start + i;
 645                compat_ulong_t reg;
 646
 647                switch (idx) {
 648                case 15:
 649                        reg = task_pt_regs(target)->pc;
 650                        break;
 651                case 16:
 652                        reg = task_pt_regs(target)->pstate;
 653                        break;
 654                case 17:
 655                        reg = task_pt_regs(target)->orig_x0;
 656                        break;
 657                default:
 658                        reg = task_pt_regs(target)->regs[idx];
 659                }
 660
 661                if (kbuf) {
 662                        memcpy(kbuf, &reg, sizeof(reg));
 663                        kbuf += sizeof(reg);
 664                } else {
 665                        ret = copy_to_user(ubuf, &reg, sizeof(reg));
 666                        if (ret) {
 667                                ret = -EFAULT;
 668                                break;
 669                        }
 670
 671                        ubuf += sizeof(reg);
 672                }
 673        }
 674
 675        return ret;
 676}
 677
 678static int compat_gpr_set(struct task_struct *target,
 679                          const struct user_regset *regset,
 680                          unsigned int pos, unsigned int count,
 681                          const void *kbuf, const void __user *ubuf)
 682{
 683        struct pt_regs newregs;
 684        int ret = 0;
 685        unsigned int i, start, num_regs;
 686
 687        /* Calculate the number of AArch32 registers contained in count */
 688        num_regs = count / regset->size;
 689
 690        /* Convert pos into an register number */
 691        start = pos / regset->size;
 692
 693        if (start + num_regs > regset->n)
 694                return -EIO;
 695
 696        newregs = *task_pt_regs(target);
 697
 698        for (i = 0; i < num_regs; ++i) {
 699                unsigned int idx = start + i;
 700                compat_ulong_t reg;
 701
 702                if (kbuf) {
 703                        memcpy(&reg, kbuf, sizeof(reg));
 704                        kbuf += sizeof(reg);
 705                } else {
 706                        ret = copy_from_user(&reg, ubuf, sizeof(reg));
 707                        if (ret) {
 708                                ret = -EFAULT;
 709                                break;
 710                        }
 711
 712                        ubuf += sizeof(reg);
 713                }
 714
 715                switch (idx) {
 716                case 15:
 717                        newregs.pc = reg;
 718                        break;
 719                case 16:
 720                        newregs.pstate = reg;
 721                        break;
 722                case 17:
 723                        newregs.orig_x0 = reg;
 724                        break;
 725                default:
 726                        newregs.regs[idx] = reg;
 727                }
 728
 729        }
 730
 731        if (valid_user_regs(&newregs.user_regs))
 732                *task_pt_regs(target) = newregs;
 733        else
 734                ret = -EINVAL;
 735
 736        return ret;
 737}
 738
 739static int compat_vfp_get(struct task_struct *target,
 740                          const struct user_regset *regset,
 741                          unsigned int pos, unsigned int count,
 742                          void *kbuf, void __user *ubuf)
 743{
 744        struct user_fpsimd_state *uregs;
 745        compat_ulong_t fpscr;
 746        int ret;
 747
 748        uregs = &target->thread.fpsimd_state.user_fpsimd;
 749
 750        /*
 751         * The VFP registers are packed into the fpsimd_state, so they all sit
 752         * nicely together for us. We just need to create the fpscr separately.
 753         */
 754        ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
 755                                  VFP_STATE_SIZE - sizeof(compat_ulong_t));
 756
 757        if (count && !ret) {
 758                fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) |
 759                        (uregs->fpcr & VFP_FPSCR_CTRL_MASK);
 760                ret = put_user(fpscr, (compat_ulong_t *)ubuf);
 761        }
 762
 763        return ret;
 764}
 765
 766static int compat_vfp_set(struct task_struct *target,
 767                          const struct user_regset *regset,
 768                          unsigned int pos, unsigned int count,
 769                          const void *kbuf, const void __user *ubuf)
 770{
 771        struct user_fpsimd_state *uregs;
 772        compat_ulong_t fpscr;
 773        int ret;
 774
 775        if (pos + count > VFP_STATE_SIZE)
 776                return -EIO;
 777
 778        uregs = &target->thread.fpsimd_state.user_fpsimd;
 779
 780        ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
 781                                 VFP_STATE_SIZE - sizeof(compat_ulong_t));
 782
 783        if (count && !ret) {
 784                ret = get_user(fpscr, (compat_ulong_t *)ubuf);
 785                uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK;
 786                uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK;
 787        }
 788
 789        fpsimd_flush_task_state(target);
 790        return ret;
 791}
 792
 793static const struct user_regset aarch32_regsets[] = {
 794        [REGSET_COMPAT_GPR] = {
 795                .core_note_type = NT_PRSTATUS,
 796                .n = COMPAT_ELF_NGREG,
 797                .size = sizeof(compat_elf_greg_t),
 798                .align = sizeof(compat_elf_greg_t),
 799                .get = compat_gpr_get,
 800                .set = compat_gpr_set
 801        },
 802        [REGSET_COMPAT_VFP] = {
 803                .core_note_type = NT_ARM_VFP,
 804                .n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
 805                .size = sizeof(compat_ulong_t),
 806                .align = sizeof(compat_ulong_t),
 807                .get = compat_vfp_get,
 808                .set = compat_vfp_set
 809        },
 810};
 811
 812static const struct user_regset_view user_aarch32_view = {
 813        .name = "aarch32", .e_machine = EM_ARM,
 814        .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets)
 815};
 816
 817static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
 818                                   compat_ulong_t __user *ret)
 819{
 820        compat_ulong_t tmp;
 821
 822        if (off & 3)
 823                return -EIO;
 824
 825        if (off == COMPAT_PT_TEXT_ADDR)
 826                tmp = tsk->mm->start_code;
 827        else if (off == COMPAT_PT_DATA_ADDR)
 828                tmp = tsk->mm->start_data;
 829        else if (off == COMPAT_PT_TEXT_END_ADDR)
 830                tmp = tsk->mm->end_code;
 831        else if (off < sizeof(compat_elf_gregset_t))
 832                return copy_regset_to_user(tsk, &user_aarch32_view,
 833                                           REGSET_COMPAT_GPR, off,
 834                                           sizeof(compat_ulong_t), ret);
 835        else if (off >= COMPAT_USER_SZ)
 836                return -EIO;
 837        else
 838                tmp = 0;
 839
 840        return put_user(tmp, ret);
 841}
 842
 843static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
 844                                    compat_ulong_t val)
 845{
 846        int ret;
 847        mm_segment_t old_fs = get_fs();
 848
 849        if (off & 3 || off >= COMPAT_USER_SZ)
 850                return -EIO;
 851
 852        if (off >= sizeof(compat_elf_gregset_t))
 853                return 0;
 854
 855        set_fs(KERNEL_DS);
 856        ret = copy_regset_from_user(tsk, &user_aarch32_view,
 857                                    REGSET_COMPAT_GPR, off,
 858                                    sizeof(compat_ulong_t),
 859                                    &val);
 860        set_fs(old_fs);
 861
 862        return ret;
 863}
 864
 865#ifdef CONFIG_HAVE_HW_BREAKPOINT
 866
 867/*
 868 * Convert a virtual register number into an index for a thread_info
 869 * breakpoint array. Breakpoints are identified using positive numbers
 870 * whilst watchpoints are negative. The registers are laid out as pairs
 871 * of (address, control), each pair mapping to a unique hw_breakpoint struct.
 872 * Register 0 is reserved for describing resource information.
 873 */
 874static int compat_ptrace_hbp_num_to_idx(compat_long_t num)
 875{
 876        return (abs(num) - 1) >> 1;
 877}
 878
 879static int compat_ptrace_hbp_get_resource_info(u32 *kdata)
 880{
 881        u8 num_brps, num_wrps, debug_arch, wp_len;
 882        u32 reg = 0;
 883
 884        num_brps        = hw_breakpoint_slots(TYPE_INST);
 885        num_wrps        = hw_breakpoint_slots(TYPE_DATA);
 886
 887        debug_arch      = debug_monitors_arch();
 888        wp_len          = 8;
 889        reg             |= debug_arch;
 890        reg             <<= 8;
 891        reg             |= wp_len;
 892        reg             <<= 8;
 893        reg             |= num_wrps;
 894        reg             <<= 8;
 895        reg             |= num_brps;
 896
 897        *kdata = reg;
 898        return 0;
 899}
 900
 901static int compat_ptrace_hbp_get(unsigned int note_type,
 902                                 struct task_struct *tsk,
 903                                 compat_long_t num,
 904                                 u32 *kdata)
 905{
 906        u64 addr = 0;
 907        u32 ctrl = 0;
 908
 909        int err, idx = compat_ptrace_hbp_num_to_idx(num);;
 910
 911        if (num & 1) {
 912                err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr);
 913                *kdata = (u32)addr;
 914        } else {
 915                err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl);
 916                *kdata = ctrl;
 917        }
 918
 919        return err;
 920}
 921
 922static int compat_ptrace_hbp_set(unsigned int note_type,
 923                                 struct task_struct *tsk,
 924                                 compat_long_t num,
 925                                 u32 *kdata)
 926{
 927        u64 addr;
 928        u32 ctrl;
 929
 930        int err, idx = compat_ptrace_hbp_num_to_idx(num);
 931
 932        if (num & 1) {
 933                addr = *kdata;
 934                err = ptrace_hbp_set_addr(note_type, tsk, idx, addr);
 935        } else {
 936                ctrl = *kdata;
 937                err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl);
 938        }
 939
 940        return err;
 941}
 942
 943static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num,
 944                                    compat_ulong_t __user *data)
 945{
 946        int ret;
 947        u32 kdata;
 948        mm_segment_t old_fs = get_fs();
 949
 950        set_fs(KERNEL_DS);
 951        /* Watchpoint */
 952        if (num < 0) {
 953                ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata);
 954        /* Resource info */
 955        } else if (num == 0) {
 956                ret = compat_ptrace_hbp_get_resource_info(&kdata);
 957        /* Breakpoint */
 958        } else {
 959                ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata);
 960        }
 961        set_fs(old_fs);
 962
 963        if (!ret)
 964                ret = put_user(kdata, data);
 965
 966        return ret;
 967}
 968
 969static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num,
 970                                    compat_ulong_t __user *data)
 971{
 972        int ret;
 973        u32 kdata = 0;
 974        mm_segment_t old_fs = get_fs();
 975
 976        if (num == 0)
 977                return 0;
 978
 979        ret = get_user(kdata, data);
 980        if (ret)
 981                return ret;
 982
 983        set_fs(KERNEL_DS);
 984        if (num < 0)
 985                ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata);
 986        else
 987                ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata);
 988        set_fs(old_fs);
 989
 990        return ret;
 991}
 992#endif  /* CONFIG_HAVE_HW_BREAKPOINT */
 993
 994long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 995                        compat_ulong_t caddr, compat_ulong_t cdata)
 996{
 997        unsigned long addr = caddr;
 998        unsigned long data = cdata;
 999        void __user *datap = compat_ptr(data);
1000        int ret;
1001
1002        switch (request) {
1003                case PTRACE_PEEKUSR:
1004                        ret = compat_ptrace_read_user(child, addr, datap);
1005                        break;
1006
1007                case PTRACE_POKEUSR:
1008                        ret = compat_ptrace_write_user(child, addr, data);
1009                        break;
1010
1011                case COMPAT_PTRACE_GETREGS:
1012                        ret = copy_regset_to_user(child,
1013                                                  &user_aarch32_view,
1014                                                  REGSET_COMPAT_GPR,
1015                                                  0, sizeof(compat_elf_gregset_t),
1016                                                  datap);
1017                        break;
1018
1019                case COMPAT_PTRACE_SETREGS:
1020                        ret = copy_regset_from_user(child,
1021                                                    &user_aarch32_view,
1022                                                    REGSET_COMPAT_GPR,
1023                                                    0, sizeof(compat_elf_gregset_t),
1024                                                    datap);
1025                        break;
1026
1027                case COMPAT_PTRACE_GET_THREAD_AREA:
1028                        ret = put_user((compat_ulong_t)child->thread.tp_value,
1029                                       (compat_ulong_t __user *)datap);
1030                        break;
1031
1032                case COMPAT_PTRACE_SET_SYSCALL:
1033                        task_pt_regs(child)->syscallno = data;
1034                        ret = 0;
1035                        break;
1036
1037                case COMPAT_PTRACE_GETVFPREGS:
1038                        ret = copy_regset_to_user(child,
1039                                                  &user_aarch32_view,
1040                                                  REGSET_COMPAT_VFP,
1041                                                  0, VFP_STATE_SIZE,
1042                                                  datap);
1043                        break;
1044
1045                case COMPAT_PTRACE_SETVFPREGS:
1046                        ret = copy_regset_from_user(child,
1047                                                    &user_aarch32_view,
1048                                                    REGSET_COMPAT_VFP,
1049                                                    0, VFP_STATE_SIZE,
1050                                                    datap);
1051                        break;
1052
1053#ifdef CONFIG_HAVE_HW_BREAKPOINT
1054                case COMPAT_PTRACE_GETHBPREGS:
1055                        ret = compat_ptrace_gethbpregs(child, addr, datap);
1056                        break;
1057
1058                case COMPAT_PTRACE_SETHBPREGS:
1059                        ret = compat_ptrace_sethbpregs(child, addr, datap);
1060                        break;
1061#endif
1062
1063                default:
1064                        ret = compat_ptrace_request(child, request, addr,
1065                                                    data);
1066                        break;
1067        }
1068
1069        return ret;
1070}
1071#endif /* CONFIG_COMPAT */
1072
1073const struct user_regset_view *task_user_regset_view(struct task_struct *task)
1074{
1075#ifdef CONFIG_COMPAT
1076        if (is_compat_thread(task_thread_info(task)))
1077                return &user_aarch32_view;
1078#endif
1079        return &user_aarch64_view;
1080}
1081
1082long arch_ptrace(struct task_struct *child, long request,
1083                 unsigned long addr, unsigned long data)
1084{
1085        return ptrace_request(child, request, addr, data);
1086}
1087
1088enum ptrace_syscall_dir {
1089        PTRACE_SYSCALL_ENTER = 0,
1090        PTRACE_SYSCALL_EXIT,
1091};
1092
1093static void tracehook_report_syscall(struct pt_regs *regs,
1094                                     enum ptrace_syscall_dir dir)
1095{
1096        int regno;
1097        unsigned long saved_reg;
1098
1099        /*
1100         * A scratch register (ip(r12) on AArch32, x7 on AArch64) is
1101         * used to denote syscall entry/exit:
1102         */
1103        regno = (is_compat_task() ? 12 : 7);
1104        saved_reg = regs->regs[regno];
1105        regs->regs[regno] = dir;
1106
1107        if (dir == PTRACE_SYSCALL_EXIT)
1108                tracehook_report_syscall_exit(regs, 0);
1109        else if (tracehook_report_syscall_entry(regs))
1110                regs->syscallno = ~0UL;
1111
1112        regs->regs[regno] = saved_reg;
1113}
1114
1115asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1116{
1117        if (test_thread_flag(TIF_SYSCALL_TRACE))
1118                tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
1119
1120        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
1121                trace_sys_enter(regs, regs->syscallno);
1122
1123        audit_syscall_entry(syscall_get_arch(), regs->syscallno,
1124                regs->orig_x0, regs->regs[1], regs->regs[2], regs->regs[3]);
1125
1126        return regs->syscallno;
1127}
1128
1129asmlinkage void syscall_trace_exit(struct pt_regs *regs)
1130{
1131        audit_syscall_exit(regs);
1132
1133        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
1134                trace_sys_exit(regs, regs_return_value(regs));
1135
1136        if (test_thread_flag(TIF_SYSCALL_TRACE))
1137                tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
1138}
1139