Index: sys/net/if.c =================================================================== --- sys/net/if.c (revision 323578) +++ sys/net/if.c (working copy) @@ -525,10 +525,10 @@ if_free(struct ifnet *ifp) { - ifp->if_flags |= IFF_DYING; /* XXX: Locking */ + IFNET_WLOCK(); + ifp->if_flags |= IFF_DYING; CURVNET_SET_QUIET(ifp->if_vnet); - IFNET_WLOCK(); KASSERT(ifp == ifnet_byindex_locked(ifp->if_index), ("%s: freeing unallocated ifnet", ifp->if_xname)); Index: sys/netinet/ip_input.c =================================================================== --- sys/netinet/ip_input.c (revision 323578) +++ sys/netinet/ip_input.c (working copy) @@ -410,15 +411,26 @@ ip_input(struct mbuf *m) IP_PROBE(receive, NULL, NULL, ip, m->m_pkthdr.rcvif, ip, NULL); - /* 127/8 must not appear on wire - RFC1122 */ + IFNET_RLOCK_NOSLEEP(); ifp = m->m_pkthdr.rcvif; + if (ifp == NULL || (ifp->if_flags & IFF_DYING)) { + IFNET_RUNLOCK_NOSLEEP(); + IPSTAT_INC(ips_odropped); + goto bad; + } + if_ref(ifp); + IFNET_RUNLOCK_NOSLEEP(); + + /* 127/8 must not appear on wire - RFC1122 */ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { if ((ifp->if_flags & IFF_LOOPBACK) == 0) { IPSTAT_INC(ips_badaddr); + if_rele(ifp); goto bad; } } + if_rele(ifp); if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) { sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID); @@ -490,9 +502,13 @@ tooshort: if (m == NULL) /* consumed by filter */ return; + /* + * PFIL may have changed m->m_pkthdr.rcvif (ifp), + * so do not use ifp from this point without re-init/lock. + */ + ip = mtod(m, struct ip *); dchg = (odst.s_addr != ip->ip_dst.s_addr); - ifp = m->m_pkthdr.rcvif; if (m->m_flags & M_FASTFWD_OURS) { m->m_flags &= ~M_FASTFWD_OURS; @@ -539,6 +555,16 @@ passin: (m->m_flags & (M_MCAST|M_BCAST)) == 0) goto ours; + IFNET_RLOCK_NOSLEEP(); + ifp = m->m_pkthdr.rcvif; + if (ifp == NULL || (ifp->if_flags & IFF_DYING)) { + IFNET_RUNLOCK_NOSLEEP(); + IPSTAT_INC(ips_odropped); + goto bad; + } + if_ref(ifp); + IFNET_RUNLOCK_NOSLEEP(); + /* * Enable a consistency check between the destination address * and the arrival interface for a unicast packet (the RFC 1122 @@ -558,13 +584,13 @@ passin: * checked with carp_iamatch() and carp_forus(). */ checkif = V_ip_checkinterface && (V_ipforwarding == 0) && - ifp != NULL && ((ifp->if_flags & IFF_LOOPBACK) == 0) && + ((ifp->if_flags & IFF_LOOPBACK) == 0) && ifp->if_carp == NULL && (dchg == 0); /* * Check for exact addresses in the hash bucket. */ - /* IN_IFADDR_RLOCK(); */ + IN_IFADDR_RLOCK(); LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) { /* * If the address matches, verify that the packet @@ -574,11 +600,11 @@ passin: if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr && (!checkif || ia->ia_ifp == ifp)) { ifa_ref(&ia->ia_ifa); - /* IN_IFADDR_RUNLOCK(); */ - goto ours; + IN_IFADDR_RUNLOCK(); + goto ours_rele; } } - /* IN_IFADDR_RUNLOCK(); */ + IN_IFADDR_RUNLOCK(); /* * Check for broadcast addresses. @@ -588,7 +614,7 @@ passin: * be handled via ip_forward() and ether_output() with the loopback * into the stack for SIMPLEX interfaces handled by ether_output(). */ - if (ifp != NULL && ifp->if_flags & IFF_BROADCAST) { + if (ifp->if_flags & IFF_BROADCAST) { IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { if (ifa->ifa_addr->sa_family != AF_INET) @@ -598,19 +624,20 @@ passin: ip->ip_dst.s_addr) { ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); - goto ours; + goto ours_rele; } #ifdef BOOTP_COMPAT if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY) { ifa_ref(ifa); IF_ADDR_RUNLOCK(ifp); - goto ours; + goto ours_rele; } #endif } IF_ADDR_RUNLOCK(ifp); ia = NULL; } + if_rele(ifp); /* RFC 3927 2.7: Do not forward datagrams for 169.254.0.0/16. */ if (IN_LINKLOCAL(ntohl(ip->ip_dst.s_addr))) { IPSTAT_INC(ips_cantforward); @@ -681,6 +708,8 @@ passin: } return; +ours_rele: + if_rele(ifp); ours: #ifdef IPSTEALTH /*