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 Reported-by: Frederick Lawler Closes: https://lkml.indiana.edu/2507.3/01388.html Reviewed-by: Aleksandr Loktionov Reviewed-by: Arkadiusz Kubalewski Tested-by: Frederick Lawler --- 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