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

Kris Van Hees kris.van.hees at oracle.com
Tue Feb 25 21:08:23 UTC 2025


ping?

On Fri, Nov 15, 2024 at 03:42:49PM -0500, Kris Van Hees wrote:
> On Tue, Nov 12, 2024 at 01:42:56PM +0000, Nick Alcock wrote:
> > 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.
> 
> I think it is useful to put the testing (and results) in the commit msg for
> this, especially since you do not have a testcase for this (and I can
> understand why - though if we were to use chroot or something a test could
> be constructed, right).  And the case of tracefs *not* being in standard
> location is worth pointing out to clearly show that this does work in the
> most generic case.
> 
> Or if output of testing is too much to include (I assume it shouldn't be),
> at least make sure you test standard and non-standard locations, and then
> confidently report here that it works for all locations that do not have
> % in the path name.
> 
> > 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                       | 30 ++++---
> >  libdtrace/dt_prov_syscall.c                   | 27 ++++---
> >  libdtrace/dt_prov_uprobe.c                    | 41 +++++-----
> >  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, 203 insertions(+), 106 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"
> 
> Since you keep KPROBE_EVENTS etc in other providers, why not here?
> 
> > -
> >  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..b5c1f5d22a06 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..6940edce6a6d 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..7ebe010efa79 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,6 +62,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;
> > @@ -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;
> > +	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..63ce3bc43ae1 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,6 +71,7 @@ struct syscall_data {
> >  static int populate(dtrace_hdl_t *dtp)
> >  {
> >  	dt_provider_t	*prv;
> > +	int		fd;
> >  	FILE		*f;
> >  	char		*buf = NULL;
> >  	size_t		n;
> > @@ -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;
> >  
> > @@ -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..6a02243ff572 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,12 @@ 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);
> > +	fd = dt_tracefs_open(dtp, "events/%s/format", O_RDONLY, prb);
> >  	free(prb);
> > -	if (rc < 0)
> > +	if (fd < 0)
> >  		return -ENOENT;
> > -	f = fopen(fn, "r");
> > -	free(fn);
> > +
> > +	f = fdopen(fd, "r");
> >  	if (f == NULL)
> >  		return -ENOENT;
> >  
> > @@ -1251,21 +1251,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 +1296,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..f129e5591465 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..5737c7575a26 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
> > +FUNCS=${tracefs}/available_filter_functions
> > +
> > +if [[ ! -e $FUNCS ]]; then
> > +	echo no tracefs found
> > +	exit 1
> > +fi
> >  
> >  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..f3e434ae76fc 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
> > +UPROBE_EVENTS=${tracefs}/uprobe_events
> > +
> > +if [[ ! -e $UPROBE_EVENTS ]]; then
> > +	echo "no tracefs/uprobe_events" >&2
> > +	exit 67
> > +fi
> >  
> >  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..cfd100088eb7 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
> > +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 $EVENTS ]]; then
> > +    exit 0
> > +fi
> >  
> >  # Check permissions
> >  if [[ ! -r ${EVENTS} ]]; then
> > -- 
> > 2.46.0.278.g36e3a12567
> > 



More information about the DTrace-devel mailing list