Commit ebbd3cc9 authored by Nikita Yushchenko's avatar Nikita Yushchenko Committed by Wen Zhiwei
Browse files

net: renesas: rswitch: fix possible early skb release

stable inclusion
from stable-v6.6.70
commit 43e3aa2f44d60421c3e0d14bf92c72a195015486
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBOHV1

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=43e3aa2f44d60421c3e0d14bf92c72a195015486



--------------------------------

[ Upstream commit 5cb099902b6b6292b3a85ffa1bb844e0ba195945 ]

When sending frame split into multiple descriptors, hardware processes
descriptors one by one, including writing back DT values. The first
descriptor could be already marked as completed when processing of
next descriptors for the same frame is still in progress.

Although only the last descriptor is configured to generate interrupt,
completion of the first descriptor could be noticed by the driver when
handling interrupt for the previous frame.

Currently, driver stores skb in the entry that corresponds to the first
descriptor. This results into skb could be unmapped and freed when
hardware did not complete the send yet. This opens a window for
corrupting the data being sent.

Fix this by saving skb in the entry that corresponds to the last
descriptor used to send the frame.

Fixes: d2c96b9d5f83 ("net: rswitch: Add jumbo frames handling for TX")
Signed-off-by: default avatarNikita Yushchenko <nikita.yoush@cogentembedded.com>
Reviewed-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Link: https://patch.msgid.link/20241208095004.69468-2-nikita.yoush@cogentembedded.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent 60d9612b
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -1632,8 +1632,9 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
	if (dma_mapping_error(ndev->dev.parent, dma_addr_orig))
		goto err_kfree;

	gq->skbs[gq->cur] = skb;
	gq->unmap_addrs[gq->cur] = dma_addr_orig;
	/* Stored the skb at the last descriptor to avoid skb free before hardware completes send */
	gq->skbs[(gq->cur + nr_desc - 1) % gq->ring_size] = skb;
	gq->unmap_addrs[(gq->cur + nr_desc - 1) % gq->ring_size] = dma_addr_orig;

	dma_wmb();