mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-31 04:45:39 +01:00
so_splice: Synchronize so_unsplice() with so_splice()
so_unsplice() assumed that if SB_SPLICED is set in the receive buffer of the first socket, then the splice is fully initialized. However, that's not true, and it's possible for so_unsplice() to race ahead of so_splice(). Modify so_unsplice() to simply bail if the splice state is embryonic. Reported by: syzkaller Reviewed by: gallatin Fixes:a1da7dc1cd("socket: Implement SO_SPLICE") MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D49814 (cherry picked from commit992b18a9ec)
This commit is contained in:
1 parent
dfbda7c53d
commit
c0c5d01e53
1 file changed
+14
-1
+14
-1
@@ -1721,6 +1721,8 @@ so_splice(struct socket *so, struct socket *so2, struct splice *splice)
|
||||
/*
|
||||
* Transfer any data already present in the socket buffer.
|
||||
*/
|
||||
KASSERT(sp->state == SPLICE_INIT,
|
||||
("so_splice: splice %p state %d", sp, sp->state));
|
||||
sp->state = SPLICE_QUEUED;
|
||||
so_splice_xfer(sp);
|
||||
return (0);
|
||||
@@ -1749,8 +1751,19 @@ so_unsplice(struct socket *so, bool timeout)
|
||||
SOCK_UNLOCK(so);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
so->so_rcv.sb_flags &= ~SB_SPLICED;
|
||||
sp = so->so_splice;
|
||||
mtx_lock(&sp->mtx);
|
||||
if (sp->state == SPLICE_INIT) {
|
||||
/*
|
||||
* A splice is in the middle of being set up.
|
||||
*/
|
||||
mtx_unlock(&sp->mtx);
|
||||
SOCK_RECVBUF_UNLOCK(so);
|
||||
SOCK_UNLOCK(so);
|
||||
return (ENOTCONN);
|
||||
}
|
||||
mtx_unlock(&sp->mtx);
|
||||
so->so_rcv.sb_flags &= ~SB_SPLICED;
|
||||
so->so_splice = NULL;
|
||||
SOCK_RECVBUF_UNLOCK(so);
|
||||
SOCK_UNLOCK(so);
|
||||
|
||||
Reference in new issue
Block a user