aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristos Margiolis <christos@FreeBSD.org>2023-05-26 15:43:37 +0000
committerChristos Margiolis <christos@FreeBSD.org>2023-05-26 15:43:37 +0000
commit5c134fba225fabb2e0f9c763aaca0eeee81d8f9f (patch)
treec614cdf6ba15a90bda05d9677acdd4e49a0092a5
parent9c80ad6839cd30ecfeff2fb946d86888815da600 (diff)
downloadsrc-5c134fba225fabb2e0f9c763aaca0eeee81d8f9f.tar.gz
src-5c134fba225fabb2e0f9c763aaca0eeee81d8f9f.zip
kinst: fix memcpy() tracing crash
Tracing memcpy() would crash the kernel, because we'd also trace the memcpy() calls from kinst_invop(). To fix this, introduce kinst_memcpy() whose arguments are 'volatile', so that we avoid having the compiler replace it with a regular memcpy(). Reviewed by: markj Approved by: markj (mentor) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D40284
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/amd64/kinst/tst.basic.ksh1
-rw-r--r--sys/cddl/dev/kinst/amd64/kinst_isa.c6
-rw-r--r--sys/cddl/dev/kinst/kinst.c21
-rw-r--r--sys/cddl/dev/kinst/kinst.h1
4 files changed, 26 insertions, 3 deletions
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/amd64/kinst/tst.basic.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/amd64/kinst/tst.basic.ksh
index e3585ca70793..3005da74c895 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/amd64/kinst/tst.basic.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/amd64/kinst/tst.basic.ksh
@@ -21,6 +21,7 @@ kinst::vm_fault: {}
kinst::amd64_syscall: {}
kinst::exit1: {}
kinst::spinlock_enter: {}
+kinst::memcpy: {}
tick-10s {exit(0);}
__EOF__
diff --git a/sys/cddl/dev/kinst/amd64/kinst_isa.c b/sys/cddl/dev/kinst/amd64/kinst_isa.c
index 7aba79c1d481..d29f1cd4181f 100644
--- a/sys/cddl/dev/kinst/amd64/kinst_isa.c
+++ b/sys/cddl/dev/kinst/amd64/kinst_isa.c
@@ -107,10 +107,10 @@ kinst_trampoline_populate(struct kinst_probe *kp, uint8_t *tramp)
ilen = kp->kp_md.tinstlen;
- memcpy(tramp, kp->kp_md.template, ilen);
+ kinst_memcpy(tramp, kp->kp_md.template, ilen);
if ((kp->kp_md.flags & KINST_F_RIPREL) != 0) {
disp = kinst_riprel_disp(kp, tramp);
- memcpy(&tramp[kp->kp_md.dispoff], &disp, sizeof(uint32_t));
+ kinst_memcpy(&tramp[kp->kp_md.dispoff], &disp, sizeof(uint32_t));
}
/*
@@ -126,7 +126,7 @@ kinst_trampoline_populate(struct kinst_probe *kp, uint8_t *tramp)
tramp[ilen + 4] = 0x00;
tramp[ilen + 5] = 0x00;
instr = kp->kp_patchpoint + kp->kp_md.instlen;
- memcpy(&tramp[ilen + 6], &instr, sizeof(uintptr_t));
+ kinst_memcpy(&tramp[ilen + 6], &instr, sizeof(uintptr_t));
}
int
diff --git a/sys/cddl/dev/kinst/kinst.c b/sys/cddl/dev/kinst/kinst.c
index 46b9bf2f41e8..e30b813e0400 100644
--- a/sys/cddl/dev/kinst/kinst.c
+++ b/sys/cddl/dev/kinst/kinst.c
@@ -65,6 +65,27 @@ static dtrace_provider_id_t kinst_id;
struct kinst_probe_list *kinst_probetab;
static struct cdev *kinst_cdev;
+/*
+ * Tracing memcpy() will crash the kernel when kinst tries to trace an instance
+ * of the memcpy() calls in kinst_invop(). To fix this, we can use
+ * kinst_memcpy() in those cases, with its arguments marked as 'volatile' to
+ * "outsmart" the compiler and avoid having it replaced by a regular memcpy().
+ */
+volatile void *
+kinst_memcpy(volatile void *dst, volatile const void *src, size_t len)
+{
+ volatile const unsigned char *src0;
+ volatile unsigned char *dst0;
+
+ src0 = src;
+ dst0 = dst;
+
+ while (len--)
+ *dst0++ = *src0++;
+
+ return (dst);
+}
+
int
kinst_excluded(const char *name)
{
diff --git a/sys/cddl/dev/kinst/kinst.h b/sys/cddl/dev/kinst/kinst.h
index ee756dc87d09..1107a274333f 100644
--- a/sys/cddl/dev/kinst/kinst.h
+++ b/sys/cddl/dev/kinst/kinst.h
@@ -46,6 +46,7 @@ extern struct kinst_probe_list *kinst_probetab;
struct linker_file;
struct linker_symval;
+volatile void *kinst_memcpy(volatile void *, volatile const void *, size_t);
int kinst_excluded(const char *);
int kinst_md_excluded(const char *);
int kinst_invop(uintptr_t, struct trapframe *, uintptr_t);