Netdev List
 help / color / mirror / Atom feed
* [PATCH net v4 0/2] net: ravb: fix PTP clock lifetime
@ 2026-08-11 10:37 Xuanqiang Luo
  2026-08-11 10:37 ` [PATCH net v4 1/2] net: ravb: avoid dereferencing an invalid PTP clock Xuanqiang Luo
  2026-08-11 10:37 ` [PATCH net v4 2/2] net: ravb: serialize PTP clock teardown Xuanqiang Luo
  0 siblings, 2 replies; 3+ messages in thread
From: Xuanqiang Luo @ 2026-08-11 10:37 UTC (permalink / raw)
  To: linux-renesas-soc, netdev, niklas.soderlund, kuba,
	vadim.fedorenko
  Cc: paul, andrew+netdev, davem, edumazet, pabeni, richardcochran,
	masaru.nagai.vx, luoxuanqiang

From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>

This series fixes RAVB PTP clock lifetime handling. It reports a cached PHC
index without accessing the clock pointer and drains PTP interrupts before
unregistering the clock.

Patch 1 caches the PHC index and handles registration failures.

Patch 2 detaches the clock with xchg() and drains the PTP IRQs before
unregistering it.

---
Changes:
v4:
  - Rebase onto Linux 7.2-rc7.
  Patch 1:
  - Cache the PHC index separately instead of locking clock access.
    (Vadim Fedorenko)
  - Reword the subject and update the commit message for the cached PHC
    index approach.
  - Add Vadim Fedorenko's Reviewed-by tag.
  Patch 2:
  - Replace priv->lock serialization with PTP interrupt disabling and IRQ
    draining before unregistering the clock. (Vadim Fedorenko)
  - Use READ_ONCE() and WRITE_ONCE() for lockless clock pointer access and
    xchg() to detach the clock atomically.
  - Track the error and management IRQs and synchronize all IRQs that can
    invoke the PTP handler.
  - Update the commit message to describe the interrupt handler race and
    the new teardown sequence.

v3: https://lore.kernel.org/all/20260806095126.57803-1-xuanqiang.luo@linux.dev/
  Patch 1:
  - Omit Niklas Söderlund's Reviewed-by tag because the implementation he
    reviewed has changed.
  - Describe the NULL pointer dereference before the first open as the most
    likely failure mode in the commit message. (Jakub Kicinski, Sashiko)
  - Normalize PTP clock registration failures to NULL.
    (Jakub Kicinski, Sashiko)
  - Keep hardware timestamping capabilities independent of PHC
    availability. (Jakub Kicinski, Sashiko)
  Patch 2 (new):
  - Serialize PTP clock publication and access with priv->lock, and detach
    the clock before unregistering it. (Jakub Kicinski, Sashiko)

v2: https://lore.kernel.org/all/20260802090750.116215-1-xuanqiang.luo@linux.dev/
  - Only advertise hardware timestamping support when a PHC is available
    (Niklas Söderlund).

v1: https://lore.kernel.org/all/20260731063254.71260-1-xuanqiang.luo@linux.dev/

Xuanqiang Luo (2):
  net: ravb: avoid dereferencing an invalid PTP clock
  net: ravb: serialize PTP clock teardown

 drivers/net/ethernet/renesas/ravb.h      |  3 ++
 drivers/net/ethernet/renesas/ravb_main.c |  9 +++--
 drivers/net/ethernet/renesas/ravb_ptp.c  | 44 ++++++++++++++++++++----
 3 files changed, 47 insertions(+), 9 deletions(-)


base-commit: db2ddb87143519e20a95aa36c60b36107b736a58
-- 
2.43.0

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH net v4 1/2] net: ravb: avoid dereferencing an invalid PTP clock
  2026-08-11 10:37 [PATCH net v4 0/2] net: ravb: fix PTP clock lifetime Xuanqiang Luo
@ 2026-08-11 10:37 ` Xuanqiang Luo
  2026-08-11 10:37 ` [PATCH net v4 2/2] net: ravb: serialize PTP clock teardown Xuanqiang Luo
  1 sibling, 0 replies; 3+ messages in thread
From: Xuanqiang Luo @ 2026-08-11 10:37 UTC (permalink / raw)
  To: linux-renesas-soc, netdev, niklas.soderlund, kuba,
	vadim.fedorenko
  Cc: paul, andrew+netdev, davem, edumazet, pabeni, richardcochran,
	masaru.nagai.vx, luoxuanqiang, stable

From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>

The PTP clock is unavailable before the first open, so querying its
index can dereference a NULL pointer. Registration failures can also
leave an error pointer in priv->ptp.clock.

Cache the PHC index separately and report -1 while no clock is
registered. Normalize registration errors to NULL and preserve the
static timestamping capabilities.

Fixes: a0d2f20650e8 ("Renesas Ethernet AVB PTP clock driver")
Cc: stable@vger.kernel.org
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
---
 drivers/net/ethernet/renesas/ravb.h      |  1 +
 drivers/net/ethernet/renesas/ravb_main.c |  3 ++-
 drivers/net/ethernet/renesas/ravb_ptp.c  | 15 +++++++++++++--
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index 5e56ec9b1013a..2a4fcb12a63cb 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -1028,6 +1028,7 @@ struct ravb_ptp_perout {
 struct ravb_ptp {
 	struct ptp_clock *clock;
 	struct ptp_clock_info info;
+	int phc_index;
 	u32 default_addend;
 	u32 current_addend;
 	int extts[N_EXT_TS];
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 5f88733094d0f..db0229e008494 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -1779,7 +1779,7 @@ static int ravb_get_ts_info(struct net_device *ndev,
 			(1 << HWTSTAMP_FILTER_NONE) |
 			(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
 			(1 << HWTSTAMP_FILTER_ALL);
-		info->phc_index = ptp_clock_index(priv->ptp.clock);
+		info->phc_index = READ_ONCE(priv->ptp.phc_index);
 	}
 
 	return 0;
@@ -2953,6 +2953,7 @@ static int ravb_probe(struct platform_device *pdev)
 	priv->rstc = rstc;
 	priv->ndev = ndev;
 	priv->pdev = pdev;
+	priv->ptp.phc_index = -1;
 	priv->num_tx_ring[RAVB_BE] = BE_TX_RING_SIZE;
 	priv->num_rx_ring[RAVB_BE] = BE_RX_RING_SIZE;
 	if (info->nc_queues) {
diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c
index 226c6c0ab945b..cbec7c057d715 100644
--- a/drivers/net/ethernet/renesas/ravb_ptp.c
+++ b/drivers/net/ethernet/renesas/ravb_ptp.c
@@ -315,6 +315,7 @@ void ravb_ptp_interrupt(struct net_device *ndev)
 void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
 {
 	struct ravb_private *priv = netdev_priv(ndev);
+	struct ptp_clock *clock;
 	unsigned long flags;
 
 	priv->ptp.info = ravb_ptp_info;
@@ -327,7 +328,15 @@ void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
 	ravb_modify(ndev, GCCR, GCCR_TCSS, GCCR_TCSS_ADJGPTP);
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	priv->ptp.clock = ptp_clock_register(&priv->ptp.info, &pdev->dev);
+	clock = ptp_clock_register(&priv->ptp.info, &pdev->dev);
+	if (IS_ERR(clock)) {
+		netdev_err(ndev, "failed to register PTP clock: %pe\n", clock);
+		clock = NULL;
+	}
+
+	priv->ptp.clock = clock;
+	if (clock)
+		WRITE_ONCE(priv->ptp.phc_index, ptp_clock_index(clock));
 }
 
 void ravb_ptp_stop(struct net_device *ndev)
@@ -337,5 +346,7 @@ void ravb_ptp_stop(struct net_device *ndev)
 	ravb_write(ndev, 0, GIC);
 	ravb_write(ndev, 0, GIS);
 
-	ptp_clock_unregister(priv->ptp.clock);
+	WRITE_ONCE(priv->ptp.phc_index, -1);
+	if (priv->ptp.clock)
+		ptp_clock_unregister(priv->ptp.clock);
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH net v4 2/2] net: ravb: serialize PTP clock teardown
  2026-08-11 10:37 [PATCH net v4 0/2] net: ravb: fix PTP clock lifetime Xuanqiang Luo
  2026-08-11 10:37 ` [PATCH net v4 1/2] net: ravb: avoid dereferencing an invalid PTP clock Xuanqiang Luo
@ 2026-08-11 10:37 ` Xuanqiang Luo
  1 sibling, 0 replies; 3+ messages in thread
From: Xuanqiang Luo @ 2026-08-11 10:37 UTC (permalink / raw)
  To: linux-renesas-soc, netdev, niklas.soderlund, kuba,
	vadim.fedorenko
  Cc: paul, andrew+netdev, davem, edumazet, pabeni, richardcochran,
	masaru.nagai.vx, luoxuanqiang, stable

From: Xuanqiang Luo <luoxuanqiang@kylinos.cn>

ravb_ptp_interrupt() can race with ravb_ptp_stop() and pass the clock to
ptp_clock_event() while ptp_clock_unregister() is freeing it. This can
lead to a use-after-free.

Use READ_ONCE() and WRITE_ONCE() for lockless access to the clock pointer.
Atomically detach it with xchg() before disabling PTP interrupts, then
synchronize all IRQs which can invoke ravb_ptp_interrupt() before
unregistering the detached clock.

A handler which read the old pointer completes before the clock is
unregistered, while later handlers read NULL and skip the event.

Fixes: a0d2f20650e8 ("Renesas Ethernet AVB PTP clock driver")
Cc: stable@vger.kernel.org
Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
---
 drivers/net/ethernet/renesas/ravb.h      |  2 ++
 drivers/net/ethernet/renesas/ravb_main.c |  6 ++--
 drivers/net/ethernet/renesas/ravb_ptp.c  | 37 +++++++++++++++++++-----
 3 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index 2a4fcb12a63cb..3ee4c61081890 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -1124,6 +1124,8 @@ struct ravb_private {
 	int msg_enable;
 	int speed;
 	int emac_irq;
+	int err_irq;
+	int mgmt_irq;
 
 	unsigned no_avb_link:1;
 	unsigned avb_link_active_low:1;
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index db0229e008494..ea1c7e536791e 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -2885,11 +2885,13 @@ static int ravb_setup_irqs(struct ravb_private *priv)
 		return error;
 
 	if (info->err_mgmt_irqs) {
-		error = ravb_setup_irq(priv, "err_a", "err_a", NULL, ravb_multi_interrupt);
+		error = ravb_setup_irq(priv, "err_a", "err_a", &priv->err_irq,
+				       ravb_multi_interrupt);
 		if (error)
 			return error;
 
-		error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", NULL, ravb_multi_interrupt);
+		error = ravb_setup_irq(priv, "mgmt_a", "mgmt_a", &priv->mgmt_irq,
+				       ravb_multi_interrupt);
 		if (error)
 			return error;
 	}
diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c
index cbec7c057d715..43218bc15b151 100644
--- a/drivers/net/ethernet/renesas/ravb_ptp.c
+++ b/drivers/net/ethernet/renesas/ravb_ptp.c
@@ -289,16 +289,17 @@ static const struct ptp_clock_info ravb_ptp_info = {
 void ravb_ptp_interrupt(struct net_device *ndev)
 {
 	struct ravb_private *priv = netdev_priv(ndev);
+	struct ptp_clock *clock = READ_ONCE(priv->ptp.clock);
 	u32 gis = ravb_read(ndev, GIS);
 
 	gis &= ravb_read(ndev, GIC);
-	if (gis & GIS_PTCF) {
+	if ((gis & GIS_PTCF) && clock) {
 		struct ptp_clock_event event;
 
 		event.type = PTP_CLOCK_EXTTS;
 		event.index = 0;
 		event.timestamp = ravb_read(ndev, GCPT);
-		ptp_clock_event(priv->ptp.clock, &event);
+		ptp_clock_event(clock, &event);
 	}
 	if (gis & GIS_PTMF) {
 		struct ravb_ptp_perout *perout = priv->ptp.perout;
@@ -334,19 +335,39 @@ void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
 		clock = NULL;
 	}
 
-	priv->ptp.clock = clock;
+	WRITE_ONCE(priv->ptp.clock, clock);
 	if (clock)
 		WRITE_ONCE(priv->ptp.phc_index, ptp_clock_index(clock));
 }
 
-void ravb_ptp_stop(struct net_device *ndev)
+static void ravb_ptp_disable(struct net_device *ndev)
 {
-	struct ravb_private *priv = netdev_priv(ndev);
-
 	ravb_write(ndev, 0, GIC);
 	ravb_write(ndev, 0, GIS);
+}
+
+static void ravb_ptp_sync_irqs(struct net_device *ndev)
+{
+	struct ravb_private *priv = netdev_priv(ndev);
+
+	synchronize_irq(ndev->irq);
+	if (priv->info->err_mgmt_irqs) {
+		synchronize_irq(priv->err_irq);
+		synchronize_irq(priv->mgmt_irq);
+	}
+}
+
+void ravb_ptp_stop(struct net_device *ndev)
+{
+	struct ravb_private *priv = netdev_priv(ndev);
+	struct ptp_clock *clock;
 
 	WRITE_ONCE(priv->ptp.phc_index, -1);
-	if (priv->ptp.clock)
-		ptp_clock_unregister(priv->ptp.clock);
+	clock = xchg(&priv->ptp.clock, NULL);
+
+	ravb_ptp_disable(ndev);
+	ravb_ptp_sync_irqs(ndev);
+
+	if (clock)
+		ptp_clock_unregister(clock);
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-11 10:39 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11 10:37 [PATCH net v4 0/2] net: ravb: fix PTP clock lifetime Xuanqiang Luo
2026-08-11 10:37 ` [PATCH net v4 1/2] net: ravb: avoid dereferencing an invalid PTP clock Xuanqiang Luo
2026-08-11 10:37 ` [PATCH net v4 2/2] net: ravb: serialize PTP clock teardown Xuanqiang Luo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox