0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/sched/signal.h>
0011 #include <linux/sched/task_stack.h>
0012 #include <linux/mm.h>
0013 #include <linux/elf.h>
0014 #include <linux/smp.h>
0015 #include <linux/ptrace.h>
0016 #include <linux/user.h>
0017 #include <linux/security.h>
0018 #include <linux/init.h>
0019 #include <linux/signal.h>
0020 #include <linux/uaccess.h>
0021 #include <linux/perf_event.h>
0022 #include <linux/hw_breakpoint.h>
0023 #include <linux/regset.h>
0024 #include <linux/audit.h>
0025 #include <linux/unistd.h>
0026
0027 #include <asm/syscall.h>
0028 #include <asm/traps.h>
0029
0030 #define CREATE_TRACE_POINTS
0031 #include <trace/events/syscalls.h>
0032
0033 #define REG_PC 15
0034 #define REG_PSR 16
0035
0036
0037
0038
0039
0040 #if 0
0041
0042
0043
0044 #define BREAKINST_ARM 0xef9f0001
0045 #define BREAKINST_THUMB 0xdf00
0046 #else
0047
0048
0049
0050
0051
0052
0053
0054
0055 #define BREAKINST_ARM 0xe7f001f0
0056 #define BREAKINST_THUMB 0xde01
0057 #endif
0058
0059 struct pt_regs_offset {
0060 const char *name;
0061 int offset;
0062 };
0063
0064 #define REG_OFFSET_NAME(r) \
0065 {.name = #r, .offset = offsetof(struct pt_regs, ARM_##r)}
0066 #define REG_OFFSET_END {.name = NULL, .offset = 0}
0067
0068 static const struct pt_regs_offset regoffset_table[] = {
0069 REG_OFFSET_NAME(r0),
0070 REG_OFFSET_NAME(r1),
0071 REG_OFFSET_NAME(r2),
0072 REG_OFFSET_NAME(r3),
0073 REG_OFFSET_NAME(r4),
0074 REG_OFFSET_NAME(r5),
0075 REG_OFFSET_NAME(r6),
0076 REG_OFFSET_NAME(r7),
0077 REG_OFFSET_NAME(r8),
0078 REG_OFFSET_NAME(r9),
0079 REG_OFFSET_NAME(r10),
0080 REG_OFFSET_NAME(fp),
0081 REG_OFFSET_NAME(ip),
0082 REG_OFFSET_NAME(sp),
0083 REG_OFFSET_NAME(lr),
0084 REG_OFFSET_NAME(pc),
0085 REG_OFFSET_NAME(cpsr),
0086 REG_OFFSET_NAME(ORIG_r0),
0087 REG_OFFSET_END,
0088 };
0089
0090
0091
0092
0093
0094
0095
0096
0097 int regs_query_register_offset(const char *name)
0098 {
0099 const struct pt_regs_offset *roff;
0100 for (roff = regoffset_table; roff->name != NULL; roff++)
0101 if (!strcmp(roff->name, name))
0102 return roff->offset;
0103 return -EINVAL;
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113 const char *regs_query_register_name(unsigned int offset)
0114 {
0115 const struct pt_regs_offset *roff;
0116 for (roff = regoffset_table; roff->name != NULL; roff++)
0117 if (roff->offset == offset)
0118 return roff->name;
0119 return NULL;
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
0131 {
0132 return ((addr & ~(THREAD_SIZE - 1)) ==
0133 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
0146 {
0147 unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
0148 addr += n;
0149 if (regs_within_kernel_stack(regs, (unsigned long)addr))
0150 return *addr;
0151 else
0152 return 0;
0153 }
0154
0155
0156
0157
0158
0159
0160
0161 static inline long get_user_reg(struct task_struct *task, int offset)
0162 {
0163 return task_pt_regs(task)->uregs[offset];
0164 }
0165
0166
0167
0168
0169
0170
0171
0172 static inline int
0173 put_user_reg(struct task_struct *task, int offset, long data)
0174 {
0175 struct pt_regs newregs, *regs = task_pt_regs(task);
0176 int ret = -EINVAL;
0177
0178 newregs = *regs;
0179 newregs.uregs[offset] = data;
0180
0181 if (valid_user_regs(&newregs)) {
0182 regs->uregs[offset] = data;
0183 ret = 0;
0184 }
0185
0186 return ret;
0187 }
0188
0189
0190
0191
0192 void ptrace_disable(struct task_struct *child)
0193 {
0194
0195 }
0196
0197
0198
0199
0200 void ptrace_break(struct pt_regs *regs)
0201 {
0202 force_sig_fault(SIGTRAP, TRAP_BRKPT,
0203 (void __user *)instruction_pointer(regs));
0204 }
0205
0206 static int break_trap(struct pt_regs *regs, unsigned int instr)
0207 {
0208 ptrace_break(regs);
0209 return 0;
0210 }
0211
0212 static struct undef_hook arm_break_hook = {
0213 .instr_mask = 0x0fffffff,
0214 .instr_val = 0x07f001f0,
0215 .cpsr_mask = PSR_T_BIT,
0216 .cpsr_val = 0,
0217 .fn = break_trap,
0218 };
0219
0220 static struct undef_hook thumb_break_hook = {
0221 .instr_mask = 0xffffffff,
0222 .instr_val = 0x0000de01,
0223 .cpsr_mask = PSR_T_BIT,
0224 .cpsr_val = PSR_T_BIT,
0225 .fn = break_trap,
0226 };
0227
0228 static struct undef_hook thumb2_break_hook = {
0229 .instr_mask = 0xffffffff,
0230 .instr_val = 0xf7f0a000,
0231 .cpsr_mask = PSR_T_BIT,
0232 .cpsr_val = PSR_T_BIT,
0233 .fn = break_trap,
0234 };
0235
0236 static int __init ptrace_break_init(void)
0237 {
0238 register_undef_hook(&arm_break_hook);
0239 register_undef_hook(&thumb_break_hook);
0240 register_undef_hook(&thumb2_break_hook);
0241 return 0;
0242 }
0243
0244 core_initcall(ptrace_break_init);
0245
0246
0247
0248
0249
0250 static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
0251 unsigned long __user *ret)
0252 {
0253 unsigned long tmp;
0254
0255 if (off & 3)
0256 return -EIO;
0257
0258 tmp = 0;
0259 if (off == PT_TEXT_ADDR)
0260 tmp = tsk->mm->start_code;
0261 else if (off == PT_DATA_ADDR)
0262 tmp = tsk->mm->start_data;
0263 else if (off == PT_TEXT_END_ADDR)
0264 tmp = tsk->mm->end_code;
0265 else if (off < sizeof(struct pt_regs))
0266 tmp = get_user_reg(tsk, off >> 2);
0267 else if (off >= sizeof(struct user))
0268 return -EIO;
0269
0270 return put_user(tmp, ret);
0271 }
0272
0273
0274
0275
0276
0277 static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
0278 unsigned long val)
0279 {
0280 if (off & 3 || off >= sizeof(struct user))
0281 return -EIO;
0282
0283 if (off >= sizeof(struct pt_regs))
0284 return 0;
0285
0286 return put_user_reg(tsk, off >> 2, val);
0287 }
0288
0289 #ifdef CONFIG_IWMMXT
0290
0291
0292
0293
0294 static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp)
0295 {
0296 struct thread_info *thread = task_thread_info(tsk);
0297
0298 if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
0299 return -ENODATA;
0300 iwmmxt_task_disable(thread);
0301 return copy_to_user(ufp, &thread->fpstate.iwmmxt, IWMMXT_SIZE)
0302 ? -EFAULT : 0;
0303 }
0304
0305
0306
0307
0308 static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
0309 {
0310 struct thread_info *thread = task_thread_info(tsk);
0311
0312 if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
0313 return -EACCES;
0314 iwmmxt_task_release(thread);
0315 return copy_from_user(&thread->fpstate.iwmmxt, ufp, IWMMXT_SIZE)
0316 ? -EFAULT : 0;
0317 }
0318
0319 #endif
0320
0321 #ifdef CONFIG_HAVE_HW_BREAKPOINT
0322
0323
0324
0325
0326
0327
0328
0329 static int ptrace_hbp_num_to_idx(long num)
0330 {
0331 if (num < 0)
0332 num = (ARM_MAX_BRP << 1) - num;
0333 return (num - 1) >> 1;
0334 }
0335
0336
0337
0338
0339
0340 static long ptrace_hbp_idx_to_num(int idx)
0341 {
0342 long mid = ARM_MAX_BRP << 1;
0343 long num = (idx << 1) + 1;
0344 return num > mid ? mid - num : num;
0345 }
0346
0347
0348
0349
0350 static void ptrace_hbptriggered(struct perf_event *bp,
0351 struct perf_sample_data *data,
0352 struct pt_regs *regs)
0353 {
0354 struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
0355 long num;
0356 int i;
0357
0358 for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i)
0359 if (current->thread.debug.hbp[i] == bp)
0360 break;
0361
0362 num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i);
0363
0364 force_sig_ptrace_errno_trap((int)num, (void __user *)(bkpt->trigger));
0365 }
0366
0367
0368
0369
0370
0371
0372 void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
0373 {
0374 memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp));
0375 }
0376
0377
0378
0379
0380
0381 void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
0382 {
0383 int i;
0384 struct thread_struct *t = &tsk->thread;
0385
0386 for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) {
0387 if (t->debug.hbp[i]) {
0388 unregister_hw_breakpoint(t->debug.hbp[i]);
0389 t->debug.hbp[i] = NULL;
0390 }
0391 }
0392 }
0393
0394 static u32 ptrace_get_hbp_resource_info(void)
0395 {
0396 u8 num_brps, num_wrps, debug_arch, wp_len;
0397 u32 reg = 0;
0398
0399 num_brps = hw_breakpoint_slots(TYPE_INST);
0400 num_wrps = hw_breakpoint_slots(TYPE_DATA);
0401 debug_arch = arch_get_debug_arch();
0402 wp_len = arch_get_max_wp_len();
0403
0404 reg |= debug_arch;
0405 reg <<= 8;
0406 reg |= wp_len;
0407 reg <<= 8;
0408 reg |= num_wrps;
0409 reg <<= 8;
0410 reg |= num_brps;
0411
0412 return reg;
0413 }
0414
0415 static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
0416 {
0417 struct perf_event_attr attr;
0418
0419 ptrace_breakpoint_init(&attr);
0420
0421
0422 attr.bp_addr = 0;
0423 attr.bp_len = HW_BREAKPOINT_LEN_4;
0424 attr.bp_type = type;
0425 attr.disabled = 1;
0426
0427 return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL,
0428 tsk);
0429 }
0430
0431 static int ptrace_gethbpregs(struct task_struct *tsk, long num,
0432 unsigned long __user *data)
0433 {
0434 u32 reg;
0435 int idx, ret = 0;
0436 struct perf_event *bp;
0437 struct arch_hw_breakpoint_ctrl arch_ctrl;
0438
0439 if (num == 0) {
0440 reg = ptrace_get_hbp_resource_info();
0441 } else {
0442 idx = ptrace_hbp_num_to_idx(num);
0443 if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
0444 ret = -EINVAL;
0445 goto out;
0446 }
0447
0448 bp = tsk->thread.debug.hbp[idx];
0449 if (!bp) {
0450 reg = 0;
0451 goto put;
0452 }
0453
0454 arch_ctrl = counter_arch_bp(bp)->ctrl;
0455
0456
0457
0458
0459
0460 while (!(arch_ctrl.len & 0x1))
0461 arch_ctrl.len >>= 1;
0462
0463 if (num & 0x1)
0464 reg = bp->attr.bp_addr;
0465 else
0466 reg = encode_ctrl_reg(arch_ctrl);
0467 }
0468
0469 put:
0470 if (put_user(reg, data))
0471 ret = -EFAULT;
0472
0473 out:
0474 return ret;
0475 }
0476
0477 static int ptrace_sethbpregs(struct task_struct *tsk, long num,
0478 unsigned long __user *data)
0479 {
0480 int idx, gen_len, gen_type, implied_type, ret = 0;
0481 u32 user_val;
0482 struct perf_event *bp;
0483 struct arch_hw_breakpoint_ctrl ctrl;
0484 struct perf_event_attr attr;
0485
0486 if (num == 0)
0487 goto out;
0488 else if (num < 0)
0489 implied_type = HW_BREAKPOINT_RW;
0490 else
0491 implied_type = HW_BREAKPOINT_X;
0492
0493 idx = ptrace_hbp_num_to_idx(num);
0494 if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
0495 ret = -EINVAL;
0496 goto out;
0497 }
0498
0499 if (get_user(user_val, data)) {
0500 ret = -EFAULT;
0501 goto out;
0502 }
0503
0504 bp = tsk->thread.debug.hbp[idx];
0505 if (!bp) {
0506 bp = ptrace_hbp_create(tsk, implied_type);
0507 if (IS_ERR(bp)) {
0508 ret = PTR_ERR(bp);
0509 goto out;
0510 }
0511 tsk->thread.debug.hbp[idx] = bp;
0512 }
0513
0514 attr = bp->attr;
0515
0516 if (num & 0x1) {
0517
0518 attr.bp_addr = user_val;
0519 } else {
0520
0521 decode_ctrl_reg(user_val, &ctrl);
0522 ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type);
0523 if (ret)
0524 goto out;
0525
0526 if ((gen_type & implied_type) != gen_type) {
0527 ret = -EINVAL;
0528 goto out;
0529 }
0530
0531 attr.bp_len = gen_len;
0532 attr.bp_type = gen_type;
0533 attr.disabled = !ctrl.enabled;
0534 }
0535
0536 ret = modify_user_hw_breakpoint(bp, &attr);
0537 out:
0538 return ret;
0539 }
0540 #endif
0541
0542
0543
0544 static int gpr_get(struct task_struct *target,
0545 const struct user_regset *regset,
0546 struct membuf to)
0547 {
0548 return membuf_write(&to, task_pt_regs(target), sizeof(struct pt_regs));
0549 }
0550
0551 static int gpr_set(struct task_struct *target,
0552 const struct user_regset *regset,
0553 unsigned int pos, unsigned int count,
0554 const void *kbuf, const void __user *ubuf)
0555 {
0556 int ret;
0557 struct pt_regs newregs = *task_pt_regs(target);
0558
0559 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0560 &newregs,
0561 0, sizeof(newregs));
0562 if (ret)
0563 return ret;
0564
0565 if (!valid_user_regs(&newregs))
0566 return -EINVAL;
0567
0568 *task_pt_regs(target) = newregs;
0569 return 0;
0570 }
0571
0572 static int fpa_get(struct task_struct *target,
0573 const struct user_regset *regset,
0574 struct membuf to)
0575 {
0576 return membuf_write(&to, &task_thread_info(target)->fpstate,
0577 sizeof(struct user_fp));
0578 }
0579
0580 static int fpa_set(struct task_struct *target,
0581 const struct user_regset *regset,
0582 unsigned int pos, unsigned int count,
0583 const void *kbuf, const void __user *ubuf)
0584 {
0585 struct thread_info *thread = task_thread_info(target);
0586
0587 thread->used_cp[1] = thread->used_cp[2] = 1;
0588
0589 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0590 &thread->fpstate,
0591 0, sizeof(struct user_fp));
0592 }
0593
0594 #ifdef CONFIG_VFP
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613 static int vfp_get(struct task_struct *target,
0614 const struct user_regset *regset,
0615 struct membuf to)
0616 {
0617 struct thread_info *thread = task_thread_info(target);
0618 struct vfp_hard_struct const *vfp = &thread->vfpstate.hard;
0619 const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
0620
0621 vfp_sync_hwstate(thread);
0622
0623 membuf_write(&to, vfp->fpregs, sizeof(vfp->fpregs));
0624 membuf_zero(&to, user_fpscr_offset - sizeof(vfp->fpregs));
0625 return membuf_store(&to, vfp->fpscr);
0626 }
0627
0628
0629
0630
0631
0632
0633 static int vfp_set(struct task_struct *target,
0634 const struct user_regset *regset,
0635 unsigned int pos, unsigned int count,
0636 const void *kbuf, const void __user *ubuf)
0637 {
0638 int ret;
0639 struct thread_info *thread = task_thread_info(target);
0640 struct vfp_hard_struct new_vfp;
0641 const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
0642 const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
0643
0644 vfp_sync_hwstate(thread);
0645 new_vfp = thread->vfpstate.hard;
0646
0647 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0648 &new_vfp.fpregs,
0649 user_fpregs_offset,
0650 user_fpregs_offset + sizeof(new_vfp.fpregs));
0651 if (ret)
0652 return ret;
0653
0654 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0655 user_fpregs_offset + sizeof(new_vfp.fpregs),
0656 user_fpscr_offset);
0657 if (ret)
0658 return ret;
0659
0660 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0661 &new_vfp.fpscr,
0662 user_fpscr_offset,
0663 user_fpscr_offset + sizeof(new_vfp.fpscr));
0664 if (ret)
0665 return ret;
0666
0667 thread->vfpstate.hard = new_vfp;
0668 vfp_flush_hwstate(thread);
0669
0670 return 0;
0671 }
0672 #endif
0673
0674 enum arm_regset {
0675 REGSET_GPR,
0676 REGSET_FPR,
0677 #ifdef CONFIG_VFP
0678 REGSET_VFP,
0679 #endif
0680 };
0681
0682 static const struct user_regset arm_regsets[] = {
0683 [REGSET_GPR] = {
0684 .core_note_type = NT_PRSTATUS,
0685 .n = ELF_NGREG,
0686 .size = sizeof(u32),
0687 .align = sizeof(u32),
0688 .regset_get = gpr_get,
0689 .set = gpr_set
0690 },
0691 [REGSET_FPR] = {
0692
0693
0694
0695
0696 .core_note_type = NT_PRFPREG,
0697 .n = sizeof(struct user_fp) / sizeof(u32),
0698 .size = sizeof(u32),
0699 .align = sizeof(u32),
0700 .regset_get = fpa_get,
0701 .set = fpa_set
0702 },
0703 #ifdef CONFIG_VFP
0704 [REGSET_VFP] = {
0705
0706
0707
0708
0709 .core_note_type = NT_ARM_VFP,
0710 .n = ARM_VFPREGS_SIZE / sizeof(u32),
0711 .size = sizeof(u32),
0712 .align = sizeof(u32),
0713 .regset_get = vfp_get,
0714 .set = vfp_set
0715 },
0716 #endif
0717 };
0718
0719 static const struct user_regset_view user_arm_view = {
0720 .name = "arm", .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
0721 .regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets)
0722 };
0723
0724 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
0725 {
0726 return &user_arm_view;
0727 }
0728
0729 long arch_ptrace(struct task_struct *child, long request,
0730 unsigned long addr, unsigned long data)
0731 {
0732 int ret;
0733 unsigned long __user *datap = (unsigned long __user *) data;
0734
0735 switch (request) {
0736 case PTRACE_PEEKUSR:
0737 ret = ptrace_read_user(child, addr, datap);
0738 break;
0739
0740 case PTRACE_POKEUSR:
0741 ret = ptrace_write_user(child, addr, data);
0742 break;
0743
0744 case PTRACE_GETREGS:
0745 ret = copy_regset_to_user(child,
0746 &user_arm_view, REGSET_GPR,
0747 0, sizeof(struct pt_regs),
0748 datap);
0749 break;
0750
0751 case PTRACE_SETREGS:
0752 ret = copy_regset_from_user(child,
0753 &user_arm_view, REGSET_GPR,
0754 0, sizeof(struct pt_regs),
0755 datap);
0756 break;
0757
0758 case PTRACE_GETFPREGS:
0759 ret = copy_regset_to_user(child,
0760 &user_arm_view, REGSET_FPR,
0761 0, sizeof(union fp_state),
0762 datap);
0763 break;
0764
0765 case PTRACE_SETFPREGS:
0766 ret = copy_regset_from_user(child,
0767 &user_arm_view, REGSET_FPR,
0768 0, sizeof(union fp_state),
0769 datap);
0770 break;
0771
0772 #ifdef CONFIG_IWMMXT
0773 case PTRACE_GETWMMXREGS:
0774 ret = ptrace_getwmmxregs(child, datap);
0775 break;
0776
0777 case PTRACE_SETWMMXREGS:
0778 ret = ptrace_setwmmxregs(child, datap);
0779 break;
0780 #endif
0781
0782 case PTRACE_GET_THREAD_AREA:
0783 ret = put_user(task_thread_info(child)->tp_value[0],
0784 datap);
0785 break;
0786
0787 case PTRACE_SET_SYSCALL:
0788 task_thread_info(child)->abi_syscall = data &
0789 __NR_SYSCALL_MASK;
0790 ret = 0;
0791 break;
0792
0793 #ifdef CONFIG_VFP
0794 case PTRACE_GETVFPREGS:
0795 ret = copy_regset_to_user(child,
0796 &user_arm_view, REGSET_VFP,
0797 0, ARM_VFPREGS_SIZE,
0798 datap);
0799 break;
0800
0801 case PTRACE_SETVFPREGS:
0802 ret = copy_regset_from_user(child,
0803 &user_arm_view, REGSET_VFP,
0804 0, ARM_VFPREGS_SIZE,
0805 datap);
0806 break;
0807 #endif
0808
0809 #ifdef CONFIG_HAVE_HW_BREAKPOINT
0810 case PTRACE_GETHBPREGS:
0811 ret = ptrace_gethbpregs(child, addr,
0812 (unsigned long __user *)data);
0813 break;
0814 case PTRACE_SETHBPREGS:
0815 ret = ptrace_sethbpregs(child, addr,
0816 (unsigned long __user *)data);
0817 break;
0818 #endif
0819
0820 default:
0821 ret = ptrace_request(child, request, addr, data);
0822 break;
0823 }
0824
0825 return ret;
0826 }
0827
0828 enum ptrace_syscall_dir {
0829 PTRACE_SYSCALL_ENTER = 0,
0830 PTRACE_SYSCALL_EXIT,
0831 };
0832
0833 static void report_syscall(struct pt_regs *regs, enum ptrace_syscall_dir dir)
0834 {
0835 unsigned long ip;
0836
0837
0838
0839
0840
0841 ip = regs->ARM_ip;
0842 regs->ARM_ip = dir;
0843
0844 if (dir == PTRACE_SYSCALL_EXIT)
0845 ptrace_report_syscall_exit(regs, 0);
0846 else if (ptrace_report_syscall_entry(regs))
0847 current_thread_info()->abi_syscall = -1;
0848
0849 regs->ARM_ip = ip;
0850 }
0851
0852 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
0853 {
0854 int scno;
0855
0856 if (test_thread_flag(TIF_SYSCALL_TRACE))
0857 report_syscall(regs, PTRACE_SYSCALL_ENTER);
0858
0859
0860 #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
0861 if (secure_computing() == -1)
0862 return -1;
0863 #else
0864
0865 secure_computing_strict(syscall_get_nr(current, regs));
0866 #endif
0867
0868
0869 scno = syscall_get_nr(current, regs);
0870
0871 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
0872 trace_sys_enter(regs, scno);
0873
0874 audit_syscall_entry(scno, regs->ARM_r0, regs->ARM_r1, regs->ARM_r2,
0875 regs->ARM_r3);
0876
0877 return scno;
0878 }
0879
0880 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
0881 {
0882
0883
0884
0885
0886 audit_syscall_exit(regs);
0887
0888
0889
0890
0891
0892
0893
0894 if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
0895 trace_sys_exit(regs, regs_return_value(regs));
0896
0897 if (test_thread_flag(TIF_SYSCALL_TRACE))
0898 report_syscall(regs, PTRACE_SYSCALL_EXIT);
0899 }