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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox