Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Jan 2020 11:09:14 +0000
From:      bugzilla-noreply@freebsd.org
To:        net@FreeBSD.org
Subject:   [Bug 240608] if_vmx(4): iflib - Panic with INVARIANTS: Memory modified after free (12.1-pre-QA)
Message-ID:  <bug-240608-7501-GwAgsmjUOb@https.bugs.freebsd.org/bugzilla/>
In-Reply-To: <bug-240608-7501@https.bugs.freebsd.org/bugzilla/>
References:  <bug-240608-7501@https.bugs.freebsd.org/bugzilla/>

next in thread | previous in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D240608

--- Comment #13 from Andriy Gapon <avg@FreeBSD.org> ---
I see one potential problem related to ifl_fragidx.
_iflib_fl_refill() has this logic:
        frag_idx =3D fl->ifl_fragidx;
<loop>
                bit_ffc_at(fl->ifl_rx_bitmap, frag_idx, fl->ifl_size,=20=20=
=20=20=20=20=20=20=20=20=20
                    &frag_idx);=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20
                if (frag_idx < 0)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20
                        bit_ffc(fl->ifl_rx_bitmap, fl->ifl_size, &frag_idx);

                bit_set(fl->ifl_rx_bitmap, frag_idx);
<end of loop>
        fl->ifl_fragidx =3D frag_idx;

So, ifl_fragidx is used to store the latest set bit in ifl_rx_bitmap.
bit_ffc_at() finds the first cleared bit at or after the start position.
Typically, that means /after/ as the bit /at/ frag_idx is set.

But let's consider this scenario.  Somehow the hardware consumes descriptors
very fast, faster than they are refilled.  Let's say we refilled descriptor=
s up
to index N, so ifl_fragidx=3DN and ifl_pidx=3DN+1.  Let's say the hardware =
consumed
all descriptors available to it.  That means that the whole ifl_rx_bitmap is
clear and ifl_cidx=3DN+1.  Now we do the next refill and we start searching=
 from
ifl_fragidx.  That position is free now, so bit_ffc_at() will return it.  At
this point ifl_fragidx and ifl_pidx get out of sync.  We populate various
software resources by frag_idx, but we program the hardware by pidx.  For
example, we will allocate a cluster at index N, but program its bus address=
 in
a descriptor at index N+1.
That will mess up things for a driver that expects that indexes are always
advanced linearly.

There is a simple solution.
Either we should store frag_idx + 1 to ifl_fragidx for the benefit of the n=
ext
refill or we should call bit_ffc_at() with frag_idx + 1 as a starting posit=
ion.

--=20
You are receiving this mail because:
You are the assignee for the bug.
You are on the CC list for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-240608-7501-GwAgsmjUOb>