The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ba3d547967c8759d0b974bdac0bda394a3e84312

commit ba3d547967c8759d0b974bdac0bda394a3e84312
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2025-06-17 11:22:26 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2025-06-17 11:22:26 +0000

    tcp: Fix the SO_REUSEPORT_LB check
    
    This needs to happen in tcp_connect() rather than tcp_usr_connect(), as
    the latter is reachable by implied connect() via sendto().
    
    Reviewed by:    glebius
    Reported by:    syzbot+eecc86e6952fd9ba9...@syzkaller.appspotmail.com
    Fixes:          c7f803c71dae ("inpcb: fix a panic with SO_REUSEPORT_LB + 
connect(2) misuse")
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D50893
---
 sys/netinet/tcp_usrreq.c                 |  8 ++++++--
 tests/sys/netinet/so_reuseport_lb_test.c | 10 ++++++++++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index cd273803dacf..3ea561e63503 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -523,7 +523,7 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, 
struct thread *td)
        }
        if ((error = prison_remote_ip4(td->td_ucred, &sinp->sin_addr)) != 0)
                goto out;
-       if (SOLISTENING(so) || so->so_options & SO_REUSEPORT_LB) {
+       if (SOLISTENING(so)) {
                error = EOPNOTSUPP;
                goto out;
        }
@@ -590,7 +590,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, 
struct thread *td)
                error = EAFNOSUPPORT;
                goto out;
        }
-       if (SOLISTENING(so) || so->so_options & SO_REUSEPORT_LB) {
+       if (SOLISTENING(so)) {
                error = EOPNOTSUPP;
                goto out;
        }
@@ -1478,6 +1478,8 @@ tcp_connect(struct tcpcb *tp, struct sockaddr_in *sin, 
struct thread *td)
            (SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING |
            SS_ISDISCONNECTED)) != 0))
                return (EISCONN);
+       if (__predict_false((so->so_options & SO_REUSEPORT_LB) != 0))
+               return (EOPNOTSUPP);
 
        INP_HASH_WLOCK(&V_tcbinfo);
        error = in_pcbconnect(inp, sin, td->td_ucred);
@@ -1520,6 +1522,8 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr_in6 *sin6, 
struct thread *td)
        if (__predict_false((so->so_state &
            (SS_ISCONNECTING | SS_ISCONNECTED)) != 0))
                return (EISCONN);
+       if (__predict_false((so->so_options & SO_REUSEPORT_LB) != 0))
+               return (EOPNOTSUPP);
 
        INP_HASH_WLOCK(&V_tcbinfo);
        error = in6_pcbconnect(inp, sin6, td->td_ucred, true);
diff --git a/tests/sys/netinet/so_reuseport_lb_test.c 
b/tests/sys/netinet/so_reuseport_lb_test.c
index a1b5a3f94f61..fa9d6e425884 100644
--- a/tests/sys/netinet/so_reuseport_lb_test.c
+++ b/tests/sys/netinet/so_reuseport_lb_test.c
@@ -505,6 +505,11 @@ ATF_TC_BODY(connect_not_bound, tc)
        ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP,
            "Expected EOPNOTSUPP on connect(2) not met. Got %d, errno %d",
            rv, errno);
+       rv = sendto(s, "test", 4, 0, (struct sockaddr *)&sin,
+           sizeof(sin));
+       ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP,
+           "Expected EOPNOTSUPP on sendto(2) not met. Got %d, errno %d",
+           rv, errno);
 
        close(p);
        close(s);
@@ -536,6 +541,11 @@ ATF_TC_BODY(connect_bound, tc)
        ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP,
            "Expected EOPNOTSUPP on connect(2) not met. Got %d, errno %d",
            rv, errno);
+       rv = sendto(s, "test", 4, 0, (struct sockaddr *)&sin,
+           sizeof(sin));
+       ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP,
+           "Expected EOPNOTSUPP on sendto(2) not met. Got %d, errno %d",
+           rv, errno);
 
        close(p);
        close(s);

Reply via email to