git: ba3d547967c8 - main - tcp: Fix the SO_REUSEPORT_LB check
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 17 Jun 2025 11:27:59 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=ba3d547967c8759d0b974bdac0bda394a3e84312
commit ba3d547967c8759d0b974bdac0bda394a3e84312
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-06-17 11:22:26 +0000
Commit: Mark Johnston <markj@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+eecc86e6952fd9ba9f11@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);