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 | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c
b/drivers/net/ethernet/intel/ice/ice_ptp.c
index ec2fd89c18a8..48296a4a8abd 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -3085,9 +3085,25 @@ void ice_ptp_rebuild(struct ice_pf *pf, enum
ice_reset_req reset_type)
static void ice_ptp_setup_adapter(struct ice_pf *pf)
{
+ guard(rwsem_write)(&pf->adapter->ctrl_pf_lock);
+
rcu_assign_pointer(pf->adapter->ctrl_pf, pf);
}
+static void ice_ptp_cleanup_adapter(struct ice_pf *pf)
+{
+ guard(rwsem_write)(&pf->adapter->ctrl_pf_lock);
+
+ /* 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;
@@ -3397,7 +3413,9 @@ void ice_ptp_init(struct ice_pf *pf)
err_clean_pf:
mutex_destroy(&ptp->port.ps_lock);
ice_ptp_cleanup_pf(pf);
+
err_exit:
+ ice_ptp_cleanup_adapter(pf);
/* If we registered a PTP clock, release it */
if (pf->ptp.clock) {
ptp_clock_unregister(ptp->clock);
@@ -3425,6 +3443,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;
@@ -3439,6 +3458,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