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 _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"