* [PATCH net v2 resend 1/4] net: renesas: rswitch: fix possible early skb release
2024-12-08 9:50 [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
@ 2024-12-08 9:50 ` Nikita Yushchenko
2024-12-08 9:50 ` [PATCH net v2 resend 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Nikita Yushchenko @ 2024-12-08 9:50 UTC (permalink / raw)
To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Geert Uytterhoeven
Cc: netdev, linux-renesas-soc, linux-kernel, Michael Dege,
Christian Mardmoeller, Dennis Ostermann, Nikita Yushchenko
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: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
---
drivers/net/ethernet/renesas/rswitch.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index b80aa27a7214..32b32aa7e01f 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -1681,8 +1681,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;
/* DT_FSTART should be set at last. So, this is reverse order. */
for (i = nr_desc; i-- > 0; ) {
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH net v2 resend 2/4] net: renesas: rswitch: fix race window between tx start and complete
2024-12-08 9:50 [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
2024-12-08 9:50 ` [PATCH net v2 resend 1/4] net: renesas: rswitch: fix possible early skb release Nikita Yushchenko
@ 2024-12-08 9:50 ` Nikita Yushchenko
2024-12-08 9:50 ` [PATCH net v2 resend 3/4] net: renesas: rswitch: fix leaked pointer on error path Nikita Yushchenko
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Nikita Yushchenko @ 2024-12-08 9:50 UTC (permalink / raw)
To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Geert Uytterhoeven
Cc: netdev, linux-renesas-soc, linux-kernel, Michael Dege,
Christian Mardmoeller, Dennis Ostermann, Nikita Yushchenko
If hardware is already transmitting, it can start handling the
descriptor being written to immediately after it observes updated DT
field, before the queue is kicked by a write to GWTRC.
If the start_xmit() execution is preempted at unfortunate moment, this
transmission can complete, and interrupt handled, before gq->cur gets
updated. With the current implementation of completion, this will cause
the last entry not completed.
Fix that by changing completion loop to check DT values directly, instead
of depending on gq->cur.
Fixes: 3590918b5d07 ("net: ethernet: renesas: Add support for "Ethernet Switch"")
Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
---
drivers/net/ethernet/renesas/rswitch.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index 32b32aa7e01f..c251becef6f8 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -862,13 +862,10 @@ static void rswitch_tx_free(struct net_device *ndev)
struct rswitch_ext_desc *desc;
struct sk_buff *skb;
- for (; rswitch_get_num_cur_queues(gq) > 0;
- gq->dirty = rswitch_next_queue_index(gq, false, 1)) {
- desc = &gq->tx_ring[gq->dirty];
- if ((desc->desc.die_dt & DT_MASK) != DT_FEMPTY)
- break;
-
+ desc = &gq->tx_ring[gq->dirty];
+ while ((desc->desc.die_dt & DT_MASK) == DT_FEMPTY) {
dma_rmb();
+
skb = gq->skbs[gq->dirty];
if (skb) {
rdev->ndev->stats.tx_packets++;
@@ -879,7 +876,10 @@ static void rswitch_tx_free(struct net_device *ndev)
dev_kfree_skb_any(gq->skbs[gq->dirty]);
gq->skbs[gq->dirty] = NULL;
}
+
desc->desc.die_dt = DT_EEMPTY;
+ gq->dirty = rswitch_next_queue_index(gq, false, 1);
+ desc = &gq->tx_ring[gq->dirty];
}
}
@@ -1685,6 +1685,8 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
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();
+
/* DT_FSTART should be set at last. So, this is reverse order. */
for (i = nr_desc; i-- > 0; ) {
desc = &gq->tx_ring[rswitch_next_queue_index(gq, true, i)];
@@ -1695,8 +1697,6 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
goto err_unmap;
}
- wmb(); /* gq->cur must be incremented after die_dt was set */
-
gq->cur = rswitch_next_queue_index(gq, true, nr_desc);
rswitch_modify(rdev->addr, GWTRC(gq->index), 0, BIT(gq->index % 32));
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH net v2 resend 3/4] net: renesas: rswitch: fix leaked pointer on error path
2024-12-08 9:50 [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
2024-12-08 9:50 ` [PATCH net v2 resend 1/4] net: renesas: rswitch: fix possible early skb release Nikita Yushchenko
2024-12-08 9:50 ` [PATCH net v2 resend 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
@ 2024-12-08 9:50 ` Nikita Yushchenko
2024-12-08 9:50 ` [PATCH net v2 resend 4/4] net: renesas: rswitch: avoid use-after-put for a device tree node Nikita Yushchenko
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Nikita Yushchenko @ 2024-12-08 9:50 UTC (permalink / raw)
To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Geert Uytterhoeven
Cc: netdev, linux-renesas-soc, linux-kernel, Michael Dege,
Christian Mardmoeller, Dennis Ostermann, Nikita Yushchenko
If error path is taken while filling descriptor for a frame, skb
pointer is left in the entry. Later, on the ring entry reuse, the
same entry could be used as a part of a multi-descriptor frame,
and skb for that new frame could be stored in a different entry.
Then, the stale pointer will reach the completion routine, and passed
to the release operation.
Fix that by clearing the saved skb pointer at the error path.
Fixes: d2c96b9d5f83 ("net: rswitch: Add jumbo frames handling for TX")
Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
---
drivers/net/ethernet/renesas/rswitch.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index c251becef6f8..af0bc95ad6ae 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -1703,6 +1703,7 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
return ret;
err_unmap:
+ gq->skbs[(gq->cur + nr_desc - 1) % gq->ring_size] = NULL;
dma_unmap_single(ndev->dev.parent, dma_addr_orig, skb->len, DMA_TO_DEVICE);
err_kfree:
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH net v2 resend 4/4] net: renesas: rswitch: avoid use-after-put for a device tree node
2024-12-08 9:50 [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
` (2 preceding siblings ...)
2024-12-08 9:50 ` [PATCH net v2 resend 3/4] net: renesas: rswitch: fix leaked pointer on error path Nikita Yushchenko
@ 2024-12-08 9:50 ` Nikita Yushchenko
2024-12-10 3:45 ` [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes Yoshihiro Shimoda
2024-12-11 3:10 ` patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: Nikita Yushchenko @ 2024-12-08 9:50 UTC (permalink / raw)
To: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Geert Uytterhoeven
Cc: netdev, linux-renesas-soc, linux-kernel, Michael Dege,
Christian Mardmoeller, Dennis Ostermann, Nikita Yushchenko
The device tree node saved in the rswitch_device structure is used at
several driver locations. So passing this node to of_node_put() after
the first use is wrong.
Move of_node_put() for this node to exit paths.
Fixes: b46f1e579329 ("net: renesas: rswitch: Simplify struct phy * handling")
Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
---
drivers/net/ethernet/renesas/rswitch.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index af0bc95ad6ae..3b57abada200 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -1891,7 +1891,6 @@ static int rswitch_device_alloc(struct rswitch_private *priv, unsigned int index
rdev->np_port = rswitch_get_port_node(rdev);
rdev->disabled = !rdev->np_port;
err = of_get_ethdev_address(rdev->np_port, ndev);
- of_node_put(rdev->np_port);
if (err) {
if (is_valid_ether_addr(rdev->etha->mac_addr))
eth_hw_addr_set(ndev, rdev->etha->mac_addr);
@@ -1921,6 +1920,7 @@ static int rswitch_device_alloc(struct rswitch_private *priv, unsigned int index
out_rxdmac:
out_get_params:
+ of_node_put(rdev->np_port);
netif_napi_del(&rdev->napi);
free_netdev(ndev);
@@ -1934,6 +1934,7 @@ static void rswitch_device_free(struct rswitch_private *priv, unsigned int index
rswitch_txdmac_free(ndev);
rswitch_rxdmac_free(ndev);
+ of_node_put(rdev->np_port);
netif_napi_del(&rdev->napi);
free_netdev(ndev);
}
--
2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread* RE: [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes
2024-12-08 9:50 [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
` (3 preceding siblings ...)
2024-12-08 9:50 ` [PATCH net v2 resend 4/4] net: renesas: rswitch: avoid use-after-put for a device tree node Nikita Yushchenko
@ 2024-12-10 3:45 ` Yoshihiro Shimoda
2024-12-11 3:10 ` patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: Yoshihiro Shimoda @ 2024-12-10 3:45 UTC (permalink / raw)
To: nikita.yoush, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Geert Uytterhoeven
Cc: netdev, linux-renesas-soc, linux-kernel, Michael Dege,
Christian Mardmoeller, Dennis Ostermann, nikita.yoush
Hello Nikita-san,
> From: Nikita Yushchenko, Sent: Sunday, December 8, 2024 6:50 PM
>
> This series fixes several glitches found in the rswitch driver.
>
> This repost fixes a mistake in the previous post at
<snip URL>
Thank you for your patches!
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Best regards,
Yoshihiro Shimoda
>
> Nikita Yushchenko (4):
> net: renesas: rswitch: fix possible early skb release
> net: renesas: rswitch: fix race window between tx start and complete
> net: renesas: rswitch: fix leaked pointer on error path
> net: renesas: rswitch: avoid use-after-put for a device tree node
>
> drivers/net/ethernet/renesas/rswitch.c | 25 ++++++++++++++-----------
> 1 file changed, 14 insertions(+), 11 deletions(-)
> ---
> v1:
<snip URL>
>
> Changes since v1:
> - changed target tree to net,
> - do not include patches that shall go via net-next,
> - added a new patch that fixes a race.
>
> --
> 2.39.5
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes
2024-12-08 9:50 [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
` (4 preceding siblings ...)
2024-12-10 3:45 ` [PATCH net v2 resend 0/4] net: renesas: rswitch: several fixes Yoshihiro Shimoda
@ 2024-12-11 3:10 ` patchwork-bot+netdevbpf
5 siblings, 0 replies; 7+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-12-11 3:10 UTC (permalink / raw)
To: Nikita Yushchenko
Cc: yoshihiro.shimoda.uh, andrew, davem, edumazet, kuba, pabeni,
geert+renesas, netdev, linux-renesas-soc, linux-kernel,
michael.dege, christian.mardmoeller, dennis.ostermann
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Sun, 8 Dec 2024 14:50:00 +0500 you wrote:
> This series fixes several glitches found in the rswitch driver.
>
> This repost fixes a mistake in the previous post at
> https://lore.kernel.org/netdev/20241206190015.4194153-1-nikita.yoush@cogentembedded.com/
>
> Nikita Yushchenko (4):
> net: renesas: rswitch: fix possible early skb release
> net: renesas: rswitch: fix race window between tx start and complete
> net: renesas: rswitch: fix leaked pointer on error path
> net: renesas: rswitch: avoid use-after-put for a device tree node
>
> [...]
Here is the summary with links:
- [net,v2,resend,1/4] net: renesas: rswitch: fix possible early skb release
https://git.kernel.org/netdev/net/c/5cb099902b6b
- [net,v2,resend,2/4] net: renesas: rswitch: fix race window between tx start and complete
https://git.kernel.org/netdev/net/c/0c9547e6ccf4
- [net,v2,resend,3/4] net: renesas: rswitch: fix leaked pointer on error path
https://git.kernel.org/netdev/net/c/bb617328bafa
- [net,v2,resend,4/4] net: renesas: rswitch: avoid use-after-put for a device tree node
https://git.kernel.org/netdev/net/c/66b7e9f85b84
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 7+ messages in thread