From: Jakub Kicinski <kuba@kernel.org>
To: anthony.l.nguyen@intel.com
Cc: Jakub Kicinski <kuba@kernel.org>,
davem@davemloft.net, pabeni@redhat.com, edumazet@google.com,
andrew+netdev@lunn.ch, netdev@vger.kernel.org, doruk@0sec.ai,
michal.swiatkowski@linux.intel.com, grzegorz.nitka@intel.com,
horms@kernel.org, przemyslaw.kitszel@intel.com,
stable@vger.kernel.org, aleksandr.loktionov@intel.com,
marcin.szycik@linux.intel.com
Subject: Re: [PATCH net 07/10] ice: eswitch: fix use-after-free of metadata_dst in repr release
Date: Thu, 6 Aug 2026 10:20:39 -0700 [thread overview]
Message-ID: <20260806172039.2935855-1-kuba@kernel.org> (raw)
In-Reply-To: <20260804222205.1580328-8-anthony.l.nguyen@intel.com>
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
ice: eswitch: fix use-after-free of metadata_dst in repr release
This replaces metadata_dst_free() with dst_release() in
ice_eswitch_release_repr() so that the port representor metadata_dst is
freed only after the last dst_entry reference goes away, instead of being
kfree()d while in-flight skbs may still reference it.
(No Link: tags present in the commit header.)
> diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
> index b069e6c514fb1..6e7bba4738989 100644
> --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
> +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
> @@ -95,7 +95,7 @@ ice_eswitch_release_repr(struct ice_pf *pf, struct ice_repr *repr)
> return;
>
> ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof);
> - metadata_dst_free(repr->dst);
> + dst_release(&repr->dst->dst);
> repr->dst = NULL;
> ice_fltr_add_mac_and_broadcast(vsi, repr->parent_mac,
> ICE_FWD_TO_VSI);
[Severity: High]
This isn't a bug introduced by this patch, but with the put side now fixed,
is the get side of repr->dst still unsynchronized?
ice_eswitch_port_start_xmit() does three separate plain loads of repr->dst
with no lock, no RCU section and no READ_ONCE():
skb_dst_drop(skb);
dst_hold((struct dst_entry *)repr->dst);
skb_dst_set(skb, (struct dst_entry *)repr->dst);
skb->dev = repr->dst->u.port_info.lower_dev;
while ice_eswitch_release_repr() drops the last reference and then stores
the NULL:
dst_release(&repr->dst->dst);
repr->dst = NULL;
In the normal teardown path the ordering appears to save this, because
ice_eswitch_detach() calls repr->ops.rem() (unregister_netdev(), which
quiesces the representor's ndo_start_xmit) before
ice_eswitch_release_repr().
The attach error path has the opposite order:
err_xa_alloc:
ice_eswitch_release_repr(pf, repr);
err_setup_repr:
repr->ops.rem(repr);
At err_xa_alloc the representor netdev is already registered, since
repr->ops.add() runs ice_repr_add_vf()/ice_repr_add_sf() ->
ice_repr_reg_netdev() -> register_netdev(), and the attach path holds
devl_lock but not RTNL, so userspace can open the interface and transmit.
Two outcomes seem possible in that window:
- the xmit CPU loaded a non-NULL repr->dst just before dst_release()
drove the rcuref to zero, so dst_hold() hits its
WARN_ON(!rcuref_get(&dst->__rcuref)), takes no reference, and the skb
carries a metadata_dst that dst_destroy_rcu() frees after the grace
period, which then gets read by ice_eswitch_set_target_vsi() or by the
skb free path;
- the xmit CPU loads repr->dst after the NULL store, giving dst_hold(NULL)
and a NULL dereference inside rcuref_get().
Would swapping the two error labels so repr->ops.rem() runs before
ice_eswitch_release_repr(), or clearing repr->dst followed by
synchronize_net() before dst_release(), close this window? Also, since
err_setup_repr is reached when metadata_dst_alloc() fails, does that path
leave a registered netdev whose repr->dst is NULL until repr->ops.rem()
runs?
[Severity: High]
This is a pre-existing issue as well, and not something this patch changes,
but does the deferred free help the LAG path at all?
ice_lag_config_eswitch() writes through repr->dst with no NULL check:
xa_for_each(&lag->pf->eswitch.reprs, id, repr)
repr->dst->u.port_info.lower_dev = netdev;
xa_for_each() expands to xa_find()/xa_find_after(), which take and drop
rcu_read_lock() internally, so repr is used outside any RCU read-side
section.
The caller ice_lag_process_event() is a work item and holds only
pf->lag_mutex, while the teardown side (ice_free_vfs() ->
ice_eswitch_detach_vf(), and the ice_reset_all_vfs() path) holds
vf->cfg_lock and devl_lock, so the locksets do not intersect.
That seems to allow:
LAG work detach thread
repr = xa_find(...)
xa_erase(...)
ice_eswitch_release_repr()
repr->dst = NULL;
ice_repr_destroy()
kfree(repr);
repr->dst->u.port_info.lower_dev = netdev;
which is either a store through NULL or a store into freed memory, since
ice_repr_destroy() does a plain kfree(repr) with no grace period.
The change from metadata_dst_free() to dst_release() only defers freeing the
metadata_dst; the repr->dst = NULL store and the kfree(repr) are still
immediate. Should this path be serialized against the eswitch teardown, or
at least keep the repr lookup inside an RCU read-side section with an
RCU-deferred repr free?
next prev parent reply other threads:[~2026-08-06 17:20 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 22:21 [PATCH net 00/10][pull request] Intel Wired LAN Driver Updates 2026-08-04 (iavf, i40e, ice, igc) Tony Nguyen
2026-08-04 22:21 ` [PATCH net 01/10] iavf: return EBUSY if reset in progress or not ready during MAC change Tony Nguyen
2026-08-06 17:20 ` Jakub Kicinski
2026-08-12 6:56 ` Jose Ignacio Tornos Martinez
2026-08-04 22:21 ` [PATCH net 02/10] i40e: skip unnecessary VF reset when setting trust Tony Nguyen
2026-08-06 17:20 ` Jakub Kicinski
2026-08-12 6:59 ` Jose Ignacio Tornos Martinez
2026-08-04 22:21 ` [PATCH net 03/10] iavf: send MAC change request synchronously Tony Nguyen
2026-08-06 17:20 ` Jakub Kicinski
2026-08-12 7:02 ` Jose Ignacio Tornos Martinez
2026-08-04 22:21 ` [PATCH net 04/10] ice: skip unnecessary VF reset when setting trust Tony Nguyen
2026-08-06 17:20 ` Jakub Kicinski
2026-08-12 7:05 ` Jose Ignacio Tornos Martinez
2026-08-04 22:21 ` [PATCH net 05/10] ice: move ice_vsi_realloc_stat_arrays() up Tony Nguyen
2026-08-04 22:21 ` [PATCH net 06/10] ice: fix stats array overflow via proper realloc Tony Nguyen
2026-08-06 17:20 ` Jakub Kicinski
2026-08-04 22:22 ` [PATCH net 07/10] ice: eswitch: fix use-after-free of metadata_dst in repr release Tony Nguyen
2026-08-06 17:20 ` Jakub Kicinski [this message]
2026-08-04 22:22 ` [PATCH net 08/10] i40e: fix memcmp of pointer in i40e_hw_set_dcb_config() Tony Nguyen
2026-08-06 17:20 ` Jakub Kicinski
2026-08-04 22:22 ` [PATCH net 09/10] i40e: fix netdev leak in i40e_vsi_setup() error paths Tony Nguyen
2026-08-06 17:20 ` Jakub Kicinski
2026-08-04 22:22 ` [PATCH net 10/10] igc: fix netdev not re-attached after resume if interface is down Tony Nguyen
2026-08-06 17:19 ` [PATCH net 00/10][pull request] Intel Wired LAN Driver Updates 2026-08-04 (iavf, i40e, ice, igc) Jakub Kicinski
2026-08-06 17:30 ` patchwork-bot+netdevbpf
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=20260806172039.2935855-1-kuba@kernel.org \
--to=kuba@kernel.org \
--cc=aleksandr.loktionov@intel.com \
--cc=andrew+netdev@lunn.ch \
--cc=anthony.l.nguyen@intel.com \
--cc=davem@davemloft.net \
--cc=doruk@0sec.ai \
--cc=edumazet@google.com \
--cc=grzegorz.nitka@intel.com \
--cc=horms@kernel.org \
--cc=marcin.szycik@linux.intel.com \
--cc=michal.swiatkowski@linux.intel.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=przemyslaw.kitszel@intel.com \
--cc=stable@vger.kernel.org \
/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.