As a follow-on to r183323, correct another case where ip_output() was

called without an inpcb pointer despite holding the tcbinfo global
lock, which lead to a deadlock or panic when ipfw tried to further
acquire it recursively.

Reported by:    Stefan Ehmann <shoesoft at gmx dot net>
MFC after:      3 days
This commit is contained in:
Robert Watson 2008-09-25 17:26:54 +00:00
parent 4ea219803e
commit 014ea782b1

View File

@ -885,13 +885,29 @@ tcp_input(struct mbuf *m, int off0)
dropwithreset:
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
tcp_dropwithreset(m, th, tp, tlen, rstreason);
/*
* If inp is non-NULL, we call tcp_dropwithreset() holding both inpcb
* and global locks. However, if NULL, we must hold neither as
* firewalls may acquire the global lock in order to look for a
* matching inpcb.
*/
if (inp != NULL) {
tcp_dropwithreset(m, th, tp, tlen, rstreason);
INP_WUNLOCK(inp);
}
INP_INFO_WUNLOCK(&V_tcbinfo);
if (inp == NULL)
tcp_dropwithreset(m, th, NULL, tlen, rstreason);
m = NULL; /* mbuf chain got consumed. */
goto drop;
dropunlock:
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
if (inp != NULL)
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
drop:
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
if (s != NULL)