mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
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:
parent
9c80ad6839
commit
5c134fba22
|
@ -21,6 +21,7 @@ kinst::vm_fault: {}
|
|||
kinst::amd64_syscall: {}
|
||||
kinst::exit1: {}
|
||||
kinst::spinlock_enter: {}
|
||||
kinst::memcpy: {}
|
||||
|
||||
tick-10s {exit(0);}
|
||||
__EOF__
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue