If a user closes the socket before we call tcp_usr_abort(), then

tcp_drop() may unlock the INP.  Currently, tcp_usr_abort() does not
check for this case, which results in a panic while trying to unlock
the already-unlocked INP (not to mention, a use-after-free violation).

Make tcp_usr_abort() check the return value of tcp_drop(). In the case
where tcp_drop() returns NULL, tcp_usr_abort() can skip further steps
to abort the connection and simply unlock the INP_INFO lock prior to
returning.

Reviewed by:	glebius
MFC after:	2 weeks
Sponsored by:	Netflix, Inc.
This commit is contained in:
Jonathan T. Looney 2018-04-06 17:20:37 +00:00
parent 047a2ef697
commit 8fa799bd74
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=332120

View File

@ -1095,7 +1095,9 @@ tcp_usr_abort(struct socket *so)
!(inp->inp_flags & INP_DROPPED)) {
tp = intotcpcb(inp);
TCPDEBUG1();
tcp_drop(tp, ECONNABORTED);
tp = tcp_drop(tp, ECONNABORTED);
if (tp == NULL)
goto dropped;
TCPDEBUG2(PRU_ABORT);
TCP_PROBE2(debug__user, tp, PRU_ABORT);
}
@ -1106,6 +1108,7 @@ tcp_usr_abort(struct socket *so)
inp->inp_flags |= INP_SOCKREF;
}
INP_WUNLOCK(inp);
dropped:
INP_INFO_RUNLOCK(&V_tcbinfo);
}