git: 541e6a989cae - main - unix/stream: do not put empty mbufs on the socket

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Thu, 08 Feb 2024 17:01:03 UTC
The branch main has been updated by glebius:

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

commit 541e6a989caec749aff7851a3dc8fb546a53dcba
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2024-02-08 17:00:23 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2024-02-08 17:00:23 +0000

    unix/stream: do not put empty mbufs on the socket
    
    It is a legitimate case to use sendmsg(2) to send control only, with zero
    bytes of data and then recvmsg(2) them with zero length iov, receiving
    control only.  This sendmsg(2)+recmsg(2) would leave a zero length mbuf on
    the top of the socket buffer.  If you now try to repeat this combo again,
    your recvmsg(2) would not return control data, because it sits behind an
    MT_DATA mbuf and you have provided zero length uio_resid. IMHO, best
    strategy to deal with zero length buffers in a chain is to not put them
    there in the first place.  Thus, solve this right in uipc_send() instead
    of touching soreceive_generic().
    
    Reviewed by:                    markj
    Differential Revision:          https://reviews.freebsd.org/D43733
---
 sys/kern/uipc_usrreq.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index a9a7dd3a1189..80458cd6a4fe 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -999,8 +999,8 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
 	switch (so->so_type) {
 	case SOCK_STREAM:
 		if (control != NULL) {
-			sbappendcontrol_locked(&so2->so_rcv, m,
-			    control, flags);
+			sbappendcontrol_locked(&so2->so_rcv,
+			    m->m_len > 0 ?  m : NULL, control, flags);
 			control = NULL;
 		} else
 			sbappend_locked(&so2->so_rcv, m, flags);