[DTrace-devel] [PATCH] cg: ensure string results in a ternary are padded to strsize

Kris Van Hees kris.van.hees at oracle.com
Fri Feb 7 06:11:05 UTC 2025


The result of a string ternary was copied from either left or right
value using a memcpy() of strsize, but that could result in garbage
being included in the result beyond the terminating 0-byte of the
string value.  If the result was e.g. assigned to a char-array
translator member, that garbage could affect consumer output.

The ternary will now copy the string using dt_cg_strcpy() which ensures
that any string < strsize will be padded with 0-bytes up to strsize.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c | 68 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 16 deletions(-)

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index a5c9aa09..b48e27f0 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -1371,6 +1371,19 @@ dt_cg_fill_gap(dt_pcb_t *pcb, int gap)
 		emit(dlp, BPF_STORE_IMM(BPF_W, BPF_REG_9, off, 0));
 }
 
+/*
+ * Store a pointer to the 'memory block of zeros' in reg.
+ */
+static void
+dt_cg_zerosptr(int reg, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+	dtrace_hdl_t	*dtp = yypcb->pcb_hdl;
+	dt_ident_t	*zero_off = dt_dlib_get_var(dtp, "ZERO_OFF");
+
+	dt_cg_access_dctx(reg, dlp, drp, DCTX_STRTAB);
+	emite(dlp, BPF_ALU64_IMM(BPF_ADD, reg, -1), zero_off);
+}
+
 static void
 dt_cg_memcpy(dt_irlist_t *dlp, dt_regset_t *drp, int dst, int src, size_t size)
 {
@@ -1394,6 +1407,43 @@ dt_cg_memcpy(dt_irlist_t *dlp, dt_regset_t *drp, int dst, int src, size_t size)
 	dt_regset_free(drp, BPF_REG_0);
 }
 
+/*
+ * Copy a string from the pointer stored in the src register to the pointer
+ * stored in the dst register.  At most strsize characters will be copied, and
+ * if the source string is less than strsize characters, the remainder will be
+ * filled with 0s.
+ */
+static void
+dt_cg_strcpy(dt_irlist_t *dlp, dt_regset_t *drp, int dst, int src)
+{
+	dtrace_hdl_t	*dtp = yypcb->pcb_hdl;
+	uint_t		lbl_ok = dt_irlist_label(dlp);
+	size_t		size = dtp->dt_options[DTRACEOPT_STRSIZE];
+
+	if (dt_regset_xalloc_args(drp) == -1)
+		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+	emit(dlp,  BPF_MOV_REG(BPF_REG_1, dst));
+	emit(dlp,  BPF_MOV_IMM(BPF_REG_2, size));
+	emit(dlp,  BPF_MOV_REG(BPF_REG_3, src));
+	dt_regset_xalloc(drp, BPF_REG_0);
+	emit(dlp,  BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel_str]));
+
+	emit(dlp,  BPF_BRANCH_IMM(BPF_JSGE, BPF_REG_0, 0, lbl_ok));
+	dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, DT_ISREG, src);
+
+	emitl(dlp, lbl_ok,
+		   BPF_NOP());
+	emit(dlp,  BPF_MOV_REG(BPF_REG_1, dst));
+	emit(dlp,  BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0));
+	emit(dlp,  BPF_MOV_IMM(BPF_REG_2, size));
+	emit(dlp,  BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_0));
+	dt_cg_zerosptr(BPF_REG_3, dlp, drp);
+	emit(dlp,  BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_kernel]));
+	dt_regset_free(drp, BPF_REG_0);
+	dt_regset_free_args(drp);
+}
+
 static void
 dt_cg_spill_store(int reg)
 {
@@ -3040,19 +3090,6 @@ dt_cg_pop_stack(int reg, dt_irlist_t *dlp, dt_regset_t *drp)
 	dt_regset_free(drp, treg);
 }
 
-/*
- * Store a pointer to the 'memory block of zeros' in reg.
- */
-static void
-dt_cg_zerosptr(int reg, dt_irlist_t *dlp, dt_regset_t *drp)
-{
-	dtrace_hdl_t	*dtp = yypcb->pcb_hdl;
-	dt_ident_t	*zero_off = dt_dlib_get_var(dtp, "ZERO_OFF");
-
-	dt_cg_access_dctx(reg, dlp, drp, DCTX_STRTAB);
-	emite(dlp, BPF_ALU64_IMM(BPF_ADD, reg, -1), zero_off);
-}
-
 /*
  * Generate code to promote signed scalars (size < 64 bits) to native register
  * size (64 bits).
@@ -4603,7 +4640,7 @@ dt_cg_ternary_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	 * dn_right).
 	 */
 	if (dt_node_is_string(dnp)) {
-		uint_t lbl_null = dt_irlist_label(dlp);
+		uint_t	lbl_null = dt_irlist_label(dlp);
 
 		emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, dnp->dn_reg, 0, lbl_null));
 
@@ -4619,8 +4656,7 @@ dt_cg_ternary_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 		dt_cg_access_dctx(dnp->dn_reg, dlp, drp, DCTX_MEM);
 		emit(dlp,  BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, dnp->dn_tstring->dn_value));
 
-		dt_cg_memcpy(dlp, drp, dnp->dn_reg, BPF_REG_0,
-			     yypcb->pcb_hdl->dt_options[DTRACEOPT_STRSIZE]);
+		dt_cg_strcpy(dlp, drp, dnp->dn_reg, BPF_REG_0);
 
 		emitl(dlp, lbl_null,
 			   BPF_NOP());
-- 
2.45.2




More information about the DTrace-devel mailing list