[DTrace-devel] [PATCH 2/2] Fix data size for value copy in dt_cg_store_var()
Eugene Loh
eugene.loh at oracle.com
Thu Sep 9 10:56:32 PDT 2021
On 9/9/21 1:29 AM, Eugene Loh wrote:
> On 9/8/21 5:07 PM, Kris Van Hees wrote:
>> The size of the data to be copied in dt_cg_store_var() was determined
>> wrongly. For strings constants we were copying the size of the string
>> constant even if that might be larger than the maximum string size.
>>
>> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
>> @@ -2245,29 +2246,28 @@ dt_cg_store_var(dt_node_t *src, dt_irlist_t
>> *dlp, dt_regset_t *drp,
>> emit(dlp, BPF_ALU64_IMM(BPF_ADD, reg, idp->di_offset));
>> /*
>> * Determine the amount of data to be copied. It is
>> - * usually the size of the identifier, except for
>> - * string constants where it is the size of the string
>> - * constant (adjusted for the variable-width length
>> - * prefix). An assignment of a string constant is a
>> - * store of type 'string' with a RHS of type
>> - * DT_TOK_STRING.
>> + * the lesser of the size of the identifier and the
>> + * size of the data being copied in.
>> */
>> - if (dt_node_is_string(src) &&
>> - src->dn_right->dn_op == DT_TOK_STRING)
>> - size = dt_node_type_size(src->dn_right) +
>> - DT_STRLEN_BYTES;
>> - else
>> - size = idp->di_size;
>> + srcsz = dt_node_type_size(src->dn_right);
>> + if (dt_node_is_string(src))
>> + srcsz += DT_STRLEN_BYTES;
>> + dstsz = idp->di_size;
>> + if (idp->di_ctfp == DT_STR_CTFP(dtp) &&
>> + idp->di_type == DT_STR_TYPE(dtp))
>> + dstsz += DT_STRLEN_BYTES;
>> + size = MIN(srcsz, dstsz);
>> dt_cg_memcpy(dlp, drp, reg, src->dn_reg, size);
>
> I'm not convinced I understand this stuff. It seems to me:
>
> *) The offsets in the gvar map for successive strings are STRSIZE
> apart... not STRSIZE+DT_STRLEN_BYTES apart. E.g., examine those
> idp->offset values.
>
> *) We copy in stuff that can be STRSIZE+DT_STRLEN_BYTES big. Wouldn't
> that overwrite another string or even outside the map?
Well, overwrite another gvar, whether or not it's a string. E.g.,
#pragma D option strsize=8
BEGIN
{
a = "ab";
b = 0xdeadbeeffeedface;
a = "abcdefghij";
printf("%x\n", b);
exit(0);
}
producing
CPU ID FUNCTION:NAME
2 1 :BEGIN deadbeeffeed6867
The string has overrun its storage by DT_STRLEN_BYTES (four hex digits).
> *) If we copy from the string table (which also has length prefixes
> on strings), we copy the length prefix over without editing it, even
> if we clipped the string. This means that the string length prefixes
> in gvar won't be right.
>
> E.g., the BPF verifier seems to complain about:
>
> #pragma D option strsize=5
> BEGIN
> {
> x = "abcd";
> y = "abcd";
> z = "abcd";
> }
>
> So far as I can tell, this stuff is buggy. The best thing to do, if
> the string length prefixes are going to disappear, is to eradicate
> them first and then clean this stuff up.
More information about the DTrace-devel
mailing list