[DTrace-devel] [PATCH 32/47] Ensure that local variables get a 0 value upon first load

Kris Van Hees kris.van.hees at oracle.com
Sun May 3 20:17:52 PDT 2020


Local variables are stored on the stack and BPF does not allow loading
from an uninitialized stack location.  Since D expects variables to
have value 0 prior to first use, we can just pretend the load happened
and instead emit an instruction storing 0 in the destination register.

Orabug: 31220527
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c                             | 13 +++++++++++--
 .../codegen/tst.load_before_store_lvar.d      | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)
 create mode 100644 test/unittest/codegen/tst.load_before_store_lvar.d

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 39ba1f6d..60037b9a 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -799,8 +799,17 @@ dt_cg_load_var(dt_node_t *dst, dt_irlist_t *dlp, dt_regset_t *drp)
 
 	idp->di_flags |= DT_IDFLG_DIFR;
 	if (idp->di_flags & DT_IDFLG_LOCAL) {		/* local var */
-		instr = BPF_LOAD(BPF_DW, dst->dn_reg, BPF_REG_FP,
-				 DT_STK_LVAR(idp->di_id));
+		/*
+		 * If this is the first read for this local variable, we know
+		 * the value is 0.  This avoids storing an initial 0 value in
+		 * the variable's stack location.
+		 */
+		if (!(idp->di_flags & DT_IDFLG_DIFW))
+			instr = BPF_MOV_IMM(dst->dn_reg, 0);
+		else
+			instr = BPF_LOAD(BPF_DW, dst->dn_reg, BPF_REG_FP,
+					 DT_STK_LVAR(idp->di_id));
+
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
 	} else if (idp->di_flags & DT_IDFLG_TLS) {	/* TLS var */
 		dt_regset_xalloc(drp, BPF_REG_1);
diff --git a/test/unittest/codegen/tst.load_before_store_lvar.d b/test/unittest/codegen/tst.load_before_store_lvar.d
new file mode 100644
index 00000000..12bb3565
--- /dev/null
+++ b/test/unittest/codegen/tst.load_before_store_lvar.d
@@ -0,0 +1,19 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2020, 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: Test that a load-before-store pattern for a local variable forces
+ *	      the local variable to be initialized prior to loading.
+ * FAILURE:   If the initialization is not done, the BPF verifier will reject
+  *	      the program due to reading from an uninitialized stack location.
+ */
+
+BEGIN
+{
+	++this->x;
+	exit(0);
+}
-- 
2.26.0




More information about the DTrace-devel mailing list