[DTrace-devel] [PATCH 1/3] Add support for the link_ntop() subroutine

Eugene Loh eugene.loh at oracle.com
Thu Dec 14 18:44:51 UTC 2023


On 12/13/23 00:03, Eugene Loh wrote:

> On 12/11/23 23:39, Kris Van Hees wrote:
>
>> On Mon, Dec 11, 2023 at 05:03:05PM -0500, Eugene Loh via DTrace-devel 
>> wrote:
>>> On 12/9/23 00:29, Kris Van Hees wrote:
>>>
>>>> On Tue, Aug 29, 2023 at 09:54:31PM -0400, eugene.loh at oracle.com wrote:
>>>>> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
>>>>> +
>>>>> +static void
>>>>> +dt_cg_subr_link_ntop(dt_node_t *dnp, dt_irlist_t *dlp, 
>>>>> dt_regset_t *drp)
>>>>> +{
>>>>> +    dt_node_t    *type = dnp->dn_args;
>>>>> +    uint_t        Lokay = dt_irlist_label(dlp);
>>>>> +
>>>>> +    /* Determine type and check it is okay. */
>>>>> +    dt_cg_node(type, dlp, drp);
>>>>> +    emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, type->dn_reg, 
>>>>> ARPHRD_INFINIBAND, Lokay));
>>>>> +    emit(dlp,  BPF_BRANCH_IMM(BPF_JEQ, type->dn_reg, 
>>>>> ARPHRD_ETHER, Lokay));
>>>>> +    dt_cg_probe_error(yypcb, DTRACEFLT_ILLOP, DT_ISREG, 
>>>>> type->dn_reg);
>>>>> +    emitl(dlp, Lokay,
>>>>> +           BPF_NOP());
>>>>> +
>>>>> +    /* Move addr into dnp->dn_args so we can call 
>>>>> dt_cg_subr_arg_to_tstring(). */
>>>>> +    dnp->dn_args = type->dn_list;
>>>> You probably should do this in a way that after the 
>>>> dt_cg_subr_arg_to_tstring()
>>>> call, you can restore the node structure.  I.e. dnp->dn_args = 
>>>> type.  That way,
>>>> depending on what type is, dt_node_free() will ensure proper 
>>>> cleanup is done
>>>> when dt_node_free( is done on dnp.
>>> Okay.
>>>
>>>> But worse, this causes the dt_cg_check_ptr_arg() in 
>>>> dt_cg_subr_arg_to_tstring()
>>>> to get bypassed (and thus err.link_ntopbadaddr.d fails) because you 
>>>> move the
>>>> 2nd argument into the 1st argument spot, and then 
>>>> dt_cg_subr_arg_to_tstring()
>>>> checks the type of the *1st* argument of link_type() according to its
>>>> prototype.  And since that is not a pointer, the check is never done.
>>> I don't follow.  dt_cg_subr_arg_to_tstring() checks the type of its 
>>> 1st arg,
>>> which is the 2nd arg to link_ntop().  E.g., for 
>>> err.link_ntopbadaddr.d, it's
>>> a pointer.  So that 2nd link_ntop() arg *is* a pointer, we do in 
>>> fact run
>>> dt_cg_check_ptr_arg(), the NULL pointer is rejected, and the test 
>>> passes.
>> The type is checked based on what the prototype of link_ntop() 
>> provides, not
>> based on the type of the passed argument.  See 
>> dt_cg_subr_arg_to_tstring():
>>
>>          isp = dnp->dn_ident->di_data;
>>          assert(isp && isp->dis_args);
>>          argtype = &isp->dis_args[0];
>>
>>          /* handle the one "input value" */
>>          /* (its type matters only as to whether we check it is null */
>>          dt_cg_node(arg, dlp, drp);
>>          if (dt_node_is_pointer(argtype) || dt_node_is_string(argtype))
>>                  dt_cg_check_ptr_arg(dlp, drp, arg, NULL);
>>
>> So, in this case you pass the 2nd argument of link_ntop(), but the 
>> check is
>> done on the expected type of the first argument of link_ntop() which 
>> is an
>> integer.
>
> Ah, "new" code (that I reviewed!) since the patch was first posted. 
> Which explains why the badaddr test started failing.
>
> Here's an alternative proposal.  dt_cg_subr_arg_to_tstring() kind of 
> takes a subroutine arg, does ptr checks, and converts it to a tstring 
> by calling a BPF function.  It can pass other arguments to the BPF 
> function, and it is sometimes used for subroutines with more than one 
> arg, but something feels "minor" about those other args. FWIW, 
> dt_cg_subr_arg_to_tstring() claims to limit them to 32-bit ints.
>
> So how about I add another arg to dt_cg_subr_arg_to_tstring() giving 
> the arg number of the subroutine where to grab the main arg. Usually, 
> this is going to be 0.  For link_ntop(int, void*), however, we just 
> say that the arg number is 1:  we want the second subroutine arg.
>
> This means that dt_cg_subr_link_ntop() doesn't need to vet the string 
> ptr or juggle args around.  And dt_cg_subr_arg_to_tstring() just needs 
> to access dis_args[argnum] instead of just dis_args[0]. And chase 
> "while(argnum-- > 0) arg = arg->dn_list;".
>
> I have a modified patch, but wanted to run the idea past you before 
> posting a v2.  Or, I can just post the v2 if you like.

I posted the v2.

Note:  This patch was originally 1/3 (the patch and then two trivial, 
mildly related changes).  I think patches 2 and 3 are still awaiting 
review.  The v2 of this patch is preceded by two other patches.  So, v1 
was 1/3, while v2 is 3/3 (the third of a 3-patch series).

>>> Is err.link_ntopbadaddr.d really failing?
>> Yes.
>>
>>>> Rather than remapping the args (exchanging type and addr), I think 
>>>> you need
>>>> to keep them as they are, and do (assuming addr = dnp->dn_args):
>>> How can we assume addr=dnp->dn_args?  The first arg of link_ntop() 
>>> -- that
>>> is, dnp->dn_args -- is the type.
>> Sorry, my mistake.  But you know what I mean by addr - the actual HW 
>> address.
>>
>>>>     dt_cg_node(addr, dlp, drp);
>>>>     dt_cg_check_ptr_arg(dlp, drp, addr, NULL);
>>>>     dt_cg_subr_arg_to_tstring(dnp, dlp, drp, "dt_link_ntop", 
>>>> DT_ISREG, addr->dn_reg, DT_IGNOR, 0);
>>>>
>>>> But then you do need to rework dt_link_ntop to accept type as the 
>>>> main argument
>>>> and addr as the extra argument.
>>>>
>>>>> +
>>>>> +    dt_cg_subr_arg_to_tstring(dnp, dlp, drp, "dt_link_ntop", 
>>>>> DT_ISREG, type->dn_reg);
>>>>> +    dt_regset_free(drp, type->dn_reg);
>>>>> +}



More information about the DTrace-devel mailing list