Add missing solock()/sounlock() dances around sbreserve().
authormpi <mpi@openbsd.org>
Tue, 27 Jun 2017 12:02:43 +0000 (12:02 +0000)
committermpi <mpi@openbsd.org>
Tue, 27 Jun 2017 12:02:43 +0000 (12:02 +0000)
While here document an abuse of parent socket's lock.

Problem reported by krw@, analysis and ok bluhm@

sys/kern/uipc_socket.c
sys/kern/uipc_socket2.c
sys/nfs/nfs_socket.c
sys/nfs/nfs_syscalls.c

index dfdc62b..c6fbdc7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_socket.c,v 1.189 2017/06/26 09:32:31 mpi Exp $   */
+/*     $OpenBSD: uipc_socket.c,v 1.190 2017/06/27 12:02:43 mpi Exp $   */
 /*     $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $        */
 
 /*
@@ -1635,11 +1635,14 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0)
                                        error = EINVAL;
                                        goto bad;
                                }
+                               s = solock(so);
                                if (sbcheckreserve(cnt, so->so_snd.sb_wat) ||
                                    sbreserve(so, &so->so_snd, cnt)) {
+                                       sounlock(s);
                                        error = ENOBUFS;
                                        goto bad;
                                }
+                               sounlock(s);
                                so->so_snd.sb_wat = cnt;
                                break;
 
@@ -1648,11 +1651,14 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m0)
                                        error = EINVAL;
                                        goto bad;
                                }
+                               s = solock(so);
                                if (sbcheckreserve(cnt, so->so_rcv.sb_wat) ||
                                    sbreserve(so, &so->so_rcv, cnt)) {
+                                       sounlock(s);
                                        error = ENOBUFS;
                                        goto bad;
                                }
+                               sounlock(s);
                                so->so_rcv.sb_wat = cnt;
                                break;
 
index 65c5dd7..9619cbd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_socket2.c,v 1.79 2017/06/26 09:32:31 mpi Exp $   */
+/*     $OpenBSD: uipc_socket2.c,v 1.80 2017/06/27 12:02:43 mpi Exp $   */
 /*     $NetBSD: uipc_socket2.c,v 1.11 1996/02/04 02:17:55 christos Exp $       */
 
 /*
@@ -148,6 +148,11 @@ sonewconn(struct socket *head, int connstatus)
        struct socket *so;
        int soqueue = connstatus ? 1 : 0;
 
+       /*
+        * XXXSMP as long as `so' and `head' share the same lock, we
+        * can call soreserve() and pr_attach() below w/o expliclitly
+        * locking `so'.
+        */
        soassertlocked(head);
 
        if (mclpools[0].pr_nout > mclpools[0].pr_hardlimit * 95 / 100)
index f120299..748fd82 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nfs_socket.c,v 1.118 2017/06/26 09:32:32 mpi Exp $    */
+/*     $OpenBSD: nfs_socket.c,v 1.119 2017/06/27 12:02:43 mpi Exp $    */
 /*     $NetBSD: nfs_socket.c,v 1.27 1996/04/15 20:20:00 thorpej Exp $  */
 
 /*
@@ -362,7 +362,9 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
                rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR +
                    sizeof (u_int32_t)) * 2;
        }
+       s = solock(so);
        error = soreserve(so, sndreserve, rcvreserve);
+       sounlock(s);
        if (error)
                goto bad;
        so->so_rcv.sb_flags |= SB_NOINTR;
index 5d9aa6e..036d81a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nfs_syscalls.c,v 1.108 2017/05/17 08:59:05 mpi Exp $  */
+/*     $OpenBSD: nfs_syscalls.c,v 1.109 2017/06/27 12:02:43 mpi Exp $  */
 /*     $NetBSD: nfs_syscalls.c,v 1.19 1996/02/18 11:53:52 fvdl Exp $   */
 
 /*
@@ -229,7 +229,7 @@ nfssvc_addsock(struct file *fp, struct mbuf *mynam)
        struct nfssvc_sock *slp;
        struct socket *so;
        struct nfssvc_sock *tslp;
-       int error;
+       int s, error;
 
        so = (struct socket *)fp->f_data;
        tslp = NULL;
@@ -247,7 +247,9 @@ nfssvc_addsock(struct file *fp, struct mbuf *mynam)
                siz = NFS_MAXPACKET + sizeof (u_long);
        else
                siz = NFS_MAXPACKET;
+       s = solock(so);
        error = soreserve(so, siz, siz); 
+       sounlock(s);
        if (error) {
                m_freem(mynam);
                return (error);