aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbdelkader Boudih <freebsd@seuros.com>2026-07-05 18:26:05 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2026-07-05 18:34:02 +0000
commit22ddc9eb1d7a4fffe78b0692bdc4ec03e1d04ac4 (patch)
tree8b18af1d84950bedd19c66d6e69ebdc2ae2d7a17
parent5dfe1956df4b37af4892aaff3fafe70c0d6d7466 (diff)
fwip: Fix M_PKTHDR loss in fwip_async_output broadcast path
M_PREPEND in the broadcast branch may call m_prepend(9) which allocates a new head mbuf and calls m_move_pkthdr(), stripping M_PKTHDR from the old mbuf. xfer->mbuf was set before M_PREPEND, so it pointed at the deheadered old mbuf. bus_dmamap_load_mbuf(9) asserts M_PKTHDR and panics. Reviewed by: zlei, adrian Differential Revision: https://reviews.freebsd.org/D57495
-rw-r--r--sys/dev/firewire/if_fwip.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/sys/dev/firewire/if_fwip.c b/sys/dev/firewire/if_fwip.c
index 0f37ce6a8e41..bdbe76e2caf4 100644
--- a/sys/dev/firewire/if_fwip.c
+++ b/sys/dev/firewire/if_fwip.c
@@ -540,13 +540,6 @@ fwip_async_output(struct fwip_softc *fwip, if_t ifp)
*/
/*
- * Put the mbuf in the xfer early in case we hit an
- * error case below - fwip_output_callback will free
- * the mbuf.
- */
- xfer->mbuf = m;
-
- /*
* We use the arp result (if any) to add a suitable firewire
* packet header before handing off to the bus.
*/
@@ -561,7 +554,18 @@ fwip_async_output(struct fwip_softc *fwip, if_t ifp)
*/
uint32_t *p;
+ /*
+ * M_PREPEND may move M_PKTHDR to a new head mbuf.
+ * Keep xfer->mbuf NULL until it succeeds.
+ */
+ xfer->mbuf = NULL;
M_PREPEND(m, 2*sizeof(uint32_t), M_NOWAIT);
+ if (m == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ fwip_output_callback(xfer);
+ continue;
+ }
+ xfer->mbuf = m;
p = mtod(m, uint32_t *);
fp->mode.stream.len = m->m_pkthdr.len;
fp->mode.stream.chtag = broadcast_channel;
@@ -584,6 +588,10 @@ fwip_async_output(struct fwip_softc *fwip, if_t ifp)
struct fw_device *fd;
struct fw_eui64 eui;
+ /*
+ * Error paths below let the callback free m.
+ */
+ xfer->mbuf = m;
eui.hi = ntohl(destfw->sender_unique_ID_hi);
eui.lo = ntohl(destfw->sender_unique_ID_lo);
if (fwip->last_dest.hi != eui.hi ||