From nobody Mon Aug 24 16:29:56 2026 X-Original-To: dev-commits-src-branches@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 4hTGbT0v2sz6pbRj for ; Mon, 24 Aug 2026 16:29:57 +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 "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hTGbS5yrZz41B8 for ; Mon, 24 Aug 2026 16:29:56 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787588996; 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=+ffkm9Ax+eYeGbaMy8loD9mAL5JOk+lc+NtBVnhP2Xk=; b=MP+OT/+UcX2JwlkKeOsus2k7BpVraF7qrECWNWYYmx7ccUgGPg4Qja6OvurgodOG5P2ZD9 KF3DwtKOFWCmLvhDcW0eueDTuZpNW3AwmvMDt5zcPdRWl/RWsrv0h5doJwoUb5VVLbSkgU A9dYCUfVrS7sYPt3i0dORUt3MyNqjBsgNRupJbonrzogGgPW3lliNd63PeWFoKZ9qMnA7z XtmPYCxxPyfqRhuxtX4rOINh0h7EDX0XeA8bzIg59aOF6OlsYvtpEPjKJsknIJ6uALls3g 1SB/rUXyoVqpOnbbAGGJ01sll9JRgx+ykvx4G/E8FNoDRZLrFy/dtQd2LiHoiw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787588996; a=rsa-sha256; cv=none; b=rKpCVs8ORdZon/pqrGNutU0mJE2iBFJKdgLOo5hvKXW8/QRxvjktHsDpEoBKHmZonIpGCl Ys25Ze2y/zUsaiG8fj8PpcpG2k43V3uueFUv48bAM0ZzewxfC2OE/4/dWHWchTF/BNMq6P 6UT+h3izf3erzYjpzF74VZ6emblzBs0vrEH7lnMOM1mdKApbu/cr8KsUF1EpEK4+1cvNsy sZ/FOFp4r7tJb0zDdsKfh3T7i9HrMvlOgRBEvkMfrk7kEscORb5EZgY6CCvxujO4HDYeVI ApInArrnkHFBKX7QmDOKoNk8JxUQ6/+dZy4s96EZF3uT5LQHcU9id6a+ZUcUPw== 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=1787588996; 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=+ffkm9Ax+eYeGbaMy8loD9mAL5JOk+lc+NtBVnhP2Xk=; b=l++wxAkCOIbL49EamAKm1Zv70+MSmr1BivdtqxuV/t7lc3K/jg4f6LJWLqxJsVBsBA8q0U yJdLupLV8MUtRgNZXClaFk2oXHJMx13F+Qtm3j5iH3WKksb0C8dfYLzJBbafk1f/7kxEyr X61p/jZMlR/32i+yJzp66/GIHL1EkpxhbNNUS7q4l07H8fumZaSQB8GPbmsbi6y32G24AH IPY5Hj0aQaOXVknxGuiy7uikxKQ17IwpD0VMClZMw8tZ+LxZ8wtWvpvz+rXSLgR89RsIIb L+3/MajyYKpS+rocD6UStK9mQv96GpLlwSBmnvEQghCfQ3g9hCo0zCgwJVU43A== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hTGbS4fmCz19SJ for ; Mon, 24 Aug 2026 16:29:56 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 21e88 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 24 Aug 2026 16:29:56 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: bc232869fafe - stable/15 - unix: Fix mchain handling in uipc_sosend_stream_or_seqpacket() List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@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/stable/15 X-Git-Reftype: branch X-Git-Commit: bc232869fafeee66dbd773e4ab546dc9aac40471 Auto-Submitted: auto-generated Date: Mon, 24 Aug 2026 16:29:56 +0000 Message-Id: <6a8c7184.21e88.efe16d4@gitrepo.freebsd.org> The branch stable/15 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=bc232869fafeee66dbd773e4ab546dc9aac40471 commit bc232869fafeee66dbd773e4ab546dc9aac40471 Author: Mark Johnston AuthorDate: 2026-08-13 14:57:54 +0000 Commit: Mark Johnston CommitDate: 2026-08-24 15:17:54 +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 (cherry picked from commit 79e0b69ce8af7d115496991ef66e525a03e9f4fe) --- 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 0061b80dfd4a..e3d1ed10df16 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1227,8 +1227,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 c303c7337680..fa132c03ece5 100644 --- a/tests/sys/kern/unix_passfd_test.c +++ b/tests/sys/kern/unix_passfd_test.c @@ -1148,6 +1148,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 @@ -1387,6 +1473,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);