Skip to content

Memory corruption on USDHC non-DMA transfer when D-Cache enabled #20

@tchebb

Description

@tchebb

The USDHC data interrupt handler, USDHC_TransferHandleData(), contains an unconditional D-Cache invalidate on completed USDHC transfer, presumably to ensure the CPU sees data written by DMA if the line was pulled back into the cache since the clean+invalidate in USDHC_TransferNonBlocking():

#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
if (handle->data->rxData != NULL)
{
DCACHE_InvalidateByRange((uintptr_t)(handle->data->rxData),
(handle->data->blockSize) * (handle->data->blockCount));
}
#endif

But that causes significant memory unsafety: if the transfer did not use DMA, the transfer function never cleaned it to begin with, meaning the new invalidate discards writes elsewhere in that line from an arbitrarily long period prior to the transfer! This happens when the if branch here is taken:

/* if the DMA desciptor configure fail or not needed , disable it */
if (error != kStatus_Success)
{
/* disable DMA, using polling mode in this situation */
USDHC_EnableInternalDMA(base, false);
enDMA = false;
}
#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL
else
{
if (data->txData != NULL)
{
/* clear the DCACHE */
DCACHE_CleanByRange((uintptr_t)data->txData, (data->blockSize) * (data->blockCount));
}
else
{
/* clear the DCACHE */
DCACHE_CleanInvalidateByRange((uintptr_t)data->rxData, (data->blockSize) * (data->blockCount));
}
}
#endif

In fact, I don't believe the invalidate is safe even when DMA is used: I don't see any requirement that DMA buffers be the only thing in their cache line, so it may still discard writes, just over a bounded time period.

I have a 100% reproducible crash in Zephyr due to stack corruption caused by this bug when using the Infineon AIROC Wi-Fi driver on an i.MX RT1061.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions