summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2020-09-29 11:48:54 +0000
committerclaudio <claudio@openbsd.org>2020-09-29 11:48:54 +0000
commit27257b4ae4e10c6fd37c4d6e3022c973aa12a97a (patch)
treea1353c6a73bacddf2593ed639a757d88448245d9
parentIntroduce a helper to check if all available swap is in use. (diff)
downloadwireguard-openbsd-27257b4ae4e10c6fd37c4d6e3022c973aa12a97a.tar.xz
wireguard-openbsd-27257b4ae4e10c6fd37c4d6e3022c973aa12a97a.zip
Move the solock() call outside of solisten(). The reason is that the
so_state and splice checks were done without the proper lock which is incorrect. This is similar to sobind(), soconnect() which also require the callee to hold the socket lock. Found by, with and OK mvs@, OK mpi@
-rw-r--r--sys/kern/uipc_socket.c12
-rw-r--r--sys/kern/uipc_syscalls.c6
2 files changed, 9 insertions, 9 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index dc1c6be333e..227e1ded9ca 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket.c,v 1.248 2020/08/07 14:35:38 cheloha Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.249 2020/09/29 11:48:54 claudio Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@@ -192,7 +192,9 @@ sobind(struct socket *so, struct mbuf *nam, struct proc *p)
int
solisten(struct socket *so, int backlog)
{
- int s, error;
+ int error;
+
+ soassertlocked(so);
if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING))
return (EINVAL);
@@ -200,13 +202,10 @@ solisten(struct socket *so, int backlog)
if (isspliced(so) || issplicedback(so))
return (EOPNOTSUPP);
#endif /* SOCKET_SPLICE */
- s = solock(so);
error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, NULL, NULL,
curproc);
- if (error) {
- sounlock(so, s);
+ if (error)
return (error);
- }
if (TAILQ_FIRST(&so->so_q) == NULL)
so->so_options |= SO_ACCEPTCONN;
if (backlog < 0 || backlog > somaxconn)
@@ -214,7 +213,6 @@ solisten(struct socket *so, int backlog)
if (backlog < sominconn)
backlog = sominconn;
so->so_qlimit = backlog;
- sounlock(so, s);
return (0);
}
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 6cd0cb04282..0b372dec7f3 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_syscalls.c,v 1.186 2020/06/10 13:24:57 visa Exp $ */
+/* $OpenBSD: uipc_syscalls.c,v 1.187 2020/09/29 11:48:54 claudio Exp $ */
/* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */
/*
@@ -194,12 +194,14 @@ sys_listen(struct proc *p, void *v, register_t *retval)
} */ *uap = v;
struct file *fp;
struct socket *so;
- int error;
+ int s, error;
if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
return (error);
so = fp->f_data;
+ s = solock(so);
error = solisten(so, SCARG(uap, backlog));
+ sounlock(so, s);
FRELE(fp, p);
return (error);
}