X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3e170ce000f1506b7b5d2c5c7faec85ceabb573d..490019cf9519204c5fb36b2fba54ceb983bb6b72:/bsd/netinet/in_pcb.c diff --git a/bsd/netinet/in_pcb.c b/bsd/netinet/in_pcb.c index 0cbd238cc..dce4177d4 100644 --- a/bsd/netinet/in_pcb.c +++ b/bsd/netinet/in_pcb.c @@ -714,11 +714,12 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct proc *p) return (EINVAL); if (!(so->so_options & (SO_REUSEADDR|SO_REUSEPORT))) wild = 1; - socket_unlock(so, 0); /* keep reference on socket */ - lck_rw_lock_exclusive(pcbinfo->ipi_lock); bzero(&laddr, sizeof(laddr)); + socket_unlock(so, 0); /* keep reference on socket */ + lck_rw_lock_exclusive(pcbinfo->ipi_lock); + if (nam != NULL) { if (nam->sa_len != sizeof (struct sockaddr_in)) { @@ -944,6 +945,17 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct proc *p) } } socket_lock(so, 0); + + /* + * We unlocked socket's protocol lock for a long time. + * The socket might have been dropped/defuncted. + * Checking if world has changed since. + */ + if (inp->inp_state == INPCB_STATE_DEAD) { + lck_rw_done(pcbinfo->ipi_lock); + return (ECONNABORTED); + } + if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY) { lck_rw_done(pcbinfo->ipi_lock); return (EINVAL); @@ -2039,7 +2051,13 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr, } /* - * Insert PCB onto various hash lists. + * @brief Insert PCB onto various hash lists. + * + * @param inp Pointer to internet protocol control block + * @param locked Implies if ipi_lock (protecting pcb list) + * is already locked or not. + * + * @return int error on failure and 0 on success */ int in_pcbinshash(struct inpcb *inp, int locked) @@ -2059,17 +2077,23 @@ in_pcbinshash(struct inpcb *inp, int locked) socket_unlock(inp->inp_socket, 0); lck_rw_lock_exclusive(pcbinfo->ipi_lock); socket_lock(inp->inp_socket, 0); - if (inp->inp_state == INPCB_STATE_DEAD) { - /* - * The socket got dropped when - * it was unlocked - */ - lck_rw_done(pcbinfo->ipi_lock); - return (ECONNABORTED); - } } } + /* + * This routine or its caller may have given up + * socket's protocol lock briefly. + * During that time the socket may have been dropped. + * Safe-guarding against that. + */ + if (inp->inp_state == INPCB_STATE_DEAD) { + if (!locked) { + lck_rw_done(pcbinfo->ipi_lock); + } + return (ECONNABORTED); + } + + #if INET6 if (inp->inp_vflag & INP_IPV6) hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */; @@ -2093,8 +2117,6 @@ in_pcbinshash(struct inpcb *inp, int locked) break; } - VERIFY(inp->inp_state != INPCB_STATE_DEAD); - /* * If none exists, malloc one and tack it on. */