From ee0a5eb928ae5ccdf1a0e619b4ba6e93d19db5fb Mon Sep 17 00:00:00 2001 From: ups Date: Tue, 18 Jul 2006 22:34:27 +0000 Subject: Fix race conditions on enumerating pcb lists by moving the initialization ( and where appropriate the destruction) of the pcb mutex to the init/finit functions of the pcb zones. This allows locking of the pcb entries and race condition free comparison of the generation count. Rearrange locking a bit to avoid extra locking operation to update the generation count in in_pcballoc(). (in_pcballoc now returns the pcb locked) I am planning to convert pcb list handling from a type safe to a reference count model soon. ( As this allows really freeing the PCBs) Reviewed by: rwatson@, mohans@ MFC after: 1 week --- sys/netinet/in_pcb.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'sys/netinet/in_pcb.c') diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 37386d7..ddb9e3c 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -167,19 +167,20 @@ SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, randomtime, CTLFLAG_RW, /* * Allocate a PCB and associate it with the socket. + * On success return with the PCB locked. */ int -in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo, const char *type) +in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo) { struct inpcb *inp; int error; INP_INFO_WLOCK_ASSERT(pcbinfo); error = 0; - inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT | M_ZERO); + inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT); if (inp == NULL) return (ENOBUFS); - inp->inp_gencnt = ++pcbinfo->ipi_gencnt; + bzero(inp,inp_zero_size); inp->inp_pcbinfo = pcbinfo; inp->inp_socket = so; #ifdef MAC @@ -209,11 +210,13 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo, const char *type) LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list); pcbinfo->ipi_count++; so->so_pcb = (caddr_t)inp; - INP_LOCK_INIT(inp, "inp", type); #ifdef INET6 if (ip6_auto_flowlabel) inp->inp_flags |= IN6P_AUTOFLOWLABEL; #endif + INP_LOCK(inp); + inp->inp_gencnt = ++pcbinfo->ipi_gencnt; + #if defined(IPSEC) || defined(FAST_IPSEC) || defined(MAC) out: if (error != 0) @@ -721,10 +724,11 @@ in_pcbfree(struct inpcb *inp) (void)m_free(inp->inp_options); ip_freemoptions(inp->inp_moptions); inp->inp_vflag = 0; - INP_LOCK_DESTROY(inp); + #ifdef MAC mac_destroy_inpcb(inp); #endif + INP_UNLOCK(inp); uma_zfree(ipi->ipi_zone, inp); } -- cgit v1.1