[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