All of lore.kernel.org
 help / color / mirror / Atom feed
From: Simon Horman <horms@kernel.org>
To: xuanqiang.luo@linux.dev
Cc: intel-wired-lan@lists.osuosl.org, anthony.l.nguyen@intel.com,
	przemyslaw.kitszel@intel.com, richardcochran@gmail.com,
	piotr.kwapulinski@intel.com, arkadiusz.kubalewski@intel.com,
	aleksandr.loktionov@intel.com, andrew+netdev@lunn.ch,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, netdev@vger.kernel.org,
	Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Subject: Re: [Intel-wired-lan] [PATCH iwl-net v1] i40e: fix races in PTP external timestamp work handling
Date: Thu, 30 Jul 2026 13:25:50 +0100	[thread overview]
Message-ID: <20260730122550.GA51943@horms.kernel.org> (raw)
In-Reply-To: <20260724093448.63154-1-xuanqiang.luo@linux.dev>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev/#/patchset/20260724093448.63154-1-xuanqiang.luo@linux.dev?part=1
---
--- Patch [1]: [PATCH iwl-net v1] i40e: fix races in PTP external timestamp work handling ---
commit 4359cf206cb2602e153fdeac3151f8d4bacf9195
Author: Xuanqiang Luo <luoxuanqiang@kylinos.cn>

i40e: fix races in PTP external timestamp work handling

This commit disables external timestamp events and drains the work
queue before unregistering the PHC to fix a use-after-free, and
moves the work initialization to device init instead of reset. It also
excludes reset recovery during teardown to avoid concurrent rebuilds.

> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index a04683004a567..2909a58d57562 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
[ ... ]
> @@ -16157,14 +16158,6 @@ static void i40e_remove(struct pci_dev *pdev)
>  
>  	i40e_devlink_unregister(pf);
>  
> -	i40e_dbg_pf_exit(pf);
> -
> -	i40e_ptp_stop(pf);
> -
> -	/* Disable RSS in hw */
> -	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), 0);
> -	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), 0);
> -
>  	/* Grab __I40E_RESET_RECOVERY_PENDING and set __I40E_IN_REMOVE
>  	 * flags, once they are set, i40e_rebuild should not be called as
>  	 * i40e_prep_for_reset always returns early.
> @@ -16173,6 +16166,14 @@ static void i40e_remove(struct pci_dev *pdev)
>  		usleep_range(1000, 2000);

Simon says: I think the issue flagged below is somewhat orthogonal to
            this patch and can be considered in the context of possible
	    follow-up.

[Severity: High]
This is a pre-existing issue, but does this ad-hoc polling loop violate core
networking synchronization rules?

The subsystem guidelines state that using retry/poll loops on flags to guard
code sections is a bug, as it evades lockdep deadlock detection and lacks
proper memory ordering guarantees. 

i40e_remove() spins on __I40E_RESET_RECOVERY_PENDING with a sleep instead of
using a standard lock or workqueue synchronization, which exposes the teardown
path to races during hotplug or PCIe AER unbinds.

>  	set_bit(__I40E_IN_REMOVE, pf->state);
>  
> +	i40e_dbg_pf_exit(pf);
> +
> +	i40e_ptp_stop(pf);

[ ... ]
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
> index ff62b5f2c8150..fd51ab8c10c20 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
[ ... ]
> @@ -1541,6 +1550,13 @@ void i40e_ptp_stop(struct i40e_pf *pf)
>  	struct i40e_hw *hw = &pf->hw;
>  	u32 regval;
>  
> +	/* Stop external timestamp events before unregistering the clock. */
> +	regval = rd32(hw, I40E_PRTTSYN_CTL0);
> +	regval &= ~I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK;
> +	wr32(hw, I40E_PRTTSYN_CTL0, regval);
> +
> +	disable_work_sync(&pf->ptp_extts0_work);
> +

[Severity: Medium]
Does this reordering introduce a TOCTOU race condition with the PTP ioctl?

The flag I40E_FLAG_PTP_ENA is still set here while we disable the workqueue.
Because i40e_remove() does not hold the rtnl_lock(), a concurrent
SIOCSHWTSTAMP ioctl could execute i40e_ptp_hwtstamp_set().

Since the ioctl checks I40E_FLAG_PTP_ENA, it might observe it as still set
and call i40e_ptp_set_timestamp_mode(). This would overwrite I40E_PRTTSYN_CTL0
and re-enable hardware interrupts immediately after i40e_ptp_stop() just
disabled them, leaving the device generating events for a disabled workqueue.

>  	clear_bit(I40E_FLAG_PTP_ENA, pf->flags);
>  	pf->ptp_tx = false;
>  	pf->ptp_rx = false;
>  
>  	if (pf->ptp_tx_skb) {
>  		struct sk_buff *skb = pf->ptp_tx_skb;
>  
>  		pf->ptp_tx_skb = NULL;
>  		clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
>  		dev_kfree_skb_any(skb);
>  	}

Simon says: Although the issue flagged below is flagged as pre-existing
            I am concerned that it is exacerbated by this patch.

[Severity: High]
This is a pre-existing issue, but could this freeing pattern result in a
double-free or use-after-free?

A user configuring PTP and transmitting a packet sets pf->ptp_tx_skb.
The watchdog task in i40e_ptp_tx_hang() checks the timeout and reads
pf->ptp_tx_skb without an atomic test-and-set claim.

If a hardware interrupt arrives at this exact time, i40e_ptp_tx_hwtstamp()
can preempt the watchdog, read the exact same pointer, set it to NULL,
call skb_tstamp_tx() and then dev_kfree_skb_any().

When the interrupt returns, the watchdog task resumes and frees the exact
same SKB pointer again. This teardown path in i40e_ptp_stop() also forcibly
frees ptp_tx_skb without atomic protections against the interrupt handler,
compounding the race.

[ ... ]

WARNING: multiple messages have this Message-ID (diff)
From: Simon Horman <horms@kernel.org>
To: xuanqiang.luo@linux.dev
Cc: intel-wired-lan@lists.osuosl.org, anthony.l.nguyen@intel.com,
	przemyslaw.kitszel@intel.com, richardcochran@gmail.com,
	piotr.kwapulinski@intel.com, arkadiusz.kubalewski@intel.com,
	aleksandr.loktionov@intel.com, andrew+netdev@lunn.ch,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, netdev@vger.kernel.org,
	Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Subject: Re: [PATCH iwl-net v1] i40e: fix races in PTP external timestamp work handling
Date: Thu, 30 Jul 2026 13:25:50 +0100	[thread overview]
Message-ID: <20260730122550.GA51943@horms.kernel.org> (raw)
In-Reply-To: <20260724093448.63154-1-xuanqiang.luo@linux.dev>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev/#/patchset/20260724093448.63154-1-xuanqiang.luo@linux.dev?part=1
---
--- Patch [1]: [PATCH iwl-net v1] i40e: fix races in PTP external timestamp work handling ---
commit 4359cf206cb2602e153fdeac3151f8d4bacf9195
Author: Xuanqiang Luo <luoxuanqiang@kylinos.cn>

i40e: fix races in PTP external timestamp work handling

This commit disables external timestamp events and drains the work
queue before unregistering the PHC to fix a use-after-free, and
moves the work initialization to device init instead of reset. It also
excludes reset recovery during teardown to avoid concurrent rebuilds.

> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index a04683004a567..2909a58d57562 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
[ ... ]
> @@ -16157,14 +16158,6 @@ static void i40e_remove(struct pci_dev *pdev)
>  
>  	i40e_devlink_unregister(pf);
>  
> -	i40e_dbg_pf_exit(pf);
> -
> -	i40e_ptp_stop(pf);
> -
> -	/* Disable RSS in hw */
> -	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), 0);
> -	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), 0);
> -
>  	/* Grab __I40E_RESET_RECOVERY_PENDING and set __I40E_IN_REMOVE
>  	 * flags, once they are set, i40e_rebuild should not be called as
>  	 * i40e_prep_for_reset always returns early.
> @@ -16173,6 +16166,14 @@ static void i40e_remove(struct pci_dev *pdev)
>  		usleep_range(1000, 2000);

Simon says: I think the issue flagged below is somewhat orthogonal to
            this patch and can be considered in the context of possible
	    follow-up.

[Severity: High]
This is a pre-existing issue, but does this ad-hoc polling loop violate core
networking synchronization rules?

The subsystem guidelines state that using retry/poll loops on flags to guard
code sections is a bug, as it evades lockdep deadlock detection and lacks
proper memory ordering guarantees. 

i40e_remove() spins on __I40E_RESET_RECOVERY_PENDING with a sleep instead of
using a standard lock or workqueue synchronization, which exposes the teardown
path to races during hotplug or PCIe AER unbinds.

>  	set_bit(__I40E_IN_REMOVE, pf->state);
>  
> +	i40e_dbg_pf_exit(pf);
> +
> +	i40e_ptp_stop(pf);

[ ... ]
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
> index ff62b5f2c8150..fd51ab8c10c20 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
[ ... ]
> @@ -1541,6 +1550,13 @@ void i40e_ptp_stop(struct i40e_pf *pf)
>  	struct i40e_hw *hw = &pf->hw;
>  	u32 regval;
>  
> +	/* Stop external timestamp events before unregistering the clock. */
> +	regval = rd32(hw, I40E_PRTTSYN_CTL0);
> +	regval &= ~I40E_PRTTSYN_CTL0_EVENT_INT_ENA_MASK;
> +	wr32(hw, I40E_PRTTSYN_CTL0, regval);
> +
> +	disable_work_sync(&pf->ptp_extts0_work);
> +

[Severity: Medium]
Does this reordering introduce a TOCTOU race condition with the PTP ioctl?

The flag I40E_FLAG_PTP_ENA is still set here while we disable the workqueue.
Because i40e_remove() does not hold the rtnl_lock(), a concurrent
SIOCSHWTSTAMP ioctl could execute i40e_ptp_hwtstamp_set().

Since the ioctl checks I40E_FLAG_PTP_ENA, it might observe it as still set
and call i40e_ptp_set_timestamp_mode(). This would overwrite I40E_PRTTSYN_CTL0
and re-enable hardware interrupts immediately after i40e_ptp_stop() just
disabled them, leaving the device generating events for a disabled workqueue.

>  	clear_bit(I40E_FLAG_PTP_ENA, pf->flags);
>  	pf->ptp_tx = false;
>  	pf->ptp_rx = false;
>  
>  	if (pf->ptp_tx_skb) {
>  		struct sk_buff *skb = pf->ptp_tx_skb;
>  
>  		pf->ptp_tx_skb = NULL;
>  		clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, pf->state);
>  		dev_kfree_skb_any(skb);
>  	}

Simon says: Although the issue flagged below is flagged as pre-existing
            I am concerned that it is exacerbated by this patch.

[Severity: High]
This is a pre-existing issue, but could this freeing pattern result in a
double-free or use-after-free?

A user configuring PTP and transmitting a packet sets pf->ptp_tx_skb.
The watchdog task in i40e_ptp_tx_hang() checks the timeout and reads
pf->ptp_tx_skb without an atomic test-and-set claim.

If a hardware interrupt arrives at this exact time, i40e_ptp_tx_hwtstamp()
can preempt the watchdog, read the exact same pointer, set it to NULL,
call skb_tstamp_tx() and then dev_kfree_skb_any().

When the interrupt returns, the watchdog task resumes and frees the exact
same SKB pointer again. This teardown path in i40e_ptp_stop() also forcibly
frees ptp_tx_skb without atomic protections against the interrupt handler,
compounding the race.

[ ... ]

  reply	other threads:[~2026-07-30 12:26 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-24  9:34 [PATCH iwl-net v1] i40e: fix races in PTP external timestamp work handling xuanqiang.luo
2026-07-24  9:34 ` [Intel-wired-lan] " xuanqiang.luo
2026-07-30 12:25 ` Simon Horman [this message]
2026-07-30 12:25   ` Simon Horman
2026-08-05  6:55   ` [Intel-wired-lan] " luoxuanqiang
2026-08-05  6:55     ` luoxuanqiang
2026-08-04 21:33 ` Vadim Fedorenko
2026-08-04 21:33   ` [Intel-wired-lan] " Vadim Fedorenko
2026-08-05  7:13   ` luoxuanqiang
2026-08-05  7:13     ` luoxuanqiang
2026-08-05  9:49     ` Vadim Fedorenko
2026-08-05  9:49       ` [Intel-wired-lan] " Vadim Fedorenko

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=20260730122550.GA51943@horms.kernel.org \
    --to=horms@kernel.org \
    --cc=aleksandr.loktionov@intel.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=anthony.l.nguyen@intel.com \
    --cc=arkadiusz.kubalewski@intel.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=kuba@kernel.org \
    --cc=luoxuanqiang@kylinos.cn \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=piotr.kwapulinski@intel.com \
    --cc=przemyslaw.kitszel@intel.com \
    --cc=richardcochran@gmail.com \
    --cc=xuanqiang.luo@linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.