Date: Fri, 17 Jul 2020 14:39:07 +0000 (UTC) From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r363272 - head/sys/cddl/dev/dtrace/aarch64 Message-ID: <202007171439.06HEd742050696@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202007171439.06HEd742050696>