Assert that dtrace_probe() doesn't re-enter itself.

This helps catch cases where an instrumented function is called while
in probe context.

Submitted by:	Domagoj Stolfa <domagoj.stolfa@gmail.com>
MFC after:	2 weeks
Sponsored by:	DARPA/AFRL
Differential Revision:	https://reviews.freebsd.org/D14863
This commit is contained in:
Mark Johnston 2018-04-10 13:47:09 +00:00
parent 391f888277
commit 8593136428
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=332364
2 changed files with 44 additions and 4 deletions

View File

@ -7256,6 +7256,44 @@ dtrace_store_by_ref(dtrace_difo_t *dp, caddr_t tomax, size_t size,
*valoffsp = valoffs;
}
/*
* Disables interrupts and sets the per-thread inprobe flag. When DEBUG is
* defined, we also assert that we are not recursing unless the probe ID is an
* error probe.
*/
static dtrace_icookie_t
dtrace_probe_enter(dtrace_id_t id)
{
dtrace_icookie_t cookie;
cookie = dtrace_interrupt_disable();
/*
* Unless this is an ERROR probe, we are not allowed to recurse in
* dtrace_probe(). Recursing into DTrace probe usually means that a
* function is instrumented that should not have been instrumented or
* that the ordering guarantee of the records will be violated,
* resulting in unexpected output. If there is an exception to this
* assertion, a new case should be added.
*/
ASSERT(curthread->t_dtrace_inprobe == 0 ||
id == dtrace_probeid_error);
curthread->t_dtrace_inprobe = 1;
return (cookie);
}
/*
* Disables interrupts and clears the per-thread inprobe flag.
*/
static void
dtrace_probe_exit(dtrace_icookie_t cookie)
{
curthread->t_dtrace_inprobe = 0;
dtrace_interrupt_enable(cookie);
}
/*
* If you're looking for the epicenter of DTrace, you just found it. This
* is the function called by the provider to fire a probe -- from which all
@ -7290,7 +7328,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
return;
#endif
cookie = dtrace_interrupt_disable();
cookie = dtrace_probe_enter(id);
probe = dtrace_probes[id - 1];
cpuid = curcpu;
onintr = CPU_ON_INTR(CPU);
@ -7301,7 +7339,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
* We have hit in the predicate cache; we know that
* this predicate would evaluate to be false.
*/
dtrace_interrupt_enable(cookie);
dtrace_probe_exit(cookie);
return;
}
@ -7313,7 +7351,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
/*
* We don't trace anything if we're panicking.
*/
dtrace_interrupt_enable(cookie);
dtrace_probe_exit(cookie);
return;
}
@ -7939,7 +7977,7 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
if (vtime)
curthread->t_dtrace_start = dtrace_gethrtime();
dtrace_interrupt_enable(cookie);
dtrace_probe_exit(cookie);
}
/*

View File

@ -46,6 +46,7 @@ typedef struct kdtrace_proc {
typedef struct kdtrace_thread {
u_int8_t td_dtrace_stop; /* Indicates a DTrace-desired stop */
u_int8_t td_dtrace_sig; /* Signal sent via DTrace's raise() */
u_int8_t td_dtrace_inprobe; /* Are we in a probe? */
u_int td_predcache; /* DTrace predicate cache */
u_int64_t td_dtrace_vtime; /* DTrace virtual time */
u_int64_t td_dtrace_start; /* DTrace slice start time */
@ -97,6 +98,7 @@ typedef struct kdtrace_thread {
#define t_dtrace_start td_dtrace->td_dtrace_start
#define t_dtrace_stop td_dtrace->td_dtrace_stop
#define t_dtrace_sig td_dtrace->td_dtrace_sig
#define t_dtrace_inprobe td_dtrace->td_dtrace_inprobe
#define t_predcache td_dtrace->td_predcache
#define t_dtrace_ft td_dtrace->td_dtrace_ft
#define t_dtrace_on td_dtrace->td_dtrace_on