accept: Call pru_accept in protocol thread
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 2 Dec 2011 11:54:17 +0000 (19:54 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 2 Dec 2011 11:57:54 +0000 (19:57 +0800)
This avoids socket.so_pcb use-after-check race against protocol thread.

There is no performance impact on the mostly used sockets:
- IPv4/IPv6 TCP implemented pru_savefaddr, so their pru_accept will not
  be called at all
- UNIX domain socket uses sync msgport, so no protocol thread dispatching

sys/kern/uipc_msg.c
sys/kern/uipc_socket.c
sys/sys/protosw.h
sys/sys/socketops.h

index 9cd1e3a..4f99828 100644 (file)
@@ -100,22 +100,16 @@ so_pru_abort_oncpu(struct socket *so)
        sofree(msg.base.nm_so);
 }
 
-/*
- * WARNING!  Synchronous call from user context
- */
 int
-so_pru_accept_direct(struct socket *so, struct sockaddr **nam)
+so_pru_accept(struct socket *so, struct sockaddr **nam)
 {
        struct netmsg_pru_accept msg;
-       netisr_fn_t func = so->so_proto->pr_usrreqs->pru_accept;
 
-       netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func);
-       msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE);
-       msg.base.lmsg.ms_flags |= MSGF_SYNC;
+       netmsg_init(&msg.base, so, &curthread->td_msgport,
+           0, so->so_proto->pr_usrreqs->pru_accept);
        msg.nm_nam = nam;
-       func((netmsg_t)&msg);
-       KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE);
-       return(msg.base.lmsg.ms_error);
+
+       return lwkt_domsg(so->so_port, &msg.base.lmsg, 0);
 }
 
 int
index 118a741..ca057c0 100644 (file)
@@ -613,7 +613,7 @@ soaccept(struct socket *so, struct sockaddr **nam)
        int error;
 
        soaccept_generic(so);
-       error = so_pru_accept_direct(so, nam);
+       error = so_pru_accept(so, nam);
        return (error);
 }
 
index 4081e62..ed71cf2 100644 (file)
@@ -218,8 +218,6 @@ struct pru_attach_info {
  * These are netmsg'd requests almost universally in the context of the
  * appropriate protocol thread.  Exceptions:
  *
- *     pru_accept() - called synchronously from user context
- *
  *     pru_sosend() - called synchronously from user context, typically
  *                    runs generic kernel code and then messages via
  *                    pru_send().
@@ -232,7 +230,7 @@ struct pru_attach_info {
  */
 struct pr_usrreqs {
        void    (*pru_abort) (netmsg_t msg);
-       void    (*pru_accept) (netmsg_t msg);   /* synchronous call */
+       void    (*pru_accept) (netmsg_t msg);
        void    (*pru_attach) (netmsg_t msg);
        void    (*pru_bind) (netmsg_t msg);
        void    (*pru_connect) (netmsg_t msg);
index b0a9b79..b7d776c 100644 (file)
@@ -77,7 +77,7 @@ so_pru_soreceive(struct socket *so, struct sockaddr **paddr, struct uio *uio,
 void so_pru_abort (struct socket *so);
 void so_pru_aborta (struct socket *so);
 void so_pru_abort_oncpu (struct socket *so);
-int so_pru_accept_direct(struct socket *so, struct sockaddr **nam);
+int so_pru_accept (struct socket *so, struct sockaddr **nam);
 int so_pru_attach (struct socket *so, int proto, struct pru_attach_info *ai);
 int so_pru_attach_direct(struct socket *so, int proto,
                struct pru_attach_info *ai);