From: Simon Horman <horms@kernel.org>
To: Linkui Xiao <xiaolinkui@126.com>
Cc: sashiko-reviews@lists.linux.dev, intel-wired-lan@lists.osuosl.org
Subject: Re: [PATCH iwl-net v3 2/3] ice: detach the VF representor when ice_start_vfs() fails
Date: Sat, 10 Oct 2026 15:05:28 +0100 [thread overview]
Message-ID: <20261010140528.GP83879@horms.kernel.org> (raw)
In-Reply-To: <c4f9c654-614a-44c9-b96a-31883df45e4b@126.com>
On Sat, Oct 10, 2026 at 10:42:49AM +0800, Linkui Xiao wrote:
>
> On 2026/10/9 21:05, sashiko-bot@kernel.org wrote:
> > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> > - [High] ice: ABBA deadlock between pf->vfs.table_lock, devl_lock, and rtnl_lock
> > --
> >
> > commit e31928012cb273c164e36248e1b33c296e805e8d
> > Author: Linkui Xiao <xiaolinkui@kylinos.cn>
> >
> > ice: detach the VF representor when ice_start_vfs() fails
> >
> > This commit modifies the error teardown path of ice_start_vfs() to explicitly
> > detach the VF representor. This prevents memory leaks, use-after-free
> > scenarios, and stale configuration states.
> >
> > > diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
> > > index bf6410c0d85d4..13d97dbd517c8 100644
> > > --- a/drivers/net/ethernet/intel/ice/ice_sriov.c
> > > +++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
> > [ ... ]
> > > @@ -520,8 +520,27 @@ static int ice_start_vfs(struct ice_pf *pf)
> > [ ... ]
> > > + /* Mark the VF disabled before its representor and its VSI go
> > > + * away, the way ice_free_vfs() does, and take cfg_lock
> > > + * around it to wait out an ice_reset_vf() already in
> > > + * progress. pf->state has no ICE_VF_DIS on this path and the
> > > + * loop leaves ICE_VF_STATE_INIT set, so without the bit a
> > > + * concurrent ice_reset_vf() would pass ice_is_vf_disabled()
> > > + * and reach ice_eswitch_update_repr() on a destroyed
> > > + * representor, or trip WARN_ON(!vsi) in ice_dis_vf_mappings().
> > > + */
> > > + mutex_lock(&vf->cfg_lock);
> > > + set_bit(ICE_VF_STATE_DIS, vf->vf_states);
> > > + mutex_unlock(&vf->cfg_lock);
> > > +
> > > + /* detach outside of cfg_lock, see ice_free_vfs() */
> > > + ice_eswitch_detach_vf(pf, vf);
> >
> > [Severity: High]
> > Does this introduce an ABBA deadlock involving pf->vfs.table_lock, devl_lock,
> > and rtnl_lock?
> >
> > ice_start_vfs() runs with pf->vfs.table_lock held. Adding a call to
> > ice_eswitch_detach_vf() here establishes a lock acquisition order of:
> >
> > table_lock -> devl_lock (acquired in ice_eswitch_detach_vf) -> rtnl_lock
> > (acquired via unregister_netdev in ice_repr_rem_vf).
> >
> > However, there is an opposing lock acquisition order during TC mqprio
> > configuration:
> >
> > rtnl_lock (held during ndo_setup_tc) -> devl_lock (acquired in
> > ice_tear_down_devlink_rate_tree) -> table_lock (acquired right after
> > devl_lock in ice_tear_down_devlink_rate_tree).
> >
> > If a user enables SR-IOV, triggering an error in ice_start_vfs(), while
> > concurrently configuring TC mqprio, could this opposing lock acquisition
> > order result in a deadlock?
> >
> > > +
> > > + mutex_lock(&vf->cfg_lock);
> > > ice_dis_vf_mappings(vf);
> > > ice_vf_vsi_release(vf);
> > > + mutex_unlock(&vf->cfg_lock);
> > > +
> > > it_cnt--;
> > > }
> > >
> >
> Thanks for the review.
>
> I agree that the three lock orders do not converge, but I do not think
> this patch introduces the inversion, and the cycle is reachable without
> it.
>
> ice_start_vfs() already runs under pf->vfs.table_lock and already takes
> devl_lock with that lock held, before any failure can happen. Its
> forward loop does
>
> if (ice_is_eswitch_mode_switchdev(pf)) {
> retval = ice_eswitch_attach_vf(pf, vf);
> ...
> }
>
> and ice_eswitch_attach_vf() takes devl_lock() around
> ice_eswitch_attach(). The teardown loop unwinds only the VFs whose
> attach succeeded -- it walks the VFs in the same order and stops once
> it_cnt reaches 0 -- so whenever the ice_eswitch_detach_vf() added here
> can reach devl_lock(), an ice_eswitch_attach_vf() has already taken it
> earlier in the same call, under the same table_lock. In legacy mode
> there are no representors to begin with: ice_eswitch_detach_vf()
> returns at its xa_load() before reaching devl_lock(), and nothing
> attached either. Either way, table_lock -> devl_lock is not a new pair
> here.
>
> The full table_lock -> devl_lock -> rtnl_lock chain is pre-existing
> too. The other two callers of the same helper hold table_lock and reach
> RTNL through it:
>
> ice_free_vfs() table_lock -> ice_eswitch_detach_vf()
> ice_reset_all_vfs() -> devl_lock()
> -> repr->ops.rem()
> -> ice_repr_rem_vf()
> -> unregister_netdev()
>
> That is in the baseline, not added by the series, and the opposite
> order, rtnl_lock -> devl_lock -> table_lock in
> ice_tear_down_devlink_rate_tree() reached from ndo_setup_tc, is equally
> untouched. So "echo 0 > sriov_numvfs" racing a TC mqprio configuration
> can reach both halves today. This is the same pair that was raised in
> the v1 review, and the conclusion has not changed.
>
> That said, the two orders do not converge, and converging them is worth
> doing. It means taking devl_lock outside pf->vfs.table_lock in
> ice_ena_vfs(), ice_free_vfs() and ice_reset_all_vfs(), plus variants of
> ice_eswitch_attach_vf() and ice_eswitch_detach_vf() that expect
> devl_lock() to be held, since devl_lock() is a plain mutex and the
> helpers take it internally. That is a lock hierarchy change across
> three callers and the eswitch API, and it is unrelated to the
> cfg_lock -> RTNL inversion this series is about, so I would rather send
> it as a separate series than carry it in an iwl-net fix that has to be
> backported to stable.
>
> No code change in this series for this report.
Thanks for the detailed response.
This seems reasonable to me.
Reviewed-by: Simon Horman <horms@kernel.org>
next prev parent reply other threads:[~2026-10-10 14:05 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-08 12:57 [PATCH iwl-net v3 0/3] ice: fix VF representor lock ordering and teardown error paths Linkui Xiao
2026-10-08 12:57 ` [PATCH iwl-net v3 1/3] ice: attach and detach VF representors outside of vf->cfg_lock Linkui Xiao
2026-10-09 13:05 ` sashiko-bot
2026-10-10 3:00 ` Linkui Xiao
2026-10-10 14:04 ` Simon Horman
2026-10-12 8:54 ` Linkui Xiao
2026-10-08 12:57 ` [PATCH iwl-net v3 2/3] ice: detach the VF representor when ice_start_vfs() fails Linkui Xiao
2026-10-09 13:05 ` sashiko-bot
2026-10-10 2:42 ` Linkui Xiao
2026-10-10 14:05 ` Simon Horman [this message]
2026-10-08 12:57 ` [PATCH iwl-net v3 3/3] ice: free the VF MSI-X vectors when VF start fails Linkui Xiao
2026-10-10 14:05 ` Simon Horman
2026-10-12 9:04 ` Loktionov, Aleksandr
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=20261010140528.GP83879@horms.kernel.org \
--to=horms@kernel.org \
--cc=intel-wired-lan@lists.osuosl.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=xiaolinkui@126.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 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.