Re: [PATCH net-next 04/12] net: stmmac: dma: create a separate dma_device pointer

Alex Elder <[email protected]> Fri, 29 May 2026 21:04:30 -0500
Newsgroups dev.linux.lists.sashiko,org.kernel.vger.bpf
Message-ID <[email protected]>
On 5/2/26 10:56 AM, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] DMA mappings are permanently leaked if an error occurs mid-packet in `stmmac_xmit`, `stmmac_tso_xmit`, or `jumbo_frm`.
> - [High] In `jumbo_frm()` (`chain_mode.c` and `ring_mode.c`), assigning a `dma_addr_t` to an `unsigned int` breaks `dma_mapping_error()` detection.
> --
> 
> commit 152df859f4e94baeb0ca419c5b87bcb9e5f13d3d
> Author: Alex Elder <[email protected]>
> 
> net: stmmac: dma: create a separate dma_device pointer
> 
> This commit adds a second dma_device pointer to the stmmac_priv structure.
> The new pointer handles all DMA operations independently from the normal
> device pointer, allowing better management of common internal IPs for
> specialized Ethernet bridge chips.
> 
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
>> index fc04a23342cf..331e6523ee01 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/chain_mode.c
>> @@ -34,10 +34,10 @@ static int jumbo_frm(struct stmmac_tx_queue *tx_q, struct sk_buff *skb,
>>   	buf_len = min_t(unsigned int, nopaged_len, bmax);
>>   	len = nopaged_len - buf_len;
>>   
>> -	des2 = dma_map_single(priv->device, skb->data,
>> +	des2 = dma_map_single(priv->dma_device, skb->data,
>>   			      buf_len, DMA_TO_DEVICE);
>>   	desc->des2 = cpu_to_le32(des2);
>> -	if (dma_mapping_error(priv->device, des2))
>> +	if (dma_mapping_error(priv->dma_device, des2))
> 
> This isn't a bug introduced by this patch, but since the patch modifies these
> DMA mapping calls, it brings up a potential issue.
> 
> Does the use of an unsigned int for des2 break error detection?
> 
> On 64-bit architectures, dma_map_single() returns a 64-bit dma_addr_t.
> Assigning this to the unsigned int des2 truncates the upper 32 bits.

I think this is a legitimate report.  I will follow up with a
separate patch that will change the type of the variable holding
the value returned by dma_map_single() to be dma_addr_t so it
doesn't affect the validity of dma_mapping_error().

> If the mapping fails, it returns an error code that becomes 0xFFFFFFFF after
> truncation. When this truncated value is passed to dma_mapping_error(), it
> is cast back to a 64-bit value, which no longer matches the expected error
> code representation.
> 
> Will this bypass the error check and record an invalid physical address in
> tx_q->tx_skbuff_dma[entry].buf? This same pattern also appears in the
> jumbo_frm() function in ring_mode.c.
> 
> [ ... ]
>> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> index ca68248dbc78..1104cf750295 100644
>> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
>> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> [ ... ]
>> @@ -4876,9 +4876,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>>   
>>   		desc = stmmac_get_tx_desc(priv, tx_q, entry);
>>   
>> -		dma_addr = skb_frag_dma_map(priv->device, frag, 0, frag_size,
>> -					    DMA_TO_DEVICE);
>> -		if (dma_mapping_error(priv->device, dma_addr))
>> +		dma_addr = skb_frag_dma_map(priv->dma_device, frag, 0,
>> +					    frag_size, DMA_TO_DEVICE);
>> +		if (dma_mapping_error(priv->dma_device, dma_addr))
>>   			goto dma_map_err; /* should reuse desc w/o issues */
> 
> Similarly, can this leak DMA mappings if an error occurs mid-packet?

It looks to me like it could.  I don't know this code especially
well, but if the loop iterates more than once, and skb_frag_dma_map()
returns an error, it seems the mappings should be "unwound" at
the dma_map_err label.  I'll look at this as something to address
in a separate patch too, but it's a little trickier than the first
suggestion.

					-Alex
> If skb_frag_dma_map() fails for a multi-fragment packet, the code jumps
> to the dma_map_err label. However, tx_q->cur_tx is only updated at the very
> end of the function upon complete success.
> 
> Because cur_tx is not advanced on the error path, stmmac_tx_clean() won't
> unmap these partially filled descriptor entries. On the next transmission,
> the driver will start at the unmodified cur_tx index and blindly overwrite
> the tx_skbuff_dma entries.
> 
> Could this result in permanently leaking the previously successful DMA
> mappings? The same concern appears to apply to stmmac_tso_xmit() and
> jumbo_frm() where multiple fragments are mapped sequentially.
> 
> [ ... ]
>