~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm64/kernel/ptrace.c

Version: ~ [ linux-5.11-rc3 ] ~ [ linux-5.10.7 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.89 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.167 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.215 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.251 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.251 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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/seccomp.h>
 31 #include <linux/security.h>
 32 #include <linux/init.h>
 33 #include <linux/signal.h>
 34 #include <linux/uaccess.h>
 35 #include <linux/perf_event.h>
 36 #include <linux/hw_breakpoint.h>
 37 #include <linux/regset.h>
 38 #include <linux/tracehook.h>
 39 #include <linux/elf.h>
 40 
 41 #include <asm/compat.h>
 42 #include <asm/debug-monitors.h>
 43 #include <asm/pgtable.h>
 44 #include <asm/syscall.h>
 45 #include <asm/traps.h>
 46 #include <asm/system_misc.h>
 47 
 48 #define CREATE_TRACE_POINTS
 49 #include <trace/events/syscalls.h>
 50 
 51 struct pt_regs_offset {
 52         const char *name;
 53         int offset;
 54 };
 55 
 56 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
 57 #define REG_OFFSET_END {.name = NULL, .offset = 0}
 58 #define GPR_OFFSET_NAME(r) \
 59         {.name = "x" #r, .offset = offsetof(struct pt_regs, regs[r])}
 60 
 61 static const struct pt_regs_offset regoffset_table[] = {
 62         GPR_OFFSET_NAME(0),
 63         GPR_OFFSET_NAME(1),
 64         GPR_OFFSET_NAME(2),
 65         GPR_OFFSET_NAME(3),
 66         GPR_OFFSET_NAME(4),
 67         GPR_OFFSET_NAME(5),
 68         GPR_OFFSET_NAME(6),
 69         GPR_OFFSET_NAME(7),
 70         GPR_OFFSET_NAME(8),
 71         GPR_OFFSET_NAME(9),
 72         GPR_OFFSET_NAME(10),
 73         GPR_OFFSET_NAME(11),
 74         GPR_OFFSET_NAME(12),
 75         GPR_OFFSET_NAME(13),
 76         GPR_OFFSET_NAME(14),
 77         GPR_OFFSET_NAME(15),
 78         GPR_OFFSET_NAME(16),
 79         GPR_OFFSET_NAME(17),
 80         GPR_OFFSET_NAME(18),
 81         GPR_OFFSET_NAME(19),
 82         GPR_OFFSET_NAME(20),
 83         GPR_OFFSET_NAME(21),
 84         GPR_OFFSET_NAME(22),
 85         GPR_OFFSET_NAME(23),
 86         GPR_OFFSET_NAME(24),
 87         GPR_OFFSET_NAME(25),
 88         GPR_OFFSET_NAME(26),
 89         GPR_OFFSET_NAME(27),
 90         GPR_OFFSET_NAME(28),
 91         GPR_OFFSET_NAME(29),
 92         GPR_OFFSET_NAME(30),
 93         {.name = "lr", .offset = offsetof(struct pt_regs, regs[30])},
 94         REG_OFFSET_NAME(sp),
 95         REG_OFFSET_NAME(pc),
 96         REG_OFFSET_NAME(pstate),
 97         REG_OFFSET_END,
 98 };
 99 
100 /**
101  * regs_query_register_offset() - query register offset from its name
102  * @name:       the name of a register
103  *
104  * regs_query_register_offset() returns the offset of a register in struct
105  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
106  */
107 int regs_query_register_offset(const char *name)
108 {
109         const struct pt_regs_offset *roff;
110 
111         for (roff = regoffset_table; roff->name != NULL; roff++)
112                 if (!strcmp(roff->name, name))
113                         return roff->offset;
114         return -EINVAL;
115 }
116 
117 /**
118  * regs_within_kernel_stack() - check the address in the stack
119  * @regs:      pt_regs which contains kernel stack pointer.
120  * @addr:      address which is checked.
121  *
122  * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
123  * If @addr is within the kernel stack, it returns true. If not, returns false.
124  */
125 static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
126 {
127         return ((addr & ~(THREAD_SIZE - 1))  ==
128                 (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))) ||
129                 on_irq_stack(addr, raw_smp_processor_id());
130 }
131 
132 /**
133  * regs_get_kernel_stack_nth() - get Nth entry of the stack
134  * @regs:       pt_regs which contains kernel stack pointer.
135  * @n:          stack entry number.
136  *
137  * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
138  * is specified by @regs. If the @n th entry is NOT in the kernel stack,
139  * this returns 0.
140  */
141 unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
142 {
143         unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
144 
145         addr += n;
146         if (regs_within_kernel_stack(regs, (unsigned long)addr))
147                 return *addr;
148         else
149                 return 0;
150 }
151 
152 /*
153  * TODO: does not yet catch signals sent when the child dies.
154  * in exit.c or in signal.c.
155  */
156 
157 /*
158  * Called by kernel/ptrace.c when detaching..
159  */
160 void ptrace_disable(struct task_struct *child)
161 {
162         /*
163          * This would be better off in core code, but PTRACE_DETACH has
164          * grown its fair share of arch-specific worts and changing it
165          * is likely to cause regressions on obscure architectures.
166          */
167         user_disable_single_step(child);
168 }
169 
170 #ifdef CONFIG_HAVE_HW_BREAKPOINT
171 /*
172  * Handle hitting a HW-breakpoint.
173  */
174 static void ptrace_hbptriggered(struct perf_event *bp,
175                                 struct perf_sample_data *data,
176                                 struct pt_regs *regs)
177 {
178         struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
179         siginfo_t info = {
180                 .si_signo       = SIGTRAP,
181                 .si_errno       = 0,
182                 .si_code        = TRAP_HWBKPT,
183                 .si_addr        = (void __user *)(bkpt->trigger),
184         };
185 
186 #ifdef CONFIG_COMPAT
187         int i;
188 
189         if (!is_compat_task())
190                 goto send_sig;
191 
192         for (i = 0; i < ARM_MAX_BRP; ++i) {
193                 if (current->thread.debug.hbp_break[i] == bp) {
194                         info.si_errno = (i << 1) + 1;
195                         break;
196                 }
197         }
198 
199         for (i = 0; i < ARM_MAX_WRP; ++i) {
200                 if (current->thread.debug.hbp_watch[i] == bp) {
201                         info.si_errno = -((i << 1) + 1);
202                         break;
203                 }
204         }
205 
206 send_sig:
207 #endif
208         force_sig_info(SIGTRAP, &info, current);
209 }
210 
211 /*
212  * Unregister breakpoints from this task and reset the pointers in
213  * the thread_struct.
214  */
215 void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
216 {
217         int i;
218         struct thread_struct *t = &tsk->thread;
219 
220         for (i = 0; i < ARM_MAX_BRP; i++) {
221                 if (t->debug.hbp_break[i]) {
222                         unregister_hw_breakpoint(t->debug.hbp_break[i]);
223                         t->debug.hbp_break[i] = NULL;
224                 }
225         }
226 
227         for (i = 0; i < ARM_MAX_WRP; i++) {
228                 if (t->debug.hbp_watch[i]) {
229                         unregister_hw_breakpoint(t->debug.hbp_watch[i]);
230                         t->debug.hbp_watch[i] = NULL;
231                 }
232         }
233 }
234 
235 void ptrace_hw_copy_thread(struct task_struct *tsk)
236 {
237         memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
238 }
239 
240 static struct perf_event *ptrace_hbp_get_event(unsigned int note_type,
241                                                struct task_struct *tsk,
242                                                unsigned long idx)
243 {
244         struct perf_event *bp = ERR_PTR(-EINVAL);
245 
246         switch (note_type) {
247         case NT_ARM_HW_BREAK:
248                 if (idx < ARM_MAX_BRP)
249                         bp = tsk->thread.debug.hbp_break[idx];
250                 break;
251         case NT_ARM_HW_WATCH:
252                 if (idx < ARM_MAX_WRP)
253                         bp = tsk->thread.debug.hbp_watch[idx];
254                 break;
255         }
256 
257         return bp;
258 }
259 
260 static int ptrace_hbp_set_event(unsigned int note_type,
261                                 struct task_struct *tsk,
262                                 unsigned long idx,
263                                 struct perf_event *bp)
264 {
265         int err = -EINVAL;
266 
267         switch (note_type) {
268         case NT_ARM_HW_BREAK:
269                 if (idx < ARM_MAX_BRP) {
270                         tsk->thread.debug.hbp_break[idx] = bp;
271                         err = 0;
272                 }
273                 break;
274         case NT_ARM_HW_WATCH:
275                 if (idx < ARM_MAX_WRP) {
276                         tsk->thread.debug.hbp_watch[idx] = bp;
277                         err = 0;
278                 }
279                 break;
280         }
281 
282         return err;
283 }
284 
285 static struct perf_event *ptrace_hbp_create(unsigned int note_type,
286                                             struct task_struct *tsk,
287                                             unsigned long idx)
288 {
289         struct perf_event *bp;
290         struct perf_event_attr attr;
291         int err, type;
292 
293         switch (note_type) {
294         case NT_ARM_HW_BREAK:
295                 type = HW_BREAKPOINT_X;
296                 break;
297         case NT_ARM_HW_WATCH:
298                 type = HW_BREAKPOINT_RW;
299                 break;
300         default:
301                 return ERR_PTR(-EINVAL);
302         }
303 
304         ptrace_breakpoint_init(&attr);
305 
306         /*
307          * Initialise fields to sane defaults
308          * (i.e. values that will pass validation).
309          */
310         attr.bp_addr    = 0;
311         attr.bp_len     = HW_BREAKPOINT_LEN_4;
312         attr.bp_type    = type;
313         attr.disabled   = 1;
314 
315         bp = register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL, tsk);
316         if (IS_ERR(bp))
317                 return bp;
318 
319         err = ptrace_hbp_set_event(note_type, tsk, idx, bp);
320         if (err)
321                 return ERR_PTR(err);
322 
323         return bp;
324 }
325 
326 static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
327                                      struct arch_hw_breakpoint_ctrl ctrl,
328                                      struct perf_event_attr *attr)
329 {
330         int err, len, type, disabled = !ctrl.enabled;
331 
332         attr->disabled = disabled;
333         if (disabled)
334                 return 0;
335 
336         err = arch_bp_generic_fields(ctrl, &len, &type);
337         if (err)
338                 return err;
339 
340         switch (note_type) {
341         case NT_ARM_HW_BREAK:
342                 if ((type & HW_BREAKPOINT_X) != type)
343                         return -EINVAL;
344                 break;
345         case NT_ARM_HW_WATCH:
346                 if ((type & HW_BREAKPOINT_RW) != type)
347                         return -EINVAL;
348                 break;
349         default:
350                 return -EINVAL;
351         }
352 
353         attr->bp_len    = len;
354         attr->bp_type   = type;
355 
356         return 0;
357 }
358 
359 static int ptrace_hbp_get_resource_info(unsigned int note_type, u32 *info)
360 {
361         u8 num;
362         u32 reg = 0;
363 
364         switch (note_type) {
365         case NT_ARM_HW_BREAK:
366                 num = hw_breakpoint_slots(TYPE_INST);
367                 break;
368         case NT_ARM_HW_WATCH:
369                 num = hw_breakpoint_slots(TYPE_DATA);
370                 break;
371         default:
372                 return -EINVAL;
373         }
374 
375         reg |= debug_monitors_arch();
376         reg <<= 8;
377         reg |= num;
378 
379         *info = reg;
380         return 0;
381 }
382 
383 static int ptrace_hbp_get_ctrl(unsigned int note_type,
384                                struct task_struct *tsk,
385                                unsigned long idx,
386                                u32 *ctrl)
387 {
388         struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
389 
390         if (IS_ERR(bp))
391                 return PTR_ERR(bp);
392 
393         *ctrl = bp ? encode_ctrl_reg(counter_arch_bp(bp)->ctrl) : 0;
394         return 0;
395 }
396 
397 static int ptrace_hbp_get_addr(unsigned int note_type,
398                                struct task_struct *tsk,
399                                unsigned long idx,
400                                u64 *addr)
401 {
402         struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
403 
404         if (IS_ERR(bp))
405                 return PTR_ERR(bp);
406 
407         *addr = bp ? bp->attr.bp_addr : 0;
408         return 0;
409 }
410 
411 static struct perf_event *ptrace_hbp_get_initialised_bp(unsigned int note_type,
412                                                         struct task_struct *tsk,
413                                                         unsigned long idx)
414 {
415         struct perf_event *bp = ptrace_hbp_get_event(note_type, tsk, idx);
416 
417         if (!bp)
418                 bp = ptrace_hbp_create(note_type, tsk, idx);
419 
420         return bp;
421 }
422 
423 static int ptrace_hbp_set_ctrl(unsigned int note_type,
424                                struct task_struct *tsk,
425                                unsigned long idx,
426                                u32 uctrl)
427 {
428         int err;
429         struct perf_event *bp;
430         struct perf_event_attr attr;
431         struct arch_hw_breakpoint_ctrl ctrl;
432 
433         bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
434         if (IS_ERR(bp)) {
435                 err = PTR_ERR(bp);
436                 return err;
437         }
438 
439         attr = bp->attr;
440         decode_ctrl_reg(uctrl, &ctrl);
441         err = ptrace_hbp_fill_attr_ctrl(note_type, ctrl, &attr);
442         if (err)
443                 return err;
444 
445         return modify_user_hw_breakpoint(bp, &attr);
446 }
447 
448 static int ptrace_hbp_set_addr(unsigned int note_type,
449                                struct task_struct *tsk,
450                                unsigned long idx,
451                                u64 addr)
452 {
453         int err;
454         struct perf_event *bp;
455         struct perf_event_attr attr;
456 
457         bp = ptrace_hbp_get_initialised_bp(note_type, tsk, idx);
458         if (IS_ERR(bp)) {
459                 err = PTR_ERR(bp);
460                 return err;
461         }
462 
463         attr = bp->attr;
464         attr.bp_addr = addr;
465         err = modify_user_hw_breakpoint(bp, &attr);
466         return err;
467 }
468 
469 #define PTRACE_HBP_ADDR_SZ      sizeof(u64)
470 #define PTRACE_HBP_CTRL_SZ      sizeof(u32)
471 #define PTRACE_HBP_PAD_SZ       sizeof(u32)
472 
473 static int hw_break_get(struct task_struct *target,
474                         const struct user_regset *regset,
475                         unsigned int pos, unsigned int count,
476                         void *kbuf, void __user *ubuf)
477 {
478         unsigned int note_type = regset->core_note_type;
479         int ret, idx = 0, offset, limit;
480         u32 info, ctrl;
481         u64 addr;
482 
483         /* Resource info */
484         ret = ptrace_hbp_get_resource_info(note_type, &info);
485         if (ret)
486                 return ret;
487 
488         ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0,
489                                   sizeof(info));
490         if (ret)
491                 return ret;
492 
493         /* Pad */
494         offset = offsetof(struct user_hwdebug_state, pad);
495         ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset,
496                                        offset + PTRACE_HBP_PAD_SZ);
497         if (ret)
498                 return ret;
499 
500         /* (address, ctrl) registers */
501         offset = offsetof(struct user_hwdebug_state, dbg_regs);
502         limit = regset->n * regset->size;
503         while (count && offset < limit) {
504                 ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
505                 if (ret)
506                         return ret;
507                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &addr,
508                                           offset, offset + PTRACE_HBP_ADDR_SZ);
509                 if (ret)
510                         return ret;
511                 offset += PTRACE_HBP_ADDR_SZ;
512 
513                 ret = ptrace_hbp_get_ctrl(note_type, target, idx, &ctrl);
514                 if (ret)
515                         return ret;
516                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &ctrl,
517                                           offset, offset + PTRACE_HBP_CTRL_SZ);
518                 if (ret)
519                         return ret;
520                 offset += PTRACE_HBP_CTRL_SZ;
521 
522                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
523                                                offset,
524                                                offset + PTRACE_HBP_PAD_SZ);
525                 if (ret)
526                         return ret;
527                 offset += PTRACE_HBP_PAD_SZ;
528                 idx++;
529         }
530 
531         return 0;
532 }
533 
534 static int hw_break_set(struct task_struct *target,
535                         const struct user_regset *regset,
536                         unsigned int pos, unsigned int count,
537                         const void *kbuf, const void __user *ubuf)
538 {
539         unsigned int note_type = regset->core_note_type;
540         int ret, idx = 0, offset, limit;
541         u32 ctrl;
542         u64 addr;
543 
544         /* Resource info and pad */
545         offset = offsetof(struct user_hwdebug_state, dbg_regs);
546         ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
547         if (ret)
548                 return ret;
549 
550         /* (address, ctrl) registers */
551         limit = regset->n * regset->size;
552         while (count && offset < limit) {
553                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
554                                          offset, offset + PTRACE_HBP_ADDR_SZ);
555                 if (ret)
556                         return ret;
557                 ret = ptrace_hbp_set_addr(note_type, target, idx, addr);
558                 if (ret)
559                         return ret;
560                 offset += PTRACE_HBP_ADDR_SZ;
561 
562                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
563                                          offset, offset + PTRACE_HBP_CTRL_SZ);
564                 if (ret)
565                         return ret;
566                 ret = ptrace_hbp_set_ctrl(note_type, target, idx, ctrl);
567                 if (ret)
568                         return ret;
569                 offset += PTRACE_HBP_CTRL_SZ;
570 
571                 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
572                                                 offset,
573                                                 offset + PTRACE_HBP_PAD_SZ);
574                 if (ret)
575                         return ret;
576                 offset += PTRACE_HBP_PAD_SZ;
577                 idx++;
578         }
579 
580         return 0;
581 }
582 #endif  /* CONFIG_HAVE_HW_BREAKPOINT */
583 
584 static int gpr_get(struct task_struct *target,
585                    const struct user_regset *regset,
586                    unsigned int pos, unsigned int count,
587                    void *kbuf, void __user *ubuf)
588 {
589         struct user_pt_regs *uregs = &task_pt_regs(target)->user_regs;
590         return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
591 }
592 
593 static int gpr_set(struct task_struct *target, const struct user_regset *regset,
594                    unsigned int pos, unsigned int count,
595                    const void *kbuf, const void __user *ubuf)
596 {
597         int ret;
598         struct user_pt_regs newregs;
599 
600         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
601         if (ret)
602                 return ret;
603 
604         if (!valid_user_regs(&newregs, target))
605                 return -EINVAL;
606 
607         task_pt_regs(target)->user_regs = newregs;
608         return 0;
609 }
610 
611 /*
612  * TODO: update fp accessors for lazy context switching (sync/flush hwstate)
613  */
614 static int fpr_get(struct task_struct *target, const struct user_regset *regset,
615                    unsigned int pos, unsigned int count,
616                    void *kbuf, void __user *ubuf)
617 {
618         struct user_fpsimd_state *uregs;
619         uregs = &target->thread.fpsimd_state.user_fpsimd;
620         return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0, -1);
621 }
622 
623 static int fpr_set(struct task_struct *target, const struct user_regset *regset,
624                    unsigned int pos, unsigned int count,
625                    const void *kbuf, const void __user *ubuf)
626 {
627         int ret;
628         struct user_fpsimd_state newstate;
629 
630         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
631         if (ret)
632                 return ret;
633 
634         target->thread.fpsimd_state.user_fpsimd = newstate;
635         fpsimd_flush_task_state(target);
636         return ret;
637 }
638 
639 static int tls_get(struct task_struct *target, const struct user_regset *regset,
640                    unsigned int pos, unsigned int count,
641                    void *kbuf, void __user *ubuf)
642 {
643         unsigned long *tls = &target->thread.tp_value;
644         return user_regset_copyout(&pos, &count, &kbuf, &ubuf, tls, 0, -1);
645 }
646 
647 static int tls_set(struct task_struct *target, const struct user_regset *regset,
648                    unsigned int pos, unsigned int count,
649                    const void *kbuf, const void __user *ubuf)
650 {
651         int ret;
652         unsigned long tls;
653 
654         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
655         if (ret)
656                 return ret;
657 
658         target->thread.tp_value = tls;
659         return ret;
660 }
661 
662 static int system_call_get(struct task_struct *target,
663                            const struct user_regset *regset,
664                            unsigned int pos, unsigned int count,
665                            void *kbuf, void __user *ubuf)
666 {
667         int syscallno = task_pt_regs(target)->syscallno;
668 
669         return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
670                                    &syscallno, 0, -1);
671 }
672 
673 static int system_call_set(struct task_struct *target,
674                            const struct user_regset *regset,
675                            unsigned int pos, unsigned int count,
676                            const void *kbuf, const void __user *ubuf)
677 {
678         int syscallno, ret;
679 
680         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1);
681         if (ret)
682                 return ret;
683 
684         task_pt_regs(target)->syscallno = syscallno;
685         return ret;
686 }
687 
688 enum aarch64_regset {
689         REGSET_GPR,
690         REGSET_FPR,
691         REGSET_TLS,
692 #ifdef CONFIG_HAVE_HW_BREAKPOINT
693         REGSET_HW_BREAK,
694         REGSET_HW_WATCH,
695 #endif
696         REGSET_SYSTEM_CALL,
697 };
698 
699 static const struct user_regset aarch64_regsets[] = {
700         [REGSET_GPR] = {
701                 .core_note_type = NT_PRSTATUS,
702                 .n = sizeof(struct user_pt_regs) / sizeof(u64),
703                 .size = sizeof(u64),
704                 .align = sizeof(u64),
705                 .get = gpr_get,
706                 .set = gpr_set
707         },
708         [REGSET_FPR] = {
709                 .core_note_type = NT_PRFPREG,
710                 .n = sizeof(struct user_fpsimd_state) / sizeof(u32),
711                 /*
712                  * We pretend we have 32-bit registers because the fpsr and
713                  * fpcr are 32-bits wide.
714                  */
715                 .size = sizeof(u32),
716                 .align = sizeof(u32),
717                 .get = fpr_get,
718                 .set = fpr_set
719         },
720         [REGSET_TLS] = {
721                 .core_note_type = NT_ARM_TLS,
722                 .n = 1,
723                 .size = sizeof(void *),
724                 .align = sizeof(void *),
725                 .get = tls_get,
726                 .set = tls_set,
727         },
728 #ifdef CONFIG_HAVE_HW_BREAKPOINT
729         [REGSET_HW_BREAK] = {
730                 .core_note_type = NT_ARM_HW_BREAK,
731                 .n = sizeof(struct user_hwdebug_state) / sizeof(u32),
732                 .size = sizeof(u32),
733                 .align = sizeof(u32),
734                 .get = hw_break_get,
735                 .set = hw_break_set,
736         },
737         [REGSET_HW_WATCH] = {
738                 .core_note_type = NT_ARM_HW_WATCH,
739                 .n = sizeof(struct user_hwdebug_state) / sizeof(u32),
740                 .size = sizeof(u32),
741                 .align = sizeof(u32),
742                 .get = hw_break_get,
743                 .set = hw_break_set,
744         },
745 #endif
746         [REGSET_SYSTEM_CALL] = {
747                 .core_note_type = NT_ARM_SYSTEM_CALL,
748                 .n = 1,
749                 .size = sizeof(int),
750                 .align = sizeof(int),
751                 .get = system_call_get,
752                 .set = system_call_set,
753         },
754 };
755 
756 static const struct user_regset_view user_aarch64_view = {
757         .name = "aarch64", .e_machine = EM_AARCH64,
758         .regsets = aarch64_regsets, .n = ARRAY_SIZE(aarch64_regsets)
759 };
760 
761 #ifdef CONFIG_COMPAT
762 #include <linux/compat.h>
763 
764 enum compat_regset {
765         REGSET_COMPAT_GPR,
766         REGSET_COMPAT_VFP,
767 };
768 
769 static int compat_gpr_get(struct task_struct *target,
770                           const struct user_regset *regset,
771                           unsigned int pos, unsigned int count,
772                           void *kbuf, void __user *ubuf)
773 {
774         int ret = 0;
775         unsigned int i, start, num_regs;
776 
777         /* Calculate the number of AArch32 registers contained in count */
778         num_regs = count / regset->size;
779 
780         /* Convert pos into an register number */
781         start = pos / regset->size;
782 
783         if (start + num_regs > regset->n)
784                 return -EIO;
785 
786         for (i = 0; i < num_regs; ++i) {
787                 unsigned int idx = start + i;
788                 compat_ulong_t reg;
789 
790                 switch (idx) {
791                 case 15:
792                         reg = task_pt_regs(target)->pc;
793                         break;
794                 case 16:
795                         reg = task_pt_regs(target)->pstate;
796                         break;
797                 case 17:
798                         reg = task_pt_regs(target)->orig_x0;
799                         break;
800                 default:
801                         reg = task_pt_regs(target)->regs[idx];
802                 }
803 
804                 if (kbuf) {
805                         memcpy(kbuf, &reg, sizeof(reg));
806                         kbuf += sizeof(reg);
807                 } else {
808                         ret = copy_to_user(ubuf, &reg, sizeof(reg));
809                         if (ret) {
810                                 ret = -EFAULT;
811                                 break;
812                         }
813 
814                         ubuf += sizeof(reg);
815                 }
816         }
817 
818         return ret;
819 }
820 
821 static int compat_gpr_set(struct task_struct *target,
822                           const struct user_regset *regset,
823                           unsigned int pos, unsigned int count,
824                           const void *kbuf, const void __user *ubuf)
825 {
826         struct pt_regs newregs;
827         int ret = 0;
828         unsigned int i, start, num_regs;
829 
830         /* Calculate the number of AArch32 registers contained in count */
831         num_regs = count / regset->size;
832 
833         /* Convert pos into an register number */
834         start = pos / regset->size;
835 
836         if (start + num_regs > regset->n)
837                 return -EIO;
838 
839         newregs = *task_pt_regs(target);
840 
841         for (i = 0; i < num_regs; ++i) {
842                 unsigned int idx = start + i;
843                 compat_ulong_t reg;
844 
845                 if (kbuf) {
846                         memcpy(&reg, kbuf, sizeof(reg));
847                         kbuf += sizeof(reg);
848                 } else {
849                         ret = copy_from_user(&reg, ubuf, sizeof(reg));
850                         if (ret) {
851                                 ret = -EFAULT;
852                                 break;
853                         }
854 
855                         ubuf += sizeof(reg);
856                 }
857 
858                 switch (idx) {
859                 case 15:
860                         newregs.pc = reg;
861                         break;
862                 case 16:
863                         newregs.pstate = reg;
864                         break;
865                 case 17:
866                         newregs.orig_x0 = reg;
867                         break;
868                 default:
869                         newregs.regs[idx] = reg;
870                 }
871 
872         }
873 
874         if (valid_user_regs(&newregs.user_regs, target))
875                 *task_pt_regs(target) = newregs;
876         else
877                 ret = -EINVAL;
878 
879         return ret;
880 }
881 
882 static int compat_vfp_get(struct task_struct *target,
883                           const struct user_regset *regset,
884                           unsigned int pos, unsigned int count,
885                           void *kbuf, void __user *ubuf)
886 {
887         struct user_fpsimd_state *uregs;
888         compat_ulong_t fpscr;
889         int ret;
890 
891         uregs = &target->thread.fpsimd_state.user_fpsimd;
892 
893         /*
894          * The VFP registers are packed into the fpsimd_state, so they all sit
895          * nicely together for us. We just need to create the fpscr separately.
896          */
897         ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
898                                   VFP_STATE_SIZE - sizeof(compat_ulong_t));
899 
900         if (count && !ret) {
901                 fpscr = (uregs->fpsr & VFP_FPSCR_STAT_MASK) |
902                         (uregs->fpcr & VFP_FPSCR_CTRL_MASK);
903                 ret = put_user(fpscr, (compat_ulong_t *)ubuf);
904         }
905 
906         return ret;
907 }
908 
909 static int compat_vfp_set(struct task_struct *target,
910                           const struct user_regset *regset,
911                           unsigned int pos, unsigned int count,
912                           const void *kbuf, const void __user *ubuf)
913 {
914         struct user_fpsimd_state *uregs;
915         compat_ulong_t fpscr;
916         int ret;
917 
918         if (pos + count > VFP_STATE_SIZE)
919                 return -EIO;
920 
921         uregs = &target->thread.fpsimd_state.user_fpsimd;
922 
923         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
924                                  VFP_STATE_SIZE - sizeof(compat_ulong_t));
925 
926         if (count && !ret) {
927                 ret = get_user(fpscr, (compat_ulong_t *)ubuf);
928                 uregs->fpsr = fpscr & VFP_FPSCR_STAT_MASK;
929                 uregs->fpcr = fpscr & VFP_FPSCR_CTRL_MASK;
930         }
931 
932         fpsimd_flush_task_state(target);
933         return ret;
934 }
935 
936 static int compat_tls_get(struct task_struct *target,
937                           const struct user_regset *regset, unsigned int pos,
938                           unsigned int count, void *kbuf, void __user *ubuf)
939 {
940         compat_ulong_t tls = (compat_ulong_t)target->thread.tp_value;
941         return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
942 }
943 
944 static int compat_tls_set(struct task_struct *target,
945                           const struct user_regset *regset, unsigned int pos,
946                           unsigned int count, const void *kbuf,
947                           const void __user *ubuf)
948 {
949         int ret;
950         compat_ulong_t tls;
951 
952         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
953         if (ret)
954                 return ret;
955 
956         target->thread.tp_value = tls;
957         return ret;
958 }
959 
960 static const struct user_regset aarch32_regsets[] = {
961         [REGSET_COMPAT_GPR] = {
962                 .core_note_type = NT_PRSTATUS,
963                 .n = COMPAT_ELF_NGREG,
964                 .size = sizeof(compat_elf_greg_t),
965                 .align = sizeof(compat_elf_greg_t),
966                 .get = compat_gpr_get,
967                 .set = compat_gpr_set
968         },
969         [REGSET_COMPAT_VFP] = {
970                 .core_note_type = NT_ARM_VFP,
971                 .n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
972                 .size = sizeof(compat_ulong_t),
973                 .align = sizeof(compat_ulong_t),
974                 .get = compat_vfp_get,
975                 .set = compat_vfp_set
976         },
977 };
978 
979 static const struct user_regset_view user_aarch32_view = {
980         .name = "aarch32", .e_machine = EM_ARM,
981         .regsets = aarch32_regsets, .n = ARRAY_SIZE(aarch32_regsets)
982 };
983 
984 static const struct user_regset aarch32_ptrace_regsets[] = {
985         [REGSET_GPR] = {
986                 .core_note_type = NT_PRSTATUS,
987                 .n = COMPAT_ELF_NGREG,
988                 .size = sizeof(compat_elf_greg_t),
989                 .align = sizeof(compat_elf_greg_t),
990                 .get = compat_gpr_get,
991                 .set = compat_gpr_set
992         },
993         [REGSET_FPR] = {
994                 .core_note_type = NT_ARM_VFP,
995                 .n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
996                 .size = sizeof(compat_ulong_t),
997                 .align = sizeof(compat_ulong_t),
998                 .get = compat_vfp_get,
999                 .set = compat_vfp_set
1000         },
1001         [REGSET_TLS] = {
1002                 .core_note_type = NT_ARM_TLS,
1003                 .n = 1,
1004                 .size = sizeof(compat_ulong_t),
1005                 .align = sizeof(compat_ulong_t),
1006                 .get = compat_tls_get,
1007                 .set = compat_tls_set,
1008         },
1009 #ifdef CONFIG_HAVE_HW_BREAKPOINT
1010         [REGSET_HW_BREAK] = {
1011                 .core_note_type = NT_ARM_HW_BREAK,
1012                 .n = sizeof(struct user_hwdebug_state) / sizeof(u32),
1013                 .size = sizeof(u32),
1014                 .align = sizeof(u32),
1015                 .get = hw_break_get,
1016                 .set = hw_break_set,
1017         },
1018         [REGSET_HW_WATCH] = {
1019                 .core_note_type = NT_ARM_HW_WATCH,
1020                 .n = sizeof(struct user_hwdebug_state) / sizeof(u32),
1021                 .size = sizeof(u32),
1022                 .align = sizeof(u32),
1023                 .get = hw_break_get,
1024                 .set = hw_break_set,
1025         },
1026 #endif
1027         [REGSET_SYSTEM_CALL] = {
1028                 .core_note_type = NT_ARM_SYSTEM_CALL,
1029                 .n = 1,
1030                 .size = sizeof(int),
1031                 .align = sizeof(int),
1032                 .get = system_call_get,
1033                 .set = system_call_set,
1034         },
1035 };
1036 
1037 static const struct user_regset_view user_aarch32_ptrace_view = {
1038         .name = "aarch32", .e_machine = EM_ARM,
1039         .regsets = aarch32_ptrace_regsets, .n = ARRAY_SIZE(aarch32_ptrace_regsets)
1040 };
1041 
1042 static int compat_ptrace_read_user(struct task_struct *tsk, compat_ulong_t off,
1043                                    compat_ulong_t __user *ret)
1044 {
1045         compat_ulong_t tmp;
1046 
1047         if (off & 3)
1048                 return -EIO;
1049 
1050         if (off == COMPAT_PT_TEXT_ADDR)
1051                 tmp = tsk->mm->start_code;
1052         else if (off == COMPAT_PT_DATA_ADDR)
1053                 tmp = tsk->mm->start_data;
1054         else if (off == COMPAT_PT_TEXT_END_ADDR)
1055                 tmp = tsk->mm->end_code;
1056         else if (off < sizeof(compat_elf_gregset_t))
1057                 return copy_regset_to_user(tsk, &user_aarch32_view,
1058                                            REGSET_COMPAT_GPR, off,
1059                                            sizeof(compat_ulong_t), ret);
1060         else if (off >= COMPAT_USER_SZ)
1061                 return -EIO;
1062         else
1063                 tmp = 0;
1064 
1065         return put_user(tmp, ret);
1066 }
1067 
1068 static int compat_ptrace_write_user(struct task_struct *tsk, compat_ulong_t off,
1069                                     compat_ulong_t val)
1070 {
1071         int ret;
1072         mm_segment_t old_fs = get_fs();
1073 
1074         if (off & 3 || off >= COMPAT_USER_SZ)
1075                 return -EIO;
1076 
1077         if (off >= sizeof(compat_elf_gregset_t))
1078                 return 0;
1079 
1080         set_fs(KERNEL_DS);
1081         ret = copy_regset_from_user(tsk, &user_aarch32_view,
1082                                     REGSET_COMPAT_GPR, off,
1083                                     sizeof(compat_ulong_t),
1084                                     &val);
1085         set_fs(old_fs);
1086 
1087         return ret;
1088 }
1089 
1090 #ifdef CONFIG_HAVE_HW_BREAKPOINT
1091 
1092 /*
1093  * Convert a virtual register number into an index for a thread_info
1094  * breakpoint array. Breakpoints are identified using positive numbers
1095  * whilst watchpoints are negative. The registers are laid out as pairs
1096  * of (address, control), each pair mapping to a unique hw_breakpoint struct.
1097  * Register 0 is reserved for describing resource information.
1098  */
1099 static int compat_ptrace_hbp_num_to_idx(compat_long_t num)
1100 {
1101         return (abs(num) - 1) >> 1;
1102 }
1103 
1104 static int compat_ptrace_hbp_get_resource_info(u32 *kdata)
1105 {
1106         u8 num_brps, num_wrps, debug_arch, wp_len;
1107         u32 reg = 0;
1108 
1109         num_brps        = hw_breakpoint_slots(TYPE_INST);
1110         num_wrps        = hw_breakpoint_slots(TYPE_DATA);
1111 
1112         debug_arch      = debug_monitors_arch();
1113         wp_len          = 8;
1114         reg             |= debug_arch;
1115         reg             <<= 8;
1116         reg             |= wp_len;
1117         reg             <<= 8;
1118         reg             |= num_wrps;
1119         reg             <<= 8;
1120         reg             |= num_brps;
1121 
1122         *kdata = reg;
1123         return 0;
1124 }
1125 
1126 static int compat_ptrace_hbp_get(unsigned int note_type,
1127                                  struct task_struct *tsk,
1128                                  compat_long_t num,
1129                                  u32 *kdata)
1130 {
1131         u64 addr = 0;
1132         u32 ctrl = 0;
1133 
1134         int err, idx = compat_ptrace_hbp_num_to_idx(num);;
1135 
1136         if (num & 1) {
1137                 err = ptrace_hbp_get_addr(note_type, tsk, idx, &addr);
1138                 *kdata = (u32)addr;
1139         } else {
1140                 err = ptrace_hbp_get_ctrl(note_type, tsk, idx, &ctrl);
1141                 *kdata = ctrl;
1142         }
1143 
1144         return err;
1145 }
1146 
1147 static int compat_ptrace_hbp_set(unsigned int note_type,
1148                                  struct task_struct *tsk,
1149                                  compat_long_t num,
1150                                  u32 *kdata)
1151 {
1152         u64 addr;
1153         u32 ctrl;
1154 
1155         int err, idx = compat_ptrace_hbp_num_to_idx(num);
1156 
1157         if (num & 1) {
1158                 addr = *kdata;
1159                 err = ptrace_hbp_set_addr(note_type, tsk, idx, addr);
1160         } else {
1161                 ctrl = *kdata;
1162                 err = ptrace_hbp_set_ctrl(note_type, tsk, idx, ctrl);
1163         }
1164 
1165         return err;
1166 }
1167 
1168 static int compat_ptrace_gethbpregs(struct task_struct *tsk, compat_long_t num,
1169                                     compat_ulong_t __user *data)
1170 {
1171         int ret;
1172         u32 kdata;
1173         mm_segment_t old_fs = get_fs();
1174 
1175         set_fs(KERNEL_DS);
1176         /* Watchpoint */
1177         if (num < 0) {
1178                 ret = compat_ptrace_hbp_get(NT_ARM_HW_WATCH, tsk, num, &kdata);
1179         /* Resource info */
1180         } else if (num == 0) {
1181                 ret = compat_ptrace_hbp_get_resource_info(&kdata);
1182         /* Breakpoint */
1183         } else {
1184                 ret = compat_ptrace_hbp_get(NT_ARM_HW_BREAK, tsk, num, &kdata);
1185         }
1186         set_fs(old_fs);
1187 
1188         if (!ret)
1189                 ret = put_user(kdata, data);
1190 
1191         return ret;
1192 }
1193 
1194 static int compat_ptrace_sethbpregs(struct task_struct *tsk, compat_long_t num,
1195                                     compat_ulong_t __user *data)
1196 {
1197         int ret;
1198         u32 kdata = 0;
1199         mm_segment_t old_fs = get_fs();
1200 
1201         if (num == 0)
1202                 return 0;
1203 
1204         ret = get_user(kdata, data);
1205         if (ret)
1206                 return ret;
1207 
1208         set_fs(KERNEL_DS);
1209         if (num < 0)
1210                 ret = compat_ptrace_hbp_set(NT_ARM_HW_WATCH, tsk, num, &kdata);
1211         else
1212                 ret = compat_ptrace_hbp_set(NT_ARM_HW_BREAK, tsk, num, &kdata);
1213         set_fs(old_fs);
1214 
1215         return ret;
1216 }
1217 #endif  /* CONFIG_HAVE_HW_BREAKPOINT */
1218 
1219 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
1220                         compat_ulong_t caddr, compat_ulong_t cdata)
1221 {
1222         unsigned long addr = caddr;
1223         unsigned long data = cdata;
1224         void __user *datap = compat_ptr(data);
1225         int ret;
1226 
1227         switch (request) {
1228                 case PTRACE_PEEKUSR:
1229                         ret = compat_ptrace_read_user(child, addr, datap);
1230                         break;
1231 
1232                 case PTRACE_POKEUSR:
1233                         ret = compat_ptrace_write_user(child, addr, data);
1234                         break;
1235 
1236                 case COMPAT_PTRACE_GETREGS:
1237                         ret = copy_regset_to_user(child,
1238                                                   &user_aarch32_view,
1239                                                   REGSET_COMPAT_GPR,
1240                                                   0, sizeof(compat_elf_gregset_t),
1241                                                   datap);
1242                         break;
1243 
1244                 case COMPAT_PTRACE_SETREGS:
1245                         ret = copy_regset_from_user(child,
1246                                                     &user_aarch32_view,
1247                                                     REGSET_COMPAT_GPR,
1248                                                     0, sizeof(compat_elf_gregset_t),
1249                                                     datap);
1250                         break;
1251 
1252                 case COMPAT_PTRACE_GET_THREAD_AREA:
1253                         ret = put_user((compat_ulong_t)child->thread.tp_value,
1254                                        (compat_ulong_t __user *)datap);
1255                         break;
1256 
1257                 case COMPAT_PTRACE_SET_SYSCALL:
1258                         task_pt_regs(child)->syscallno = data;
1259                         ret = 0;
1260                         break;
1261 
1262                 case COMPAT_PTRACE_GETVFPREGS:
1263                         ret = copy_regset_to_user(child,
1264                                                   &user_aarch32_view,
1265                                                   REGSET_COMPAT_VFP,
1266                                                   0, VFP_STATE_SIZE,
1267                                                   datap);
1268                         break;
1269 
1270                 case COMPAT_PTRACE_SETVFPREGS:
1271                         ret = copy_regset_from_user(child,
1272                                                     &user_aarch32_view,
1273                                                     REGSET_COMPAT_VFP,
1274                                                     0, VFP_STATE_SIZE,
1275                                                     datap);
1276                         break;
1277 
1278 #ifdef CONFIG_HAVE_HW_BREAKPOINT
1279                 case COMPAT_PTRACE_GETHBPREGS:
1280                         ret = compat_ptrace_gethbpregs(child, addr, datap);
1281                         break;
1282 
1283                 case COMPAT_PTRACE_SETHBPREGS:
1284                         ret = compat_ptrace_sethbpregs(child, addr, datap);
1285                         break;
1286 #endif
1287 
1288                 default:
1289                         ret = compat_ptrace_request(child, request, addr,
1290                                                     data);
1291                         break;
1292         }
1293 
1294         return ret;
1295 }
1296 #endif /* CONFIG_COMPAT */
1297 
1298 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
1299 {
1300 #ifdef CONFIG_COMPAT
1301         /*
1302          * Core dumping of 32-bit tasks or compat ptrace requests must use the
1303          * user_aarch32_view compatible with arm32. Native ptrace requests on
1304          * 32-bit children use an extended user_aarch32_ptrace_view to allow
1305          * access to the TLS register.
1306          */
1307         if (is_compat_task())
1308                 return &user_aarch32_view;
1309         else if (is_compat_thread(task_thread_info(task)))
1310                 return &user_aarch32_ptrace_view;
1311 #endif
1312         return &user_aarch64_view;
1313 }
1314 
1315 long arch_ptrace(struct task_struct *child, long request,
1316                  unsigned long addr, unsigned long data)
1317 {
1318         return ptrace_request(child, request, addr, data);
1319 }
1320 
1321 enum ptrace_syscall_dir {
1322         PTRACE_SYSCALL_ENTER = 0,
1323         PTRACE_SYSCALL_EXIT,
1324 };
1325 
1326 static void tracehook_report_syscall(struct pt_regs *regs,
1327                                      enum ptrace_syscall_dir dir)
1328 {
1329         int regno;
1330         unsigned long saved_reg;
1331 
1332         /*
1333          * A scratch register (ip(r12) on AArch32, x7 on AArch64) is
1334          * used to denote syscall entry/exit:
1335          */
1336         regno = (is_compat_task() ? 12 : 7);
1337         saved_reg = regs->regs[regno];
1338         regs->regs[regno] = dir;
1339 
1340         if (dir == PTRACE_SYSCALL_EXIT)
1341                 tracehook_report_syscall_exit(regs, 0);
1342         else if (tracehook_report_syscall_entry(regs))
1343                 regs->syscallno = ~0UL;
1344 
1345         regs->regs[regno] = saved_reg;
1346 }
1347 
1348 asmlinkage int syscall_trace_enter(struct pt_regs *regs)
1349 {
1350         if (test_thread_flag(TIF_SYSCALL_TRACE))
1351                 tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
1352 
1353         /* Do the secure computing after ptrace; failures should be fast. */
1354         if (secure_computing(NULL) == -1)
1355                 return -1;
1356 
1357         if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
1358                 trace_sys_enter(regs, regs->syscallno);
1359 
1360         audit_syscall_entry(regs->syscallno, regs->orig_x0, regs->regs[1],
1361                             regs->regs[2], regs->regs[3]);
1362 
1363         return regs->syscallno;
1364 }
1365 
1366 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
1367 {
1368         audit_syscall_exit(regs);
1369 
1370         if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
1371                 trace_sys_exit(regs, regs_return_value(regs));
1372 
1373         if (test_thread_flag(TIF_SYSCALL_TRACE))
1374                 tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
1375 }
1376 
1377 /*
1378  * Bits which are always architecturally RES0 per ARM DDI 0487A.h
1379  * Userspace cannot use these until they have an architectural meaning.
1380  * We also reserve IL for the kernel; SS is handled dynamically.
1381  */
1382 #define SPSR_EL1_AARCH64_RES0_BITS \
1383         (GENMASK_ULL(63,32) | GENMASK_ULL(27, 22) | GENMASK_ULL(20, 10) | \
1384          GENMASK_ULL(5, 5))
1385 #define SPSR_EL1_AARCH32_RES0_BITS \
1386         (GENMASK_ULL(63,32) | GENMASK_ULL(24, 22) | GENMASK_ULL(20,20))
1387 
1388 static int valid_compat_regs(struct user_pt_regs *regs)
1389 {
1390         regs->pstate &= ~SPSR_EL1_AARCH32_RES0_BITS;
1391 
1392         if (!system_supports_mixed_endian_el0()) {
1393                 if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
1394                         regs->pstate |= COMPAT_PSR_E_BIT;
1395                 else
1396                         regs->pstate &= ~COMPAT_PSR_E_BIT;
1397         }
1398 
1399         if (user_mode(regs) && (regs->pstate & PSR_MODE32_BIT) &&
1400             (regs->pstate & COMPAT_PSR_A_BIT) == 0 &&
1401             (regs->pstate & COMPAT_PSR_I_BIT) == 0 &&
1402             (regs->pstate & COMPAT_PSR_F_BIT) == 0) {
1403                 return 1;
1404         }
1405 
1406         /*
1407          * Force PSR to a valid 32-bit EL0t, preserving the same bits as
1408          * arch/arm.
1409          */
1410         regs->pstate &= COMPAT_PSR_N_BIT | COMPAT_PSR_Z_BIT |
1411                         COMPAT_PSR_C_BIT | COMPAT_PSR_V_BIT |
1412                         COMPAT_PSR_Q_BIT | COMPAT_PSR_IT_MASK |
1413                         COMPAT_PSR_GE_MASK | COMPAT_PSR_E_BIT |
1414                         COMPAT_PSR_T_BIT;
1415         regs->pstate |= PSR_MODE32_BIT;
1416 
1417         return 0;
1418 }
1419 
1420 static int valid_native_regs(struct user_pt_regs *regs)
1421 {
1422         regs->pstate &= ~SPSR_EL1_AARCH64_RES0_BITS;
1423 
1424         if (user_mode(regs) && !(regs->pstate & PSR_MODE32_BIT) &&
1425             (regs->pstate & PSR_D_BIT) == 0 &&
1426             (regs->pstate & PSR_A_BIT) == 0 &&
1427             (regs->pstate & PSR_I_BIT) == 0 &&
1428             (regs->pstate & PSR_F_BIT) == 0) {
1429                 return 1;
1430         }
1431 
1432         /* Force PSR to a valid 64-bit EL0t */
1433         regs->pstate &= PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT;
1434 
1435         return 0;
1436 }
1437 
1438 /*
1439  * Are the current registers suitable for user mode? (used to maintain
1440  * security in signal handlers)
1441  */
1442 int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task)
1443 {
1444         if (!test_tsk_thread_flag(task, TIF_SINGLESTEP))
1445                 regs->pstate &= ~DBG_SPSR_SS;
1446 
1447         if (is_compat_thread(task_thread_info(task)))
1448                 return valid_compat_regs(regs);
1449         else
1450                 return valid_native_regs(regs);
1451 }
1452 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp