Author: glebius
Date: Thu Nov  7 20:49:56 2019
New Revision: 354477
URL: https://svnweb.freebsd.org/changeset/base/354477

Log:
  Since r353292 on input path we are always in network epoch, when
  we lookup PCBs.  Thus, do not enter epoch recursively in
  in_pcblookup_hash() and in6_pcblookup_hash().  Same applies to
  tcp_ctlinput() and tcp6_ctlinput().
  
  This leaves several sysctl(9) handlers that return PCB credentials
  unprotected.  Add epoch enter/exit to all of them.
  
  Differential Revision:        https://reviews.freebsd.org/D22197

Modified:
  head/sys/netinet/in_pcb.c
  head/sys/netinet/tcp_subr.c
  head/sys/netinet/udp_usrreq.c
  head/sys/netinet6/in6_pcb.c
  head/sys/netinet6/udp6_usrreq.c

Modified: head/sys/netinet/in_pcb.c
==============================================================================
--- head/sys/netinet/in_pcb.c   Thu Nov  7 20:44:34 2019        (r354476)
+++ head/sys/netinet/in_pcb.c   Thu Nov  7 20:49:56 2019        (r354477)
@@ -2252,12 +2252,10 @@ in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, st
        struct inpcb *inp, *tmpinp;
        u_short fport = fport_arg, lport = lport_arg;
 
-#ifdef INVARIANTS
        KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
            ("%s: invalid lookup flags %d", __func__, lookupflags));
-       if (!mtx_owned(&pcbinfo->ipi_hash_lock))
-               MPASS(in_epoch_verbose(net_epoch_preempt, 1));
-#endif
+       INP_HASH_LOCK_ASSERT(pcbinfo);
+
        /*
         * First look for an exact match.
         */
@@ -2384,7 +2382,6 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in
 {
        struct inpcb *inp;
 
-       INP_HASH_RLOCK(pcbinfo);
        inp = in_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
            (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp);
        if (inp != NULL) {
@@ -2411,7 +2408,7 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in
                }
 #endif
        }
-       INP_HASH_RUNLOCK(pcbinfo);
+
        return (inp);
 }
 

Modified: head/sys/netinet/tcp_subr.c
==============================================================================
--- head/sys/netinet/tcp_subr.c Thu Nov  7 20:44:34 2019        (r354476)
+++ head/sys/netinet/tcp_subr.c Thu Nov  7 20:49:56 2019        (r354477)
@@ -2257,6 +2257,7 @@ tcp_getcred(SYSCTL_HANDLER_ARGS)
 {
        struct xucred xuc;
        struct sockaddr_in addrs[2];
+       struct epoch_tracker et;
        struct inpcb *inp;
        int error;
 
@@ -2266,8 +2267,10 @@ tcp_getcred(SYSCTL_HANDLER_ARGS)
        error = SYSCTL_IN(req, addrs, sizeof(addrs));
        if (error)
                return (error);
+       NET_EPOCH_ENTER(et);
        inp = in_pcblookup(&V_tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
            addrs[0].sin_addr, addrs[0].sin_port, INPLOOKUP_RLOCKPCB, NULL);
+       NET_EPOCH_EXIT(et);
        if (inp != NULL) {
                if (inp->inp_socket == NULL)
                        error = ENOENT;
@@ -2292,6 +2295,7 @@ SYSCTL_PROC(_net_inet_tcp, OID_AUTO, getcred,
 static int
 tcp6_getcred(SYSCTL_HANDLER_ARGS)
 {
+       struct epoch_tracker et;
        struct xucred xuc;
        struct sockaddr_in6 addrs[2];
        struct inpcb *inp;
@@ -2319,6 +2323,7 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS)
                        return (EINVAL);
        }
 
+       NET_EPOCH_ENTER(et);
 #ifdef INET
        if (mapped == 1)
                inp = in_pcblookup(&V_tcbinfo,
@@ -2332,6 +2337,7 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS)
                        &addrs[1].sin6_addr, addrs[1].sin6_port,
                        &addrs[0].sin6_addr, addrs[0].sin6_port,
                        INPLOOKUP_RLOCKPCB, NULL);
+       NET_EPOCH_EXIT(et);
        if (inp != NULL) {
                if (inp->inp_socket == NULL)
                        error = ENOENT;
@@ -2365,7 +2371,6 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
        struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
        struct icmp *icp;
        struct in_conninfo inc;
-       struct epoch_tracker et;
        tcp_seq icmp_tcp_seq;
        int mtu;
 
@@ -2397,7 +2402,6 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
 
        icp = (struct icmp *)((caddr_t)ip - offsetof(struct icmp, icmp_ip));
        th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
-       INP_INFO_RLOCK_ET(&V_tcbinfo, et);
        inp = in_pcblookup(&V_tcbinfo, faddr, th->th_dport, ip->ip_src,
            th->th_sport, INPLOOKUP_WLOCKPCB, NULL);
        if (inp != NULL && PRC_IS_REDIRECT(cmd)) {
@@ -2462,7 +2466,6 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
 out:
        if (inp != NULL)
                INP_WUNLOCK(inp);
-       INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
 }
 #endif /* INET */
 
@@ -2480,7 +2483,6 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
        struct ip6ctlparam *ip6cp = NULL;
        const struct sockaddr_in6 *sa6_src = NULL;
        struct in_conninfo inc;
-       struct epoch_tracker et;
        struct tcp_ports {
                uint16_t th_sport;
                uint16_t th_dport;
@@ -2542,7 +2544,6 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
        }
        bzero(&t_ports, sizeof(struct tcp_ports));
        m_copydata(m, off, sizeof(struct tcp_ports), (caddr_t)&t_ports);
-       INP_INFO_RLOCK_ET(&V_tcbinfo, et);
        inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_dst, t_ports.th_dport,
            &ip6->ip6_src, t_ports.th_sport, INPLOOKUP_WLOCKPCB, NULL);
        if (inp != NULL && PRC_IS_REDIRECT(cmd)) {
@@ -2614,7 +2615,6 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
 out:
        if (inp != NULL)
                INP_WUNLOCK(inp);
-       INP_INFO_RUNLOCK_ET(&V_tcbinfo, et);
 }
 #endif /* INET6 */
 

Modified: head/sys/netinet/udp_usrreq.c
==============================================================================
--- head/sys/netinet/udp_usrreq.c       Thu Nov  7 20:44:34 2019        
(r354476)
+++ head/sys/netinet/udp_usrreq.c       Thu Nov  7 20:49:56 2019        
(r354477)
@@ -963,6 +963,7 @@ udp_getcred(SYSCTL_HANDLER_ARGS)
 {
        struct xucred xuc;
        struct sockaddr_in addrs[2];
+       struct epoch_tracker et;
        struct inpcb *inp;
        int error;
 
@@ -972,9 +973,11 @@ udp_getcred(SYSCTL_HANDLER_ARGS)
        error = SYSCTL_IN(req, addrs, sizeof(addrs));
        if (error)
                return (error);
+       NET_EPOCH_ENTER(et);
        inp = in_pcblookup(&V_udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
            addrs[0].sin_addr, addrs[0].sin_port,
            INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL);
+       NET_EPOCH_EXIT(et);
        if (inp != NULL) {
                INP_RLOCK_ASSERT(inp);
                if (inp->inp_socket == NULL)

Modified: head/sys/netinet6/in6_pcb.c
==============================================================================
--- head/sys/netinet6/in6_pcb.c Thu Nov  7 20:44:34 2019        (r354476)
+++ head/sys/netinet6/in6_pcb.c Thu Nov  7 20:49:56 2019        (r354477)
@@ -1245,7 +1245,6 @@ in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct i
 {
        struct inpcb *inp;
 
-       INP_HASH_RLOCK(pcbinfo);
        inp = in6_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
            (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp);
        if (inp != NULL) {
@@ -1272,7 +1271,6 @@ in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct i
                }
 #endif
        }
-       INP_HASH_RUNLOCK(pcbinfo);
        return (inp);
 }
 

Modified: head/sys/netinet6/udp6_usrreq.c
==============================================================================
--- head/sys/netinet6/udp6_usrreq.c     Thu Nov  7 20:44:34 2019        
(r354476)
+++ head/sys/netinet6/udp6_usrreq.c     Thu Nov  7 20:49:56 2019        
(r354477)
@@ -634,6 +634,7 @@ udp6_getcred(SYSCTL_HANDLER_ARGS)
 {
        struct xucred xuc;
        struct sockaddr_in6 addrs[2];
+       struct epoch_tracker et;
        struct inpcb *inp;
        int error;
 
@@ -652,9 +653,11 @@ udp6_getcred(SYSCTL_HANDLER_ARGS)
            (error = sa6_embedscope(&addrs[1], V_ip6_use_defzone)) != 0) {
                return (error);
        }
+       NET_EPOCH_ENTER(et);
        inp = in6_pcblookup(&V_udbinfo, &addrs[1].sin6_addr,
            addrs[1].sin6_port, &addrs[0].sin6_addr, addrs[0].sin6_port,
            INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL);
+       NET_EPOCH_EXIT(et);
        if (inp != NULL) {
                INP_RLOCK_ASSERT(inp);
                if (inp->inp_socket == NULL)
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to