Zero out the ctrl_pf pointer in ice_adapter when the control PF is removed.
This prevents potential dangling pointer dereference when accessing
PTP-related structures from other PFs of the same adapter.

Fixes: e800654e85b5b ("ice: Use ice_adapter for PTP shared data instead of 
auxdev")

Signed-off-by: Sergey Temerkhanov <[email protected]>
Reported-by: Frederick Lawler <[email protected]>
Closes: https://lkml.indiana.edu/2507.3/01388.html
Reviewed-by: Aleksandr Loktionov <[email protected]>
Reviewed-by: Arkadiusz Kubalewski <[email protected]>
Tested-by: Frederick Lawler <[email protected]>
---
 drivers/net/ethernet/intel/ice/ice_ptp.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c 
b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 732964fd7c78..7d9c0775fd79 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -3106,6 +3106,18 @@ static void ice_ptp_setup_adapter(struct ice_pf *pf)
        rcu_assign_pointer(pf->adapter->ctrl_pf, pf);
 }
 
+static void ice_ptp_cleanup_adapter(struct ice_pf *pf)
+{
+       /* Zero out adapter->ctrl_pf pointer when the ctrl_pf itself
+        * is being removed to prevent any secondary PFs from accessing
+        * it after it is deleted.
+        */
+       if (cmpxchg(&pf->adapter->ctrl_pf,
+                   (struct ice_pf __rcu *)pf, NULL) ==
+                       (struct ice_pf __rcu *)pf)
+               synchronize_rcu();
+}
+
 static int ice_ptp_setup_pf(struct ice_pf *pf)
 {
        struct ice_ptp *ptp = &pf->ptp;
@@ -3386,6 +3398,8 @@ void ice_ptp_init(struct ice_pf *pf)
 err_clean_pf:
        mutex_destroy(&ptp->port.ps_lock);
        ice_ptp_cleanup_pf(pf);
+
+       ice_ptp_cleanup_adapter(pf);
 err_exit:
        /* If we registered a PTP clock, release it */
        if (pf->ptp.clock) {
@@ -3414,6 +3428,7 @@ void ice_ptp_release(struct ice_pf *pf)
        if (pf->ptp.state != ICE_PTP_READY) {
                mutex_destroy(&pf->ptp.port.ps_lock);
                ice_ptp_cleanup_pf(pf);
+               ice_ptp_cleanup_adapter(pf);
                if (pf->ptp.clock) {
                        ptp_clock_unregister(pf->ptp.clock);
                        pf->ptp.clock = NULL;
@@ -3428,6 +3443,8 @@ void ice_ptp_release(struct ice_pf *pf)
 
        ice_ptp_cleanup_pf(pf);
 
+       ice_ptp_cleanup_adapter(pf);
+
        ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
 
        ice_ptp_disable_all_extts(pf);
-- 
2.53.0

Reply via email to