From 27427a72e313439258e46363f1bc801d3c750a5c Mon Sep 17 00:00:00 2001 From: anton Date: Sun, 12 Apr 2020 16:15:18 +0000 Subject: [PATCH] In sosplice(), temporarily release the socket lock before calling FRELE() as the last reference could be dropped which in turn will cause soclose() to be called where the socket lock is unconditionally acquired. Note that this is only a problem for sockets protected by the non-recursive NET_LOCK() right now. ok mpi@ visa@ Reported-by: syzbot+7c805a09545d997b924d@syzkaller.appspotmail.com --- sys/kern/uipc_socket.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 17794c199bf5..d6f2eb6ca3ca 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_socket.c,v 1.243 2020/04/07 13:27:51 visa Exp $ */ +/* $OpenBSD: uipc_socket.c,v 1.244 2020/04/12 16:15:18 anton Exp $ */ /* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */ /* @@ -1259,7 +1259,15 @@ sosplice(struct socket *so, int fd, off_t max, struct timeval *tv) sbunlock(sosp, &sosp->so_snd); sbunlock(so, &so->so_rcv); frele: + /* + * FRELE() must not be called with the socket lock held. It is safe to + * release the lock here as long as no other operation happen on the + * socket when sosplice() returns. The dance could be avoided by + * grabbing the socket lock inside this function. + */ + sounlock(so, SL_LOCKED); FRELE(fp, curproc); + solock(so); return (error); }