[DTrace-devel] [PATCH v2] Need -w for destructive actions, even if clause is not used

eugene.loh at oracle.com eugene.loh at oracle.com
Fri Aug 1 19:16:21 UTC 2025


From: Eugene Loh <eugene.loh at oracle.com>

If a clause includes a destructive action but -w is not used, dtrace
should not start up, even if the clause is ignored (due to -Z).
Solaris treated this as a runtime error.  We should do the same.

The test err.Z_no-w.sh was misguided and is replaced by a more
direct test.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
Reviewed-by: Nick Alcock <nick.alcock at oracle.com>
---
 libdtrace/dt_bpf.c                            | 15 ++--
 libdtrace/dt_cg.c                             |  1 +
 libdtrace/dt_impl.h                           |  1 +
 .../options/err.no-w-or-destructive2.d        | 26 +++++++
 .../options/err.no-w-or-destructive2.r        |  3 +
 test/unittest/usdt/err.Z_no-w.r               |  4 -
 test/unittest/usdt/err.Z_no-w.sh              | 76 -------------------
 7 files changed, 40 insertions(+), 86 deletions(-)
 create mode 100644 test/unittest/options/err.no-w-or-destructive2.d
 create mode 100644 test/unittest/options/err.no-w-or-destructive2.r
 delete mode 100644 test/unittest/usdt/err.Z_no-w.r
 delete mode 100755 test/unittest/usdt/err.Z_no-w.sh

diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index cbf59c1d9..8b617d65e 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -1343,6 +1343,15 @@ dt_bpf_load_progs(dtrace_hdl_t *dtp, uint_t cflags)
 	 */
 	dtrace_getopt(dtp, "destructive", &dest_ok);
 
+	/*
+	 * If we have any destructive actions at all and -w is not set,
+	 * error out.  Solaris would reject this as a runtime error.  So,
+	 * although we could have detected this problem at compilation,
+	 * we mimic Solaris and wait until now to report.
+	 */
+	if (dtp->dt_destructive && dest_ok == DTRACEOPT_UNSET)
+		return dt_set_errno(dtp, EDT_DESTRUCTIVE);
+
 	dp = NULL;
 	for (prp = dt_list_next(&dtp->dt_enablings); prp != NULL;
 	     prp = dt_list_next(prp)) {
@@ -1362,12 +1371,6 @@ dt_bpf_load_progs(dtrace_hdl_t *dtp, uint_t cflags)
 
 		DT_DISASM_PROG_LINKED(dtp, cflags, dp, stderr, NULL, prp->desc);
 
-		if (dp->dtdo_flags & DIFOFLG_DESTRUCTIVE &&
-		    dest_ok == DTRACEOPT_UNSET) {
-			dt_set_errno(dtp, EDT_DESTRUCTIVE);
-			goto fail;
-		}
-
 		fd = dt_bpf_load_prog(dtp, prp, dp, cflags);
 		if (fd == -1)
 			goto fail;
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index a1eff8efe..0593a497a 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -1876,6 +1876,7 @@ dt_cg_clsflags(dt_pcb_t *pcb, dtrace_actkind_t kind, const dt_node_t *dnp)
 
 	if (DTRACEACT_ISDESTRUCTIVE(kind)) {
 		*cfp |= DT_CLSFLAG_DESTRUCT;
+		pcb->pcb_hdl->dt_destructive |= 1;
 
 		if (kind == DTRACEACT_RETURN)
 			*cfp |= DT_CLSFLAG_RETURN;
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index bf4f6c7bd..7300af6ad 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -367,6 +367,7 @@ struct dtrace_hdl {
 	char *dt_sysslice;	/* the systemd system slice: set via -xsysslice */
 	uint_t dt_lazyload;	/* boolean:  set via -xlazyload */
 	uint_t dt_droptags;	/* boolean:  set via -xdroptags */
+	uint_t dt_destructive;	/* have any destructive actions */
 	uint_t dt_active;	/* boolean:  set once tracing is active */
 	uint_t dt_stopped;	/* boolean:  set once tracing is stopped */
 	processorid_t dt_beganon; /* CPU that executed BEGIN probe (if any) */
diff --git a/test/unittest/options/err.no-w-or-destructive2.d b/test/unittest/options/err.no-w-or-destructive2.d
new file mode 100644
index 000000000..c0a8486c2
--- /dev/null
+++ b/test/unittest/options/err.no-w-or-destructive2.d
@@ -0,0 +1,26 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2025, 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.
+ */
+
+/*
+ * ASSERTION: Without -w or -xdestructive, destructive operations are not ok,
+ *            even if a clause will be ignored (since the associated probe
+ *            does not exist at the point of initial program construction
+ *            and loading).
+ *
+ * SECTION: Options and Tunables/Consumer Options
+ */
+/* @@runtest-opts: -Z */
+
+BEGIN
+{
+	exit(0);
+}
+
+bogus:bogus:bogus:bogus
+{
+	system("echo ok");
+}
diff --git a/test/unittest/options/err.no-w-or-destructive2.r b/test/unittest/options/err.no-w-or-destructive2.r
new file mode 100644
index 000000000..1a6959475
--- /dev/null
+++ b/test/unittest/options/err.no-w-or-destructive2.r
@@ -0,0 +1,3 @@
+-- @@stderr --
+dtrace: script 'test/unittest/options/err.no-w-or-destructive2.d' matched 1 probe
+dtrace: could not enable tracing: Destructive actions not allowed
diff --git a/test/unittest/usdt/err.Z_no-w.r b/test/unittest/usdt/err.Z_no-w.r
deleted file mode 100644
index b81622481..000000000
--- a/test/unittest/usdt/err.Z_no-w.r
+++ /dev/null
@@ -1,4 +0,0 @@
-dtrace is running so start the trigger
-dtrace died as expected after trigger started
--- @@stderr --
-dtrace: processing aborted: Destructive actions not allowed
diff --git a/test/unittest/usdt/err.Z_no-w.sh b/test/unittest/usdt/err.Z_no-w.sh
deleted file mode 100755
index 4f129341d..000000000
--- a/test/unittest/usdt/err.Z_no-w.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/bash
-#
-# Oracle Linux DTrace.
-# Copyright (c) 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.
-#
-# This test verifies that dtrace will not run a destructive script
-# for USDT probes if -w is not specified.
-#
-# Specifically, the script is launched with -Z and no USDT processes are
-# initially present.  Only once a USDT process is detected does dtrace
-# fail due to the destructive action.
-
-dtrace=$1
-trigger=`pwd`/test/triggers/usdt-tst-defer
-
-# Set up test directory.
-
-DIRNAME=$tmpdir/Z_no-w.$$.$RANDOM
-mkdir -p $DIRNAME
-cd $DIRNAME
-
-# Make a private copy of the trigger executable so that we get our
-# own DOF stash.
-
-cp $trigger main
-
-# Run dtrace.
-
-$dtrace $dt_flags -Zq -o dtrace.out -n '
-testprov*:::foo
-{
-	raise(SIGUSR1);
-}' &
-dtpid=$!
-
-# Wait up to half of the timeout period for dtrace to start up.
-
-iter=$((timeout / 2))
-while [ $iter -gt 0 ]; do
-	sleep 1
-	if [ -e dtrace.out ]; then
-		break
-	fi
-	iter=$((iter - 1))
-done
-if [[ $iter -eq 0 ]]; then
-	echo ERROR starting DTrace job
-	cat dtrace.out
-	exit 1
-fi
-
-# Start a trigger process.
-
-echo dtrace is running so start the trigger
-./main > main.out &
-pid=$!
-
-# Check again if dtrace is still running.
-
-sleep 2
-if [[ ! -d /proc/$dtpid ]]; then
-	echo dtrace died as expected after trigger started
-else
-	echo dtrace is unexpectedly still running
-	kill -9 $dtpid
-	wait    $dtpid
-fi
-
-# Tell the trigger to proceed to completion.
-
-kill -USR1 $pid
-wait       $pid
-
-exit 1
-- 
2.43.5




More information about the DTrace-devel mailing list