svn commit: r363272 - head/sys/cddl/dev/dtrace/aarch64

Andrew Turner andrew at FreeBSD.org
Fri Jul 17 14:39:08 UTC 2020


Author: andrew
Date: Fri Jul 17 14:39:07 2020
New Revision: 363272
URL: https://svnweb.freebsd.org/changeset/base/363272

Log:
  Don't overflow the trap frame when accessing lr or xzr.
  
  When emulating a load pair or store pair in dtrace on arm64 we need to
  copy the data between the stack and trap frame. When the registers are
  either the link register or the zero register we will access memory
  past the end of the trap frame as these are encoded as registers 30 and
  31 respectively while the array they access only has 30 entries.
  
  Fix this by creating 2 helper functions to perform the operation with
  special cases for these registers.
  
  Sponsored by:	Innovate UK

Modified:
  head/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c

Modified: head/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
==============================================================================
--- head/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c	Fri Jul 17 14:17:13 2020	(r363271)
+++ head/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c	Fri Jul 17 14:39:07 2020	(r363272)
@@ -231,6 +231,31 @@ dtrace_probe_error(dtrace_state_t *state, dtrace_epid_
 	    (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs);
 }
 
+static void
+dtrace_load64(uint64_t *addr, struct trapframe *frame, u_int reg)
+{
+
+	KASSERT(reg <= 31, ("dtrace_load64: Invalid register %u", reg));
+	if (reg < nitems(frame->tf_x))
+		frame->tf_x[reg] = *addr;
+	else if (reg == 30) /* lr */
+		frame->tf_lr = *addr;
+	/* Nothing to do for load to xzr */
+}
+
+static void
+dtrace_store64(uint64_t *addr, struct trapframe *frame, u_int reg)
+{
+
+	KASSERT(reg <= 31, ("dtrace_store64: Invalid register %u", reg));
+	if (reg < nitems(frame->tf_x))
+		*addr = frame->tf_x[reg];
+	else if (reg == 30) /* lr */
+		*addr = frame->tf_lr;
+	else if (reg == 31) /* xzr */
+		*addr = 0;
+}
+
 static int
 dtrace_invop_start(struct trapframe *frame)
 {
@@ -258,12 +283,12 @@ dtrace_invop_start(struct trapframe *frame)
 				sp -= (~offs & OFFSET_MASK) + 1;
 			else
 				sp += (offs);
-			*(sp + 0) = frame->tf_x[arg1];
-			*(sp + 1) = frame->tf_x[arg2];
+			dtrace_store64(sp + 0, frame, arg1);
+			dtrace_store64(sp + 1, frame, arg2);
 			break;
 		case LDP_64:
-			frame->tf_x[arg1] = *(sp + 0);
-			frame->tf_x[arg2] = *(sp + 1);
+			dtrace_load64(sp + 0, frame, arg1);
+			dtrace_load64(sp + 1, frame, arg2);
 			if (offs >> (OFFSET_SIZE - 1))
 				sp -= (~offs & OFFSET_MASK) + 1;
 			else


More information about the svn-src-all mailing list