git: c0c5d01e5374 - stable/14 - so_splice: Synchronize so_unsplice() with so_splice()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 29 Apr 2025 00:47:55 UTC
The branch stable/14 has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=c0c5d01e53745f97a1fa132d47c27a8c300ab4f8
commit c0c5d01e53745f97a1fa132d47c27a8c300ab4f8
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-04-15 00:55:00 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-04-29 00:44:04 +0000
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: a1da7dc1cdad ("socket: Implement SO_SPLICE")
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D49814
(cherry picked from commit 992b18a9ec9f21cdf15b70b2f510fa2a69844385)
---
sys/kern/uipc_socket.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index fffb1d5b9af4..6468b3001b3e 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -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);