[DTrace-devel] [PATCH] cg, parser: fix handling of alloca()'d string values

Kris Van Hees kris.van.hees at oracle.com
Sat Feb 18 01:33:00 UTC 2023


When alloca()'d memory is used as a string, special handling is needed
to ensure variable assignment and storing in the output buffer works
correctly.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                             | 19 ++++++++++---
 libdtrace/dt_parser.c                         | 10 ++++---
 .../actions/printf/tst.conv_s_alloca_var.d    | 22 +++++++++++++++
 .../actions/printf/tst.conv_s_alloca_var.r    |  1 +
 .../actions/printf/tst.conv_s_copyin.d        | 27 +++++++++++++++++++
 .../actions/printf/tst.conv_s_copyin.r        |  3 +++
 .../actions/printf/tst.conv_s_copyinstr.d     | 27 +++++++++++++++++++
 .../actions/printf/tst.conv_s_copyinstr.r     |  3 +++
 .../funcs/bcopy/err.bcopy-into-string.d       | 18 +++++++++++++
 .../funcs/bcopy/tst.bcopy-into-alloca.d       | 21 +++++++++++++++
 .../funcs/bcopy/tst.bcopy-into-alloca.r       |  1 +
 .../bcopy/tst.bcopy-into-string-indirect.d    | 21 +++++++++++++++
 .../bcopy/tst.bcopy-into-string-indirect.r    |  1 +
 13 files changed, 166 insertions(+), 8 deletions(-)
 create mode 100644 test/unittest/actions/printf/tst.conv_s_alloca_var.d
 create mode 100644 test/unittest/actions/printf/tst.conv_s_alloca_var.r
 create mode 100644 test/unittest/actions/printf/tst.conv_s_copyin.d
 create mode 100644 test/unittest/actions/printf/tst.conv_s_copyin.r
 create mode 100644 test/unittest/actions/printf/tst.conv_s_copyinstr.d
 create mode 100644 test/unittest/actions/printf/tst.conv_s_copyinstr.r
 create mode 100644 test/unittest/funcs/bcopy/err.bcopy-into-string.d
 create mode 100644 test/unittest/funcs/bcopy/tst.bcopy-into-alloca.d
 create mode 100644 test/unittest/funcs/bcopy/tst.bcopy-into-alloca.r
 create mode 100644 test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.d
 create mode 100644 test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.r

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 8e767c2f..0b8cc80a 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -1163,7 +1163,7 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
 		size_t	strsize = pcb->pcb_hdl->dt_options[DTRACEOPT_STRSIZE];
 
 		if (!not_null)
-			dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
+			dt_cg_check_ptr_arg(dlp, drp, dnp, NULL);
 
 		TRACE_REGSET("store_val(): Begin ");
 		off = dt_rec_add(pcb->pcb_hdl, dt_cg_fill_gap, kind, size + 1,
@@ -3009,7 +3009,19 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
 			srcsz = dt_node_type_size(dnp->dn_right);
 			size = MIN(srcsz, idp->di_size);
 
+			dt_cg_check_ptr_arg(dlp, drp, dnp->dn_right, NULL);
 			dt_cg_memcpy(dlp, drp, reg, dnp->dn_reg, size);
+
+			/*
+			 * Since strings are passed by value, we need to force
+			 * the value of the assignment to be the destination
+			 * address.
+			 */
+			if (dt_node_is_string(dnp)) {
+				dt_regset_free(drp, dnp->dn_reg);
+				dnp->dn_reg = reg;
+			} else
+				dt_regset_free(drp, reg);
 		} else {
 			size = idp->di_size;
 
@@ -3017,10 +3029,9 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
 			       (size & (size - 1)) == 0);
 
 			emit(dlp, BPF_STORE(ldstw[size], reg, idp->di_offset, dnp->dn_reg));
+			dt_regset_free(drp, reg);
 		}
 
-		dt_regset_free(drp, reg);
-
 		TRACE_REGSET("    store_var: End  ");
 
 		return;
@@ -5412,7 +5423,7 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 
 	case DT_TOK_STRINGOF:
 		dt_cg_node(dnp->dn_child, dlp, drp);
-		dt_cg_check_ptr_arg(dlp, drp, dnp->dn_child, NULL);
+		dt_cg_check_notnull(dlp, drp, dnp->dn_child->dn_reg);
 		dnp->dn_reg = dnp->dn_child->dn_reg;
 		break;
 
diff --git a/libdtrace/dt_parser.c b/libdtrace/dt_parser.c
index c718680e..e4d6a062 100644
--- a/libdtrace/dt_parser.c
+++ b/libdtrace/dt_parser.c
@@ -3855,11 +3855,13 @@ asgn_common:
 			lp_idp = lp->dn_ident;
 
 		/*
-		 * Transfer alloca taint.  Stores of non-alloca, non-literal-0
-		 * values turn on DT_IDFLG_NONALLOCA to prevent this identifier
-		 * from being used for alloca storage anywhere in the program.
+		 * Transfer alloca taint unless the value is a string because
+		 * those are assigned by value.
+		 * Stores of non-alloca, non-literal-0 values turn on
+		 * DT_IDFLG_NONALLOCA to prevent this identifier from being
+		 * used for alloca storage anywhere in the program.
 		 */
-		if (rp->dn_flags & DT_NF_ALLOCA)
+		if (rp->dn_flags & DT_NF_ALLOCA && !dt_node_is_string(rp))
 			dt_cook_taint_alloca(lp, lp_idp, rp);
 		else if (lp_idp && !(rp->dn_kind == DT_NODE_INT && rp->dn_value == 0))
 			lp_idp->di_flags |= DT_IDFLG_NONALLOCA;
diff --git a/test/unittest/actions/printf/tst.conv_s_alloca_var.d b/test/unittest/actions/printf/tst.conv_s_alloca_var.d
new file mode 100644
index 00000000..7a32cfc5
--- /dev/null
+++ b/test/unittest/actions/printf/tst.conv_s_alloca_var.d
@@ -0,0 +1,22 @@
+/*
+ * Oracle Linux DTrace.
+ * 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.
+ */
+
+/*
+ * ASSERTION: The printf action supports '%s' for alloca()'d string variables.
+ *
+ * SECTION: Actions/printf()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	s = alloca(10);
+	bcopy(probename, s, 5);
+	printf("'%s'", (string)s);
+	exit(0);
+}
diff --git a/test/unittest/actions/printf/tst.conv_s_alloca_var.r b/test/unittest/actions/printf/tst.conv_s_alloca_var.r
new file mode 100644
index 00000000..a1880528
--- /dev/null
+++ b/test/unittest/actions/printf/tst.conv_s_alloca_var.r
@@ -0,0 +1 @@
+'BEGIN'
diff --git a/test/unittest/actions/printf/tst.conv_s_copyin.d b/test/unittest/actions/printf/tst.conv_s_copyin.d
new file mode 100644
index 00000000..11e7745f
--- /dev/null
+++ b/test/unittest/actions/printf/tst.conv_s_copyin.d
@@ -0,0 +1,27 @@
+/*
+ * Oracle Linux DTrace.
+ * 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.
+ */
+
+/*
+ * ASSERTION: The printf action supports '%s' for copyin()'d string values.
+ *
+ * SECTION: Actions/printf()
+ */
+/* @@trigger: delaydie */
+
+#pragma D option quiet
+
+syscall::write:entry
+/pid == $target/
+{
+	printf("'%s'", (string)copyin(arg1, 32));
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/actions/printf/tst.conv_s_copyin.r b/test/unittest/actions/printf/tst.conv_s_copyin.r
new file mode 100644
index 00000000..16e2bbcc
--- /dev/null
+++ b/test/unittest/actions/printf/tst.conv_s_copyin.r
@@ -0,0 +1,3 @@
+'Delay in ns needed in delay env '
+-- @@stderr --
+Delay in ns needed in delay env var.
diff --git a/test/unittest/actions/printf/tst.conv_s_copyinstr.d b/test/unittest/actions/printf/tst.conv_s_copyinstr.d
new file mode 100644
index 00000000..ee4f9a79
--- /dev/null
+++ b/test/unittest/actions/printf/tst.conv_s_copyinstr.d
@@ -0,0 +1,27 @@
+/*
+ * Oracle Linux DTrace.
+ * 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.
+ */
+
+/*
+ * ASSERTION: The printf action supports '%s' for copyinstr()'d values.
+ *
+ * SECTION: Actions/printf()
+ */
+/* @@trigger: delaydie */
+
+#pragma D option quiet
+
+syscall::write:entry
+/pid == $target/
+{
+	printf("'%s'", copyinstr(arg1, 32));
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
diff --git a/test/unittest/actions/printf/tst.conv_s_copyinstr.r b/test/unittest/actions/printf/tst.conv_s_copyinstr.r
new file mode 100644
index 00000000..7e80ec2d
--- /dev/null
+++ b/test/unittest/actions/printf/tst.conv_s_copyinstr.r
@@ -0,0 +1,3 @@
+'Delay in ns needed in delay env'
+-- @@stderr --
+Delay in ns needed in delay env var.
diff --git a/test/unittest/funcs/bcopy/err.bcopy-into-string.d b/test/unittest/funcs/bcopy/err.bcopy-into-string.d
new file mode 100644
index 00000000..4529a609
--- /dev/null
+++ b/test/unittest/funcs/bcopy/err.bcopy-into-string.d
@@ -0,0 +1,18 @@
+/*
+ * Oracle Linux DTrace.
+ * 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.
+ */
+
+/*
+ * ASSERTION: A bcopy() into an alloca()'d string variable yields an error.
+ *
+ * SECTION: Actions and Subroutines/bcopy()
+ */
+
+BEGIN {
+	s = (string)alloca(10);
+	bcopy(probename, s, 5);
+	exit(0);
+}
diff --git a/test/unittest/funcs/bcopy/tst.bcopy-into-alloca.d b/test/unittest/funcs/bcopy/tst.bcopy-into-alloca.d
new file mode 100644
index 00000000..ff57bda6
--- /dev/null
+++ b/test/unittest/funcs/bcopy/tst.bcopy-into-alloca.d
@@ -0,0 +1,21 @@
+/*
+ * Oracle Linux DTrace.
+ * 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.
+ */
+
+/*
+ * ASSERTION: A bcopy() into an alloca()'d space can be used as a string.
+ *
+ * SECTION: Actions and Subroutines/bcopy()
+ */
+
+#pragma D option quiet
+
+BEGIN {
+	s = alloca(10);
+	bcopy(probename, s, 5);
+	trace((string)s);
+	exit(0);
+}
diff --git a/test/unittest/funcs/bcopy/tst.bcopy-into-alloca.r b/test/unittest/funcs/bcopy/tst.bcopy-into-alloca.r
new file mode 100644
index 00000000..1bf4c3f4
--- /dev/null
+++ b/test/unittest/funcs/bcopy/tst.bcopy-into-alloca.r
@@ -0,0 +1 @@
+BEGIN
diff --git a/test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.d b/test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.d
new file mode 100644
index 00000000..0161e7e2
--- /dev/null
+++ b/test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.d
@@ -0,0 +1,21 @@
+/*
+ * Oracle Linux DTrace.
+ * 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.
+ */
+
+/*
+ * ASSERTION: A bcopy() into an alloca()'d space can be used as a string.
+ *
+ * SECTION: Actions and Subroutines/bcopy()
+ */
+
+#pragma D option quiet
+
+BEGIN {
+	s = alloca(0);
+	bcopy(probename, alloca(10), 5);
+	trace((string)s);
+	exit(0);
+}
diff --git a/test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.r b/test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.r
new file mode 100644
index 00000000..1bf4c3f4
--- /dev/null
+++ b/test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.r
@@ -0,0 +1 @@
+BEGIN
-- 
2.39.1




More information about the DTrace-devel mailing list