Date: Thu, 9 Oct 2003 12:53:19 -0700 From: Skye Poier <skye@isilon.com> To: freebsd-net@freebsd.org Subject: Panic in NFS (tcp_output) on -current Message-ID: <20031009195319.GE929@isilon.com>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031009195319.GE929>