[DTrace-devel] [PATCH] Fix size of string data in the trace output buffer

Eugene Loh eugene.loh at oracle.com
Wed Sep 8 07:52:53 PDT 2021


On 9/8/21 2:30 AM, Kris Van Hees wrote:

> On Wed, Sep 08, 2021 at 12:49:12AM -0400, Eugene Loh wrote:
>> Also, does dt_cg_store_var() have the same issues?
> No, this is only really needed for store_val because of how the consumer
> handles strings.

Let's put it this way:  dt_cg_store_var() has issues.  Perhaps they are 
not the "same" issues since they have nothing to do with the consumer, 
but the fix (replacing a straight copy with a custom prefix+data+NULL 
construction) would be the same.  E.g., you have a test case:
     #pragma D option strsize=5
     BEGIN
     {
         trace(probeprov);
     }
If we modified that to be:
     #pragma D option strsize=5
     BEGIN
     {
         p = "dtrace";
         trace(p);
     }
the BPF verifier would erupt.  I think that's because in 
dt_cg_store_var(), we assume we'll have enough space to copy over the 
string.  We probably need, instead, well, basically the same fix you 
give in this patch.  If you like, I can propose a patch.  Or, we can 
wait... especially if the length prefix is going away anyhow.

>
>> On 9/7/21 8:37 PM, Kris Van Hees wrote:
>>>    		dt_regset_xalloc(drp, BPF_REG_0);
>>>    		emit(dlp,  BPF_CALL_HELPER(BPF_FUNC_probe_read));
>>>    		dt_regset_free_args(drp);
>>> -		dt_regset_free(drp, BPF_REG_0);
>>> +
>>> +		/*
>>> +		 * Write the NUL terminating byte in case we are truncating.
>>> +		 */
>>> +		emit(dlp,  BPF_MOV_REG(BPF_REG_0, BPF_REG_9));
>>> +		emit(dlp,  BPF_ALU64_REG(BPF_ADD, BPF_REG_0, reg));
>>> +		emit(dlp,  BPF_STORE_IMM(BPF_B, BPF_REG_0, off + DT_STRLEN_BYTES, 0));
>> I sure do not understand the register management here.  Earlier, you use
>> %r0 for writing the length prefix, but never xalloc'ing the register.
>> Here, you xalloc(r0) but you removed the free(r0).  Isn't that wrong?
>> But I tried iterating on this and it appears someone else is freeing the
>> register?  Who?  I'm confused.
> Ah, I forgot to paste the freeing of %r0 apparently - good catch.

Thanks, but this sort of thing should be caught automatically.  I think 
what was happening was that since we were not checking the return from 
dt_regset_xalloc(%r0), we just reused and respilled the same register 
over and over again.  So, we should probably:

1)  Check the return value of regset alloc() (here and wherever else 
that check has been omitted).

2)  Or perhaps just push the longjmp(NOREG) down into dt_regset.c, both 
making sure the error is caught and reducing the boilerplate code of 
checking the return.




More information about the DTrace-devel mailing list