[DTrace-devel] [PATCH] cg: fix store/load for struct and union members for alloca pointers

Kris Van Hees kris.van.hees at oracle.com
Thu Aug 31 02:54:27 UTC 2023


Storing to and loading from struct or unnion members of alloca pointers
was not properly turning the alloca pointer into a real pointer, nor was
it performing boundary checks.

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

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 40df8d65..95dd57ad 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -3051,7 +3051,7 @@ dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
 	int		dreg = dst->dn_reg;
 
 	/*
-	 * If we're loading a bit-field, the size of our store is found by
+	 * If we're storing into a bit-field, the size of our store is found by
 	 * rounding dst's cte_bits up to a byte boundary and then finding the
 	 * nearest power of two to this value (see clp2(), above).
 	 */
@@ -3062,13 +3062,18 @@ dt_cg_store(dt_node_t *src, dt_irlist_t *dlp, dt_regset_t *drp, dt_node_t *dst)
 		size = dt_node_type_size(dst);
 
 	/*
-	 * If we're loading a writable non-alloca lvalue, and it's a
+	 * If we're storing into a writable non-alloca lvalue, and it's a
 	 * dereference, and *its* child is an alloca pointer, then this is a
 	 * dereferenced alloca pointer and needs bounds-checking (which could
 	 * not be done at deref time due to not knowing the size of the write).
+	 *
+	 * If we're storing into a writable alloca lvalue, we know it needs
+	 * bounds-checking as well.
 	 */
-	if (dst->dn_flags & DT_NF_WRITABLE && dst->dn_flags & DT_NF_LVALUE
-	    && dst->dn_op == DT_TOK_DEREF && dst->dn_child->dn_flags & DT_NF_ALLOCA) {
+	if (dst->dn_flags & DT_NF_WRITABLE && dst->dn_flags & DT_NF_LVALUE &&
+	    ((dst->dn_op == DT_TOK_DEREF &&
+	      dst->dn_child->dn_flags & DT_NF_ALLOCA) ||
+	     dst->dn_flags & DT_NF_ALLOCA)) {
 		assert(!(dst->dn_flags & DT_NF_BITFIELD));
 
 		if ((dreg = dt_regset_alloc(drp)) == -1)
@@ -6480,8 +6485,20 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 
 			op = dt_cg_ldsize(dnp, ctfp, m.ctm_type, &size);
 
+			/*
+			 * If the left-hand side of PTR or DOT is an alloca
+			 * pointer, bounds-check the pointer reference.
+			 */
+			if (dnp->dn_left->dn_flags & DT_NF_ALLOCA) {
+				assert(dnp->dn_flags & DT_NF_ALLOCA);
+				dt_cg_alloca_access_check(dlp, drp, dnp->dn_reg,
+							  DT_ISIMM, size);
+				dt_cg_alloca_ptr(dlp, drp, dnp->dn_reg,
+						 dnp->dn_reg);
+			}
+
 			if (dnp->dn_left->dn_flags & (DT_NF_ALLOCA | DT_NF_DPTR))
-				emit(dlp, BPF_LOAD(op, dnp->dn_left->dn_reg, dnp->dn_left->dn_reg, 0));
+				emit(dlp, BPF_LOAD(op, dnp->dn_reg, dnp->dn_reg, 0));
 			else
 				dt_cg_load_scalar(dnp->dn_left, op, size, dlp, drp);
 		}
-- 
2.40.1




More information about the DTrace-devel mailing list