[DTrace-devel] [PATCH v2 05/14] probe: improve dt_probe_lookup2()

Nick Alcock nick.alcock at oracle.com
Mon Oct 28 21:17:54 UTC 2024


This function had numerous problems:

 - it broke _FORTIFY_SOURCE due to using a function that snprintf()ed
   with a size of INT_MAX, into a much smaller alloca()ed buffer
 - it claimed to call down to the dtrace kernel module for a probe
   description (long obsolete)
 - it invariably leaked the probe description it constructed by calling
   dtrace_xstr2desc()
 - it did meaningless errno testing to determine whether to return
   EDT_NOPROBE on error, which more or less led to EDT_NOPROBE never
   being returned even though it should always be in this case (there
   is no other cause for the ID hash lookup failing).

Fix the lot: while we're at it, implement a dt_desc_destroy() to
undo the strdup()s done by dtrace_xstr2desc(), and use it additionally
in dt_probe_destroy() instead of an identical sequence of dt_free()s.

Bug: https://github.com/oracle/dtrace-utils/issues/78
Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
---
 libdtrace/dt_impl.h  |  2 ++
 libdtrace/dt_probe.c | 44 +++++++++++++-------------------------------
 libdtrace/dt_subr.c  | 10 ++++++++++
 3 files changed, 25 insertions(+), 31 deletions(-)

diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 340dc1960c5e..d11ad2839f8e 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -759,6 +759,8 @@ extern dtrace_difo_t *dt_difo_copy(dtrace_hdl_t *dtp, const dtrace_difo_t *odp);
 extern int dt_consume_init(dtrace_hdl_t *);
 extern void dt_consume_fini(dtrace_hdl_t *);
 
+extern void dt_desc_destroy(dtrace_hdl_t *dtp, dtrace_probedesc_t *);
+
 extern dtrace_datadesc_t *dt_datadesc_hold(dtrace_datadesc_t *ddp);
 extern void dt_datadesc_release(dtrace_hdl_t *, dtrace_datadesc_t *);
 extern dtrace_datadesc_t *dt_datadesc_create(dtrace_hdl_t *);
diff --git a/libdtrace/dt_probe.c b/libdtrace/dt_probe.c
index 686e2a661253..f84581687caf 100644
--- a/libdtrace/dt_probe.c
+++ b/libdtrace/dt_probe.c
@@ -172,24 +172,9 @@ dt_probe_alloc_args(dt_probe_t *prp, int nargc, int xargc)
 	}
 }
 
-static size_t
-dt_probe_keylen(const dtrace_probedesc_t *pdp)
-{
-	return strlen(pdp->mod) + 1 + strlen(pdp->fun) + 1 +
-		strlen(pdp->prb) + 1;
-}
-
-static char *
-dt_probe_key(const dtrace_probedesc_t *pdp, char *s)
-{
-	snprintf(s, INT_MAX, "%s:%s:%s", pdp->mod, pdp->fun, pdp->prb);
-	return s;
-}
-
 /*
  * Lookup a probe declaration based on a known provider and full or partially
- * specified module, function, and name.  If the probe is not known to us yet,
- * ask dtrace(7D) to match the description and then cache any useful results.
+ * specified module, function, and name.
  */
 dt_probe_t *
 dt_probe_lookup2(dt_provider_t *pvp, const char *s)
@@ -197,28 +182,28 @@ dt_probe_lookup2(dt_provider_t *pvp, const char *s)
 	dtrace_hdl_t *dtp = pvp->pv_hdl;
 	dtrace_probedesc_t pd;
 	dt_ident_t *idp;
-	size_t keylen;
 	char *key;
 
 	if (dtrace_str2desc(dtp, DTRACE_PROBESPEC_NAME, s, &pd) != 0)
 		return NULL; /* dt_errno is set for us */
 
-	keylen = dt_probe_keylen(&pd);
-	key = dt_probe_key(&pd, alloca(keylen));
+	if (asprintf(&key, "%s:%s:%s", pd.mod, pd.fun, pd.prb) == -1) {
+		dt_set_errno(dtp, errno);
+		goto out;
+	}
 
 	/*
 	 * If the probe is already declared, then return the dt_probe_t from
-	 * the existing identifier.  This could come from a static declaration
-	 * or it could have been cached from an earlier call to this function.
+	 * the existing identifier.
 	 */
-	if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL)
+	if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL) {
+		dt_desc_destroy(dtp, &pd);
 		return idp->di_data;
+	}
 
-	if (errno == ESRCH || errno == EBADF)
-		dt_set_errno(dtp, EDT_NOPROBE);
-	else
-		dt_set_errno(dtp, errno);
-
+	dt_set_errno(dtp, EDT_NOPROBE);
+ out:
+	dt_desc_destroy(dtp, &pd);
 	return NULL;
 }
 
@@ -387,10 +372,7 @@ dt_probe_destroy(dt_probe_t *prp)
 	dt_free(dtp, prp->mapping);
 	dt_free(dtp, prp->argv);
 	if (prp->desc) {
-		dt_free(dtp, (void *)prp->desc->prv);
-		dt_free(dtp, (void *)prp->desc->mod);
-		dt_free(dtp, (void *)prp->desc->fun);
-		dt_free(dtp, (void *)prp->desc->prb);
+		dt_desc_destroy(dtp, (dtrace_probedesc_t *)prp->desc);
 		dt_free(dtp, (void *)prp->desc);
 	}
 	dt_free(dtp, prp);
diff --git a/libdtrace/dt_subr.c b/libdtrace/dt_subr.c
index d6aad7637fb9..72631b33a0ad 100644
--- a/libdtrace/dt_subr.c
+++ b/libdtrace/dt_subr.c
@@ -175,6 +175,16 @@ dtrace_desc2str(const dtrace_probedesc_t *pdp, char *buf, size_t len)
 	return buf;
 }
 
+/* Only use on probedescs derived from dtrace_xstr2desc above. */
+void
+dt_desc_destroy(dtrace_hdl_t *dtp, dtrace_probedesc_t *pdp)
+{
+	dt_free(dtp, (void *) pdp->prv);
+	dt_free(dtp, (void *) pdp->mod);
+	dt_free(dtp, (void *) pdp->fun);
+	dt_free(dtp, (void *) pdp->prb);
+}
+
 char *
 dtrace_attr2str(dtrace_attribute_t attr, char *buf, size_t len)
 {
-- 
2.46.0.278.g36e3a12567




More information about the DTrace-devel mailing list