xref: /openbmc/linux/arch/xtensa/kernel/ptrace.c (revision 8cf543c0)
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2001 - 2007  Tensilica Inc.
7  *
8  * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
9  * Chris Zankel <chris@zankel.net>
10  * Scott Foehner<sfoehner@yahoo.com>,
11  * Kevin Chea
12  * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
13  */
14 
15 #include <linux/audit.h>
16 #include <linux/errno.h>
17 #include <linux/hw_breakpoint.h>
18 #include <linux/kernel.h>
19 #include <linux/mm.h>
20 #include <linux/perf_event.h>
21 #include <linux/ptrace.h>
22 #include <linux/regset.h>
23 #include <linux/sched.h>
24 #include <linux/sched/task_stack.h>
25 #include <linux/seccomp.h>
26 #include <linux/security.h>
27 #include <linux/signal.h>
28 #include <linux/smp.h>
29 #include <linux/uaccess.h>
30 
31 #define CREATE_TRACE_POINTS
32 #include <trace/events/syscalls.h>
33 
34 #include <asm/coprocessor.h>
35 #include <asm/elf.h>
36 #include <asm/page.h>
37 #include <asm/ptrace.h>
38 
gpr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)39 static int gpr_get(struct task_struct *target,
40 		   const struct user_regset *regset,
41 		   struct membuf to)
42 {
43 	struct pt_regs *regs = task_pt_regs(target);
44 	struct user_pt_regs newregs = {
45 		.pc = regs->pc,
46 		.ps = regs->ps & ~(1 << PS_EXCM_BIT),
47 		.lbeg = regs->lbeg,
48 		.lend = regs->lend,
49 		.lcount = regs->lcount,
50 		.sar = regs->sar,
51 		.threadptr = regs->threadptr,
52 		.windowbase = regs->windowbase,
53 		.windowstart = regs->windowstart,
54 		.syscall = regs->syscall,
55 	};
56 
57 	memcpy(newregs.a,
58 	       regs->areg + XCHAL_NUM_AREGS - regs->windowbase * 4,
59 	       regs->windowbase * 16);
60 	memcpy(newregs.a + regs->windowbase * 4,
61 	       regs->areg,
62 	       (WSBITS - regs->windowbase) * 16);
63 
64 	return membuf_write(&to, &newregs, sizeof(newregs));
65 }
66 
gpr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)67 static int gpr_set(struct task_struct *target,
68 		   const struct user_regset *regset,
69 		   unsigned int pos, unsigned int count,
70 		   const void *kbuf, const void __user *ubuf)
71 {
72 	int ret;
73 	struct user_pt_regs newregs = {0};
74 	struct pt_regs *regs;
75 	const u32 ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
76 
77 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
78 	if (ret)
79 		return ret;
80 
81 	if (newregs.windowbase >= XCHAL_NUM_AREGS / 4)
82 		return -EINVAL;
83 
84 	regs = task_pt_regs(target);
85 	regs->pc = newregs.pc;
86 	regs->ps = (regs->ps & ~ps_mask) | (newregs.ps & ps_mask);
87 	regs->lbeg = newregs.lbeg;
88 	regs->lend = newregs.lend;
89 	regs->lcount = newregs.lcount;
90 	regs->sar = newregs.sar;
91 	regs->threadptr = newregs.threadptr;
92 
93 	if (newregs.syscall)
94 		regs->syscall = newregs.syscall;
95 
96 	if (newregs.windowbase != regs->windowbase ||
97 	    newregs.windowstart != regs->windowstart) {
98 		u32 rotws, wmask;
99 
100 		rotws = (((newregs.windowstart |
101 			   (newregs.windowstart << WSBITS)) >>
102 			  newregs.windowbase) &
103 			 ((1 << WSBITS) - 1)) & ~1;
104 		wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) |
105 			(rotws & 0xF) | 1;
106 		regs->windowbase = newregs.windowbase;
107 		regs->windowstart = newregs.windowstart;
108 		regs->wmask = wmask;
109 	}
110 
111 	memcpy(regs->areg + XCHAL_NUM_AREGS - newregs.windowbase * 4,
112 	       newregs.a, newregs.windowbase * 16);
113 	memcpy(regs->areg, newregs.a + newregs.windowbase * 4,
114 	       (WSBITS - newregs.windowbase) * 16);
115 
116 	return 0;
117 }
118 
tie_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)119 static int tie_get(struct task_struct *target,
120 		   const struct user_regset *regset,
121 		   struct membuf to)
122 {
123 	int ret;
124 	struct pt_regs *regs = task_pt_regs(target);
125 	struct thread_info *ti = task_thread_info(target);
126 	elf_xtregs_t *newregs = kzalloc(sizeof(elf_xtregs_t), GFP_KERNEL);
127 
128 	if (!newregs)
129 		return -ENOMEM;
130 
131 	newregs->opt = regs->xtregs_opt;
132 	newregs->user = ti->xtregs_user;
133 
134 #if XTENSA_HAVE_COPROCESSORS
135 	/* Flush all coprocessor registers to memory. */
136 	coprocessor_flush_all(ti);
137 	newregs->cp0 = ti->xtregs_cp.cp0;
138 	newregs->cp1 = ti->xtregs_cp.cp1;
139 	newregs->cp2 = ti->xtregs_cp.cp2;
140 	newregs->cp3 = ti->xtregs_cp.cp3;
141 	newregs->cp4 = ti->xtregs_cp.cp4;
142 	newregs->cp5 = ti->xtregs_cp.cp5;
143 	newregs->cp6 = ti->xtregs_cp.cp6;
144 	newregs->cp7 = ti->xtregs_cp.cp7;
145 #endif
146 	ret = membuf_write(&to, newregs, sizeof(*newregs));
147 	kfree(newregs);
148 	return ret;
149 }
150 
tie_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)151 static int tie_set(struct task_struct *target,
152 		   const struct user_regset *regset,
153 		   unsigned int pos, unsigned int count,
154 		   const void *kbuf, const void __user *ubuf)
155 {
156 	int ret;
157 	struct pt_regs *regs = task_pt_regs(target);
158 	struct thread_info *ti = task_thread_info(target);
159 	elf_xtregs_t *newregs = kzalloc(sizeof(elf_xtregs_t), GFP_KERNEL);
160 
161 	if (!newregs)
162 		return -ENOMEM;
163 
164 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
165 				 newregs, 0, -1);
166 
167 	if (ret)
168 		goto exit;
169 	regs->xtregs_opt = newregs->opt;
170 	ti->xtregs_user = newregs->user;
171 
172 #if XTENSA_HAVE_COPROCESSORS
173 	/* Flush all coprocessors before we overwrite them. */
174 	coprocessor_flush_release_all(ti);
175 	ti->xtregs_cp.cp0 = newregs->cp0;
176 	ti->xtregs_cp.cp1 = newregs->cp1;
177 	ti->xtregs_cp.cp2 = newregs->cp2;
178 	ti->xtregs_cp.cp3 = newregs->cp3;
179 	ti->xtregs_cp.cp4 = newregs->cp4;
180 	ti->xtregs_cp.cp5 = newregs->cp5;
181 	ti->xtregs_cp.cp6 = newregs->cp6;
182 	ti->xtregs_cp.cp7 = newregs->cp7;
183 #endif
184 exit:
185 	kfree(newregs);
186 	return ret;
187 }
188 
189 enum xtensa_regset {
190 	REGSET_GPR,
191 	REGSET_TIE,
192 };
193 
194 static const struct user_regset xtensa_regsets[] = {
195 	[REGSET_GPR] = {
196 		.core_note_type = NT_PRSTATUS,
197 		.n = sizeof(struct user_pt_regs) / sizeof(u32),
198 		.size = sizeof(u32),
199 		.align = sizeof(u32),
200 		.regset_get = gpr_get,
201 		.set = gpr_set,
202 	},
203 	[REGSET_TIE] = {
204 		.core_note_type = NT_PRFPREG,
205 		.n = sizeof(elf_xtregs_t) / sizeof(u32),
206 		.size = sizeof(u32),
207 		.align = sizeof(u32),
208 		.regset_get = tie_get,
209 		.set = tie_set,
210 	},
211 };
212 
213 static const struct user_regset_view user_xtensa_view = {
214 	.name = "xtensa",
215 	.e_machine = EM_XTENSA,
216 	.regsets = xtensa_regsets,
217 	.n = ARRAY_SIZE(xtensa_regsets)
218 };
219 
task_user_regset_view(struct task_struct * task)220 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
221 {
222 	return &user_xtensa_view;
223 }
224 
user_enable_single_step(struct task_struct * child)225 void user_enable_single_step(struct task_struct *child)
226 {
227 	set_tsk_thread_flag(child, TIF_SINGLESTEP);
228 }
229 
user_disable_single_step(struct task_struct * child)230 void user_disable_single_step(struct task_struct *child)
231 {
232 	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
233 }
234 
235 /*
236  * Called by kernel/ptrace.c when detaching to disable single stepping.
237  */
238 
ptrace_disable(struct task_struct * child)239 void ptrace_disable(struct task_struct *child)
240 {
241 	/* Nothing to do.. */
242 }
243 
ptrace_getregs(struct task_struct * child,void __user * uregs)244 static int ptrace_getregs(struct task_struct *child, void __user *uregs)
245 {
246 	return copy_regset_to_user(child, &user_xtensa_view, REGSET_GPR,
247 				   0, sizeof(xtensa_gregset_t), uregs);
248 }
249 
ptrace_setregs(struct task_struct * child,void __user * uregs)250 static int ptrace_setregs(struct task_struct *child, void __user *uregs)
251 {
252 	return copy_regset_from_user(child, &user_xtensa_view, REGSET_GPR,
253 				     0, sizeof(xtensa_gregset_t), uregs);
254 }
255 
ptrace_getxregs(struct task_struct * child,void __user * uregs)256 static int ptrace_getxregs(struct task_struct *child, void __user *uregs)
257 {
258 	return copy_regset_to_user(child, &user_xtensa_view, REGSET_TIE,
259 				   0, sizeof(elf_xtregs_t), uregs);
260 }
261 
ptrace_setxregs(struct task_struct * child,void __user * uregs)262 static int ptrace_setxregs(struct task_struct *child, void __user *uregs)
263 {
264 	return copy_regset_from_user(child, &user_xtensa_view, REGSET_TIE,
265 				     0, sizeof(elf_xtregs_t), uregs);
266 }
267 
ptrace_peekusr(struct task_struct * child,long regno,long __user * ret)268 static int ptrace_peekusr(struct task_struct *child, long regno,
269 			  long __user *ret)
270 {
271 	struct pt_regs *regs;
272 	unsigned long tmp;
273 
274 	regs = task_pt_regs(child);
275 	tmp = 0;  /* Default return value. */
276 
277 	switch(regno) {
278 	case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
279 		tmp = regs->areg[regno - REG_AR_BASE];
280 		break;
281 
282 	case REG_A_BASE ... REG_A_BASE + 15:
283 		tmp = regs->areg[regno - REG_A_BASE];
284 		break;
285 
286 	case REG_PC:
287 		tmp = regs->pc;
288 		break;
289 
290 	case REG_PS:
291 		/* Note: PS.EXCM is not set while user task is running;
292 		 * its being set in regs is for exception handling
293 		 * convenience.
294 		 */
295 		tmp = (regs->ps & ~(1 << PS_EXCM_BIT));
296 		break;
297 
298 	case REG_WB:
299 		break;		/* tmp = 0 */
300 
301 	case REG_WS:
302 		{
303 			unsigned long wb = regs->windowbase;
304 			unsigned long ws = regs->windowstart;
305 			tmp = ((ws >> wb) | (ws << (WSBITS - wb))) &
306 				((1 << WSBITS) - 1);
307 			break;
308 		}
309 	case REG_LBEG:
310 		tmp = regs->lbeg;
311 		break;
312 
313 	case REG_LEND:
314 		tmp = regs->lend;
315 		break;
316 
317 	case REG_LCOUNT:
318 		tmp = regs->lcount;
319 		break;
320 
321 	case REG_SAR:
322 		tmp = regs->sar;
323 		break;
324 
325 	case SYSCALL_NR:
326 		tmp = regs->syscall;
327 		break;
328 
329 	default:
330 		return -EIO;
331 	}
332 	return put_user(tmp, ret);
333 }
334 
ptrace_pokeusr(struct task_struct * child,long regno,long val)335 static int ptrace_pokeusr(struct task_struct *child, long regno, long val)
336 {
337 	struct pt_regs *regs;
338 	regs = task_pt_regs(child);
339 
340 	switch (regno) {
341 	case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
342 		regs->areg[regno - REG_AR_BASE] = val;
343 		break;
344 
345 	case REG_A_BASE ... REG_A_BASE + 15:
346 		regs->areg[regno - REG_A_BASE] = val;
347 		break;
348 
349 	case REG_PC:
350 		regs->pc = val;
351 		break;
352 
353 	case SYSCALL_NR:
354 		regs->syscall = val;
355 		break;
356 
357 	default:
358 		return -EIO;
359 	}
360 	return 0;
361 }
362 
363 #ifdef CONFIG_HAVE_HW_BREAKPOINT
ptrace_hbptriggered(struct perf_event * bp,struct perf_sample_data * data,struct pt_regs * regs)364 static void ptrace_hbptriggered(struct perf_event *bp,
365 				struct perf_sample_data *data,
366 				struct pt_regs *regs)
367 {
368 	int i;
369 	struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
370 
371 	if (bp->attr.bp_type & HW_BREAKPOINT_X) {
372 		for (i = 0; i < XCHAL_NUM_IBREAK; ++i)
373 			if (current->thread.ptrace_bp[i] == bp)
374 				break;
375 		i <<= 1;
376 	} else {
377 		for (i = 0; i < XCHAL_NUM_DBREAK; ++i)
378 			if (current->thread.ptrace_wp[i] == bp)
379 				break;
380 		i = (i << 1) | 1;
381 	}
382 
383 	force_sig_ptrace_errno_trap(i, (void __user *)bkpt->address);
384 }
385 
ptrace_hbp_create(struct task_struct * tsk,int type)386 static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
387 {
388 	struct perf_event_attr attr;
389 
390 	ptrace_breakpoint_init(&attr);
391 
392 	/* Initialise fields to sane defaults. */
393 	attr.bp_addr	= 0;
394 	attr.bp_len	= 1;
395 	attr.bp_type	= type;
396 	attr.disabled	= 1;
397 
398 	return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL,
399 					   tsk);
400 }
401 
402 /*
403  * Address bit 0 choose instruction (0) or data (1) break register, bits
404  * 31..1 are the register number.
405  * Both PTRACE_GETHBPREGS and PTRACE_SETHBPREGS transfer two 32-bit words:
406  * address (0) and control (1).
407  * Instruction breakpoint contorl word is 0 to clear breakpoint, 1 to set.
408  * Data breakpoint control word bit 31 is 'trigger on store', bit 30 is
409  * 'trigger on load, bits 29..0 are length. Length 0 is used to clear a
410  * breakpoint. To set a breakpoint length must be a power of 2 in the range
411  * 1..64 and the address must be length-aligned.
412  */
413 
ptrace_gethbpregs(struct task_struct * child,long addr,long __user * datap)414 static long ptrace_gethbpregs(struct task_struct *child, long addr,
415 			      long __user *datap)
416 {
417 	struct perf_event *bp;
418 	u32 user_data[2] = {0};
419 	bool dbreak = addr & 1;
420 	unsigned idx = addr >> 1;
421 
422 	if ((!dbreak && idx >= XCHAL_NUM_IBREAK) ||
423 	    (dbreak && idx >= XCHAL_NUM_DBREAK))
424 		return -EINVAL;
425 
426 	if (dbreak)
427 		bp = child->thread.ptrace_wp[idx];
428 	else
429 		bp = child->thread.ptrace_bp[idx];
430 
431 	if (bp) {
432 		user_data[0] = bp->attr.bp_addr;
433 		user_data[1] = bp->attr.disabled ? 0 : bp->attr.bp_len;
434 		if (dbreak) {
435 			if (bp->attr.bp_type & HW_BREAKPOINT_R)
436 				user_data[1] |= DBREAKC_LOAD_MASK;
437 			if (bp->attr.bp_type & HW_BREAKPOINT_W)
438 				user_data[1] |= DBREAKC_STOR_MASK;
439 		}
440 	}
441 
442 	if (copy_to_user(datap, user_data, sizeof(user_data)))
443 		return -EFAULT;
444 
445 	return 0;
446 }
447 
ptrace_sethbpregs(struct task_struct * child,long addr,long __user * datap)448 static long ptrace_sethbpregs(struct task_struct *child, long addr,
449 			      long __user *datap)
450 {
451 	struct perf_event *bp;
452 	struct perf_event_attr attr;
453 	u32 user_data[2];
454 	bool dbreak = addr & 1;
455 	unsigned idx = addr >> 1;
456 	int bp_type = 0;
457 
458 	if ((!dbreak && idx >= XCHAL_NUM_IBREAK) ||
459 	    (dbreak && idx >= XCHAL_NUM_DBREAK))
460 		return -EINVAL;
461 
462 	if (copy_from_user(user_data, datap, sizeof(user_data)))
463 		return -EFAULT;
464 
465 	if (dbreak) {
466 		bp = child->thread.ptrace_wp[idx];
467 		if (user_data[1] & DBREAKC_LOAD_MASK)
468 			bp_type |= HW_BREAKPOINT_R;
469 		if (user_data[1] & DBREAKC_STOR_MASK)
470 			bp_type |= HW_BREAKPOINT_W;
471 	} else {
472 		bp = child->thread.ptrace_bp[idx];
473 		bp_type = HW_BREAKPOINT_X;
474 	}
475 
476 	if (!bp) {
477 		bp = ptrace_hbp_create(child,
478 				       bp_type ? bp_type : HW_BREAKPOINT_RW);
479 		if (IS_ERR(bp))
480 			return PTR_ERR(bp);
481 		if (dbreak)
482 			child->thread.ptrace_wp[idx] = bp;
483 		else
484 			child->thread.ptrace_bp[idx] = bp;
485 	}
486 
487 	attr = bp->attr;
488 	attr.bp_addr = user_data[0];
489 	attr.bp_len = user_data[1] & ~(DBREAKC_LOAD_MASK | DBREAKC_STOR_MASK);
490 	attr.bp_type = bp_type;
491 	attr.disabled = !attr.bp_len;
492 
493 	return modify_user_hw_breakpoint(bp, &attr);
494 }
495 #endif
496 
arch_ptrace(struct task_struct * child,long request,unsigned long addr,unsigned long data)497 long arch_ptrace(struct task_struct *child, long request,
498 		 unsigned long addr, unsigned long data)
499 {
500 	int ret = -EPERM;
501 	void __user *datap = (void __user *) data;
502 
503 	switch (request) {
504 	case PTRACE_PEEKUSR:	/* read register specified by addr. */
505 		ret = ptrace_peekusr(child, addr, datap);
506 		break;
507 
508 	case PTRACE_POKEUSR:	/* write register specified by addr. */
509 		ret = ptrace_pokeusr(child, addr, data);
510 		break;
511 
512 	case PTRACE_GETREGS:
513 		ret = ptrace_getregs(child, datap);
514 		break;
515 
516 	case PTRACE_SETREGS:
517 		ret = ptrace_setregs(child, datap);
518 		break;
519 
520 	case PTRACE_GETXTREGS:
521 		ret = ptrace_getxregs(child, datap);
522 		break;
523 
524 	case PTRACE_SETXTREGS:
525 		ret = ptrace_setxregs(child, datap);
526 		break;
527 #ifdef CONFIG_HAVE_HW_BREAKPOINT
528 	case PTRACE_GETHBPREGS:
529 		ret = ptrace_gethbpregs(child, addr, datap);
530 		break;
531 
532 	case PTRACE_SETHBPREGS:
533 		ret = ptrace_sethbpregs(child, addr, datap);
534 		break;
535 #endif
536 	default:
537 		ret = ptrace_request(child, request, addr, data);
538 		break;
539 	}
540 
541 	return ret;
542 }
543 
do_syscall_trace_enter(struct pt_regs * regs)544 int do_syscall_trace_enter(struct pt_regs *regs)
545 {
546 	if (regs->syscall == NO_SYSCALL)
547 		regs->areg[2] = -ENOSYS;
548 
549 	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
550 	    ptrace_report_syscall_entry(regs)) {
551 		regs->areg[2] = -ENOSYS;
552 		regs->syscall = NO_SYSCALL;
553 		return 0;
554 	}
555 
556 	if (regs->syscall == NO_SYSCALL ||
557 	    secure_computing() == -1) {
558 		do_syscall_trace_leave(regs);
559 		return 0;
560 	}
561 
562 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
563 		trace_sys_enter(regs, syscall_get_nr(current, regs));
564 
565 	audit_syscall_entry(regs->syscall, regs->areg[6],
566 			    regs->areg[3], regs->areg[4],
567 			    regs->areg[5]);
568 	return 1;
569 }
570 
do_syscall_trace_leave(struct pt_regs * regs)571 void do_syscall_trace_leave(struct pt_regs *regs)
572 {
573 	int step;
574 
575 	audit_syscall_exit(regs);
576 
577 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
578 		trace_sys_exit(regs, regs_return_value(regs));
579 
580 	step = test_thread_flag(TIF_SINGLESTEP);
581 
582 	if (step || test_thread_flag(TIF_SYSCALL_TRACE))
583 		ptrace_report_syscall_exit(regs, step);
584 }
585