Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys - fsocreate: set SS_NBIO before the file descriptor is a...



details:   https://anonhg.NetBSD.org/src/rev/ec568c67bf3c
branches:  trunk
changeset: 329281:ec568c67bf3c
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sat May 17 23:27:59 2014 +0000

description:
- fsocreate: set SS_NBIO before the file descriptor is affixed as there is
  a theoretical race condition (hard to trigger, though); remove the LWP
  parameter and clean up the code a little.
- Sprinkle few comments.
- Remove M_SOOPTS while here.

diffstat:

 sys/kern/uipc_socket.c   |  118 ++++++++++++++++++++++++----------------------
 sys/kern/uipc_syscalls.c |    6 +-
 sys/net/if_gre.c         |    6 +-
 sys/sys/mbuf.h           |    3 +-
 sys/sys/socketvar.h      |    4 +-
 5 files changed, 71 insertions(+), 66 deletions(-)

diffs (truncated from 344 to 300 lines):

diff -r 6a8f4389f343 -r ec568c67bf3c sys/kern/uipc_socket.c
--- a/sys/kern/uipc_socket.c    Sat May 17 22:52:36 2014 +0000
+++ b/sys/kern/uipc_socket.c    Sat May 17 23:27:59 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_socket.c,v 1.221 2014/02/25 18:30:11 pooka Exp $  */
+/*     $NetBSD: uipc_socket.c,v 1.222 2014/05/17 23:27:59 rmind Exp $  */
 
 /*-
  * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -62,8 +62,16 @@
  *     @(#)uipc_socket.c       8.6 (Berkeley) 5/2/95
  */
 
+/*
+ * Socket operation routines.
+ *
+ * These routines are called by the routines in sys_socket.c or from a
+ * system process, and implement the semantics of socket operations by
+ * switching out to the protocol specific routines.
+ */
+
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.221 2014/02/25 18:30:11 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.222 2014/05/17 23:27:59 rmind Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_sock_counters.h"
@@ -103,7 +111,6 @@
 #include <uvm/uvm_loan.h>
 #include <uvm/uvm_page.h>
 
-MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");
 MALLOC_DEFINE(M_SONAME, "soname", "socket name");
 
 extern const struct fileops socketops;
@@ -479,13 +486,11 @@
 }
 
 /*
- * Socket operation routines.
- * These routines are called by the routines in
- * sys_socket.c or from a system process, and
- * implement the semantics of socket operations by
- * switching out to the protocol specific routines.
- */
-/*ARGSUSED*/
+ * socreate: create a new socket of the specified type and the protocol.
+ *
+ * => Caller may specify another socket for lock sharing (must not be held).
+ * => Returns the new socket without lock held.
+*/
 int
 socreate(int dom, struct socket **aso, int type, int proto, struct lwp *l,
         struct socket *lockso)
@@ -547,6 +552,7 @@
            (struct mbuf *)(long)proto, NULL, l);
        KASSERT(solocked(so));
        if (error != 0) {
+               KASSERT(so->so_pcb == NULL);
                so->so_state |= SS_NOFDREF;
                sofree(so);
                return error;
@@ -557,38 +563,46 @@
        return 0;
 }
 
-/* On success, write file descriptor to fdout and return zero.  On
- * failure, return non-zero; *fdout will be undefined.
+/*
+ * fsocreate: create a socket and a file descriptor associated with it.
+ *
+ * => On success, write file descriptor to fdout and return zero.
+ * => On failure, return non-zero; *fdout will be undefined.
  */
 int
-fsocreate(int domain, struct socket **sop, int type, int protocol,
-    struct lwp *l, int *fdout)
+fsocreate(int domain, struct socket **sop, int type, int proto, int *fdout)
 {
-       struct socket   *so;
-       struct file     *fp;
-       int             fd, error;
-       int             flags = type & SOCK_FLAGS_MASK;
+       lwp_t *l = curlwp;
+       int error, fd, flags;
+       struct socket *so;
+       struct file *fp;
 
-       type &= ~SOCK_FLAGS_MASK;
-       if ((error = fd_allocfile(&fp, &fd)) != 0)
+       if ((error = fd_allocfile(&fp, &fd)) != 0) {
                return error;
+       }
+       flags = type & SOCK_FLAGS_MASK;
        fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0);
        fp->f_flag = FREAD|FWRITE|((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)|
            ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0);
        fp->f_type = DTYPE_SOCKET;
        fp->f_ops = &socketops;
-       error = socreate(domain, &so, type, protocol, l, NULL);
-       if (error != 0) {
+
+       type &= ~SOCK_FLAGS_MASK;
+       error = socreate(domain, &so, type, proto, l, NULL);
+       if (error) {
                fd_abort(curproc, fp, fd);
-       } else {
-               if (sop != NULL)
-                       *sop = so;
-               fp->f_data = so;
-               fd_affix(curproc, fp, fd);
-               *fdout = fd;
-               if (flags & SOCK_NONBLOCK)
-                       so->so_state |= SS_NBIO;
+               return error;
+       }
+       if (flags & SOCK_NONBLOCK) {
+               so->so_state |= SS_NBIO;
        }
+       fp->f_data = so;
+       fd_affix(curproc, fp, fd);
+
+       if (sop != NULL) {
+               *sop = so;
+       }
+       *fdout = fd;
        return error;
 }
 
@@ -624,8 +638,8 @@
        solock(so);
        if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | 
            SS_ISDISCONNECTING)) != 0) {
-               sounlock(so);
-               return (EINVAL);
+               sounlock(so);
+               return EINVAL;
        }
        error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL,
            NULL, NULL, l);
@@ -685,18 +699,15 @@
 }
 
 /*
- * Close a socket on last file table reference removal.
- * Initiate disconnect if connected.
- * Free socket when disconnect complete.
+ * soclose: close a socket on last file table reference removal.
+ * Initiate disconnect if connected.  Free socket when disconnect complete.
  */
 int
 soclose(struct socket *so)
 {
-       struct socket   *so2;
-       int             error;
-       int             error2;
+       struct socket *so2;
+       int error = 0;
 
-       error = 0;
        solock(so);
        if (so->so_options & SO_ACCEPTCONN) {
                for (;;) {
@@ -719,7 +730,7 @@
                        break;
                }
        }
-       if (so->so_pcb == 0)
+       if (so->so_pcb == NULL)
                goto discard;
        if (so->so_state & SS_ISCONNECTED) {
                if ((so->so_state & SS_ISDISCONNECTING) == 0) {
@@ -740,18 +751,17 @@
        }
  drop:
        if (so->so_pcb) {
-               error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
+               int error2 = (*so->so_proto->pr_usrreq)(so, PRU_DETACH,
                    NULL, NULL, NULL, NULL);
                if (error == 0)
                        error = error2;
        }
  discard:
-       if (so->so_state & SS_NOFDREF)
-               panic("soclose: NOFDREF");
+       KASSERT((so->so_state & SS_NOFDREF) == 0);
        kauth_cred_free(so->so_cred);
        so->so_state |= SS_NOFDREF;
        sofree(so);
-       return (error);
+       return error;
 }
 
 /*
@@ -781,13 +791,11 @@
 int
 soaccept(struct socket *so, struct mbuf *nam)
 {
-       int     error;
+       int error;
 
        KASSERT(solocked(so));
+       KASSERT((so->so_state & SS_NOFDREF) != 0);
 
-       error = 0;
-       if ((so->so_state & SS_NOFDREF) == 0)
-               panic("soaccept: !NOFDREF");
        so->so_state &= ~SS_NOFDREF;
        if ((so->so_state & SS_ISDISCONNECTED) == 0 ||
            (so->so_proto->pr_flags & PR_ABRTACPTDIS) == 0)
@@ -796,18 +804,18 @@
        else
                error = ECONNABORTED;
 
-       return (error);
+       return error;
 }
 
 int
 soconnect(struct socket *so, struct mbuf *nam, struct lwp *l)
 {
-       int             error;
+       int error;
 
        KASSERT(solocked(so));
 
        if (so->so_options & SO_ACCEPTCONN)
-               return (EOPNOTSUPP);
+               return EOPNOTSUPP;
        /*
         * If protocol is connection-based, can only connect once.
         * Otherwise, if connected, try to disconnect first.
@@ -821,19 +829,17 @@
        else
                error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
                    NULL, nam, NULL, l);
-       return (error);
+
+       return error;
 }
 
 int
 soconnect2(struct socket *so1, struct socket *so2)
 {
-       int     error;
-
        KASSERT(solocked2(so1, so2));
 
-       error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
+       return (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT2,
            NULL, (struct mbuf *)so2, NULL, NULL);
-       return (error);
 }
 
 int
diff -r 6a8f4389f343 -r ec568c67bf3c sys/kern/uipc_syscalls.c
--- a/sys/kern/uipc_syscalls.c  Sat May 17 22:52:36 2014 +0000
+++ b/sys/kern/uipc_syscalls.c  Sat May 17 23:27:59 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_syscalls.c,v 1.168 2014/05/17 21:48:48 rmind Exp $        */
+/*     $NetBSD: uipc_syscalls.c,v 1.169 2014/05/17 23:27:59 rmind Exp $        */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.168 2014/05/17 21:48:48 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.169 2014/05/17 23:27:59 rmind Exp $");
 
 #include "opt_pipe.h"
 
@@ -103,7 +103,7 @@
        int fd, error;
 
        error = fsocreate(SCARG(uap, domain), NULL, SCARG(uap, type),
-           SCARG(uap, protocol), l, &fd);
+           SCARG(uap, protocol), &fd);
        if (error == 0) {
                *retval = fd;
        }
diff -r 6a8f4389f343 -r ec568c67bf3c sys/net/if_gre.c
--- a/sys/net/if_gre.c  Sat May 17 22:52:36 2014 +0000
+++ b/sys/net/if_gre.c  Sat May 17 23:27:59 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_gre.c,v 1.153 2013/11/07 21:44:48 christos Exp $ */
+/*     $NetBSD: if_gre.c,v 1.154 2014/05/17 23:27:59 rmind Exp $ */
 
 /*
  * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@@ -45,7 +45,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.153 2013/11/07 21:44:48 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1.154 2014/05/17 23:27:59 rmind Exp $");
 
 #include "opt_atalk.h"
 #include "opt_gre.h"



Home | Main Index | Thread Index | Old Index