From nobody Thu Aug 13 15:00:01 2026 X-Original-To: dev-commits-src-all@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 4hLT6t6ZKMz6np6j for ; Thu, 13 Aug 2026 15:00:06 +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 "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hLT6t4JBxz3CmS for ; Thu, 13 Aug 2026 15:00:06 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1786633206; 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=myGRWxqEB/1m8XGSMbpzu7Bh3vBlySZ0rmKcfr6jLS8=; b=LOli5owO+fbtCyPFCN8rCXkZNgU+8GkA1zqNVa9egQ5jI3ZZxpRv63TgIlL4H7VzjLwNQJ zUuyvwZkqM8jljueTVmpyWHBc/p+ptCXFanZoVzuW/zE0Hxm1m1Jcs+qSA+xd9jWZJSebQ +OMB+wlDG2adJ1R+NEQ6HpiKnDL0bcHSvfdQ76dt1aiRn0lsTshg/+PxA3o8uxEmRnjYzJ z0lbaejlVWrmN3NCHW99fVJBEU9bBWme4Q8ApdMbp7j3UvGOUW7aCDhv0Zz0boeOew7jQr NIfxZnjFVNgwFRM9ukVXxkYMKnCeXhn4qYxs7jBPzTAFXYgEv5r7qGYVsbr92A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1786633206; a=rsa-sha256; cv=none; b=nUzkWEwISCxMETAv3asWs8aFYECiIecveaUbwLdeva4j5PdVtyU6RcF6zsJ1KFSvUgX+LX E6HyjnolYinH3rmnT4RvotEquR2EEDkNdRYW4jxlWSBik4lbrt8k8Xt/NRNqxLG5NzF/qH eVk/IGWVnzFXBpRawYcVD9pJGUYy2OZXtOo4PN0Okh4TSQdKbPQc/ic9RjaDbBAeSYPROw poekaH6dduO4pkWYraIjTEHtc1d0a4vXkv1JsgKp65L0Zwa7JoaTJesBeLCCePwdkmoIOM S4DV7TzbSnRilNPqv5xqT90SQLTHpP3QC0qxz+jqq5VmRLa286aAnQ4a24kwCA== 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=1786633206; 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=myGRWxqEB/1m8XGSMbpzu7Bh3vBlySZ0rmKcfr6jLS8=; b=cxNSF655b9n8Ao066g5j+C7dxYHHZwVXhv0u8/mIR+reW5n5wnjz8z7gAkXqYwCLxGUdc8 XdjUOq6h8t0EwlKwhOssvKGm26Xbk4T3RgY1SlVYPzyU3p+z6qNPs8I3sw5hucJ6zDjnMR vXu5kr/ekaCY3rMDOwaCvpL5D6LtLwBkk+bDdtI37PjEgtrsuKVO5BwQEAIB1ywDxrH77U wTdEsMxX5en5OS2S17ETgiSUKj6/cNvkTSXnawB7OGV0x2u7ol+x82Z5XMwhz4VfQlBGty MX1ST1h4ImbbnZhFTymOHJIRO+JWp64HF45rat3IKG7ZGuL+bo1eEVjdkuUHCQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hLT6t2xHyz1kM for ; Thu, 13 Aug 2026 15:00:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3cd7b by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 13 Aug 2026 15:00:01 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: 79e0b69ce8af - main - unix: Fix mchain handling in uipc_sosend_stream_or_seqpacket() List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 79e0b69ce8af7d115496991ef66e525a03e9f4fe Auto-Submitted: auto-generated Date: Thu, 13 Aug 2026 15:00:01 +0000 Message-Id: <6a7ddbf1.3cd7b.1f3d4218@gitrepo.freebsd.org> The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=79e0b69ce8af7d115496991ef66e525a03e9f4fe commit 79e0b69ce8af7d115496991ef66e525a03e9f4fe Author: Mark Johnston AuthorDate: 2026-08-13 14:57:54 +0000 Commit: Mark Johnston CommitDate: 2026-08-13 14:59:14 +0000 unix: Fix mchain handling in uipc_sosend_stream_or_seqpacket() Empty mchains cannot be copied with simple assignment. I think this bug is mostly harmless: if mcnext is empty, then it won't be accessed again before it is reinitialized in the next loop iteration. So the bug only trips an assertion in INVARIANTS kernels and won't be visible otherwise. Add a regression test which triggers this corner case. Reported by: Jan Bramkamp Fixes: d15792780760 ("unix: new implementation of unix/stream & unix/seqpacket") Reviewed by: glebius MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D58791 --- sys/kern/uipc_usrreq.c | 4 +- tests/sys/kern/unix_passfd_test.c | 87 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 4a3bc90b0132..8c67b623323e 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1284,8 +1284,8 @@ restart: if (space == 0) { /* There is space only to send control. */ MPASS(!STAILQ_EMPTY(&cmc.mc_q)); - mcnext = mc; - mc = MCHAIN_INITIALIZER(&mc); + mc_init(&mcnext); + mc_concat(&mcnext, &mc); } else if (space < mc.mc_len) { /* Not enough space. */ if (__predict_false(mc_split(&mc, &mcnext, space, diff --git a/tests/sys/kern/unix_passfd_test.c b/tests/sys/kern/unix_passfd_test.c index 56893750354f..330d045885cd 100644 --- a/tests/sys/kern/unix_passfd_test.c +++ b/tests/sys/kern/unix_passfd_test.c @@ -1303,6 +1303,92 @@ ATF_TC_BODY(empty_rights_message, tc) (void)close(putfd); } +/* + * Exercise a corner case where the receiving socket buffer has exactly enough + * space for a single fd cmsg. + */ +ATF_TC_WITHOUT_HEAD(nonblocking_passfd_ctl_space); +ATF_TC_BODY(nonblocking_passfd_ctl_space, tc) +{ + static char chunk[65536]; + size_t chunksz, room; + ssize_t n; + int delivered, fd[2], putfd; + + devnull(&putfd); + chunksz = getsendspace(); + ATF_REQUIRE(chunksz <= sizeof(chunk)); + + /* + * How much space does a single internalized fd take? + */ + domainsocketpair(fd); + ATF_REQUIRE_MSG(sendfd_payload(fd[0], putfd, chunk, 0) == 0, + "sendmsg: %s", strerror(errno)); + ATF_REQUIRE_MSG(fcntl(fd[0], F_SETFL, O_NONBLOCK) != -1, + "fcntl: %s", strerror(errno)); + for (room = 0; (n = send(fd[0], chunk, chunksz, 0)) > 0; ) + room += (size_t)n; + ATF_REQUIRE(errno == EAGAIN || errno == ENOBUFS); + closesocketpair(fd); + + /* + * Fill the socket buffer, leaving exactly enough room for a single fd + * cmsg. + */ + domainsocketpair(fd); + for (size_t sofar = 0; sofar < room; sofar += (size_t)n) { + size_t req; + + req = room - sofar; + if (req > chunksz) + req = chunksz; + n = send(fd[0], chunk, (size_t)req, 0); + ATF_REQUIRE_MSG(n > 0, "fill send: %s", strerror(errno)); + } + ATF_REQUIRE_MSG(fcntl(fd[0], F_SETFL, O_NONBLOCK) != -1, + "fcntl: %s", strerror(errno)); + ATF_REQUIRE_MSG(sendfd_payload(fd[0], putfd, chunk, 0) == 0, + "zero-length sendmsg with SCM_RIGHTS failed: %s", strerror(errno)); + + /* Drain receiver and verify the fd was delivered. */ + delivered = 0; + { + static char buf[1 << 20]; + char cmsgbuf[CMSG_SPACE(sizeof(int) * 8)]; + struct iovec iov; + struct msghdr msghdr; + + memset(&msghdr, 0, sizeof(msghdr)); + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + msghdr.msg_iov = &iov; + msghdr.msg_iovlen = 1; + msghdr.msg_control = cmsgbuf; + msghdr.msg_controllen = sizeof(cmsgbuf); + while ((n = recvmsg(fd[1], &msghdr, MSG_DONTWAIT)) >= 0) { + for (struct cmsghdr *cm = CMSG_FIRSTHDR(&msghdr); + cm != NULL; cm = CMSG_NXTHDR(&msghdr, cm)) { + if (cm->cmsg_level == SOL_SOCKET && + cm->cmsg_type == SCM_RIGHTS) { + int rxfd; + + memcpy(&rxfd, CMSG_DATA(cm), + sizeof(rxfd)); + ATF_CHECK(close(rxfd) == 0); + delivered++; + } + } + msghdr.msg_controllen = sizeof(cmsgbuf); + } + } + ATF_CHECK_MSG(delivered == 1, "expected 1 fd delivered, got %d", + delivered); + + closesocketpair(fd); + ATF_CHECK(close(putfd) == 0); +} + /* * Check that sending control creates records in a stream socket, making it * behave like a seqpacket socket. If we stack several control+data writes @@ -1545,6 +1631,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, copyout_rights_error); ATF_TP_ADD_TC(tp, externalize_error_partial_read); ATF_TP_ADD_TC(tp, empty_rights_message); + ATF_TP_ADD_TC(tp, nonblocking_passfd_ctl_space); ATF_TP_ADD_TC(tp, control_creates_records); ATF_TP_ADD_TC(tp, cross_jail_dirfd); ATF_TP_ADD_TC(tp, resolve_beneath_preserved);