git: 4287aa56197f - main - tcp_usr_shutdown: don't cast inp_ppcb to tcpcb before checking inp_flags
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 28 Dec 2021 16:53:24 UTC
The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=4287aa56197fc2e37cad07c23b52f9ed4f1a7fd0 commit 4287aa56197fc2e37cad07c23b52f9ed4f1a7fd0 Author: Gleb Smirnoff <glebius@FreeBSD.org> AuthorDate: 2021-12-28 16:50:02 +0000 Commit: Gleb Smirnoff <glebius@FreeBSD.org> CommitDate: 2021-12-28 16:50:02 +0000 tcp_usr_shutdown: don't cast inp_ppcb to tcpcb before checking inp_flags While here move out one more erroneous condition out of the epoch and common return. The only functional change is that if we send control on a shut down socket we would get EINVAL instead of ECONNRESET. Reviewed by: tuexen Reported by: syzbot+8388cf7f401a7b6bece6@syzkaller.appspotmail.com Fixes: f64dc2ab5be38e5366271ef85ea90d8cb1c7841a --- sys/netinet/tcp_usrreq.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 2dea7253e0d6..def7d477c72b 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -993,34 +993,31 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m, bool restoreflags; TCPDEBUG0; - /* - * We require the pcbinfo "read lock" if we will close the socket - * as part of this call. - */ - NET_EPOCH_ENTER(et); - inp = sotoinpcb(so); - KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL")); - INP_WLOCK(inp); - tp = intotcpcb(inp); - vflagsav = inp->inp_vflag; - incflagsav = inp->inp_inc.inc_flags; - restoreflags = false; - if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { - if (control) - m_freem(control); - error = ECONNRESET; - goto out; - } if (control != NULL) { /* TCP doesn't do control messages (rights, creds, etc) */ if (control->m_len) { m_freem(control); - error = EINVAL; - goto out; + return (EINVAL); } m_freem(control); /* empty control, just free it */ - control = NULL; } + + inp = sotoinpcb(so); + KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL")); + INP_WLOCK(inp); + if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { + if (m != NULL && (flags & PRUS_NOTREADY) == 0) + m_freem(m); + INP_WUNLOCK(inp); + return (ECONNRESET); + } + + vflagsav = inp->inp_vflag; + incflagsav = inp->inp_inc.inc_flags; + restoreflags = false; + tp = intotcpcb(inp); + + NET_EPOCH_ENTER(et); if ((flags & PRUS_OOB) != 0 && (error = tcp_pru_options_support(tp, PRUS_OOB)) != 0) goto out;