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
This commit is contained in:
Christos Margiolis 2023-05-26 18:43:37 +03:00
parent 9c80ad6839
commit 5c134fba22
4 changed files with 26 additions and 3 deletions

View File

@ -21,6 +21,7 @@ kinst::vm_fault: {}
kinst::amd64_syscall: {}
kinst::exit1: {}
kinst::spinlock_enter: {}
kinst::memcpy: {}
tick-10s {exit(0);}
__EOF__

View File

@ -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

View File

@ -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)
{

View File

@ -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);