From nobody Fri Mar 07 07:00:52 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Z8HHn2JSLzt5kL; Fri, 07 Mar 2025 07:00:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Z8HHn045hz3gmm; Fri, 07 Mar 2025 07:00:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1741330853; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=JvNVPK4VqFWWNTabFBBa5w+hiSym3DwYizvv2a/qn1Q=; b=HKRMjPHzqZTb4d9KgZQv+82ywnlcfJb05McJxQzb/uA7LcUuYv9N+EmHVzlV1kA7twO0ui yf73GwW52EGVjmKAR4asjTEnTYKgNoh/RrOOmjxp8hhbZVUN6CKoSVFlcTqYYyEeFOvgy2 TxWWIUcgh5bPoYwqZX6Dk341LudMPQkMK/h2X/PTTe4mocVL+3jWfoo6dDtXEW1b1LQMCN 0yFmJ3nDcFiKWf6V6TdBgKRP+0BgzaIRSyc0G9eQW6g3gFYVXRRniKp1FC4acG27ruNxdk yh+B0xHaejIHqZ0BA77pBZMBOzgOkFHUOHpJrr/ucZTtxQeNa1xtXB2XzecYFQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1741330853; a=rsa-sha256; cv=none; b=PYhuAwXmrUxldy7G8ogyV4QZcnay/4+eMOwa8FynPOBYrltKA5ijoMaQ+z+ukqSGXIaYyb wFp0Vi/isMWM3a3K8fQd8ntpEQPjRxDxWKLdKLianOviAqiqsz/elv2iGqqEahXAbrQuzv +ycDu5kADmIi1Euv24oevblz7RYVYdmQvIB8+azu8p05W/59yMjD39QME2G267d077U0pi jUbrlnA41xg8LSBYIUiSUW3waPy41+7Qxsvme8gIjcd9NM11fIFuDYFrQ+OO+mk9Cmk7S1 8bATeiZGPeAgaW4R2D5G9A0KTlqwViCMcvmG0fQNgSFNQ8h7/JryxERkfl2A1Q== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1741330853; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=JvNVPK4VqFWWNTabFBBa5w+hiSym3DwYizvv2a/qn1Q=; b=wNHpmuue+5ObWbBR10dP1dK9xZESeBjEzNRj0W3u1UBaZFrp7abKcHpkcCChTL4Dag7Rcn Q2HdtFUCRguHk+74NXDag8Z1QA889VsBoCxztu3Pu05WaThxpy0v33kGqcBR2MJadkD4BY FwEWnbjAyROwtS5nPRhL3yW/L2EIYcKsxZuZATD+9kYyFKdHZDKB/vF62nKbtX8wczjE0x NnwoBamK4hlVfH8LR4MQ443FV49z5p5OT4wODyEPP8CUFHRFxWeWUpWrr7jSFQxhTiMYNY vkKQ7nRJQqLDiqPRXiPogfan9YGyfcR4IDv2vG0gDs3KzQhfNWTp6vkdCo6/Qw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Z8HHm6cDZz9hh; Fri, 07 Mar 2025 07:00:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 52770qvJ060720; Fri, 7 Mar 2025 07:00:52 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 52770qIu060717; Fri, 7 Mar 2025 07:00:52 GMT (envelope-from git) Date: Fri, 7 Mar 2025 07:00:52 GMT Message-Id: <202503070700.52770qIu060717@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: c7f803c71dae - main - inpcb: fix a panic with SO_REUSEPORT_LB + connect(2) misuse List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c7f803c71dae9ca64abccc0b17e9014fe66e6d21 Auto-Submitted: auto-generated The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=c7f803c71dae9ca64abccc0b17e9014fe66e6d21 commit c7f803c71dae9ca64abccc0b17e9014fe66e6d21 Author: Gleb Smirnoff AuthorDate: 2025-03-07 06:57:44 +0000 Commit: Gleb Smirnoff CommitDate: 2025-03-07 06:57:44 +0000 inpcb: fix a panic with SO_REUSEPORT_LB + connect(2) misuse This combination doesn't make any sense. This socket option makes sense only on a socket that is going to be a listening one. There are two options here: refuse connect(2) on a socket that has the option set previously, or ignore (and clear) the option. After some discussion on phabricator, we have chosen the former, for safety and consistency reasons. Any programmer that runs this sequence is doing something wrong and should be informed of that with appropriate error code. Since connect(2) is a SUS API that has a defined set of error codes, none of which corresponds to "a socket has non-standard incompatible socket option set", we decided to return the same error that an already listening socket would return. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D49150 --- sys/netinet/tcp_usrreq.c | 4 +- tests/sys/netinet/so_reuseport_lb_test.c | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 03687c1d3515..13e66f758d45 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -526,7 +526,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)) { + if (SOLISTENING(so) || so->so_options & SO_REUSEPORT_LB) { error = EOPNOTSUPP; goto out; } @@ -593,7 +593,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) error = EAFNOSUPPORT; goto out; } - if (SOLISTENING(so)) { + if (SOLISTENING(so) || so->so_options & SO_REUSEPORT_LB) { error = EOPNOTSUPP; goto out; } diff --git a/tests/sys/netinet/so_reuseport_lb_test.c b/tests/sys/netinet/so_reuseport_lb_test.c index aaadaead5e23..a1b5a3f94f61 100644 --- a/tests/sys/netinet/so_reuseport_lb_test.c +++ b/tests/sys/netinet/so_reuseport_lb_test.c @@ -478,6 +478,69 @@ ATF_TC_BODY(bind_without_listen, tc) ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno)); } +/* + * Check that SO_REUSEPORT_LB doesn't mess with connect(2). + * Two sockets: + * 1) auxiliary peer socket 'p', where we connect to + * 2) test socket 's', that sets SO_REUSEPORT_LB and then connect(2)s to 'p' + */ +ATF_TC_WITHOUT_HEAD(connect_not_bound); +ATF_TC_BODY(connect_not_bound, tc) +{ + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_len = sizeof(sin), + .sin_addr = { htonl(INADDR_LOOPBACK) }, + }; + socklen_t slen = sizeof(struct sockaddr_in); + int p, s, rv; + + ATF_REQUIRE((p = socket(PF_INET, SOCK_STREAM, 0)) > 0); + ATF_REQUIRE(bind(p, (struct sockaddr *)&sin, sizeof(sin)) == 0); + ATF_REQUIRE(listen(p, 1) == 0); + ATF_REQUIRE(getsockname(p, (struct sockaddr *)&sin, &slen) == 0); + + s = lb_listen_socket(PF_INET, 0); + rv = connect(s, (struct sockaddr *)&sin, sizeof(sin)); + ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP, + "Expected EOPNOTSUPP on connect(2) not met. Got %d, errno %d", + rv, errno); + + close(p); + close(s); +} + +/* + * Same as above, but we also bind(2) between setsockopt(2) of SO_REUSEPORT_LB + * and the connect(2). + */ +ATF_TC_WITHOUT_HEAD(connect_bound); +ATF_TC_BODY(connect_bound, tc) +{ + struct sockaddr_in sin = { + .sin_family = AF_INET, + .sin_len = sizeof(sin), + .sin_addr = { htonl(INADDR_LOOPBACK) }, + }; + socklen_t slen = sizeof(struct sockaddr_in); + int p, s, rv; + + ATF_REQUIRE((p = socket(PF_INET, SOCK_STREAM, 0)) > 0); + ATF_REQUIRE(bind(p, (struct sockaddr *)&sin, sizeof(sin)) == 0); + ATF_REQUIRE(listen(p, 1) == 0); + + s = lb_listen_socket(PF_INET, 0); + ATF_REQUIRE(bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0); + ATF_REQUIRE(getsockname(p, (struct sockaddr *)&sin, &slen) == 0); + rv = connect(s, (struct sockaddr *)&sin, sizeof(sin)); + ATF_REQUIRE_MSG(rv == -1 && errno == EOPNOTSUPP, + "Expected EOPNOTSUPP on connect(2) not met. Got %d, errno %d", + rv, errno); + + close(p); + close(s); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, basic_ipv4); @@ -486,6 +549,8 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, double_listen_ipv4); ATF_TP_ADD_TC(tp, double_listen_ipv6); ATF_TP_ADD_TC(tp, bind_without_listen); + ATF_TP_ADD_TC(tp, connect_not_bound); + ATF_TP_ADD_TC(tp, connect_bound); return (atf_no_error()); }