[DTrace-devel] [PATCH v2] Allow arbitrary tracefs mount points

Nick Alcock nick.alcock at oracle.com
Mon Nov 11 16:05:08 UTC 2024


So as of kernel 6.3 (upstream commit 2455f0e124d317dd08d337a75), the
canonical tracefs location has moved to /sys/kernel/tracing.  Unfortunately
this requires an explicit mount, and a great many installations have not
done this and perhaps never will.  So if the debugfs is mounted on
/sys/kernel/debug, it automatically makes /sys/kernel/debug/tracing appear
as it used to, as another tracefs mount.  And of course there's nothing
special about the "canonical location": it's up to the admin, who might
choose to remount the thing anywhere at all.

To make this even more fun, it's quite possible to end up with the tracefs
on /sys/kernel/debug/tracing, but an empty directory at /sys/kernel/tracing
(I got that during testing with no effort at all).

All this means that the existing DTrace hardwiring for tracefs/eventsfs
locations isn't good enough.  Instead, hunt for a suitable tracefs mount with
getmntent(), and add a function to open files under that directory, allowing
the path to be created using a printf-style format string (mimicking the
things we used to do with EVENTSFS defines and the like).  This is actually
all we need; there is no need to ever return these paths at all, so there
is no clogging up the code with free()s -- and actually there's a
noticeable simplification in most cases.

Tested with both in-practice-observed locations of debugfs, and the
obviously crazy and bad-in-a-format-string path of "/%s/%s/%n" to make sure
that is properly rejected.

Bug: https://github.com/oracle/dtrace-utils/issues/111
Signed-off-by: Nick Alcock <nick.alcock at oracle.com>
---
 include/tracefs.h                             | 14 ----
 libdtrace/dt_error.c                          |  3 +-
 libdtrace/dt_impl.h                           |  3 +
 libdtrace/dt_open.c                           |  1 +
 libdtrace/dt_prov_dtrace.c                    | 27 +++----
 libdtrace/dt_prov_fbt.c                       | 37 ++++-----
 libdtrace/dt_prov_rawtp.c                     |  9 ++-
 libdtrace/dt_prov_sdt.c                       | 34 +++++---
 libdtrace/dt_prov_syscall.c                   | 31 +++----
 libdtrace/dt_prov_uprobe.c                    | 42 +++++-----
 libdtrace/dt_provider.h                       |  1 -
 libdtrace/dt_subr.c                           | 80 +++++++++++++++++++
 runtest.sh                                    |  8 ++
 test/unittest/funcs/tst.rw_.x                 |  7 +-
 test/unittest/providers/tst.dtrace_cleanup.sh |  9 ++-
 test/utils/clean_probes.sh                    | 12 ++-
 16 files changed, 207 insertions(+), 111 deletions(-)
 delete mode 100644 include/tracefs.h

diff --git a/include/tracefs.h b/include/tracefs.h
deleted file mode 100644
index d671f51adefc..000000000000
--- a/include/tracefs.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Oracle Linux DTrace; simple uprobe helper functions
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
- * Licensed under the Universal Permissive License v 1.0 as shown at
- * http://oss.oracle.com/licenses/upl.
- */
-
-#ifndef	_TRACEFS_H
-#define	_TRACEFS_H
-
-#define TRACEFS		"/sys/kernel/debug/tracing/"
-#define EVENTSFS	TRACEFS "events/"
-
-#endif /* _TRACEFS_H */
diff --git a/libdtrace/dt_error.c b/libdtrace/dt_error.c
index 213f0d9e1385..9c4a2b32888e 100644
--- a/libdtrace/dt_error.c
+++ b/libdtrace/dt_error.c
@@ -98,7 +98,8 @@ static const struct {
 	{ EDT_READMAXSTACK, "Cannot read kernel param perf_event_max_stack" },
 	{ EDT_TRACEMEM, "Missing or corrupt tracemem() record" },
 	{ EDT_PCAP, "Missing or corrupt pcap() record" },
-	{ EDT_PRINT, "Missing or corrupt print() record" }
+	{ EDT_PRINT, "Missing or corrupt print() record" },
+	{ EDT_TRACEFS, "Cannot find tracefs" }
 };
 
 static const int _dt_nerr = sizeof(_dt_errlist) / sizeof(_dt_errlist[0]);
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 68fb8ec53c06..950cb34819aa 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -354,6 +354,7 @@ struct dtrace_hdl {
 	char *dt_module_path;	/* pathname of kernel module root */
 	dt_version_t dt_kernver;/* kernel version, used in the libpath */
 	char *dt_dofstash_path;	/* Path to the DOF stash.  */
+	char *dt_tracefs_path;	/* Path to tracefs.  */
 	uid_t dt_useruid;	/* lowest non-system uid: set via -xuseruid */
 	char *dt_sysslice;	/* the systemd system slice: set via -xsysslice */
 	uint_t dt_lazyload;	/* boolean:  set via -xlazyload */
@@ -643,6 +644,7 @@ enum {
 	EDT_TRACEMEM,		/* missing or corrupt tracemem() record */
 	EDT_PCAP,		/* missing or corrupt pcap() record */
 	EDT_PRINT,		/* missing or corrupt print() record */
+	EDT_TRACEFS,		/* cannot find tracefs */
 };
 
 /*
@@ -713,6 +715,7 @@ extern void dt_conf_init(dtrace_hdl_t *);
 
 extern int dt_gmatch(const char *, const char *);
 extern char *dt_basename(char *);
+extern int dt_tracefs_open(dtrace_hdl_t *, const char *fn, int flags, ...);
 
 extern ulong_t dt_popc(ulong_t);
 extern ulong_t dt_popcb(const ulong_t *, ulong_t);
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index e1972aa821e7..775830f64492 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -1317,6 +1317,7 @@ dtrace_close(dtrace_hdl_t *dtp)
 	free(dtp->dt_cpp_argv);
 	free(dtp->dt_cpp_path);
 	free(dtp->dt_ld_path);
+	free(dtp->dt_tracefs_path);
 	free(dtp->dt_sysslice);
 	free(dtp->dt_dofstash_path);
 
diff --git a/libdtrace/dt_prov_dtrace.c b/libdtrace/dt_prov_dtrace.c
index 34b5d8e2467f..670954beb4c9 100644
--- a/libdtrace/dt_prov_dtrace.c
+++ b/libdtrace/dt_prov_dtrace.c
@@ -23,8 +23,6 @@ static const char		funname[] = "";
 
 #define PROBE_FUNC_SUFFIX	"_probe"
 
-#define UPROBE_EVENTS		TRACEFS "uprobe_events"
-
 static const dtrace_pattr_t	pattr = {
 { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
@@ -229,11 +227,9 @@ out:
 static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 {
 	if (!dt_tp_probe_has_info(prp)) {
-		char	*spec;
-		char	*fn;
-		FILE	*f;
-		size_t	len;
-		int	fd, rc = -1;
+		char		*spec;
+		FILE		*f;
+		int		fd = -1, rc = -1;
 
 		/* get a uprobe specification for this probe */
 		spec = uprobe_spec(getpid(), prp->desc->prb);
@@ -241,7 +237,8 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 			return -ENOENT;
 
 		/* add a uprobe */
-		fd = open(UPROBE_EVENTS, O_WRONLY | O_APPEND);
+		fd = dt_tracefs_open(dtp, "uprobe_events", O_WRONLY | O_APPEND);
+
 		if (fd != -1) {
 			rc = dprintf(fd, "p:" GROUP_FMT "/%s %s\n",
 				     GROUP_DATA, prp->desc->prb, spec);
@@ -252,16 +249,12 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 			return -ENOENT;
 
 		/* open format file */
-		len = snprintf(NULL, 0, "%s" GROUP_FMT "/%s/format",
-			       EVENTSFS, GROUP_DATA, prp->desc->prb) + 1;
-		fn = dt_alloc(dtp, len);
-		if (fn == NULL)
+		fd = dt_tracefs_open(dtp, "events/" GROUP_FMT "/%s/format",
+				     O_RDONLY, GROUP_DATA, prp->desc->prb);
+		if (fd < 0)
 			return -ENOENT;
 
-		snprintf(fn, len, "%s" GROUP_FMT "/%s/format",
-			 EVENTSFS, GROUP_DATA, prp->desc->prb);
-		f = fopen(fn, "r");
-		dt_free(dtp, fn);
+		f = fdopen(fd, "r");
 		if (f == NULL)
 			return -ENOENT;
 
@@ -296,7 +289,7 @@ static void detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
 
 	dt_tp_probe_detach(dtp, prp);
 
-	fd = open(UPROBE_EVENTS, O_WRONLY | O_APPEND);
+	fd = dt_tracefs_open(dtp, "uprobe_events", O_WRONLY | O_APPEND);
 	if (fd == -1)
 		return;
 
diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
index 21f63ddffc73..e20d0283d956 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -43,8 +43,8 @@
 static const char		prvname[] = "fbt";
 static const char		modname[] = "vmlinux";
 
-#define KPROBE_EVENTS		TRACEFS "kprobe_events"
-#define PROBE_LIST		TRACEFS "available_filter_functions"
+#define KPROBE_EVENTS		"kprobe_events"
+#define PROBE_LIST		"available_filter_functions"
 
 #define FBT_GROUP_FMT		GROUP_FMT "_%s"
 #define FBT_GROUP_DATA		GROUP_DATA, prp->desc->prb
@@ -65,6 +65,7 @@ static int populate(dtrace_hdl_t *dtp)
 {
 	dt_provider_t		*prv;
 	dt_provimpl_t		*impl;
+	int			fd;
 	FILE			*f;
 	char			*buf = NULL;
 	char			*p;
@@ -79,7 +80,11 @@ static int populate(dtrace_hdl_t *dtp)
 	if (prv == NULL)
 		return -1;			/* errno already set */
 
-	f = fopen(PROBE_LIST, "r");
+	fd = dt_tracefs_open(dtp, PROBE_LIST, O_RDONLY);
+	if (fd < 0)
+		return 0;
+
+        f = fdopen(fd, "r");
 	if (f == NULL)
 		return 0;
 
@@ -363,16 +368,14 @@ static int kprobe_trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 {
 	if (!dt_tp_probe_has_info(prp)) {
-		char	*fn;
-		FILE	*f;
-		size_t	len;
-		int	fd, rc = -1;
+		FILE		*f;
+		int		fd, rc = -1;
 
 		/*
 		 * Register the kprobe with the tracing subsystem.  This will
 		 * create a tracepoint event.
 		 */
-		fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
+		fd = dt_tracefs_open(dtp, KPROBE_EVENTS, O_WRONLY | O_APPEND);
 		if (fd == -1)
 			return -ENOENT;
 
@@ -383,19 +386,13 @@ static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 		if (rc == -1)
 			return -ENOENT;
 
-		/* create format file name */
-		len = snprintf(NULL, 0, "%s" FBT_GROUP_FMT "/%s/format",
-			       EVENTSFS, FBT_GROUP_DATA, prp->desc->fun) + 1;
-		fn = dt_alloc(dtp, len);
-		if (fn == NULL)
+		/* open format file */
+		fd = dt_tracefs_open(dtp, "events/" FBT_GROUP_FMT "/%s/format",
+				     O_RDONLY, FBT_GROUP_DATA, prp->desc->fun);
+		if (fd < 0)
 			return -ENOENT;
 
-		snprintf(fn, len, "%s" FBT_GROUP_FMT "/%s/format", EVENTSFS,
-			 FBT_GROUP_DATA, prp->desc->fun);
-
-		/* open format file */
-		f = fopen(fn, "r");
-		dt_free(dtp, fn);
+		f = fdopen(fd, "r");
 		if (f == NULL)
 			return -ENOENT;
 
@@ -431,7 +428,7 @@ static void kprobe_detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
 
 	dt_tp_probe_detach(dtp, prp);
 
-	fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
+	fd = dt_tracefs_open(dtp, KPROBE_EVENTS, O_WRONLY | O_APPEND);
 	if (fd == -1)
 		return;
 
diff --git a/libdtrace/dt_prov_rawtp.c b/libdtrace/dt_prov_rawtp.c
index 778a6f9cde90..c6b3c7947b3c 100644
--- a/libdtrace/dt_prov_rawtp.c
+++ b/libdtrace/dt_prov_rawtp.c
@@ -38,7 +38,7 @@
 static const char		prvname[] = "rawtp";
 static const char		modname[] = "vmlinux";
 
-#define PROBE_LIST		TRACEFS "available_events"
+#define PROBE_LIST		"available_events"
 
 #define KPROBES			"kprobes"
 #define SYSCALLS		"syscalls"
@@ -64,6 +64,7 @@ static const dtrace_pattr_t	pattr = {
 static int populate(dtrace_hdl_t *dtp)
 {
 	dt_provider_t	*prv;
+	int		fd;
 	FILE		*f;
 	char		*buf = NULL;
 	char		*p;
@@ -73,7 +74,11 @@ static int populate(dtrace_hdl_t *dtp)
 	if (prv == NULL)
 		return -1;			/* errno already set */
 
-	f = fopen(PROBE_LIST, "r");
+	fd = dt_tracefs_open(dtp, PROBE_LIST, O_RDONLY);
+	if (fd < 0)
+		return 0;
+
+        f = fdopen(fd, "r");
 	if (f == NULL)
 		return 0;
 
diff --git a/libdtrace/dt_prov_sdt.c b/libdtrace/dt_prov_sdt.c
index 675e0458ca4c..2c07707e04b4 100644
--- a/libdtrace/dt_prov_sdt.c
+++ b/libdtrace/dt_prov_sdt.c
@@ -36,7 +36,7 @@
 static const char		prvname[] = "sdt";
 static const char		modname[] = "vmlinux";
 
-#define PROBE_LIST		TRACEFS "available_events"
+#define PROBE_LIST		"available_events"
 
 #define KPROBES			"kprobes"
 #define SYSCALLS		"syscalls"
@@ -62,7 +62,8 @@ static const dtrace_pattr_t	pattr = {
 static int populate(dtrace_hdl_t *dtp)
 {
 	dt_provider_t	*prv;
-	FILE		*f;
+	int		fd;
+        FILE		*f;
 	char		*buf = NULL;
 	char		*p;
 	size_t		n;
@@ -71,7 +72,11 @@ static int populate(dtrace_hdl_t *dtp)
 	if (prv == NULL)
 		return -1;			/* errno already set */
 
-	f = fopen(PROBE_LIST, "r");
+	fd = dt_tracefs_open(dtp, PROBE_LIST, O_RDONLY);
+	if (fd < 0)
+		return 0;
+
+	f = fdopen(fd, "r");
 	if (f == NULL)
 		return 0;
 
@@ -192,16 +197,16 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 static int probe_info_tracefs(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 			      int *argcp, dt_argdesc_t **argvp)
 {
+	int				fd;
 	FILE				*f;
-	char				*fn;
 	int				rc;
 	const dtrace_probedesc_t	*pdp = prp->desc;
 
-	if (asprintf(&fn, EVENTSFS "%s/%s/format", pdp->mod, pdp->prb) == -1)
-		return dt_set_errno(dtp, EDT_NOMEM);
+	fd = dt_tracefs_open(dtp, "events/%s/%s/format", O_RDONLY, pdp->mod, pdp->prb);
+	if (fd < 0)
+		return -ENOENT;
 
-	f = fopen(fn, "r");
-	free(fn);
+	f = fdopen(fd, "r");
 	if (!f)
 		return -ENOENT;
 
@@ -223,15 +228,18 @@ static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 	int			argc = 0;
 	dt_argdesc_t		*argv = NULL;
 	dtrace_typeinfo_t	sym;
-	FILE			*f;
+	int			fd;
+        FILE			*f;
 	uint32_t		id;
 
 	/* Retrieve the event id. */
-	if (asprintf(&str, EVENTSFS "%s/%s/id", prp->desc->mod, prp->desc->prb) == -1)
-		return dt_set_errno(dtp, EDT_NOMEM);
 
-	f = fopen(str, "r");
-	free(str);
+	fd = dt_tracefs_open(dtp, "events/%s/%s/id", O_RDONLY,
+			     prp->desc->mod, prp->desc->prb);
+	if (fd < 0)
+		return dt_set_errno(dtp, EDT_ENABLING_ERR);
+
+	f = fdopen(fd, "r");
 	if (!f)
 		return dt_set_errno(dtp, EDT_ENABLING_ERR);
 
diff --git a/libdtrace/dt_prov_syscall.c b/libdtrace/dt_prov_syscall.c
index 20843c6f538e..3f816a0d6ba1 100644
--- a/libdtrace/dt_prov_syscall.c
+++ b/libdtrace/dt_prov_syscall.c
@@ -38,7 +38,7 @@
 static const char		prvname[] = "syscall";
 static const char		modname[] = "vmlinux";
 
-#define SYSCALLSFS		EVENTSFS "syscalls/"
+#define SYSCALLSFS		"events/syscalls/"
 
 /*
  * We need to skip over an extra field: __syscall_nr.
@@ -61,7 +61,7 @@ struct syscall_data {
 
 #define SCD_ARG(n)	offsetof(struct syscall_data, arg[n])
 
-#define PROBE_LIST	TRACEFS "available_events"
+#define PROBE_LIST	"available_events"
 
 #define PROV_PREFIX	"syscalls:"
 #define ENTRY_PREFIX	"sys_enter_"
@@ -71,7 +71,8 @@ struct syscall_data {
 static int populate(dtrace_hdl_t *dtp)
 {
 	dt_provider_t	*prv;
-	FILE		*f;
+	int		fd;
+        FILE		*f;
 	char		*buf = NULL;
 	size_t		n;
 
@@ -79,8 +80,12 @@ static int populate(dtrace_hdl_t *dtp)
 	if (prv == NULL)
 		return -1;			/* errno already set */
 
-	f = fopen(PROBE_LIST, "r");
-	if (f == NULL)
+	fd = dt_tracefs_open(dtp, PROBE_LIST, O_RDONLY);
+	if (fd < 0)
+		return 0;
+
+	f = fdopen(fd, "r");
+        if (f == NULL)
 		return 0;
 
 	while (getline(&buf, &n, f) >= 0) {
@@ -195,23 +200,21 @@ static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 		      int *argcp, dt_argdesc_t **argvp)
 {
+	int		fd;
 	FILE		*f;
-	char		fn[256];
 	int		rc;
 
 	/*
 	 * We know that the probe name is either "entry" or "return", so we can
 	 * just check the first character.
 	 */
-	strcpy(fn, SYSCALLSFS);
-	if (prp->desc->prb[0] == 'e')
-		strcat(fn, "sys_enter_");
-	else
-		strcat(fn, "sys_exit_");
-	strcat(fn, prp->desc->fun);
-	strcat(fn, "/format");
+	fd = dt_tracefs_open(dtp, SYSCALLSFS "/sys_%s_%s/format", O_RDONLY,
+			     (prp->desc->prb[0] == 'e') ? "enter" : "exit",
+			     prp->desc->fun);
+	if (fd < 0)
+		return -ENOENT;
 
-	f = fopen(fn, "r");
+        f = fdopen(fd, "r");
 	if (!f)
 		return -ENOENT;
 
diff --git a/libdtrace/dt_prov_uprobe.c b/libdtrace/dt_prov_uprobe.c
index 205014617586..4bd834276912 100644
--- a/libdtrace/dt_prov_uprobe.c
+++ b/libdtrace/dt_prov_uprobe.c
@@ -1116,13 +1116,13 @@ static char *uprobe_name(dev_t dev, ino_t ino, uint64_t addr, int flags)
  * uprobe may be a uretprobe.  Return the probe's name as
  * a new dynamically-allocated string, or NULL on error.
  */
-static char *uprobe_create(dev_t dev, ino_t ino, const char *mapping_fn,
-			   uint64_t addr, int flags)
+static char *uprobe_create(dtrace_hdl_t *dtp, dev_t dev, ino_t ino,
+			   const char *mapping_fn, uint64_t addr, int flags)
 {
-	int	fd = -1;
-	int	rc = -1;
-	char	*name;
-	char	*spec;
+	int		fd = -1;
+	int		rc = -1;
+	char		*name;
+	char		*spec;
 
 	if (asprintf(&spec, "%s:0x%lx", mapping_fn, addr) < 0)
 		return NULL;
@@ -1132,8 +1132,8 @@ static char *uprobe_create(dev_t dev, ino_t ino, const char *mapping_fn,
 		goto out;
 
 	/* Add the uprobe. */
-	fd = open(TRACEFS "uprobe_events", O_WRONLY | O_APPEND);
-	if (fd == -1)
+	fd = dt_tracefs_open(dtp, "uprobe_events", O_WRONLY | O_APPEND);
+	if (fd < 0)
 		goto out;
 
 	rc = dprintf(fd, "%c:%s %s\n", flags & PP_IS_RETURN ? 'r' : 'p', name, spec);
@@ -1153,8 +1153,8 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *uprp, int bpf_fd)
 {
 	dt_uprobe_t	*upp = uprp->prv_data;
 	tp_probe_t	*tpp = upp->tp;
+	int		fd;
 	FILE		*f;
-	char		*fn;
 	char		*prb = NULL;
 	int		rc = -1;
 
@@ -1163,7 +1163,7 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *uprp, int bpf_fd)
 
 	assert(upp->fn != NULL);
 
-	prb = uprobe_create(upp->dev, upp->inum, upp->fn, upp->off,
+	prb = uprobe_create(dtp, upp->dev, upp->inum, upp->fn, upp->off,
 			    upp->flags);
 
 	/*
@@ -1177,12 +1177,11 @@ static int attach(dtrace_hdl_t *dtp, const dt_probe_t *uprp, int bpf_fd)
 				  upp->flags);
 
 	/* open format file */
-	rc = asprintf(&fn, "%s%s/format", EVENTSFS, prb);
-	free(prb);
-	if (rc < 0)
+	fd = dt_tracefs_open(dtp, "events/%s/format", O_RDONLY, prb);
+	if (fd < 0)
 		return -ENOENT;
-	f = fopen(fn, "r");
-	free(fn);
+
+	f = fdopen(fd, "r");
 	if (f == NULL)
 		return -ENOENT;
 
@@ -1251,21 +1250,20 @@ done:
  * Destroy a uprobe for a given device and address.
  */
 static int
-uprobe_delete(dev_t dev, ino_t ino, uint64_t addr, int flags)
+uprobe_delete(dtrace_hdl_t *dtp, dev_t dev, ino_t ino, uint64_t addr, int flags)
 {
-	int	fd = -1;
-	int	rc = -1;
-	char	*name;
+	int		fd = -1;
+	int		rc = -1;
+	char		*name;
 
 	name = uprobe_name(dev, ino, addr, flags);
 	if (!name)
 		goto out;
 
-	fd = open(TRACEFS "uprobe_events", O_WRONLY | O_APPEND);
+	fd = dt_tracefs_open(dtp, "uprobe_events", O_WRONLY | O_APPEND);
 	if (fd == -1)
 		goto out;
 
-
 	rc = dprintf(fd, "-:%s\n", name);
 
 out:
@@ -1297,7 +1295,7 @@ static void detach(dtrace_hdl_t *dtp, const dt_probe_t *uprp)
 
 	dt_tp_detach(dtp, tpp);
 
-	uprobe_delete(upp->dev, upp->inum, upp->off, upp->flags);
+	uprobe_delete(dtp, upp->dev, upp->inum, upp->off, upp->flags);
 }
 
 /*
diff --git a/libdtrace/dt_provider.h b/libdtrace/dt_provider.h
index 8f143dceaed7..4598a380b950 100644
--- a/libdtrace/dt_provider.h
+++ b/libdtrace/dt_provider.h
@@ -12,7 +12,6 @@
 #include <dt_impl.h>
 #include <dt_ident.h>
 #include <dt_list.h>
-#include <tracefs.h>
 
 #ifdef	__cplusplus
 extern "C" {
diff --git a/libdtrace/dt_subr.c b/libdtrace/dt_subr.c
index d5dca164861e..9887c4fc5ffa 100644
--- a/libdtrace/dt_subr.c
+++ b/libdtrace/dt_subr.c
@@ -20,6 +20,7 @@
 #include <assert.h>
 #include <limits.h>
 #include <sys/ioctl.h>
+#include <mntent.h>
 #include <port.h>
 
 #include <dt_impl.h>
@@ -998,3 +999,82 @@ uint32_t dt_gen_hval(const char *p, uint32_t hval, size_t len)
 
 	return hval;
 }
+
+/*
+ * Find the tracefs and store it away in dtp.
+ */
+static int
+find_tracefs_path(dtrace_hdl_t *dtp)
+{
+	FILE *mounts;
+	struct mntent *mnt;
+
+	if ((mounts = setmntent("/proc/mounts", "r")) == NULL) {
+		dt_dprintf("Cannot open /proc/mounts: %s\n", strerror(errno));
+		return dt_set_errno(dtp, EDT_TRACEFS);
+	}
+
+	while ((mnt = getmntent(mounts)) != NULL) {
+		/*
+		 * Only accept tracefs paths that do not contain percent
+		 * characters in their mounted paths, since we use this
+		 * to augment a format string in dt_tracefs_vfn().
+		 */
+		if ((strcmp(mnt->mnt_type, "tracefs") == 0) &&
+		    (strchr(mnt->mnt_dir, '%') == NULL)) {
+			dtp->dt_tracefs_path = strdup(mnt->mnt_dir);
+			break;
+		}
+	}
+	endmntent(mounts);
+
+	if (!dtp->dt_tracefs_path) {
+		dt_dprintf("Cannot find a suitable tracefs path.\n");
+		return dt_set_errno(dtp, EDT_TRACEFS);
+	}
+
+	dt_dprintf("Found tracefs at %s\n", dtp->dt_tracefs_path);
+
+	return 0;
+}
+
+static char *
+dt_tracefs_vfn(dtrace_hdl_t *dtp, const char *fn, va_list ap)
+{
+	char *full_fn;
+	char *str;
+
+        if (!dtp->dt_tracefs_path)
+		if (find_tracefs_path(dtp) < 0)
+			return NULL;		/* errno is set for us. */
+
+	if (asprintf(&full_fn, "%s/%s", dtp->dt_tracefs_path, fn) < 0) {
+		dt_set_errno(dtp, EDT_NOMEM);
+		return NULL;
+	}
+
+        if (vasprintf(&str, full_fn, ap) < 0) {
+		str = NULL;
+		dt_set_errno(dtp, EDT_NOMEM);
+	}
+	free(full_fn);
+	return str;
+}
+
+int
+dt_tracefs_open(dtrace_hdl_t *dtp, const char *fn, int flags, ...)
+{
+	va_list ap;
+	char *str;
+	int fd;
+
+	va_start(ap, flags);
+	if ((str = dt_tracefs_vfn(dtp, fn, ap)) == NULL) {
+		va_end(ap);
+		return -1; 			/* errno is set for us. */
+	}
+
+	fd = open(str, flags, 0666);
+	free(str);
+	return fd;				/* errno is set for us. */
+}
diff --git a/runtest.sh b/runtest.sh
index 46b532d7e161..fbf4e60c82a9 100755
--- a/runtest.sh
+++ b/runtest.sh
@@ -607,6 +607,14 @@ elif ! /usr/bin/cpp -x c -fno-show-column - /dev/null < /dev/null 2>&1 | \
     export DTRACE_OPT_CPPARGS="-fno-show-column"
 fi
 
+# Find the tracefs.
+tracefs="$(awk '$3 == "tracefs" { print $2; exit; }' /proc/mounts)"
+if [[ -z $tracefs ]]; then
+    echo "Cannot find any tracefs mounts in /proc/mounts.  Some tests will fail." >&2
+fi
+
+export tracefs
+
 # More than one dtrace tree -> run tests for all dtraces, and verify identical
 # intermediate code is produced by each dtrace.
 
diff --git a/test/unittest/funcs/tst.rw_.x b/test/unittest/funcs/tst.rw_.x
index 29c581116154..06e1f0b3c3eb 100755
--- a/test/unittest/funcs/tst.rw_.x
+++ b/test/unittest/funcs/tst.rw_.x
@@ -1,6 +1,11 @@
 #!/bin/sh
 
-FUNCS=/sys/kernel/debug/tracing/available_filter_functions
+if [[ ! -e $tracefs/available_filter_functions ]]; then
+	echo no tracefs found
+	exit 1
+fi
+
+FUNCS=${tracefs}/available_filter_functions
 
 if ! grep -qw  _raw_read_lock $FUNCS; then
         echo no _raw_read_lock FBT probe due to kernel config
diff --git a/test/unittest/providers/tst.dtrace_cleanup.sh b/test/unittest/providers/tst.dtrace_cleanup.sh
index 4ac59ccb4315..69e3ab369caf 100755
--- a/test/unittest/providers/tst.dtrace_cleanup.sh
+++ b/test/unittest/providers/tst.dtrace_cleanup.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 #
 # Oracle Linux DTrace.
-# Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
 # Licensed under the Universal Permissive License v 1.0 as shown at
 # http://oss.oracle.com/licenses/upl.
 
@@ -14,7 +14,12 @@
 ##
 
 dtrace=$1
-UPROBE_EVENTS=/sys/kernel/debug/tracing/uprobe_events
+if [[ ! -e $tracefs/uprobe_events ]]; then
+	echo "no tracefs/uprobe_events" >&2
+	exit 67
+fi
+
+UPROBE_EVENTS=${tracefs}/uprobe_events
 
 out=/tmp/output.$$
 $dtrace $dt_flags -n BEGIN,END &>> $out &
diff --git a/test/utils/clean_probes.sh b/test/utils/clean_probes.sh
index 8292b3096424..8372e8a26da7 100755
--- a/test/utils/clean_probes.sh
+++ b/test/utils/clean_probes.sh
@@ -1,9 +1,13 @@
 #!/usr/bin/bash
 
-TRACEFS=/sys/kernel/debug/tracing
-EVENTS=${TRACEFS}/available_events
-KPROBES=${TRACEFS}/kprobe_events
-UPROBES=${TRACEFS}/uprobe_events
+# We can't work without the tracefs: just give up quietly.
+if [[ ! -e $tracefs/available_events ]]; then
+    exit 0
+fi
+
+EVENTS=${tracefs}/available_events
+KPROBES=${tracefs}/kprobe_events
+UPROBES=${tracefs}/uprobe_events
 
 # Check permissions
 if [[ ! -r ${EVENTS} ]]; then
-- 
2.46.0.278.g36e3a12567




More information about the DTrace-devel mailing list