From: Jacob Keller <jacob.e.keller@intel.com>
To: <netdev-bot+sashiko@kernel.org>, <anthony.l.nguyen@intel.com>
Cc: <davem@davemloft.net>, <kuba@kernel.org>, <pabeni@redhat.com>,
<edumazet@kernel.org>, <andrew+netdev@lunn.ch>,
<netdev@vger.kernel.org>, <maciej.machnikowski@intel.com>,
<przemyslaw.korba@intel.com>, <grzegorz.nitka@intel.com>,
<sergey.temerkhanov@intel.com>, <arkadiusz.kubalewski@intel.com>,
<poros@redhat.com>, <richardcochran@gmail.com>,
<horms@kernel.org>, <pmenzel@molgen.mpg.de>,
<aleksandr.loktionov@intel.com>, <alexander.nowlin@intel.com>
Subject: Re: [PATCH net v2 03/15] ice: fix PHY port restart serialization
Date: Tue, 13 Oct 2026 14:43:17 -0700 [thread overview]
Message-ID: <5089c30e-b9a0-4fc1-abec-e3dcb6157f4c@intel.com> (raw)
In-Reply-To: <179184692111.434549.8926605466860924920@kernel.org>
On 10/12/2026 4:15 PM, netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider.
>
> Critical: 0 · High: 1 (2) · Medium: 0 · Low: 0
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [High] net: ice: UAF/NULL deref of PTP kworker on error path during PHY
> restart
>
> Pre-existing issues:
> - [High] On E822 (ICE_MAC_GENERIC), ice_ptp_port_phy_restart() can call
> kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work, 0)…
> - [High] ice_ptp_link_change() checks `pf->ptp.state != ICE_PTP_READY`
> (line 1308) before it takes adapter->ps_lock (line 1313), and does not…
>
> --
>
> ice: fix PHY port restart serialization
>
> This commit replaces the per-port ps_lock with one mutex for the whole
> adapter. The mutex is taken in ice_ptp_restart_all_phy(),
> ice_ptp_link_change(), ice_ptp_init() and ice_ptp_release(), and the
> stop/restart helpers now assert that it is held. The cached link_up field
> is now written in the same critical section as the PHY restart.
>
> Closes: https://lore.kernel.org/netdev/20260916011228.1632848-1-kuba@kernel.org/
>
>> diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
>> index 94a66e9d8c05d..adc5308baefce 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_ptp.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
>
> [ ... ]
>
>> @@ -1310,12 +1310,13 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
>>
>> ptp_port = &pf->ptp.port;
>>
>> - /* Update cached link status for this port immediately */
>> + mutex_lock(&pf->adapter->ps_lock);
>> +
>> ptp_port->link_up = linkup;
>
> [Severity: High]
> This is a pre-existing issue, but now that ps_lock is taken here, should
> ice_ptp_link_change() check ICE_PTP_READY again after mutex_lock()?
>
> Right now the state is only checked before the lock is taken:
>
> if (pf->ptp.state != ICE_PTP_READY)
> return;
>
> ptp_port = &pf->ptp.port;
>
> mutex_lock(&pf->adapter->ps_lock);
>
> ice_ptp_release() does three things in order. It sets the state to
> ICE_PTP_UNINIT, it takes and drops ps_lock around ice_ptp_port_phy_stop(),
> and then it destroys the worker:
>
> mutex_lock(&pf->adapter->ps_lock);
> ice_ptp_port_phy_stop(&pf->ptp.port);
> mutex_unlock(&pf->adapter->ps_lock);
>
> if (pf->ptp.kworker) {
> kthread_destroy_worker(pf->ptp.kworker);
> pf->ptp.kworker = NULL;
> }
>
> Suppose a link change passes the READY check and then blocks on ps_lock,
> for example behind a sibling PF's restart holding the adapter-wide mutex.
> If release takes the lock first, the link change then runs against the
> torn-down port:
>
> - E82x with linkup == false: ice_ptp_port_phy_stop() calls
> kthread_cancel_delayed_work_sync(&ptp_port->ov_work), but
> ov_work.work->worker still points at the freed kthread_worker.
>
> - linkup == true: ice_ptp_port_phy_restart() calls
> kthread_queue_delayed_work() with pf->ptp.kworker == NULL.
>
> Two callers can race with ice_unload()->ice_deinit_features()->
> ice_ptp_release(). One is ice_down() (ndo_stop under rtnl). The other is
> ice_link_event(), called from the service task.
>
> The service task keeps running through ice_unload(), because
> ice_service_task_stop() is only called later, from ice_deinit_dev().
>
> Later in the series the ice_down() caller goes away. ice_link_event() and
> ice_rebuild() still call ice_ptp_link_change() from the service task,
> though, and the state check is still outside the lock at the end of the
> series. The same window existed with the old per-port lock.
>
> [ ... ]
>
>> @@ -3404,14 +3403,16 @@ void ice_ptp_init(struct ice_pf *pf)
>>
>> err = ice_ptp_init_port(pf, &ptp->port);
>> if (err)
>> - goto err_destroy_ps_lock;
>> + goto err_exit;
>>
>> err = ice_ptp_setup_pf(pf);
>> if (err)
>> goto err_release_tx_tracker;
>>
>> /* Start the PHY timestamping block */
>> - ice_ptp_reset_phy_timestamping(pf);
>> + mutex_lock(&pf->adapter->ps_lock);
>> + ice_ptp_port_phy_restart(&ptp->port);
>> + mutex_unlock(&pf->adapter->ps_lock);
>
> [Severity: High]
> This isn't a bug introduced by this patch, but on E822, can the
> ice_ptp_port_phy_restart() call here dereference a NULL pf->ptp.kworker?
>
> On the ICE_MAC_GENERIC success path, the restart queues work without
> checking the worker:
>
> kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work,
> 0);
>
> ice_ptp_init_work() only runs later in ice_ptp_init(). That is after this
> restart, and after ptp->state is set to ICE_PTP_READY.
>
> ice_ptp_release() destroys the worker and sets pf->ptp.kworker = NULL, but
> it never clears ptp.port.link_up. Link events after release return early
> because the state is not READY.
>
> So take a devlink reload (ice_unload() -> ice_load()) while the link is
> up. link_up is still true when this restart runs, and
> kthread_queue_delayed_work() then takes worker->lock on a NULL worker
> while ps_lock is held.
>
> Two other paths reach the same call:
>
> - A sibling PF's ice_ptp_restart_all_phy() (from owner settime64 or
> rebuild) can find this port as soon as ice_ptp_setup_pf() has added it
> to the adapter ports list with list_add_rcu().
>
> - A link-up event can see ICE_PTP_READY before the worker exists.
>
> The later patch "ice: call PTP link change only from link events" moves
> ice_ptp_init_work() ahead of the restart and the READY transition, and
> seeds link_up. That covers this init-path restart and the link-up event.
>
> The sibling PF path still looks open at the end of the series.
> ice_ptp_setup_pf() still publishes the port on the list before the worker
> is created and before link_up is reseeded. ice_ptp_restart_all_phy() also
> does not check ptp.state.
>
> Would creating the worker, or clearing link_up, before the port is added
> to the ports list close this window?
>
> [ ... ]
>
>> @@ -3470,7 +3469,6 @@ void ice_ptp_release(struct ice_pf *pf)
>> }
>> ice_ptp_cleanup_pf(pf);
>> ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
>> - mutex_destroy(&pf->ptp.port.ps_lock);
>> return;
>> }
>>
>
> [Severity: High]
> This hunk only drops the mutex_destroy(). Looking at the rest of this
> branch, though, can a sibling PF still reach this port after its
> kworker has been destroyed?
>
> In the ice_ptp_release() branch for a PF whose state is not
> ICE_PTP_READY, the order is:
>
> - kthread_destroy_worker() is called and pf->ptp.kworker is set to
> NULL.
> - ice_ptp_cleanup_pf() is called after that.
>
> ice_ptp_cleanup_pf() is what removes the port from adapter->ports.list.
> Until it runs, the port is still published on the list.
>
> During that window, another PF can call ice_ptp_restart_all_phy(), for
> example from ice_ptp_settime64() on the clock owner or from rebuild.
> That function:
>
> - walks the list under SRCU,
> - takes a port->ref,
> - calls ice_ptp_port_phy_restart() without looking at ptp.state.
>
> Nothing in release clears ptp_port->link_up, so it can still be true.
> On ICE_MAC_GENERIC the restart then ends in:
>
> kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work,
> 0);
>
> Depending on timing, pf->ptp.kworker is either already freed or NULL.
> If link_up is false, the walker goes through ice_ptp_port_phy_stop()
> instead. Its kthread_cancel_delayed_work_sync(&ptp_port->ov_work) may
> also end up taking the lock of the freed worker that
> ov_work.work.worker still points to.
>
> This matters for this patch because ice_ptp_restart_all_phy() now
> holds adapter->ps_lock across the walk, and ps_lock is meant to be
> what serializes PHY start/stop. This branch of ice_ptp_release() never
> takes ps_lock, so the new lock does not order the teardown against a
> concurrent restart from a sibling PF. As I read it, the READY branch
> unpublishes the port before the worker goes away, so it does not have
> this window.
>
> Should ice_ptp_cleanup_pf() run before the worker is destroyed here,
> as in the READY path? The idea is that the port is unpublished, and
> any SRCU walker that already found it has finished, before
> pf->ptp.kworker is freed. Or would you rather take ps_lock around this
> teardown?
>
This is the same problem outlined in the first patch. Will fix in v3 :\
next prev parent reply other threads:[~2026-10-13 21:43 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-08 21:55 [PATCH net v2 00/15][pull request] ice: E82x: timestamp processing logic fixes Tony Nguyen
2026-10-08 21:55 ` [PATCH net v2 01/15] ice: fix removal of PTP timestamp tracker during reset Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 21:31 ` Jacob Keller
2026-10-08 21:55 ` [PATCH net v2 02/15] ice: use reference counting and SRCU for PTP port access Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 21:41 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 03/15] ice: fix PHY port restart serialization Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 21:43 ` Jacob Keller [this message]
2026-10-08 21:56 ` [PATCH net v2 04/15] ice: set in_use only after preparing Tx timestamp index Tony Nguyen
2026-10-08 21:56 ` [PATCH net v2 05/15] ice: call PTP link change only from link events Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 21:58 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 06/15] ice: E822: keep Tx timestamps disabled during offset calibration Tony Nguyen
2026-10-08 21:56 ` [PATCH net v2 07/15] ice: E822: cancel offset verification work during reset preparation Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:07 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 08/15] ice: E825: stop clearing PHY_REG_TX_OFFSET_READY Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:08 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 09/15] ice: E825: clear PHY_REG_TX_MEMORY_STATUS prior to soft reset Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:11 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 10/15] ice: E825: perform a soft reset when starting the PHY timer Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:32 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 11/15] ice: wait for in-flight Tx timestamps before flushing the tracker Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:39 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 12/15] ice: keep Tx timestamp slots tracked until completion or timeout Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:44 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 13/15] ice: skip reading Tx ready bitmap on ports with no timestamps Tony Nguyen
2026-10-08 21:56 ` [PATCH net v2 14/15] ice: don't clear in_use until HW clears ready bitmap Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 22:59 ` Jacob Keller
2026-10-08 21:56 ` [PATCH net v2 15/15] ice: Recalibrate PHY after settime64 on E825-C Tony Nguyen
2026-10-12 23:15 ` netdev-bot+sashiko
2026-10-13 23:04 ` Jacob Keller
2026-10-14 0:59 ` Jacob Keller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5089c30e-b9a0-4fc1-abec-e3dcb6157f4c@intel.com \
--to=jacob.e.keller@intel.com \
--cc=aleksandr.loktionov@intel.com \
--cc=alexander.nowlin@intel.com \
--cc=andrew+netdev@lunn.ch \
--cc=anthony.l.nguyen@intel.com \
--cc=arkadiusz.kubalewski@intel.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=grzegorz.nitka@intel.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=maciej.machnikowski@intel.com \
--cc=netdev-bot+sashiko@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pmenzel@molgen.mpg.de \
--cc=poros@redhat.com \
--cc=przemyslaw.korba@intel.com \
--cc=richardcochran@gmail.com \
--cc=sergey.temerkhanov@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox