* [PATCH net v2 0/4] net: renesas: rswitch: several fixes
@ 2024-12-06 19:00 Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 1/4] net: renesas: rswitch: fix possible early skb release Nikita Yushchenko
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Nikita Yushchenko @ 2024-12-06 19:00 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
This series fixes several glitches found in the rswitch driver.
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 | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
---
v1: https://lore.kernel.org/lkml/20241202134904.3882317-1-nikita.yoush@cogentembedded.com/
Changes since v1:
- changed target tree to -net,
- do not group together bugfixes and improvements so those could go via
different trees,
- added a new patch that fixes a race.
--
2.39.5
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH net v2 1/4] net: renesas: rswitch: fix possible early skb release
2024-12-06 19:00 [PATCH net v2 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
@ 2024-12-06 19:00 ` Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Nikita Yushchenko @ 2024-12-06 19:00 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 related [flat|nested] 8+ messages in thread
* [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete
2024-12-06 19:00 [PATCH net v2 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 1/4] net: renesas: rswitch: fix possible early skb release Nikita Yushchenko
@ 2024-12-06 19:00 ` Nikita Yushchenko
2024-12-06 19:18 ` Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 3/4] net: renesas: rswitch: fix leaked pointer on error path Nikita Yushchenko
` (2 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Nikita Yushchenko @ 2024-12-06 19:00 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.
3590918b5d07 ("net: ethernet: renesas: Add support for "Ethernet Switch"")
Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
---
drivers/net/ethernet/renesas/rswitch.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index 32b32aa7e01f..800744a6c25b 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,9 @@ 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(); /* ensure that hw won't start and complete before
+ skb pointer was saved */
+
/* 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 +1698,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 related [flat|nested] 8+ messages in thread
* [PATCH net v2 3/4] net: renesas: rswitch: fix leaked pointer on error path
2024-12-06 19:00 [PATCH net v2 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 1/4] net: renesas: rswitch: fix possible early skb release Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
@ 2024-12-06 19:00 ` Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 4/4] net: renesas: rswitch: avoid use-after-put for a device tree node Nikita Yushchenko
2024-12-06 19:16 ` [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
4 siblings, 0 replies; 8+ messages in thread
From: Nikita Yushchenko @ 2024-12-06 19:00 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 800744a6c25b..9c55f3480678 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -1704,6 +1704,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 related [flat|nested] 8+ messages in thread
* [PATCH net v2 4/4] net: renesas: rswitch: avoid use-after-put for a device tree node
2024-12-06 19:00 [PATCH net v2 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
` (2 preceding siblings ...)
2024-12-06 19:00 ` [PATCH net v2 3/4] net: renesas: rswitch: fix leaked pointer on error path Nikita Yushchenko
@ 2024-12-06 19:00 ` Nikita Yushchenko
2024-12-06 19:16 ` [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
4 siblings, 0 replies; 8+ messages in thread
From: Nikita Yushchenko @ 2024-12-06 19:00 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 9c55f3480678..57cf211ac1e1 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -1892,7 +1892,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);
@@ -1922,6 +1921,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);
@@ -1935,6 +1935,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 related [flat|nested] 8+ messages in thread
* [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete
2024-12-06 19:00 [PATCH net v2 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
` (3 preceding siblings ...)
2024-12-06 19:00 ` [PATCH net v2 4/4] net: renesas: rswitch: avoid use-after-put for a device tree node Nikita Yushchenko
@ 2024-12-06 19:16 ` Nikita Yushchenko
4 siblings, 0 replies; 8+ messages in thread
From: Nikita Yushchenko @ 2024-12-06 19:16 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 related [flat|nested] 8+ messages in thread
* Re: [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete
2024-12-06 19:00 ` [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
@ 2024-12-06 19:18 ` Nikita Yushchenko
2024-12-08 1:23 ` Jakub Kicinski
0 siblings, 1 reply; 8+ messages in thread
From: Nikita Yushchenko @ 2024-12-06 19:18 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
> 3590918b5d07 ("net: ethernet: renesas: Add support for "Ethernet Switch"")
Sorry this patch sent out broken, I've reposted it fixed.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete
2024-12-06 19:18 ` Nikita Yushchenko
@ 2024-12-08 1:23 ` Jakub Kicinski
0 siblings, 0 replies; 8+ messages in thread
From: Jakub Kicinski @ 2024-12-08 1:23 UTC (permalink / raw)
To: Nikita Yushchenko
Cc: Yoshihiro Shimoda, Andrew Lunn, David S. Miller, Eric Dumazet,
Paolo Abeni, Geert Uytterhoeven, netdev, linux-renesas-soc,
linux-kernel, Michael Dege, Christian Mardmoeller,
Dennis Ostermann
On Sat, 7 Dec 2024 00:18:11 +0500 Nikita Yushchenko wrote:
> > 3590918b5d07 ("net: ethernet: renesas: Add support for "Ethernet Switch"")
>
> Sorry this patch sent out broken, I've reposted it fixed.
You need to repost the whole thing, sorry. Patchwork is not clever
enough to understand patch replacement.
Quoting documentation:
Partial resends
~~~~~~~~~~~~~~~
Please always resend the entire patch series and make sure you do number your
patches such that it is clear this is the latest and greatest set of patches
that can be applied. Do not try to resend just the patches which changed.
See: https://www.kernel.org/doc/html/next/process/maintainer-netdev.html#partial-resends
--
pw-bot: cr
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2024-12-08 1:23 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-06 19:00 [PATCH net v2 0/4] net: renesas: rswitch: several fixes Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 1/4] net: renesas: rswitch: fix possible early skb release Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
2024-12-06 19:18 ` Nikita Yushchenko
2024-12-08 1:23 ` Jakub Kicinski
2024-12-06 19:00 ` [PATCH net v2 3/4] net: renesas: rswitch: fix leaked pointer on error path Nikita Yushchenko
2024-12-06 19:00 ` [PATCH net v2 4/4] net: renesas: rswitch: avoid use-after-put for a device tree node Nikita Yushchenko
2024-12-06 19:16 ` [PATCH net v2 2/4] net: renesas: rswitch: fix race window between tx start and complete Nikita Yushchenko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).