Fix a kernel assertion issue introduced with r286227:

Avoid too strict INP_INFO_RLOCK_ASSERT checks due to
tcp_notify() being called from in6_pcbnotify().

Reported by:	Larry Rosenman <ler@lerctr.org>
Submitted by:	markj, jch
This commit is contained in:
jch 2015-08-08 08:40:36 +00:00
parent 607712fac9
commit 349429fe82
4 changed files with 13 additions and 7 deletions

View File

@ -1259,7 +1259,7 @@ in_pcbfree(struct inpcb *inp)
#ifdef INVARIANTS
if (pcbinfo == &V_tcbinfo) {
INP_INFO_RLOCK_ASSERT(pcbinfo);
INP_INFO_LOCK_ASSERT(pcbinfo);
} else {
INP_INFO_WLOCK_ASSERT(pcbinfo);
}

View File

@ -491,6 +491,7 @@ short inp_so_options(const struct inpcb *inp);
#define INP_INFO_TRY_RLOCK(ipi) rw_try_rlock(&(ipi)->ipi_lock)
#define INP_INFO_TRY_WLOCK(ipi) rw_try_wlock(&(ipi)->ipi_lock)
#define INP_INFO_TRY_UPGRADE(ipi) rw_try_upgrade(&(ipi)->ipi_lock)
#define INP_INFO_WLOCKED(ipi) rw_wowned(&(ipi)->ipi_lock)
#define INP_INFO_RUNLOCK(ipi) rw_runlock(&(ipi)->ipi_lock)
#define INP_INFO_WUNLOCK(ipi) rw_wunlock(&(ipi)->ipi_lock)
#define INP_INFO_LOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_LOCKED)

View File

@ -906,7 +906,7 @@ tcp_drop(struct tcpcb *tp, int errno)
{
struct socket *so = tp->t_inpcb->inp_socket;
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_INFO_LOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(tp->t_inpcb);
if (TCPS_HAVERCVDSYN(tp->t_state)) {
@ -1108,7 +1108,7 @@ tcp_close(struct tcpcb *tp)
struct inpcb *inp = tp->t_inpcb;
struct socket *so;
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_INFO_LOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
#ifdef TCP_OFFLOAD
@ -1186,7 +1186,7 @@ tcp_notify(struct inpcb *inp, int error)
{
struct tcpcb *tp;
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_INFO_LOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
if ((inp->inp_flags & INP_TIMEWAIT) ||

View File

@ -163,7 +163,7 @@ tcp_detach(struct socket *so, struct inpcb *inp)
{
struct tcpcb *tp;
INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_INFO_LOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
KASSERT(so->so_pcb == inp, ("tcp_detach: so_pcb != inp"));
@ -241,15 +241,20 @@ static void
tcp_usr_detach(struct socket *so)
{
struct inpcb *inp;
int rlock = 0;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_detach: inp == NULL"));
INP_INFO_RLOCK(&V_tcbinfo);
if (!INP_INFO_WLOCKED(&V_tcbinfo)) {
INP_INFO_RLOCK(&V_tcbinfo);
rlock = 1;
}
INP_WLOCK(inp);
KASSERT(inp->inp_socket != NULL,
("tcp_usr_detach: inp_socket == NULL"));
tcp_detach(so, inp);
INP_INFO_RUNLOCK(&V_tcbinfo);
if (rlock)
INP_INFO_RUNLOCK(&V_tcbinfo);
}
#ifdef INET