mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-26 10:53:39 +01:00
inpcb: reoder inpcb destruction
First, merge in_pcbdetach() with in_pcbfree(). The comment for in_pcbdetach() was no longer correct. Then, make sure we remove the inpcb from the hash before we commit any destructive actions on it. There are couple functions that rely on the hash lock skipping SMR + inpcb lock to lookup an inpcb. Although there are no known functions that similarly rely on the global inpcb list lock, also do list removal before destructive actions. PR: 273890 Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D43122
This commit is contained in:
parent
2b1c477d88
commit
a13039e270
@ -1403,26 +1403,6 @@ in_pcbdisconnect(struct inpcb *inp)
|
||||
}
|
||||
#endif /* INET */
|
||||
|
||||
/*
|
||||
* in_pcbdetach() is responsibe for disassociating a socket from an inpcb.
|
||||
* For most protocols, this will be invoked immediately prior to calling
|
||||
* in_pcbfree(). However, with TCP the inpcb may significantly outlive the
|
||||
* socket, in which case in_pcbfree() is deferred.
|
||||
*/
|
||||
void
|
||||
in_pcbdetach(struct inpcb *inp)
|
||||
{
|
||||
|
||||
KASSERT(inp->inp_socket != NULL, ("%s: inp_socket == NULL", __func__));
|
||||
|
||||
#ifdef RATELIMIT
|
||||
if (inp->inp_snd_tag != NULL)
|
||||
in_pcbdetach_txrtlmt(inp);
|
||||
#endif
|
||||
inp->inp_socket->so_pcb = NULL;
|
||||
inp->inp_socket = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* inpcb hash lookups are protected by SMR section.
|
||||
*
|
||||
@ -1733,19 +1713,30 @@ in_pcbfree(struct inpcb *inp)
|
||||
#endif
|
||||
|
||||
INP_WLOCK_ASSERT(inp);
|
||||
KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL", __func__));
|
||||
KASSERT(inp->inp_socket != NULL, ("%s: inp_socket == NULL", __func__));
|
||||
KASSERT((inp->inp_flags & INP_FREED) == 0,
|
||||
("%s: called twice for pcb %p", __func__, inp));
|
||||
|
||||
inp->inp_flags |= INP_FREED;
|
||||
/*
|
||||
* in_pcblookup_local() and in6_pcblookup_local() may return an inpcb
|
||||
* from the hash without acquiring inpcb lock, they rely on the hash
|
||||
* lock, thus in_pcbremhash() should be the first action.
|
||||
*/
|
||||
if (inp->inp_flags & INP_INHASHLIST)
|
||||
in_pcbremhash(inp);
|
||||
INP_INFO_WLOCK(pcbinfo);
|
||||
inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
|
||||
pcbinfo->ipi_count--;
|
||||
CK_LIST_REMOVE(inp, inp_list);
|
||||
INP_INFO_WUNLOCK(pcbinfo);
|
||||
|
||||
if (inp->inp_flags & INP_INHASHLIST)
|
||||
in_pcbremhash(inp);
|
||||
#ifdef RATELIMIT
|
||||
if (inp->inp_snd_tag != NULL)
|
||||
in_pcbdetach_txrtlmt(inp);
|
||||
#endif
|
||||
inp->inp_flags |= INP_FREED;
|
||||
inp->inp_socket->so_pcb = NULL;
|
||||
inp->inp_socket = NULL;
|
||||
|
||||
RO_INVALIDATE_CACHE(&inp->inp_route);
|
||||
#ifdef MAC
|
||||
|
@ -670,7 +670,6 @@ int in_pcbconnect(struct inpcb *, struct sockaddr_in *, struct ucred *,
|
||||
bool);
|
||||
int in_pcbconnect_setup(struct inpcb *, struct sockaddr_in *, in_addr_t *,
|
||||
u_short *, in_addr_t *, u_short *, struct ucred *);
|
||||
void in_pcbdetach(struct inpcb *);
|
||||
void in_pcbdisconnect(struct inpcb *);
|
||||
void in_pcbdrop(struct inpcb *);
|
||||
void in_pcbfree(struct inpcb *);
|
||||
|
@ -860,7 +860,6 @@ rip_detach(struct socket *so)
|
||||
ip_rsvp_force_done(so);
|
||||
if (so == V_ip_rsvpd)
|
||||
ip_rsvp_done();
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
}
|
||||
|
||||
|
@ -803,7 +803,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
|
||||
}
|
||||
inp = sotoinpcb(so);
|
||||
if ((tp = tcp_newtcpcb(inp)) == NULL) {
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
sodealloc(so);
|
||||
goto allocfail;
|
||||
@ -1051,7 +1050,6 @@ allocfail:
|
||||
return (NULL);
|
||||
|
||||
abort:
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
sodealloc(so);
|
||||
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
|
||||
|
@ -175,7 +175,6 @@ tcp_usr_attach(struct socket *so, int proto, struct thread *td)
|
||||
tp = tcp_newtcpcb(inp);
|
||||
if (tp == NULL) {
|
||||
error = ENOBUFS;
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
goto out;
|
||||
}
|
||||
@ -213,7 +212,6 @@ tcp_usr_detach(struct socket *so)
|
||||
("%s: inp %p not dropped or embryonic", __func__, inp));
|
||||
|
||||
tcp_discardcb(tp);
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
}
|
||||
|
||||
|
@ -1641,7 +1641,6 @@ udp_detach(struct socket *so)
|
||||
KASSERT(inp->inp_faddr.s_addr == INADDR_ANY,
|
||||
("udp_detach: not disconnected"));
|
||||
INP_WLOCK(inp);
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
}
|
||||
|
||||
|
@ -687,7 +687,6 @@ rip6_detach(struct socket *so)
|
||||
/* xxx: RSVP */
|
||||
INP_WLOCK(inp);
|
||||
free(inp->in6p_icmp6filt, M_PCB);
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
}
|
||||
|
||||
|
@ -1201,7 +1201,6 @@ udp6_detach(struct socket *so)
|
||||
KASSERT(inp != NULL, ("udp6_detach: inp == NULL"));
|
||||
|
||||
INP_WLOCK(inp);
|
||||
in_pcbdetach(inp);
|
||||
in_pcbfree(inp);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user