From nobody@FreeBSD.org  Fri Apr 25 22:33:57 2014
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115])
	(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by hub.freebsd.org (Postfix) with ESMTPS id 50DA8F6A
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 25 Apr 2014 22:33:57 +0000 (UTC)
Received: from cgiserv.freebsd.org (cgiserv.freebsd.org [IPv6:2001:1900:2254:206a::50:4])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(Client did not present a certificate)
	by mx1.freebsd.org (Postfix) with ESMTPS id 3D88F116A
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 25 Apr 2014 22:33:57 +0000 (UTC)
Received: from cgiserv.freebsd.org ([127.0.1.6])
	by cgiserv.freebsd.org (8.14.8/8.14.8) with ESMTP id s3PMXv0j083843
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 25 Apr 2014 22:33:57 GMT
	(envelope-from nobody@cgiserv.freebsd.org)
Received: (from nobody@localhost)
	by cgiserv.freebsd.org (8.14.8/8.14.8/Submit) id s3PMXvVM083834;
	Fri, 25 Apr 2014 22:33:57 GMT
	(envelope-from nobody)
Message-Id: <201404252233.s3PMXvVM083834@cgiserv.freebsd.org>
Date: Fri, 25 Apr 2014 22:33:57 GMT
From: Alan Somers <asomers@freebsd.org>
To: freebsd-gnats-submit@FreeBSD.org
Subject: Page fault in lacp_req() while the lagg is being destroyed
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         189003
>Category:       kern
>Synopsis:       [lagg] Page fault in lacp_req() while the lagg is being destroyed
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    asomers
>State:          patched
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Apr 25 22:40:01 UTC 2014
>Closed-Date:    
>Last-Modified:  Fri May  2 16:30:00 UTC 2014
>Originator:     Alan Somers
>Release:        11.0 CURRENT
>Organization:
Spectra Logic
>Environment:
FreeBSD alans-fbsd-head 11.0-CURRENT FreeBSD 11.0-CURRENT #53 r264920M: Fri Apr 25 13:52:21 MDT 2014     alans@ns1.eng.sldomain.com:/vmpool/obj/usr/home/alans/freebsd/head/sys/GENERIC  amd64
>Description:
If you do an "ifconfig -am" in one thread while doing an "ifconfig lagg0 destroy" in another thread, at least two panics may result.  One is in lacp_req(), caused by NULL == lsc.

What happens is that the "ifconfig lagg0 destroy" thread does this:
1) lagg_clone_destroy() acquires LAGG_WLOCK(sc)
2) lagg_clone_destroy() calls lagg_lacp_detach, which calls lacp_detach, which sets sc->sc_psc = NULL
3) lagg_clone_destroy() calls LAGG_WUNLOCK(sc)

then the "ifconfig status" thread does this:
1) calls lagg_ioctl(SIOCGLAGG)
2) lagg_ioctl() acquires LAGG_RLOCK(sc, &tracker)
3) lagg_ioctl() calls sc->sc_req, which dereferences to lacp_req
4) lacp_req does *lsc = LACP_SOFTC(sc), which returns NULL
5) lacp_req dereferences lsc, and panics


db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe009781d380
kdb_backtrace() at kdb_backtrace+0x39/frame 0xfffffe009781d430
witness_warn() at witness_warn+0x4b5/frame 0xfffffe009781d4f0
trap_pfault() at trap_pfault+0x59/frame 0xfffffe009781d590
trap() at trap+0x4d5/frame 0xfffffe009781d7a0
calltrap() at calltrap+0x8/frame 0xfffffe009781d7a0
--- trap 0xc, rip = 0xffffffff81eb9b44, rsp = 0xfffffe009781d860, rbp = 0xfffffe009781d890 ---
lacp_req() at lacp_req+0x14/frame 0xfffffe009781d890
lagg_ioctl() at lagg_ioctl+0x270/frame 0xfffffe009781d970
ifioctl() at ifioctl+0xbf7/frame 0xfffffe009781da30
kern_ioctl() at kern_ioctl+0x22b/frame 0xfffffe009781da90
sys_ioctl() at sys_ioctl+0x13c/frame 0xfffffe009781dae0
amd64_syscall() at amd64_syscall+0x25a/frame 0xfffffe009781dbf0
Xfast_syscall() at Xfast_syscall+0xfb/frame 0xfffffe009781dbf0
--- syscall (54, FreeBSD ELF64, sys_ioctl), rip = 0x800fa045a, rsp = 0x7fffffffd808, rbp = 0x7fffffffe290 ---

>How-To-Repeat:
First, backout change 253687.  That will increase the likelihood of hitting this panic.

Run this script:

#! /usr/local/bin/bash

ifconfig tap0 create
sleep .2
ifconfig tap1 create
sleep .2
ifconfig tap2 create
sleep .2
ifconfig tap0 up
sleep .2
ifconfig tap1 up
sleep .2
ifconfig tap2 up
sleep .2

while true; do
        echo "About to create"
        ifconfig lagg0 create
        #sleep 0.2

        echo "About to up"
        ifconfig lagg0 up laggproto lacp laggport tap0 laggport tap1 laggport tap2 192.0.0.2/24
        sleep 0.2

        echo "About to destroy"
        ifconfig lagg0 destroy
        sleep 0.2
done &

while true; do
        ifconfig -am > /dev/null
done

>Fix:
The purpose of lacp_req is to return LACP property information to userland when you do "ifconfig lagg0".  So I think that it would be ok if it returned a block full of zeros.  This would only happen while the interface is being destroyed, and userland should be able to deal with that.  So my proposed fix (attached), is to simply check for NULL == lsc and return early.

Patch attached with submission follows:

Index: sys/net/ieee8023ad_lacp.c
===================================================================
--- sys/net/ieee8023ad_lacp.c	(revision 264920)
+++ sys/net/ieee8023ad_lacp.c	(working copy)
@@ -590,10 +590,20 @@
 {
 	struct lacp_opreq *req = (struct lacp_opreq *)data;
 	struct lacp_softc *lsc = LACP_SOFTC(sc);
-	struct lacp_aggregator *la = lsc->lsc_active_aggregator;
+	struct lacp_aggregator *la;
 
+	bzero(req, sizeof(struct lacp_opreq));
+	
+	/* 
+	 * If the LACP softc is NULL, return with the opreq structure full of
+	 * zeros.  It is normal for the softc to be NULL while the lagg is
+	 * being destroyed.
+	 */
+	if (NULL == lsc)
+		return;
+
+	la = lsc->lsc_active_aggregator;
 	LACP_LOCK(lsc);
-	bzero(req, sizeof(struct lacp_opreq));
 	if (la != NULL) {
 		req->actor_prio = ntohs(la->la_actor.lip_systemid.lsi_prio);
 		memcpy(&req->actor_mac, &la->la_actor.lip_systemid.lsi_mac,


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->asomers 
Responsible-Changed-By: asomers 
Responsible-Changed-When: Fri Apr 25 22:41:09 UTC 2014 
Responsible-Changed-Why:  
I'll take it 

http://www.freebsd.org/cgi/query-pr.cgi?pr=189003 
State-Changed-From-To: open->patched 
State-Changed-By: asomers 
State-Changed-When: Fri May 2 16:25:04 UTC 2014 
State-Changed-Why:  
Patched by revision 265232 

http://www.freebsd.org/cgi/query-pr.cgi?pr=189003 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/189003: commit references a PR
Date: Fri,  2 May 2014 16:24:13 +0000 (UTC)

 Author: asomers
 Date: Fri May  2 16:24:09 2014
 New Revision: 265232
 URL: http://svnweb.freebsd.org/changeset/base/265232
 
 Log:
   Fix a panic caused by doing "ifconfig -am" while a lagg is being destroyed.
   The thread that is destroying the lagg has already set sc->sc_psc=NULL when
   the "ifconfig -am" thread gets to lacp_req().  It tries to dereference
   sc->sc_psc and panics.  The solution is for lacp_req() to check the value of
   sc->sc_psc.  If NULL, harmlessly return an lacp_opreq structure full of
   zeros.  Full details in GNATS.
   
   PR:		kern/189003
   Reviewed by:	timeout on freebsd-net@
   MFC after:	3 weeks
   Sponsored by:	Spectra Logic Corporation
 
 Modified:
   head/sys/net/ieee8023ad_lacp.c
 
 Modified: head/sys/net/ieee8023ad_lacp.c
 ==============================================================================
 --- head/sys/net/ieee8023ad_lacp.c	Fri May  2 16:15:34 2014	(r265231)
 +++ head/sys/net/ieee8023ad_lacp.c	Fri May  2 16:24:09 2014	(r265232)
 @@ -590,10 +590,20 @@ lacp_req(struct lagg_softc *sc, caddr_t 
  {
  	struct lacp_opreq *req = (struct lacp_opreq *)data;
  	struct lacp_softc *lsc = LACP_SOFTC(sc);
 -	struct lacp_aggregator *la = lsc->lsc_active_aggregator;
 +	struct lacp_aggregator *la;
  
 -	LACP_LOCK(lsc);
  	bzero(req, sizeof(struct lacp_opreq));
 +	
 +	/* 
 +	 * If the LACP softc is NULL, return with the opreq structure full of
 +	 * zeros.  It is normal for the softc to be NULL while the lagg is
 +	 * being destroyed.
 +	 */
 +	if (NULL == lsc)
 +		return;
 +
 +	la = lsc->lsc_active_aggregator;
 +	LACP_LOCK(lsc);
  	if (la != NULL) {
  		req->actor_prio = ntohs(la->la_actor.lip_systemid.lsi_prio);
  		memcpy(&req->actor_mac, &la->la_actor.lip_systemid.lsi_mac,
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
