[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 16:27:45 UTC 2023


On Thu, Aug 31, 2023 at 12:20:49PM -0400, Eugene Loh via DTrace-devel wrote:
> I'm not sure I follow alloca-taint logic well enough to review this.  Maybe
> Nick can take a peek?

This actually does not have anything to do with the taint :)

> Also, did you say you had tests for this?  They should be included in the
> patch.  Once the inet_ntop patch has been added (after this patch), there
> will be a test, but more basic and thorough test coverage as a part of the
> current patch would be even better. Particularly since more than one code
> path is being modified.

Well, yes.. and I don't know why they are not in this one...  Let me post v2
after carefully reviewing that they are actually part of the patch.

> And a few other things...
> 
> On 8/30/23 22:54, Kris Van Hees via DTrace-devel wrote:
> > Storing to and loading from struct or unnion members of alloca pointers
> 
> union
> 
> > 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
> 
> non-alloca?  IIUC, we do not check that.  So, the "non-alloca" comment does
> not agree with what the code is doing?
> 
> In general, this comment doesn't make things any clearer than what the code
> says and so does not have much value;  it can be pruned down.
> 
> And I'm not sure of the logic... this is perhaps where Nick can chime in.
> 
> >   	 * 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));
> 
> Okay on s/dn_left->//, but then there is another instance where this change
> should be made as well, right above this code at "if (m.ctm_offset != 0)".
> 
> >   			else
> >   				dt_cg_load_scalar(dnp->dn_left, op, size, dlp, drp);
> >   		}
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list