From 59b1fdfb3dd6929af682e540e48580113f2f9279 Mon Sep 17 00:00:00 2001 From: markj Date: Tue, 10 Apr 2018 13:47:09 +0000 Subject: [PATCH] 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 MFC after: 2 weeks Sponsored by: DARPA/AFRL Differential Revision: https://reviews.freebsd.org/D14863 --- .../opensolaris/uts/common/dtrace/dtrace.c | 46 +++++++++++++++++-- sys/cddl/dev/dtrace/dtrace_cddl.h | 2 + 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index f9b8af9b78d8..10c01397ab8f 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -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); } /* diff --git a/sys/cddl/dev/dtrace/dtrace_cddl.h b/sys/cddl/dev/dtrace/dtrace_cddl.h index b8ea17a23a54..b69da4d18da1 100644 --- a/sys/cddl/dev/dtrace/dtrace_cddl.h +++ b/sys/cddl/dev/dtrace/dtrace_cddl.h @@ -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