From owner-svn-src-head@FreeBSD.ORG Mon Apr 8 23:16:43 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 35294380; Mon, 8 Apr 2013 23:16:43 +0000 (UTC) (envelope-from will@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 0D4622AB; Mon, 8 Apr 2013 23:16:43 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r38NGgJE060738; Mon, 8 Apr 2013 23:16:42 GMT (envelope-from will@svn.freebsd.org) Received: (from will@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r38NGgLZ060737; Mon, 8 Apr 2013 23:16:42 GMT (envelope-from will@svn.freebsd.org) Message-Id: <201304082316.r38NGgLZ060737@svn.freebsd.org> From: Will Andrews Date: Mon, 8 Apr 2013 23:16:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r249291 - head/sys/dev/firewire X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 08 Apr 2013 23:16:43 -0000 Author: will Date: Mon Apr 8 23:16:42 2013 New Revision: 249291 URL: http://svnweb.freebsd.org/changeset/base/249291 Log: FireWire: Don't allow a tlabel to reference an xfer after free. sys/dev/firewire/firewire.c: - fw_xfer_unload(): Since we are about to free this xfer, call fw_tl_free() to remove the xfer from its tlabel's list, if it has a tlabel. - In every occasion when a xfer is removed from a tlabel's list, reset xfer->tl to -1 while holding fc->tlabel_lock, so that the xfer isn't mis-identified as belonging to a tlabel. This doesn't fix all the use-after-free problems for M_FWMEM, but is an incremental towards that goal. Reviewed by: kan, sbruno Sponsored by: Spectra Logic Modified: head/sys/dev/firewire/firewire.c Modified: head/sys/dev/firewire/firewire.c ============================================================================== --- head/sys/dev/firewire/firewire.c Mon Apr 8 23:06:25 2013 (r249290) +++ head/sys/dev/firewire/firewire.c Mon Apr 8 23:16:42 2013 (r249291) @@ -374,6 +374,7 @@ firewire_xfer_timeout(void *arg, int pen "tl=0x%x flag=0x%02x\n", i, xfer->flag); fw_dump_hdr(&xfer->send.hdr, "send"); xfer->resp = ETIMEDOUT; + xfer->tl = -1; STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel); STAILQ_INSERT_TAIL(&xfer_timeout, xfer, tlabel); } @@ -608,6 +609,7 @@ fw_drain_txq(struct firewire_comm *fc) while ((xfer = STAILQ_FIRST(&fc->tlabels[i])) != NULL) { if (firewire_debug) printf("tl=%d flag=%d\n", i, xfer->flag); + xfer->tl = -1; xfer->resp = EAGAIN; STAILQ_REMOVE_HEAD(&fc->tlabels[i], tlabel); STAILQ_INSERT_TAIL(&xfer_drain, xfer, tlabel); @@ -1044,11 +1046,12 @@ fw_tl_free(struct firewire_comm *fc, str struct fw_xfer *txfer; int s; - if (xfer->tl < 0) - return; - s = splfw(); mtx_lock(&fc->tlabel_lock); + if (xfer->tl < 0) { + mtx_unlock(&fc->tlabel_lock); + return; + } #if 1 /* make sure the label is allocated */ STAILQ_FOREACH(txfer, &fc->tlabels[xfer->tl], tlabel) if(txfer == xfer) @@ -1067,6 +1070,7 @@ fw_tl_free(struct firewire_comm *fc, str #endif STAILQ_REMOVE(&fc->tlabels[xfer->tl], xfer, fw_xfer, tlabel); + xfer->tl = -1; mtx_unlock(&fc->tlabel_lock); splx(s); return; @@ -1191,6 +1195,11 @@ fw_xfer_unload(struct fw_xfer* xfer) splx(s); } if (xfer->fc != NULL) { + /* + * Ensure that any tlabel owner can't access this + * xfer after it's freed. + */ + fw_tl_free(xfer->fc, xfer); #if 1 if(xfer->flag & FWXF_START) /*