Page MenuHomeFreeBSD

Fix possible use-after-frees with m_cat(9) usage.
ClosedPublic

Authored by markj on Feb 29 2016, 8:50 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Nov 26, 5:49 AM
Unknown Object (File)
Fri, Nov 22, 2:57 AM
Unknown Object (File)
Mon, Nov 18, 11:50 PM
Unknown Object (File)
Oct 2 2024, 5:42 AM
Unknown Object (File)
Sep 17 2024, 10:54 AM
Unknown Object (File)
Sep 8 2024, 9:32 AM
Unknown Object (File)
Sep 8 2024, 5:35 AM
Unknown Object (File)
Aug 17 2024, 12:38 AM
Subscribers

Details

Summary

m_cat(9) will copy mbufs from the beginning of the second chain into the
last mbuf in the first chain if space is available. In this case, mbufs
from the beginning of the second chain are freed. However, the mbuf man
page claims that the second mbuf chain is always valid on return from
m_cat(9), and there are several use-after-frees that result from this
false assumption.

This is most noticeable in ieee80211_defrag() when INVARIANTS is on: the
mbuf zone destructor overwrites the second chain's pktheader with
0xdeadc0de, resulting in a bogus length that gets added into a valid
mbuf header.

This change fixes the examples of this issue that I can find, documents
m_catpkt, and fixes the m_cat documentation. The code changes would be
committed individually.

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

markj retitled this revision from to Fix possible use-after-frees with m_cat(9) usage..
markj edited the test plan for this revision. (Show Details)
markj updated this object.

Thanks for doing that. The change to soreceive_stream() worries me, however. At first glance it definitely is not a noop. Reviewing...

Thanks for doing that. The change to soreceive_stream() worries me, however. At first glance it definitely is not a noop. Reviewing...

Thanks. Note that the soreceive_stream() change only affects callers that pass in a non-empty mbuf to soreceive(), but I can't find any examples of that in the tree.

The code in soreceive_stream() is a problem. In original BSD code *mp0 was never dereferenced, being a write only variable. We still have places in kernel, where *mp0 is passed uninitalized. So, this m_cat() code is very strange. I'd delete it, but it did appeared quite recently. Commit by Andre in r242309. The revision log doesn't shed light to me.

Also, there is one more unhandled m_cat() with use of second argument down below.

glebius edited edge metadata.

My suggestion is to go on with checkin of m_cat(), but not touching soreceive_stream(). If you "fix" this place, you will add only extra confusion to subversion log. After checking in the main change, we can sit and investigate soreceive_stream(). I believe code can be deleted. But better first to understand what Andre tried to fix. There is also Mikolay referenced in commit. May be he is still reachable and can shed light.

This revision is now accepted and ready to land.Feb 29 2016, 10:42 PM
In D5497#117238, @glebius wrote: me.

Also, there is one more unhandled m_cat() with use of second argument down below.

Hm, I don't see the problem. "m" is not referenced after the second m_cat() call in soreceive_stream().

Right, it isn't used. Sorry for confusion.

This revision was automatically updated to reflect the committed changes.