1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * linux/arch/arm/kernel/ptrace.c |
4 | * |
5 | * By Ross Biro 1/23/92 |
6 | * edited by Linus Torvalds |
7 | * ARM modifications Copyright (C) 2000 Russell King |
8 | */ |
9 | #include <linux/kernel.h> |
10 | #include <linux/sched/signal.h> |
11 | #include <linux/sched/task_stack.h> |
12 | #include <linux/mm.h> |
13 | #include <linux/elf.h> |
14 | #include <linux/smp.h> |
15 | #include <linux/ptrace.h> |
16 | #include <linux/user.h> |
17 | #include <linux/security.h> |
18 | #include <linux/init.h> |
19 | #include <linux/signal.h> |
20 | #include <linux/uaccess.h> |
21 | #include <linux/perf_event.h> |
22 | #include <linux/hw_breakpoint.h> |
23 | #include <linux/regset.h> |
24 | #include <linux/audit.h> |
25 | #include <linux/unistd.h> |
26 | |
27 | #include <asm/syscall.h> |
28 | #include <asm/traps.h> |
29 | |
30 | #define CREATE_TRACE_POINTS |
31 | #include <trace/events/syscalls.h> |
32 | |
33 | #define REG_PC 15 |
34 | #define REG_PSR 16 |
35 | /* |
36 | * does not yet catch signals sent when the child dies. |
37 | * in exit.c or in signal.c. |
38 | */ |
39 | |
40 | #if 0 |
41 | /* |
42 | * Breakpoint SWI instruction: SWI &9F0001 |
43 | */ |
44 | #define BREAKINST_ARM 0xef9f0001 |
45 | #define BREAKINST_THUMB 0xdf00 /* fill this in later */ |
46 | #else |
47 | /* |
48 | * New breakpoints - use an undefined instruction. The ARM architecture |
49 | * reference manual guarantees that the following instruction space |
50 | * will produce an undefined instruction exception on all CPUs: |
51 | * |
52 | * ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx |
53 | * Thumb: 1101 1110 xxxx xxxx |
54 | */ |
55 | #define BREAKINST_ARM 0xe7f001f0 |
56 | #define BREAKINST_THUMB 0xde01 |
57 | #endif |
58 | |
59 | struct pt_regs_offset { |
60 | const char *name; |
61 | int offset; |
62 | }; |
63 | |
64 | #define REG_OFFSET_NAME(r) \ |
65 | {.name = #r, .offset = offsetof(struct pt_regs, ARM_##r)} |
66 | #define REG_OFFSET_END {.name = NULL, .offset = 0} |
67 | |
68 | static const struct pt_regs_offset regoffset_table[] = { |
69 | REG_OFFSET_NAME(r0), |
70 | REG_OFFSET_NAME(r1), |
71 | REG_OFFSET_NAME(r2), |
72 | REG_OFFSET_NAME(r3), |
73 | REG_OFFSET_NAME(r4), |
74 | REG_OFFSET_NAME(r5), |
75 | REG_OFFSET_NAME(r6), |
76 | REG_OFFSET_NAME(r7), |
77 | REG_OFFSET_NAME(r8), |
78 | REG_OFFSET_NAME(r9), |
79 | REG_OFFSET_NAME(r10), |
80 | REG_OFFSET_NAME(fp), |
81 | REG_OFFSET_NAME(ip), |
82 | REG_OFFSET_NAME(sp), |
83 | REG_OFFSET_NAME(lr), |
84 | REG_OFFSET_NAME(pc), |
85 | REG_OFFSET_NAME(cpsr), |
86 | REG_OFFSET_NAME(ORIG_r0), |
87 | REG_OFFSET_END, |
88 | }; |
89 | |
90 | /** |
91 | * regs_query_register_offset() - query register offset from its name |
92 | * @name: the name of a register |
93 | * |
94 | * regs_query_register_offset() returns the offset of a register in struct |
95 | * pt_regs from its name. If the name is invalid, this returns -EINVAL; |
96 | */ |
97 | int regs_query_register_offset(const char *name) |
98 | { |
99 | const struct pt_regs_offset *roff; |
100 | for (roff = regoffset_table; roff->name != NULL; roff++) |
101 | if (!strcmp(roff->name, name)) |
102 | return roff->offset; |
103 | return -EINVAL; |
104 | } |
105 | |
106 | /** |
107 | * regs_query_register_name() - query register name from its offset |
108 | * @offset: the offset of a register in struct pt_regs. |
109 | * |
110 | * regs_query_register_name() returns the name of a register from its |
111 | * offset in struct pt_regs. If the @offset is invalid, this returns NULL; |
112 | */ |
113 | const char *regs_query_register_name(unsigned int offset) |
114 | { |
115 | const struct pt_regs_offset *roff; |
116 | for (roff = regoffset_table; roff->name != NULL; roff++) |
117 | if (roff->offset == offset) |
118 | return roff->name; |
119 | return NULL; |
120 | } |
121 | |
122 | /** |
123 | * regs_within_kernel_stack() - check the address in the stack |
124 | * @regs: pt_regs which contains kernel stack pointer. |
125 | * @addr: address which is checked. |
126 | * |
127 | * regs_within_kernel_stack() checks @addr is within the kernel stack page(s). |
128 | * If @addr is within the kernel stack, it returns true. If not, returns false. |
129 | */ |
130 | bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr) |
131 | { |
132 | return ((addr & ~(THREAD_SIZE - 1)) == |
133 | (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1))); |
134 | } |
135 | |
136 | /** |
137 | * regs_get_kernel_stack_nth() - get Nth entry of the stack |
138 | * @regs: pt_regs which contains kernel stack pointer. |
139 | * @n: stack entry number. |
140 | * |
141 | * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which |
142 | * is specified by @regs. If the @n th entry is NOT in the kernel stack, |
143 | * this returns 0. |
144 | */ |
145 | unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n) |
146 | { |
147 | unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs); |
148 | addr += n; |
149 | if (regs_within_kernel_stack(regs, addr: (unsigned long)addr)) |
150 | return *addr; |
151 | else |
152 | return 0; |
153 | } |
154 | |
155 | /* |
156 | * this routine will get a word off of the processes privileged stack. |
157 | * the offset is how far from the base addr as stored in the THREAD. |
158 | * this routine assumes that all the privileged stacks are in our |
159 | * data space. |
160 | */ |
161 | static inline long get_user_reg(struct task_struct *task, int offset) |
162 | { |
163 | return task_pt_regs(task)->uregs[offset]; |
164 | } |
165 | |
166 | /* |
167 | * this routine will put a word on the processes privileged stack. |
168 | * the offset is how far from the base addr as stored in the THREAD. |
169 | * this routine assumes that all the privileged stacks are in our |
170 | * data space. |
171 | */ |
172 | static inline int |
173 | put_user_reg(struct task_struct *task, int offset, long data) |
174 | { |
175 | struct pt_regs newregs, *regs = task_pt_regs(task); |
176 | int ret = -EINVAL; |
177 | |
178 | newregs = *regs; |
179 | newregs.uregs[offset] = data; |
180 | |
181 | if (valid_user_regs(&newregs)) { |
182 | regs->uregs[offset] = data; |
183 | ret = 0; |
184 | } |
185 | |
186 | return ret; |
187 | } |
188 | |
189 | /* |
190 | * Called by kernel/ptrace.c when detaching.. |
191 | */ |
192 | void ptrace_disable(struct task_struct *child) |
193 | { |
194 | /* Nothing to do. */ |
195 | } |
196 | |
197 | /* |
198 | * Handle hitting a breakpoint. |
199 | */ |
200 | void ptrace_break(struct pt_regs *regs) |
201 | { |
202 | force_sig_fault(SIGTRAP, TRAP_BRKPT, |
203 | addr: (void __user *)instruction_pointer(regs)); |
204 | } |
205 | |
206 | static int break_trap(struct pt_regs *regs, unsigned int instr) |
207 | { |
208 | ptrace_break(regs); |
209 | return 0; |
210 | } |
211 | |
212 | static struct undef_hook arm_break_hook = { |
213 | .instr_mask = 0x0fffffff, |
214 | .instr_val = 0x07f001f0, |
215 | .cpsr_mask = PSR_T_BIT, |
216 | .cpsr_val = 0, |
217 | .fn = break_trap, |
218 | }; |
219 | |
220 | static struct undef_hook thumb_break_hook = { |
221 | .instr_mask = 0xffffffff, |
222 | .instr_val = 0x0000de01, |
223 | .cpsr_mask = PSR_T_BIT, |
224 | .cpsr_val = PSR_T_BIT, |
225 | .fn = break_trap, |
226 | }; |
227 | |
228 | static struct undef_hook thumb2_break_hook = { |
229 | .instr_mask = 0xffffffff, |
230 | .instr_val = 0xf7f0a000, |
231 | .cpsr_mask = PSR_T_BIT, |
232 | .cpsr_val = PSR_T_BIT, |
233 | .fn = break_trap, |
234 | }; |
235 | |
236 | static int __init ptrace_break_init(void) |
237 | { |
238 | register_undef_hook(&arm_break_hook); |
239 | register_undef_hook(&thumb_break_hook); |
240 | register_undef_hook(&thumb2_break_hook); |
241 | return 0; |
242 | } |
243 | |
244 | core_initcall(ptrace_break_init); |
245 | |
246 | /* |
247 | * Read the word at offset "off" into the "struct user". We |
248 | * actually access the pt_regs stored on the kernel stack. |
249 | */ |
250 | static int ptrace_read_user(struct task_struct *tsk, unsigned long off, |
251 | unsigned long __user *ret) |
252 | { |
253 | unsigned long tmp; |
254 | |
255 | if (off & 3) |
256 | return -EIO; |
257 | |
258 | tmp = 0; |
259 | if (off == PT_TEXT_ADDR) |
260 | tmp = tsk->mm->start_code; |
261 | else if (off == PT_DATA_ADDR) |
262 | tmp = tsk->mm->start_data; |
263 | else if (off == PT_TEXT_END_ADDR) |
264 | tmp = tsk->mm->end_code; |
265 | else if (off < sizeof(struct pt_regs)) |
266 | tmp = get_user_reg(task: tsk, offset: off >> 2); |
267 | else if (off >= sizeof(struct user)) |
268 | return -EIO; |
269 | |
270 | return put_user(tmp, ret); |
271 | } |
272 | |
273 | /* |
274 | * Write the word at offset "off" into "struct user". We |
275 | * actually access the pt_regs stored on the kernel stack. |
276 | */ |
277 | static int ptrace_write_user(struct task_struct *tsk, unsigned long off, |
278 | unsigned long val) |
279 | { |
280 | if (off & 3 || off >= sizeof(struct user)) |
281 | return -EIO; |
282 | |
283 | if (off >= sizeof(struct pt_regs)) |
284 | return 0; |
285 | |
286 | return put_user_reg(task: tsk, offset: off >> 2, data: val); |
287 | } |
288 | |
289 | #ifdef CONFIG_IWMMXT |
290 | |
291 | /* |
292 | * Get the child iWMMXt state. |
293 | */ |
294 | static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp) |
295 | { |
296 | struct thread_info *thread = task_thread_info(tsk); |
297 | |
298 | if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) |
299 | return -ENODATA; |
300 | iwmmxt_task_disable(thread); /* force it to ram */ |
301 | return copy_to_user(ufp, &thread->fpstate.iwmmxt, IWMMXT_SIZE) |
302 | ? -EFAULT : 0; |
303 | } |
304 | |
305 | /* |
306 | * Set the child iWMMXt state. |
307 | */ |
308 | static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) |
309 | { |
310 | struct thread_info *thread = task_thread_info(tsk); |
311 | |
312 | if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT)) |
313 | return -EACCES; |
314 | iwmmxt_task_release(thread); /* force a reload */ |
315 | return copy_from_user(&thread->fpstate.iwmmxt, ufp, IWMMXT_SIZE) |
316 | ? -EFAULT : 0; |
317 | } |
318 | |
319 | #endif |
320 | |
321 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
322 | /* |
323 | * Convert a virtual register number into an index for a thread_info |
324 | * breakpoint array. Breakpoints are identified using positive numbers |
325 | * whilst watchpoints are negative. The registers are laid out as pairs |
326 | * of (address, control), each pair mapping to a unique hw_breakpoint struct. |
327 | * Register 0 is reserved for describing resource information. |
328 | */ |
329 | static int ptrace_hbp_num_to_idx(long num) |
330 | { |
331 | if (num < 0) |
332 | num = (ARM_MAX_BRP << 1) - num; |
333 | return (num - 1) >> 1; |
334 | } |
335 | |
336 | /* |
337 | * Returns the virtual register number for the address of the |
338 | * breakpoint at index idx. |
339 | */ |
340 | static long ptrace_hbp_idx_to_num(int idx) |
341 | { |
342 | long mid = ARM_MAX_BRP << 1; |
343 | long num = (idx << 1) + 1; |
344 | return num > mid ? mid - num : num; |
345 | } |
346 | |
347 | /* |
348 | * Handle hitting a HW-breakpoint. |
349 | */ |
350 | static void ptrace_hbptriggered(struct perf_event *bp, |
351 | struct perf_sample_data *data, |
352 | struct pt_regs *regs) |
353 | { |
354 | struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp); |
355 | long num; |
356 | int i; |
357 | |
358 | for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i) |
359 | if (current->thread.debug.hbp[i] == bp) |
360 | break; |
361 | |
362 | num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i); |
363 | |
364 | force_sig_ptrace_errno_trap(errno: (int)num, addr: (void __user *)(bkpt->trigger)); |
365 | } |
366 | |
367 | /* |
368 | * Set ptrace breakpoint pointers to zero for this task. |
369 | * This is required in order to prevent child processes from unregistering |
370 | * breakpoints held by their parent. |
371 | */ |
372 | void clear_ptrace_hw_breakpoint(struct task_struct *tsk) |
373 | { |
374 | memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp)); |
375 | } |
376 | |
377 | /* |
378 | * Unregister breakpoints from this task and reset the pointers in |
379 | * the thread_struct. |
380 | */ |
381 | void flush_ptrace_hw_breakpoint(struct task_struct *tsk) |
382 | { |
383 | int i; |
384 | struct thread_struct *t = &tsk->thread; |
385 | |
386 | for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) { |
387 | if (t->debug.hbp[i]) { |
388 | unregister_hw_breakpoint(bp: t->debug.hbp[i]); |
389 | t->debug.hbp[i] = NULL; |
390 | } |
391 | } |
392 | } |
393 | |
394 | static u32 ptrace_get_hbp_resource_info(void) |
395 | { |
396 | u8 num_brps, num_wrps, debug_arch, wp_len; |
397 | u32 reg = 0; |
398 | |
399 | num_brps = hw_breakpoint_slots(TYPE_INST); |
400 | num_wrps = hw_breakpoint_slots(TYPE_DATA); |
401 | debug_arch = arch_get_debug_arch(); |
402 | wp_len = arch_get_max_wp_len(); |
403 | |
404 | reg |= debug_arch; |
405 | reg <<= 8; |
406 | reg |= wp_len; |
407 | reg <<= 8; |
408 | reg |= num_wrps; |
409 | reg <<= 8; |
410 | reg |= num_brps; |
411 | |
412 | return reg; |
413 | } |
414 | |
415 | static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type) |
416 | { |
417 | struct perf_event_attr attr; |
418 | |
419 | ptrace_breakpoint_init(attr: &attr); |
420 | |
421 | /* Initialise fields to sane defaults. */ |
422 | attr.bp_addr = 0; |
423 | attr.bp_len = HW_BREAKPOINT_LEN_4; |
424 | attr.bp_type = type; |
425 | attr.disabled = 1; |
426 | |
427 | return register_user_hw_breakpoint(attr: &attr, triggered: ptrace_hbptriggered, NULL, |
428 | tsk); |
429 | } |
430 | |
431 | static int ptrace_gethbpregs(struct task_struct *tsk, long num, |
432 | unsigned long __user *data) |
433 | { |
434 | u32 reg; |
435 | int idx, ret = 0; |
436 | struct perf_event *bp; |
437 | struct arch_hw_breakpoint_ctrl arch_ctrl; |
438 | |
439 | if (num == 0) { |
440 | reg = ptrace_get_hbp_resource_info(); |
441 | } else { |
442 | idx = ptrace_hbp_num_to_idx(num); |
443 | if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { |
444 | ret = -EINVAL; |
445 | goto out; |
446 | } |
447 | |
448 | bp = tsk->thread.debug.hbp[idx]; |
449 | if (!bp) { |
450 | reg = 0; |
451 | goto put; |
452 | } |
453 | |
454 | arch_ctrl = counter_arch_bp(bp)->ctrl; |
455 | |
456 | /* |
457 | * Fix up the len because we may have adjusted it |
458 | * to compensate for an unaligned address. |
459 | */ |
460 | while (!(arch_ctrl.len & 0x1)) |
461 | arch_ctrl.len >>= 1; |
462 | |
463 | if (num & 0x1) |
464 | reg = bp->attr.bp_addr; |
465 | else |
466 | reg = encode_ctrl_reg(arch_ctrl); |
467 | } |
468 | |
469 | put: |
470 | if (put_user(reg, data)) |
471 | ret = -EFAULT; |
472 | |
473 | out: |
474 | return ret; |
475 | } |
476 | |
477 | static int ptrace_sethbpregs(struct task_struct *tsk, long num, |
478 | unsigned long __user *data) |
479 | { |
480 | int idx, gen_len, gen_type, implied_type, ret = 0; |
481 | u32 user_val; |
482 | struct perf_event *bp; |
483 | struct arch_hw_breakpoint_ctrl ctrl; |
484 | struct perf_event_attr attr; |
485 | |
486 | if (num == 0) |
487 | goto out; |
488 | else if (num < 0) |
489 | implied_type = HW_BREAKPOINT_RW; |
490 | else |
491 | implied_type = HW_BREAKPOINT_X; |
492 | |
493 | idx = ptrace_hbp_num_to_idx(num); |
494 | if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) { |
495 | ret = -EINVAL; |
496 | goto out; |
497 | } |
498 | |
499 | if (get_user(user_val, data)) { |
500 | ret = -EFAULT; |
501 | goto out; |
502 | } |
503 | |
504 | bp = tsk->thread.debug.hbp[idx]; |
505 | if (!bp) { |
506 | bp = ptrace_hbp_create(tsk, type: implied_type); |
507 | if (IS_ERR(ptr: bp)) { |
508 | ret = PTR_ERR(ptr: bp); |
509 | goto out; |
510 | } |
511 | tsk->thread.debug.hbp[idx] = bp; |
512 | } |
513 | |
514 | attr = bp->attr; |
515 | |
516 | if (num & 0x1) { |
517 | /* Address */ |
518 | attr.bp_addr = user_val; |
519 | } else { |
520 | /* Control */ |
521 | decode_ctrl_reg(user_val, &ctrl); |
522 | ret = arch_bp_generic_fields(x86_len: ctrl, x86_type: &gen_len, gen_len: &gen_type); |
523 | if (ret) |
524 | goto out; |
525 | |
526 | if ((gen_type & implied_type) != gen_type) { |
527 | ret = -EINVAL; |
528 | goto out; |
529 | } |
530 | |
531 | attr.bp_len = gen_len; |
532 | attr.bp_type = gen_type; |
533 | attr.disabled = !ctrl.enabled; |
534 | } |
535 | |
536 | ret = modify_user_hw_breakpoint(bp, attr: &attr); |
537 | out: |
538 | return ret; |
539 | } |
540 | #endif |
541 | |
542 | /* regset get/set implementations */ |
543 | |
544 | static int gpr_get(struct task_struct *target, |
545 | const struct user_regset *regset, |
546 | struct membuf to) |
547 | { |
548 | return membuf_write(s: &to, task_pt_regs(target), size: sizeof(struct pt_regs)); |
549 | } |
550 | |
551 | static int gpr_set(struct task_struct *target, |
552 | const struct user_regset *regset, |
553 | unsigned int pos, unsigned int count, |
554 | const void *kbuf, const void __user *ubuf) |
555 | { |
556 | int ret; |
557 | struct pt_regs newregs = *task_pt_regs(target); |
558 | |
559 | ret = user_regset_copyin(pos: &pos, count: &count, kbuf: &kbuf, ubuf: &ubuf, |
560 | data: &newregs, |
561 | start_pos: 0, end_pos: sizeof(newregs)); |
562 | if (ret) |
563 | return ret; |
564 | |
565 | if (!valid_user_regs(&newregs)) |
566 | return -EINVAL; |
567 | |
568 | *task_pt_regs(target) = newregs; |
569 | return 0; |
570 | } |
571 | |
572 | static int fpa_get(struct task_struct *target, |
573 | const struct user_regset *regset, |
574 | struct membuf to) |
575 | { |
576 | return membuf_write(&to, &task_thread_info(target)->fpstate, |
577 | sizeof(struct user_fp)); |
578 | } |
579 | |
580 | static int fpa_set(struct task_struct *target, |
581 | const struct user_regset *regset, |
582 | unsigned int pos, unsigned int count, |
583 | const void *kbuf, const void __user *ubuf) |
584 | { |
585 | struct thread_info *thread = task_thread_info(target); |
586 | |
587 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
588 | &thread->fpstate, |
589 | 0, sizeof(struct user_fp)); |
590 | } |
591 | |
592 | #ifdef CONFIG_VFP |
593 | /* |
594 | * VFP register get/set implementations. |
595 | * |
596 | * With respect to the kernel, struct user_fp is divided into three chunks: |
597 | * 16 or 32 real VFP registers (d0-d15 or d0-31) |
598 | * These are transferred to/from the real registers in the task's |
599 | * vfp_hard_struct. The number of registers depends on the kernel |
600 | * configuration. |
601 | * |
602 | * 16 or 0 fake VFP registers (d16-d31 or empty) |
603 | * i.e., the user_vfp structure has space for 32 registers even if |
604 | * the kernel doesn't have them all. |
605 | * |
606 | * vfp_get() reads this chunk as zero where applicable |
607 | * vfp_set() ignores this chunk |
608 | * |
609 | * 1 word for the FPSCR |
610 | */ |
611 | static int vfp_get(struct task_struct *target, |
612 | const struct user_regset *regset, |
613 | struct membuf to) |
614 | { |
615 | struct thread_info *thread = task_thread_info(target); |
616 | struct vfp_hard_struct const *vfp = &thread->vfpstate.hard; |
617 | const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); |
618 | |
619 | vfp_sync_hwstate(thread); |
620 | |
621 | membuf_write(&to, vfp->fpregs, sizeof(vfp->fpregs)); |
622 | membuf_zero(&to, user_fpscr_offset - sizeof(vfp->fpregs)); |
623 | return membuf_store(&to, vfp->fpscr); |
624 | } |
625 | |
626 | /* |
627 | * For vfp_set() a read-modify-write is done on the VFP registers, |
628 | * in order to avoid writing back a half-modified set of registers on |
629 | * failure. |
630 | */ |
631 | static int vfp_set(struct task_struct *target, |
632 | const struct user_regset *regset, |
633 | unsigned int pos, unsigned int count, |
634 | const void *kbuf, const void __user *ubuf) |
635 | { |
636 | int ret; |
637 | struct thread_info *thread = task_thread_info(target); |
638 | struct vfp_hard_struct new_vfp; |
639 | const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs); |
640 | const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr); |
641 | |
642 | vfp_sync_hwstate(thread); |
643 | new_vfp = thread->vfpstate.hard; |
644 | |
645 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
646 | &new_vfp.fpregs, |
647 | user_fpregs_offset, |
648 | user_fpregs_offset + sizeof(new_vfp.fpregs)); |
649 | if (ret) |
650 | return ret; |
651 | |
652 | user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, |
653 | user_fpregs_offset + sizeof(new_vfp.fpregs), |
654 | user_fpscr_offset); |
655 | |
656 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
657 | &new_vfp.fpscr, |
658 | user_fpscr_offset, |
659 | user_fpscr_offset + sizeof(new_vfp.fpscr)); |
660 | if (ret) |
661 | return ret; |
662 | |
663 | thread->vfpstate.hard = new_vfp; |
664 | vfp_flush_hwstate(thread); |
665 | |
666 | return 0; |
667 | } |
668 | #endif /* CONFIG_VFP */ |
669 | |
670 | enum arm_regset { |
671 | REGSET_GPR, |
672 | REGSET_FPR, |
673 | #ifdef CONFIG_VFP |
674 | REGSET_VFP, |
675 | #endif |
676 | }; |
677 | |
678 | static const struct user_regset arm_regsets[] = { |
679 | [REGSET_GPR] = { |
680 | .core_note_type = NT_PRSTATUS, |
681 | .n = ELF_NGREG, |
682 | .size = sizeof(u32), |
683 | .align = sizeof(u32), |
684 | .regset_get = gpr_get, |
685 | .set = gpr_set |
686 | }, |
687 | [REGSET_FPR] = { |
688 | /* |
689 | * For the FPA regs in fpstate, the real fields are a mixture |
690 | * of sizes, so pretend that the registers are word-sized: |
691 | */ |
692 | .core_note_type = NT_PRFPREG, |
693 | .n = sizeof(struct user_fp) / sizeof(u32), |
694 | .size = sizeof(u32), |
695 | .align = sizeof(u32), |
696 | .regset_get = fpa_get, |
697 | .set = fpa_set |
698 | }, |
699 | #ifdef CONFIG_VFP |
700 | [REGSET_VFP] = { |
701 | /* |
702 | * Pretend that the VFP regs are word-sized, since the FPSCR is |
703 | * a single word dangling at the end of struct user_vfp: |
704 | */ |
705 | .core_note_type = NT_ARM_VFP, |
706 | .n = ARM_VFPREGS_SIZE / sizeof(u32), |
707 | .size = sizeof(u32), |
708 | .align = sizeof(u32), |
709 | .regset_get = vfp_get, |
710 | .set = vfp_set |
711 | }, |
712 | #endif /* CONFIG_VFP */ |
713 | }; |
714 | |
715 | static const struct user_regset_view user_arm_view = { |
716 | .name = "arm" , .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI, |
717 | .regsets = arm_regsets, .n = ARRAY_SIZE(arm_regsets) |
718 | }; |
719 | |
720 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) |
721 | { |
722 | return &user_arm_view; |
723 | } |
724 | |
725 | long arch_ptrace(struct task_struct *child, long request, |
726 | unsigned long addr, unsigned long data) |
727 | { |
728 | int ret; |
729 | unsigned long __user *datap = (unsigned long __user *) data; |
730 | |
731 | switch (request) { |
732 | case PTRACE_PEEKUSR: |
733 | ret = ptrace_read_user(tsk: child, off: addr, ret: datap); |
734 | break; |
735 | |
736 | case PTRACE_POKEUSR: |
737 | ret = ptrace_write_user(tsk: child, off: addr, val: data); |
738 | break; |
739 | |
740 | case PTRACE_GETREGS: |
741 | ret = copy_regset_to_user(target: child, |
742 | view: &user_arm_view, setno: REGSET_GPR, |
743 | offset: 0, size: sizeof(struct pt_regs), |
744 | data: datap); |
745 | break; |
746 | |
747 | case PTRACE_SETREGS: |
748 | ret = copy_regset_from_user(target: child, |
749 | view: &user_arm_view, setno: REGSET_GPR, |
750 | offset: 0, size: sizeof(struct pt_regs), |
751 | data: datap); |
752 | break; |
753 | |
754 | case PTRACE_GETFPREGS: |
755 | ret = copy_regset_to_user(child, |
756 | &user_arm_view, REGSET_FPR, |
757 | 0, sizeof(union fp_state), |
758 | datap); |
759 | break; |
760 | |
761 | case PTRACE_SETFPREGS: |
762 | ret = copy_regset_from_user(child, |
763 | &user_arm_view, REGSET_FPR, |
764 | 0, sizeof(union fp_state), |
765 | datap); |
766 | break; |
767 | |
768 | #ifdef CONFIG_IWMMXT |
769 | case PTRACE_GETWMMXREGS: |
770 | ret = ptrace_getwmmxregs(child, datap); |
771 | break; |
772 | |
773 | case PTRACE_SETWMMXREGS: |
774 | ret = ptrace_setwmmxregs(child, datap); |
775 | break; |
776 | #endif |
777 | |
778 | case PTRACE_GET_THREAD_AREA: |
779 | ret = put_user(task_thread_info(child)->tp_value[0], |
780 | datap); |
781 | break; |
782 | |
783 | case PTRACE_SET_SYSCALL: |
784 | if (data != -1) |
785 | data &= __NR_SYSCALL_MASK; |
786 | task_thread_info(child)->abi_syscall = data; |
787 | ret = 0; |
788 | break; |
789 | |
790 | #ifdef CONFIG_VFP |
791 | case PTRACE_GETVFPREGS: |
792 | ret = copy_regset_to_user(child, |
793 | &user_arm_view, REGSET_VFP, |
794 | 0, ARM_VFPREGS_SIZE, |
795 | datap); |
796 | break; |
797 | |
798 | case PTRACE_SETVFPREGS: |
799 | ret = copy_regset_from_user(child, |
800 | &user_arm_view, REGSET_VFP, |
801 | 0, ARM_VFPREGS_SIZE, |
802 | datap); |
803 | break; |
804 | #endif |
805 | |
806 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
807 | case PTRACE_GETHBPREGS: |
808 | ret = ptrace_gethbpregs(tsk: child, num: addr, |
809 | data: (unsigned long __user *)data); |
810 | break; |
811 | case PTRACE_SETHBPREGS: |
812 | ret = ptrace_sethbpregs(tsk: child, num: addr, |
813 | data: (unsigned long __user *)data); |
814 | break; |
815 | #endif |
816 | |
817 | default: |
818 | ret = ptrace_request(child, request, addr, data); |
819 | break; |
820 | } |
821 | |
822 | return ret; |
823 | } |
824 | |
825 | enum ptrace_syscall_dir { |
826 | PTRACE_SYSCALL_ENTER = 0, |
827 | PTRACE_SYSCALL_EXIT, |
828 | }; |
829 | |
830 | static void report_syscall(struct pt_regs *regs, enum ptrace_syscall_dir dir) |
831 | { |
832 | unsigned long ip; |
833 | |
834 | /* |
835 | * IP is used to denote syscall entry/exit: |
836 | * IP = 0 -> entry, =1 -> exit |
837 | */ |
838 | ip = regs->ARM_ip; |
839 | regs->ARM_ip = dir; |
840 | |
841 | if (dir == PTRACE_SYSCALL_EXIT) |
842 | ptrace_report_syscall_exit(regs, step: 0); |
843 | else if (ptrace_report_syscall_entry(regs)) |
844 | current_thread_info()->abi_syscall = -1; |
845 | |
846 | regs->ARM_ip = ip; |
847 | } |
848 | |
849 | asmlinkage int syscall_trace_enter(struct pt_regs *regs) |
850 | { |
851 | int scno; |
852 | |
853 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
854 | report_syscall(regs, dir: PTRACE_SYSCALL_ENTER); |
855 | |
856 | /* Do seccomp after ptrace; syscall may have changed. */ |
857 | #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER |
858 | if (secure_computing() == -1) |
859 | return -1; |
860 | #else |
861 | /* XXX: remove this once OABI gets fixed */ |
862 | secure_computing_strict(syscall_get_nr(current, regs)); |
863 | #endif |
864 | |
865 | /* Tracer or seccomp may have changed syscall. */ |
866 | scno = syscall_get_nr(current, regs); |
867 | |
868 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) |
869 | trace_sys_enter(regs, id: scno); |
870 | |
871 | audit_syscall_entry(major: scno, a0: regs->ARM_r0, a1: regs->ARM_r1, a2: regs->ARM_r2, |
872 | a3: regs->ARM_r3); |
873 | |
874 | return scno; |
875 | } |
876 | |
877 | asmlinkage void syscall_trace_exit(struct pt_regs *regs) |
878 | { |
879 | /* |
880 | * Audit the syscall before anything else, as a debugger may |
881 | * come in and change the current registers. |
882 | */ |
883 | audit_syscall_exit(pt_regs: regs); |
884 | |
885 | /* |
886 | * Note that we haven't updated the ->syscall field for the |
887 | * current thread. This isn't a problem because it will have |
888 | * been set on syscall entry and there hasn't been an opportunity |
889 | * for a PTRACE_SET_SYSCALL since then. |
890 | */ |
891 | if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) |
892 | trace_sys_exit(regs, ret: regs_return_value(regs)); |
893 | |
894 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
895 | report_syscall(regs, dir: PTRACE_SYSCALL_EXIT); |
896 | } |
897 | |