lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <d8112193-0386-4e14-b516-37c2d838171a@nvidia.com>
Date: Wed, 27 Nov 2024 18:39:53 +0000
From: Jon Hunter <jonathanh@...dia.com>
To: Furong Xu <0x1207@...il.com>, netdev@...r.kernel.org,
 linux-stm32@...md-mailman.stormreply.com,
 linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org
Cc: Alexandre Torgue <alexandre.torgue@...s.st.com>,
 Jose Abreu <joabreu@...opsys.com>, "David S. Miller" <davem@...emloft.net>,
 Eric Dumazet <edumazet@...gle.com>, Jakub Kicinski <kuba@...nel.org>,
 Paolo Abeni <pabeni@...hat.com>, Maxime Coquelin
 <mcoquelin.stm32@...il.com>, xfr@...look.com,
 Suraj Jaiswal <quic_jsuraj@...cinc.com>, Thierry Reding
 <treding@...dia.com>,
 "linux-tegra@...r.kernel.org" <linux-tegra@...r.kernel.org>
Subject: Re: [PATCH net v1] net: stmmac: TSO: Fix unbalanced DMA map/unmap for
 non-paged SKB data

Hi Furong,

On 21/10/2024 07:10, Furong Xu wrote:
> In case the non-paged data of a SKB carries protocol header and protocol
> payload to be transmitted on a certain platform that the DMA AXI address
> width is configured to 40-bit/48-bit, or the size of the non-paged data
> is bigger than TSO_MAX_BUFF_SIZE on a certain platform that the DMA AXI
> address width is configured to 32-bit, then this SKB requires at least
> two DMA transmit descriptors to serve it.
> 
> For example, three descriptors are allocated to split one DMA buffer
> mapped from one piece of non-paged data:
>      dma_desc[N + 0],
>      dma_desc[N + 1],
>      dma_desc[N + 2].
> Then three elements of tx_q->tx_skbuff_dma[] will be allocated to hold
> extra information to be reused in stmmac_tx_clean():
>      tx_q->tx_skbuff_dma[N + 0],
>      tx_q->tx_skbuff_dma[N + 1],
>      tx_q->tx_skbuff_dma[N + 2].
> Now we focus on tx_q->tx_skbuff_dma[entry].buf, which is the DMA buffer
> address returned by DMA mapping call. stmmac_tx_clean() will try to
> unmap the DMA buffer _ONLY_IF_ tx_q->tx_skbuff_dma[entry].buf
> is a valid buffer address.
> 
> The expected behavior that saves DMA buffer address of this non-paged
> data to tx_q->tx_skbuff_dma[entry].buf is:
>      tx_q->tx_skbuff_dma[N + 0].buf = NULL;
>      tx_q->tx_skbuff_dma[N + 1].buf = NULL;
>      tx_q->tx_skbuff_dma[N + 2].buf = dma_map_single();
> Unfortunately, the current code misbehaves like this:
>      tx_q->tx_skbuff_dma[N + 0].buf = dma_map_single();
>      tx_q->tx_skbuff_dma[N + 1].buf = NULL;
>      tx_q->tx_skbuff_dma[N + 2].buf = NULL;
> 
> On the stmmac_tx_clean() side, when dma_desc[N + 0] is closed by the
> DMA engine, tx_q->tx_skbuff_dma[N + 0].buf is a valid buffer address
> obviously, then the DMA buffer will be unmapped immediately.
> There may be a rare case that the DMA engine does not finish the
> pending dma_desc[N + 1], dma_desc[N + 2] yet. Now things will go
> horribly wrong, DMA is going to access a unmapped/unreferenced memory
> region, corrupted data will be transmited or iommu fault will be
> triggered :(
> 
> In contrast, the for-loop that maps SKB fragments behaves perfectly
> as expected, and that is how the driver should do for both non-paged
> data and paged frags actually.
> 
> This patch corrects DMA map/unmap sequences by fixing the array index
> for tx_q->tx_skbuff_dma[entry].buf when assigning DMA buffer address.
> 
> Tested and verified on DWXGMAC CORE 3.20a
> 
> Reported-by: Suraj Jaiswal <quic_jsuraj@...cinc.com>
> Fixes: f748be531d70 ("stmmac: support new GMAC4")
> Signed-off-by: Furong Xu <0x1207@...il.com>
> ---
>   .../net/ethernet/stmicro/stmmac/stmmac_main.c | 22 ++++++++++++++-----
>   1 file changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index d3895d7eecfc..208dbc68aaf9 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -4304,11 +4304,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
>   	if (dma_mapping_error(priv->device, des))
>   		goto dma_map_err;
>   
> -	tx_q->tx_skbuff_dma[first_entry].buf = des;
> -	tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
> -	tx_q->tx_skbuff_dma[first_entry].map_as_page = false;
> -	tx_q->tx_skbuff_dma[first_entry].buf_type = STMMAC_TXBUF_T_SKB;
> -
>   	if (priv->dma_cap.addr64 <= 32) {
>   		first->des0 = cpu_to_le32(des);
>   
> @@ -4327,6 +4322,23 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
>   
>   	stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);
>   
> +	/* In case two or more DMA transmit descriptors are allocated for this
> +	 * non-paged SKB data, the DMA buffer address should be saved to
> +	 * tx_q->tx_skbuff_dma[].buf corresponding to the last descriptor,
> +	 * and leave the other tx_q->tx_skbuff_dma[].buf as NULL to guarantee
> +	 * that stmmac_tx_clean() does not unmap the entire DMA buffer too early
> +	 * since the tail areas of the DMA buffer can be accessed by DMA engine
> +	 * sooner or later.
> +	 * By saving the DMA buffer address to tx_q->tx_skbuff_dma[].buf
> +	 * corresponding to the last descriptor, stmmac_tx_clean() will unmap
> +	 * this DMA buffer right after the DMA engine completely finishes the
> +	 * full buffer transmission.
> +	 */
> +	tx_q->tx_skbuff_dma[tx_q->cur_tx].buf = des;
> +	tx_q->tx_skbuff_dma[tx_q->cur_tx].len = skb_headlen(skb);
> +	tx_q->tx_skbuff_dma[tx_q->cur_tx].map_as_page = false;
> +	tx_q->tx_skbuff_dma[tx_q->cur_tx].buf_type = STMMAC_TXBUF_T_SKB;
> +
>   	/* Prepare fragments */
>   	for (i = 0; i < nfrags; i++) {
>   		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];


I have noticed a lot of intermittent failures on a couple of our boards
starting with Linux v6.12. I have finally bisected the issue to this
change and reverting this change fixes the problem.

The boards where I am seeing this issue on are our Tegra186 Jetson TX2
(tegra186-p2771-0000) and Tegra194 Jetson AGX Xavier
(tegra194-p2972-0000).

Tegra184 has:
  dwc-eth-dwmac 2490000.ethernet: User ID: 0x10, Synopsys ID: 0x41

Tegra194 has:
  dwc-eth-dwmac 2490000.ethernet: User ID: 0x10, Synopsys ID: 0x50

Otherwise all the other propreties printed on boot are the same for both ...

  dwc-eth-dwmac 2490000.ethernet: 	DWMAC4/5
  dwc-eth-dwmac 2490000.ethernet: DMA HW capability register supported
  dwc-eth-dwmac 2490000.ethernet: RX Checksum Offload Engine supported
  dwc-eth-dwmac 2490000.ethernet: TX Checksum insertion supported
  dwc-eth-dwmac 2490000.ethernet: Wake-Up On Lan supported
  dwc-eth-dwmac 2490000.ethernet: TSO supported
  dwc-eth-dwmac 2490000.ethernet: Enable RX Mitigation via HW Watchdog Timer
  dwc-eth-dwmac 2490000.ethernet: Enabled L3L4 Flow TC (entries=8)
  dwc-eth-dwmac 2490000.ethernet: Enabled RFS Flow TC (entries=10)
  dwc-eth-dwmac 2490000.ethernet: TSO feature enabled
  dwc-eth-dwmac 2490000.ethernet: Using 40/40 bits DMA host/device width


Looking at the console logs, when the problem occurs I see the
following prints ...

[  245.571688] dwc-eth-dwmac 2490000.ethernet eth0: Tx DMA map failed
[  245.575349] dwc-eth-dwmac 2490000.ethernet eth0: Tx DMA map failed

I also caught this crash ...

[  245.576690] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008
[  245.576715] Mem abort info:
[  245.577009]   ESR = 0x0000000096000004
[  245.577040]   EC = 0x25: DABT (current EL), IL = 32 bits
[  245.577142]   SET = 0, FnV = 0
[  245.577355]   EA = 0, S1PTW = 0
[  245.577439]   FSC = 0x04: level 0 translation fault
[  245.577557] Data abort info:
[  245.577628]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[  245.577753]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[  245.577878]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[  245.578018] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000106300000
[  245.578168] [0000000000000008] pgd=0000000000000000, p4d=0000000000000000
[  245.578390] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
[  245.578528] Modules linked in: snd_soc_tegra210_admaif snd_soc_tegra_pcm tegra_drm snd_soc_tegra186_asrc snd_soc_tegra210_mixer snd_soc_tegra210_mvc snd_soc_tegra210_ope snd_soc_tegra210_dmic drm_dp_aux_bus snd_soc_tegra210_adx snd_soc_tegra210_amx cec snd_soc_tegra210_sfc drm_display_helper snd_soc_tegra210_i2s drm_kms_helper snd_soc_tegra_audio_graph_card ucsi_ccg typec_ucsi snd_soc_rt5659 snd_soc_audio_graph_card drm backlight tegra210_adma snd_soc_tegra210_ahub crct10dif_ce snd_soc_simple_card_utils pwm_fan snd_soc_rl6231 typec ina3221 snd_hda_codec_hdmi tegra_aconnect pwm_tegra snd_hda_tegra snd_hda_codec snd_hda_core phy_tegra194_p2u tegra_xudc at24 lm90 pcie_tegra194 host1x tegra_bpmp_thermal ip_tables x_tables ipv6
[  245.626942] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Tainted: G        W          6.12.0 #5
[  245.635072] Tainted: [W]=WARN
[  245.638220] Hardware name: NVIDIA Jetson AGX Xavier Developer Kit (DT)
[  245.645039] pstate: 40400009 (nZcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  245.651870] pc : skb_release_data+0x100/0x1e4
[  245.656334] lr : sk_skb_reason_drop+0x44/0xb0
[  245.660797] sp : ffff800080003c80
[  245.664206] x29: ffff800080003c80 x28: ffff000083d58980 x27: 0000000000000900
[  245.671813] x26: ffff000083d5c980 x25: ffff0000937c03c0 x24: 0000000000000002
[  245.678906] x23: 00000000ffffffff x22: 0000000000000001 x21: ffff000096ae8200
[  245.686258] x20: 0000000000000000 x19: 0000000000000000 x18: 0000000000004860
[  245.693605] x17: ffff80037be97000 x16: ffff800080000000 x15: ffff8000827d4968
[  245.700870] x14: fffffffffffe485f x13: 2e656572662d7265 x12: 7466612d65737520
[  245.707957] x11: ffff8000827d49e8 x10: ffff8000827d49e8 x9 : 00000000ffffefff
[  245.715306] x8 : ffff80008282c9e8 x7 : 0000000000017fe8 x6 : 00000000fffff000
[  245.722825] x5 : ffff0003fde07348 x4 : ffff0000937c03c0 x3 : ffff0000937c0280
[  245.729762] x2 : 0000000000000140 x1 : ffff0000937c03c0 x0 : 0000000000000000
[  245.737009] Call trace:
[  245.739459]  skb_release_data+0x100/0x1e4
[  245.743657]  sk_skb_reason_drop+0x44/0xb0
[  245.747684]  dev_kfree_skb_any_reason+0x44/0x50
[  245.752490]  stmmac_tx_clean+0x1ec/0x798
[  245.756177]  stmmac_napi_poll_tx+0x6c/0x144
[  245.760199]  __napi_poll+0x38/0x190
[  245.763868]  net_rx_action+0x140/0x294
[  245.767888]  handle_softirqs+0x120/0x24c
[  245.771574]  __do_softirq+0x14/0x20
[  245.775326]  ____do_softirq+0x10/0x1c
[  245.778748]  call_on_irq_stack+0x24/0x4c
[  245.782510]  do_softirq_own_stack+0x1c/0x2c
[  245.786964]  irq_exit_rcu+0x8c/0xc4
[  245.790463]  el1_interrupt+0x38/0x68
[  245.794139]  el1h_64_irq_handler+0x18/0x24
[  245.798166]  el1h_64_irq+0x64/0x68
[  245.801318]  default_idle_call+0x28/0x3c
[  245.805166]  do_idle+0x208/0x264
[  245.808576]  cpu_startup_entry+0x34/0x3c
[  245.812088]  kernel_init+0x0/0x1d8
[  245.815594]  start_kernel+0x5c0/0x708
[  245.819076]  __primary_switched+0x80/0x88
[  245.823295] Code: 97fff632 72001c1f 54000161 370005b3 (f9400661)
[  245.829151] ---[ end trace 0000000000000000 ]---


And here is another crash ...

[  149.986210] dwc-eth-dwmac 2490000.ethernet eth0: Tx DMA map failed
[  149.992845] kernel BUG at lib/dynamic_queue_limits.c:99!
[  149.998152] Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP
[  150.004928] Modules linked in: snd_soc_tegra210_admaif snd_soc_tegra186_asrc snd_soc_tegra_pcm snd_soc_tegra210_mixer snd_soc_tegra210_mvc snd_soc_tegra210_ope snd_soc_tegra210_dmic snd_soc_tegra186_dspk snd_soc_tegra210_adx snd_soc_tegra210_amx snd_soc_tegra210_sfc snd_soc_tegra210_i2s tegra_drm drm_dp_aux_bus cec drm_display_helper drm_kms_helper tegra210_adma snd_soc_tegra210_ahub drm backlight snd_soc_tegra_audio_graph_card snd_soc_audio_graph_card snd_soc_simple_card_utils crct10dif_ce tegra_bpmp_thermal at24 tegra_aconnect snd_hda_codec_hdmi tegra_xudc snd_hda_tegra snd_hda_codec snd_hda_core ina3221 host1x ip_tables x_tables ipv6
[  150.061268] CPU: 5 UID: 102 PID: 240 Comm: systemd-resolve Tainted: G S      W          6.12.0-dirty #7
[  150.070654] Tainted: [S]=CPU_OUT_OF_SPEC, [W]=WARN
[  150.075438] Hardware name: NVIDIA Jetson TX2 Developer Kit (DT)
[  150.081348] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[  150.088303] pc : dql_completed+0x1fc/0x20c
[  150.092401] lr : stmmac_tx_clean+0x3b4/0x798
[  150.096669] sp : ffff800082d73d00
[  150.099979] x29: ffff800082d73d00 x28: ffff000080898980 x27: 0000000000002ce0
[  150.107115] x26: ffff00008089c980 x25: 0000000000000000 x24: ffff000083c88000
[  150.114248] x23: 0000000000000000 x22: 0000000000000001 x21: ffff000080898980
[  150.121380] x20: 0000000000000000 x19: 0000000000000168 x18: 0000000000006540
[  150.128513] x17: ffff800172d32000 x16: ffff800082d70000 x15: ffff8000827d4968
[  150.135646] x14: fffffffffffe653f x13: 2e656572662d7265 x12: 7466612d65737520
[  150.142781] x11: ffff8000827d49e8 x10: ffff8000827d49e8 x9 : 0000000000000000
[  150.149913] x8 : 000000000003ca11 x7 : 0000000000017fe8 x6 : 000000000003ca11
[  150.157046] x5 : ffff000080d09140 x4 : ffff0001f4cb0840 x3 : 000000000010fe05
[  150.164181] x2 : 0000000000000000 x1 : 000000000000004a x0 : ffff000083c88080
[  150.171314] Call trace:
[  150.173757]  dql_completed+0x1fc/0x20c
[  150.177507]  stmmac_napi_poll_tx+0x6c/0x144
[  150.181688]  __napi_poll+0x38/0x190
[  150.185174]  net_rx_action+0x140/0x294
[  150.188921]  handle_softirqs+0x120/0x24c
[  150.192843]  __do_softirq+0x14/0x20
[  150.196328]  ____do_softirq+0x10/0x1c
[  150.199987]  call_on_irq_stack+0x24/0x4c
[  150.203908]  do_softirq_own_stack+0x1c/0x2c
[  150.208088]  do_softirq+0x54/0x6c
[  150.211401]  __local_bh_enable_ip+0x8c/0x98
[  150.215583]  __dev_queue_xmit+0x4e4/0xd6c
[  150.219588]  ip_finish_output2+0x4cc/0x5e8
[  150.223682]  __ip_finish_output+0xac/0x17c
[  150.227776]  ip_finish_output+0x34/0x10c
[  150.231696]  ip_output+0x68/0xfc
[  150.234921]  __ip_queue_xmit+0x16c/0x464
[  150.238840]  ip_queue_xmit+0x14/0x20
[  150.242413]  __tcp_transmit_skb+0x490/0xc4c
[  150.246593]  tcp_connect+0xa08/0xdbc
[  150.250167]  tcp_v4_connect+0x35c/0x494
[  150.253999]  __inet_stream_connect+0xf8/0x3c8
[  150.258354]  inet_stream_connect+0x48/0x70
[  150.262447]  __sys_connect+0xe0/0xfc
[  150.266021]  __arm64_sys_connect+0x20/0x30
[  150.270113]  invoke_syscall+0x48/0x110
[  150.273860]  el0_svc_common.constprop.0+0xc8/0xe8
[  150.278561]  do_el0_svc+0x20/0x2c
[  150.281875]  el0_svc+0x30/0xd0
[  150.284929]  el0t_64_sync_handler+0x13c/0x158
[  150.289282]  el0t_64_sync+0x190/0x194
[  150.292945] Code: 7a401860 5400008b 2a0403e3 17ffff9c (d4210000)
[  150.299033] ---[ end trace 0000000000000000 ]---
[  150.303647] Kernel panic - not syncing: Oops - BUG: Fatal exception in interrupt

Let me know if you need any more information.

Thanks
Jon

-- 
nvpublic


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ