Panic in NFS (tcp_output) on -current

Skye Poier skye at isilon.com
Thu Oct 9 13:00:57 PDT 2003


Hi BSDers,

I'm running with an older version of -current and saw a panic from the
NFS server socket upcall which I'll describe in detail.  I had a close
look at the latest sources and there doesn't appear to be any changes
that would have prevented this panic.  Only ever seen this once in about
a year, so its a pretty rare but fatal case.  Not sure if it applies to
the 4.x branch but anyway...

Here's the stack dump:

	panic
	tcp_output
	tcp_usr_rcvd
	soreceive
	nfsrv_rcv
	sowakeup
	soisdisconnected
	tcp_close
	tcp_drop
	tcp_timer_keep
	softclock

Here's what's happening:  at the end of tcp_close (tcp_discardcb in
-current) the code does this:

	inp->inp_ppcb = NULL;
	...
	soisdisconnected(so);

soisdisconnected does a sorwakeup which calls the nfsrv_rcv upcall which
calls soreceive.  At the end of soreceive we have this:

        if ((flags & MSG_PEEK) == 0) {
		...
                if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
                        (*pr->pr_usrreqs->pru_rcvd)(so, flags);

Which calls tcp_usr_rcvd.  When it gets the TCP protocol control block
via intotcpcb(sotoinpcb(so)) it ends up with a NULL pointer because of
the assignment to inp_ppcb before calling soisdisconnected above.
Voila, panic in tcp_output on NULL deref.  This would also have happened
if any TCP socket upcall had tried to soreceive MSG_OOB under these
conditions.

My question is this, why is the TCP pcb disconnected from the inpcb
before calling soisdisconnected???  I don't see any benefit to doing
this half-way teardown BEFORE calling soisdisconnected - the only
possible uses (that I can see) of that variable would result in a panic
in every case.  And right after the soisdisconnected, the pcb is
destroyed.  The only thing that is ever checked is so->so_pcb which is
still valid.

Thoughts??  Seems like either the inp->inp_ppcb = NULL (and t_inpcb =
NULL in -current) should be moved AFTER the soisdisconnected, or the
socket should be torn down further (invalidate so->so_pcb?) before
calling soisdisconnected

Thanks!
Skye



More information about the freebsd-net mailing list