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