Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Jan 2015 20:03:47 +0000 (UTC)
From:      Will Andrews <will@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r277508 - head/sys/dev/firewire
Message-ID:  <201501212003.t0LK3lHX099841@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: will
Date: Wed Jan 21 20:03:46 2015
New Revision: 277508
URL: https://svnweb.freebsd.org/changeset/base/277508

Log:
  Fix panic in firewire and creation of invalid config ROM.
  
  sys/boot/i386/libfirewire/firewire.c:
  sys/dev/firewire/firewire.c:
  	Fix configuration ROM generation count wrapping logic
  	so that the generation count is never outside of
  	allowed limits (0x2 -> 0xF).
  
  sys/dev/firewire/firewire.c:
  	In fw_xfer_unload(), xfer->fc may be NULL.  Protect
  	against this before taking the fc lock.
  
  Submitted by:	gibbs
  MFC after:	1 week
  Sponsored by:	Spectra Logic
  MFSpectraBSD:	1110685 on 2015/01/05

Modified:
  head/sys/dev/firewire/firewire.c

Modified: head/sys/dev/firewire/firewire.c
==============================================================================
--- head/sys/dev/firewire/firewire.c	Wed Jan 21 20:02:16 2015	(r277507)
+++ head/sys/dev/firewire/firewire.c	Wed Jan 21 20:03:46 2015	(r277508)
@@ -761,8 +761,15 @@ fw_busreset(struct firewire_comm *fc, ui
 	src = &fc->crom_src_buf->src;
 	crom_load(src, newrom, CROMSIZE);
 	if (bcmp(newrom, fc->config_rom, CROMSIZE) != 0) {
-		if (src->businfo.generation++ > FW_MAX_GENERATION)
+		/* Bump generation and reload. */
+		src->businfo.generation++;
+
+		/* Handle generation count wraps. */
+		if (src->businfo.generation < FW_GENERATION_CHANGEABLE)
 			src->businfo.generation = FW_GENERATION_CHANGEABLE;
+
+		/* Recalculate CRC to account for generation change. */
+		crom_load(src, newrom, CROMSIZE);
 		bcopy(newrom, fc->config_rom, CROMSIZE);
 	}
 	free(newrom, M_FW);
@@ -1156,16 +1163,18 @@ fw_xfer_unload(struct fw_xfer *xfer)
 
 	if (xfer == NULL)
 		return;
-	FW_GLOCK(xfer->fc);
-	if (xfer->flag & FWXF_INQ) {
-		STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link);
-		xfer->flag &= ~FWXF_INQ;
-#if 0
-		xfer->q->queued--;
-#endif
-	}
-	FW_GUNLOCK(xfer->fc);
+
 	if (xfer->fc != NULL) {
+		FW_GLOCK(xfer->fc);
+		if (xfer->flag & FWXF_INQ) {
+			STAILQ_REMOVE(&xfer->q->q, xfer, fw_xfer, link);
+			xfer->flag &= ~FWXF_INQ;
+	#if 0
+			xfer->q->queued--;
+	#endif
+		}
+		FW_GUNLOCK(xfer->fc);
+
 		/*
 		 * Ensure that any tlabel owner can't access this
 		 * xfer after it's freed.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501212003.t0LK3lHX099841>