kern/116034: Giant not owned at /usr/src/sys/netinet/tcp_sack.c:271=tcp_clean_sackreport(tp)

Dan Lukes dan at obluda.cz
Sun Sep 2 15:30:05 PDT 2007


>Number:         116034
>Category:       kern
>Synopsis:       Giant not owned at /usr/src/sys/netinet/tcp_sack.c:271=tcp_clean_sackreport(tp)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Sep 02 22:30:02 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Dan Lukes
>Release:        FreeBSD 6.2-STABLE i386
>Organization:
Obludarium
>Environment:
System: FreeBSD 6.2-STABLE (sources from Sep 2 21:30:25 CEST 2007)
src/sys/netinet/tcp_sack.c,v 1.26.2.3 2007/06/12 19:21:54 jhb
src/sys/netinet/tcp_subr.c,v 1.228.2.14 2006/12/30 17:58:46 jhb
src/sys/kern/kern_mbuf.c,v 1.9.2.9 2007/02/11 03:31:18 mohans
src/sys/netinet/tcp_input.c,v 1.281.2.13 2007/06/12 18:53:32 jhb

Kernel compiled with IPSEC (=> MPSAFE network stack forced disabled; IPSEC require Giant)
Kernel compiled with INVARIANTS and INVARIANT_SUPPORT so missing lock trigger panic

NOTE: This doesn't apply for CURRENT, but may be significant for 6.3-RELEASE unless
Giant dependency completely MFCed-out from network stack code

>Description:

tcp_clean_sackreport() called from tcp_drain() without Giant but calee require it when
not on MPSAFE network stack 


The relevant code fragments (the INP_LOCK_ASSERT call is the point of panic):

 -----------------------
tcp_clean_sackreport(tp)
        struct tcpcb *tp;
{
        int i;

        INP_LOCK_ASSERT(tp->t_inpcb);
        tp->rcv_numsacks = 0;
        for (i = 0; i < MAX_SACK_BLKS; i++)
                tp->sackblks[i].start = tp->sackblks[i].end=0;
}

 -----------------------

#define INP_LOCK_ASSERT(inp)    do {                                    \
        mtx_assert(&(inp)->inp_mtx, MA_OWNED);                          \
        NET_ASSERT_GIANT();                                             \
} while (0)

 -----------------------

#define NET_ASSERT_GIANT() do {                                         \
        if (!debug_mpsafenet)                                           \
                mtx_assert(&Giant, MA_OWNED);                           \
} while (0)

 -----------------------


1. debug->mpsafenet is forced to off because IPSEC compiled in kernel. 
2. The INP_LOCK_ASSERT(tp->t_inpcb) test for Giant when mpsafenet off. 
3. tcp_clean_sackreport called from tcp_drain called from mb_reclaim without Giant

4. ABEND on kernel compiled with INVARIANTS/INVARIANT_SUPPORT; possible race condition 
	when compiled without INVARIANT



 ===================================================

Kernel code backtrace:

#2  0xc04b9b7d in panic (fmt=0xc064cd1e "mutex %s not owned at %s:%d")
    at /usr/src/sys/kern/kern_shutdown.c:565
#3  0xc04b1e4f in _mtx_assert (m=0xc06a8880, what=0,
    file=0xc065a3bb "/usr/src/sys/netinet/tcp_sack.c", line=271)
    at /usr/src/sys/kern/kern_mutex.c:768
#4  0xc05480bb in tcp_clean_sackreport (tp=0xc49aa910)
    at /usr/src/sys/netinet/tcp_sack.c:271
#5  0xc0549927 in tcp_drain () at /usr/src/sys/netinet/tcp_subr.c:891
#6  0xc04b0a69 in mb_reclaim (junk=0x0) at /usr/src/sys/kern/kern_mbuf.c:557
#7  0xc05d6cd4 in vm_pageout_scan (pass=0) at /usr/src/sys/vm/vm_pageout.c:724
#8  0xc05d7eaf in vm_pageout () at /usr/src/sys/vm/vm_pageout.c:1554

>How-To-Repeat:
	Compile kernel with INVARIANTS/INVARIANT_SUPPORT + (IPSEC or set mpsafenet to 0)

	Do something that trigger mb_reclaim
>Fix:

	Workaround is simple:
net.inet.tcp.do_tcpdrain=0

	Fix:

add NET_LOCK_GIANT() / NET_UNLOCK_GIANT() into tcp_drain()
unless someone smarter than me claim that Giant is NOT required here
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list