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
This commit is contained in:
Gleb Smirnoff 2024-02-08 09:00:23 -08:00
parent 3f0b108924
commit 541e6a989c

View file

@ -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);