The branch main has been updated by christos:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=5c134fba225fabb2e0f9c763aaca0eeee81d8f9f

commit 5c134fba225fabb2e0f9c763aaca0eeee81d8f9f
Author:     Christos Margiolis <[email protected]>
AuthorDate: 2023-05-26 15:43:37 +0000
Commit:     Christos Margiolis <[email protected]>
CommitDate: 2023-05-26 15:43:37 +0000

    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
---
 .../cmd/dtrace/test/tst/amd64/kinst/tst.basic.ksh   |  1 +
 sys/cddl/dev/kinst/amd64/kinst_isa.c                |  6 +++---
 sys/cddl/dev/kinst/kinst.c                          | 21 +++++++++++++++++++++
 sys/cddl/dev/kinst/kinst.h                          |  1 +
 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);

Reply via email to