sbappendcontrol() needs to avoid clearing M_NOTREADY on data mbufs.

If LOCAL_CREDS is set on a unix socket and sendfile() is called,
sendfile will call uipc_send(PRUS_NOTREADY), prepending a control
message to the M_NOTREADY mbufs.  uipc_send() then calls
sbappendcontrol() instead of sbappend(), and sbappendcontrol() would
erroneously clear M_NOTREADY.

Pass send flags to sbappendcontrol(), like we do for sbappend(), to
preserve M_READY when necessary.

Reported by:	syzkaller
MFC after:	2 weeks
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D24333
This commit is contained in:
Mark Johnston 2020-04-10 20:42:11 +00:00
parent a50b1900a0
commit 25f4ddfb2b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=359779
3 changed files with 8 additions and 7 deletions

View File

@ -1101,11 +1101,11 @@ sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa,
void
sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
struct mbuf *control)
struct mbuf *control, int flags)
{
struct mbuf *m, *mlast;
m_clrprotoflags(m0);
sbm_clrprotoflags(m0, flags);
m_last(control)->m_next = m0;
SBLASTRECORDCHK(sb);
@ -1123,11 +1123,12 @@ sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
}
void
sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control)
sbappendcontrol(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control,
int flags)
{
SOCKBUF_LOCK(sb);
sbappendcontrol_locked(sb, m0, control);
sbappendcontrol_locked(sb, m0, control, flags);
SOCKBUF_UNLOCK(sb);
}

View File

@ -1192,7 +1192,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
case SOCK_STREAM:
if (control != NULL) {
sbappendcontrol_locked(&so2->so_rcv, m,
control);
control, flags);
control = NULL;
} else
sbappend_locked(&so2->so_rcv, m, flags);

View File

@ -145,9 +145,9 @@ int sbappendaddr_locked(struct sockbuf *sb, const struct sockaddr *asa,
int sbappendaddr_nospacecheck_locked(struct sockbuf *sb,
const struct sockaddr *asa, struct mbuf *m0, struct mbuf *control);
void sbappendcontrol(struct sockbuf *sb, struct mbuf *m0,
struct mbuf *control);
struct mbuf *control, int flags);
void sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0,
struct mbuf *control);
struct mbuf *control, int flags);
void sbappendrecord(struct sockbuf *sb, struct mbuf *m0);
void sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0);
void sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n);