Skip to content

It is not possible to pass the ID of the garbage collection when the .NET provider is enabled with the GCHeapCollect(0x800000) keyword #102572

Closed
@chrisnas

Description

@chrisnas

Description

It is possible to trigger a garbage collection by enabling the .NET runtime provider with the GCHeapCollect(0x800000) keyword and an Informal verbosity. In the payload, an id can provided and it is supposed to be passed to ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber) as a custom collection id; unrelated to the normal incremented one.
However, this id is not well parsed in the CLR
Discussed with @noahfalk and @brianrob

Reproduction Steps

  • the payload contains a string such as "id=42" (see an example from the diagnostics client)
  • in provider_invoke_callback, this string is stored into a buffer to get rrid of = and ; characters. So, "Id=42" becomes "Id\042\0"
  • next, ep_event_filter_desc_init() used that buffer to fill up the 3 fields of the EventFilterDescriptor that is used later (see next step)
uint64_t ptr = address of the buffer
uint32_t size = size of the buffer (=6 for id\042\0)
uint32_t type = 0
  • finally, EtwCallbackCommon receives the filterdata and tries the following to get the collection id:
PEVENT_FILTER_DESCRIPTOR FilterData = (PEVENT_FILTER_DESCRIPTOR)pFilterData;
if ((FilterData != NULL) &&
   (FilterData->Type == 1) &&
   (FilterData->Size == sizeof(l64ClientSequenceNumber)))
{
    l64ClientSequenceNumber = *(LONGLONG *) (FilterData->Ptr);
}

it will fail because:

  • the received type value is 0
  • the received size is not the size of a 64 bit number
  • the ptr field does not point to the value as 64 bit number (but as a string)

Expected behavior

I don't know if things are different for ETW but I'm expecting the buffer pointed to by Ptr to be parsed to:

  • extract the key and compare it with a well known string such as "ClientSequenceNumber"
  • extract the value and convert it as a 64 bit number

Actual behavior

The client sequence number cannot be set

Regression?

I don't know if it works for .NET Framework

Known Workarounds

No workaround

Configuration

I'm reproducing with .NET 8

Other information

The following code should fix the problem in EtwCallbackCommon():

if ((FilterData != NULL) && (FilterData->Type == 0))
{
    // look for the value without checking the provided id
    char* clientSequenceNumberAsString = (char*)FilterData->Ptr;
    clientSequenceNumberAsString += strlen(clientSequenceNumberAsString) + 1;

    // extract the client sequence number from the string
    int result = sscanf_s(clientSequenceNumberAsString, "%u", &l64ClientSequenceNumber, FilterData->Size - (strlen((char*)FilterData->Ptr) + 1));
    if (result == 1)
    {
        //  use the client sequence number
    }
}

Metadata

Metadata

Assignees

Labels

area-Tracing-coreclrin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions