Hi,

I am trying to hunt some ENOBUFS bugs reported from the socket
layer.  This may also happen if pool(9) or malloc(9) fails, so this
an easy first step.  A system call should not fail due to temporary
memory shortage.  It is the kernel's job to handle that, usually
by sleeping.

So from socreate(9) I pass M_WAIT to the protocol attach function.
As sonewconn() may be called from softnet, I pass M_DONTWAIT.

The rest of the diff is just passing down the flag to pool(9) and
malloc(9).

ok?

bluhm

Index: kern/uipc_socket.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.234
diff -u -p -r1.234 uipc_socket.c
--- kern/uipc_socket.c  22 Jul 2019 15:34:07 -0000      1.234
+++ kern/uipc_socket.c  2 Aug 2019 14:12:56 -0000
@@ -143,7 +143,7 @@ socreate(int dom, struct socket **aso, i
        so->so_proto = prp;

        s = solock(so);
-       error = (*prp->pr_attach)(so, proto);
+       error = (*prp->pr_attach)(so, proto, M_WAIT);
        if (error) {
                so->so_state |= SS_NOFDREF;
                /* sofree() calls sounlock(). */
Index: kern/uipc_socket2.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_socket2.c,v
retrieving revision 1.101
diff -u -p -r1.101 uipc_socket2.c
--- kern/uipc_socket2.c 16 Apr 2019 13:15:32 -0000      1.101
+++ kern/uipc_socket2.c 2 Aug 2019 14:15:15 -0000
@@ -190,7 +190,7 @@ sonewconn(struct socket *head, int conns
        sigio_copy(&so->so_sigio, &head->so_sigio);

        soqinsque(head, so, soqueue);
-       if ((*so->so_proto->pr_attach)(so, 0)) {
+       if ((*so->so_proto->pr_attach)(so, 0, M_DONTWAIT)) {
                (void) soqremque(so, soqueue);
                sigio_free(&so->so_sigio);
                pool_put(&socket_pool, so);
Index: kern/uipc_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.142
diff -u -p -r1.142 uipc_usrreq.c
--- kern/uipc_usrreq.c  16 Jul 2019 21:41:37 -0000      1.142
+++ kern/uipc_usrreq.c  2 Aug 2019 15:16:00 -0000
@@ -354,7 +354,7 @@ u_long      unpdg_recvspace = 4*1024;
 int    unp_rights;                     /* file descriptors in flight */

 int
-uipc_attach(struct socket *so, int proto)
+uipc_attach(struct socket *so, int proto, int wait)
 {
        struct unpcb *unp;
        int error;
@@ -379,7 +379,8 @@ uipc_attach(struct socket *so, int proto
                if (error)
                        return (error);
        }
-       unp = pool_get(&unpcb_pool, PR_NOWAIT|PR_ZERO);
+       unp = pool_get(&unpcb_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) |
+           PR_ZERO);
        if (unp == NULL)
                return (ENOBUFS);
        unp->unp_socket = so;
Index: net/pfkeyv2.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pfkeyv2.c,v
retrieving revision 1.198
diff -u -p -r1.198 pfkeyv2.c
--- net/pfkeyv2.c       17 Jul 2019 18:52:46 -0000      1.198
+++ net/pfkeyv2.c       2 Aug 2019 14:18:15 -0000
@@ -177,7 +177,7 @@ static int npromisc = 0;

 void pfkey_init(void);

-int pfkeyv2_attach(struct socket *, int);
+int pfkeyv2_attach(struct socket *, int, int);
 int pfkeyv2_detach(struct socket *);
 int pfkeyv2_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
     struct mbuf *, struct proc *);
@@ -261,7 +261,7 @@ pfkey_init(void)
  * Attach a new PF_KEYv2 socket.
  */
 int
-pfkeyv2_attach(struct socket *so, int proto)
+pfkeyv2_attach(struct socket *so, int proto, int wait)
 {
        struct pkpcb *kp;
        int error;
@@ -269,6 +269,7 @@ pfkeyv2_attach(struct socket *so, int pr
        if ((so->so_state & SS_PRIV) == 0)
                return EACCES;

+       KASSERT(wait == M_WAIT);
        kp = pool_get(&pkpcb_pool, PR_WAITOK|PR_ZERO);
        so->so_pcb = kp;
        refcnt_init(&kp->kcb_refcnt);
Index: net/rtsock.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/rtsock.c,v
retrieving revision 1.289
diff -u -p -r1.289 rtsock.c
--- net/rtsock.c        17 Jul 2019 19:57:32 -0000      1.289
+++ net/rtsock.c        2 Aug 2019 14:19:11 -0000
@@ -288,7 +288,7 @@ route_usrreq(struct socket *so, int req,
 }

 int
-route_attach(struct socket *so, int proto)
+route_attach(struct socket *so, int proto, int wait)
 {
        struct rtpcb    *rop;
        int              error;
@@ -298,6 +298,7 @@ route_attach(struct socket *so, int prot
         * code does not care about the additional fields
         * and works directly on the raw socket.
         */
+       KASSERT(wait == M_WAIT);
        rop = pool_get(&rtpcb_pool, PR_WAITOK|PR_ZERO);
        so->so_pcb = rop;
        /* Init the timeout structure */
Index: netinet/in_pcb.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.248
diff -u -p -r1.248 in_pcb.c
--- netinet/in_pcb.c    15 Jul 2019 12:40:42 -0000      1.248
+++ netinet/in_pcb.c    2 Aug 2019 15:12:34 -0000
@@ -221,14 +221,15 @@ in_rootonly(u_int16_t port, u_int16_t pr
 }

 int
-in_pcballoc(struct socket *so, struct inpcbtable *table)
+in_pcballoc(struct socket *so, struct inpcbtable *table, int wait)
 {
        struct inpcb *inp;
        struct inpcbhead *head;

        NET_ASSERT_LOCKED();

-       inp = pool_get(&inpcb_pool, PR_NOWAIT|PR_ZERO);
+       inp = pool_get(&inpcb_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) |
+           PR_ZERO);
        if (inp == NULL)
                return (ENOBUFS);
        inp->inp_table = table;
Index: netinet/in_pcb.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.h,v
retrieving revision 1.116
diff -u -p -r1.116 in_pcb.h
--- netinet/in_pcb.h    15 Jul 2019 12:40:42 -0000      1.116
+++ netinet/in_pcb.h    2 Aug 2019 15:01:11 -0000
@@ -258,7 +258,7 @@ extern int in_pcbnotifymiss;

 void    in_init(void);
 void    in_losing(struct inpcb *);
-int     in_pcballoc(struct socket *, struct inpcbtable *);
+int     in_pcballoc(struct socket *, struct inpcbtable *, int);
 int     in_pcbbind(struct inpcb *, struct mbuf *, struct proc *);
 int     in_pcbaddrisavail(struct inpcb *, struct sockaddr_in *, int,
            struct proc *);
Index: netinet/ip_divert.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_divert.c,v
retrieving revision 1.61
diff -u -p -r1.61 ip_divert.c
--- netinet/ip_divert.c 4 Feb 2019 21:40:52 -0000       1.61
+++ netinet/ip_divert.c 2 Aug 2019 15:02:19 -0000
@@ -308,7 +308,7 @@ release:
 }

 int
-divert_attach(struct socket *so, int proto)
+divert_attach(struct socket *so, int proto, int wait)
 {
        int error;

@@ -317,7 +317,7 @@ divert_attach(struct socket *so, int pro
        if ((so->so_state & SS_PRIV) == 0)
                return EACCES;

-       error = in_pcballoc(so, &divbtable);
+       error = in_pcballoc(so, &divbtable, wait);
        if (error)
                return error;

Index: netinet/ip_divert.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_divert.h,v
retrieving revision 1.11
diff -u -p -r1.11 ip_divert.h
--- netinet/ip_divert.h 2 Nov 2017 14:01:18 -0000       1.11
+++ netinet/ip_divert.h 2 Aug 2019 15:02:36 -0000
@@ -77,7 +77,7 @@ int    divert_packet(struct mbuf *, int, u
 int     divert_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int     divert_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
-int     divert_attach(struct socket *, int);
+int     divert_attach(struct socket *, int, int);
 int     divert_detach(struct socket *);
 #endif /* _KERNEL */
 #endif /* _IP_DIVERT_H_ */
Index: netinet/ip_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.85
diff -u -p -r1.85 ip_var.h
--- netinet/ip_var.h    15 Nov 2017 11:48:59 -0000      1.85
+++ netinet/ip_var.h    2 Aug 2019 14:19:58 -0000
@@ -250,7 +250,7 @@ int  rip_output(struct mbuf *, struct so
            struct mbuf *);
 int     rip_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
-int     rip_attach(struct socket *, int);
+int     rip_attach(struct socket *, int, int);
 int     rip_detach(struct socket *);
 #ifdef MROUTING
 extern struct socket *ip_mrouter[];    /* multicast routing daemon */
Index: netinet/raw_ip.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.119
diff -u -p -r1.119 raw_ip.c
--- netinet/raw_ip.c    4 Feb 2019 21:40:52 -0000       1.119
+++ netinet/raw_ip.c    2 Aug 2019 15:08:44 -0000
@@ -577,7 +577,7 @@ release:
 }

 int
-rip_attach(struct socket *so, int proto)
+rip_attach(struct socket *so, int proto, int wait)
 {
        struct inpcb *inp;
        int error;
@@ -592,7 +592,7 @@ rip_attach(struct socket *so, int proto)
        if ((error = soreserve(so, rip_sendspace, rip_recvspace)))
                return error;
        NET_ASSERT_LOCKED();
-       if ((error = in_pcballoc(so, &rawcbtable)))
+       if ((error = in_pcballoc(so, &rawcbtable, wait)))
                return error;
        inp = sotoinpcb(so);
        inp->inp_ip.ip_p = proto;
Index: netinet/tcp_subr.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.174
diff -u -p -r1.174 tcp_subr.c
--- netinet/tcp_subr.c  4 Oct 2018 17:33:41 -0000       1.174
+++ netinet/tcp_subr.c  2 Aug 2019 15:07:06 -0000
@@ -411,12 +411,13 @@ tcp_respond(struct tcpcb *tp, caddr_t te
  * protocol control block.
  */
 struct tcpcb *
-tcp_newtcpcb(struct inpcb *inp)
+tcp_newtcpcb(struct inpcb *inp, int wait)
 {
        struct tcpcb *tp;
        int i;

-       tp = pool_get(&tcpcb_pool, PR_NOWAIT|PR_ZERO);
+       tp = pool_get(&tcpcb_pool, (wait == M_WAIT ? PR_WAITOK : PR_NOWAIT) |
+           PR_ZERO);
        if (tp == NULL)
                return (NULL);
        TAILQ_INIT(&tp->t_segq);
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.172
diff -u -p -r1.172 tcp_usrreq.c
--- netinet/tcp_usrreq.c        12 Jul 2019 19:43:51 -0000      1.172
+++ netinet/tcp_usrreq.c        2 Aug 2019 15:08:12 -0000
@@ -558,7 +558,7 @@ tcp_ctloutput(int op, struct socket *so,
  * buffer space, and entering LISTEN state to accept connections.
  */
 int
-tcp_attach(struct socket *so, int proto)
+tcp_attach(struct socket *so, int proto, int wait)
 {
        struct tcpcb *tp;
        struct inpcb *inp;
@@ -575,11 +575,11 @@ tcp_attach(struct socket *so, int proto)
        }

        NET_ASSERT_LOCKED();
-       error = in_pcballoc(so, &tcbtable);
+       error = in_pcballoc(so, &tcbtable, wait);
        if (error)
                return (error);
        inp = sotoinpcb(so);
-       tp = tcp_newtcpcb(inp);
+       tp = tcp_newtcpcb(inp, wait);
        if (tp == NULL) {
                unsigned int nofd = so->so_state & SS_NOFDREF;  /* XXX */

Index: netinet/tcp_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_var.h,v
retrieving revision 1.134
diff -u -p -r1.134 tcp_var.h
--- netinet/tcp_var.h   12 Jul 2019 19:43:51 -0000      1.134
+++ netinet/tcp_var.h   2 Aug 2019 15:09:06 -0000
@@ -709,7 +709,7 @@ void        tcp6_mtudisc(struct inpcb *, int);
 void   tcp6_mtudisc_callback(struct sockaddr_in6 *, u_int);
 #endif
 struct tcpcb *
-        tcp_newtcpcb(struct inpcb *);
+        tcp_newtcpcb(struct inpcb *, int);
 void    tcp_notify(struct inpcb *, int);
 int     tcp_output(struct tcpcb *);
 void    tcp_pulloutofband(struct socket *, u_int, struct mbuf *, int);
@@ -730,7 +730,7 @@ struct tcpcb *
 int     tcp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int     tcp_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
-int     tcp_attach(struct socket *, int);
+int     tcp_attach(struct socket *, int, int);
 int     tcp_detach(struct socket *);
 void    tcp_xmit_timer(struct tcpcb *, int);
 void    tcpdropoldhalfopen(struct tcpcb *, u_int16_t);
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.255
diff -u -p -r1.255 udp_usrreq.c
--- netinet/udp_usrreq.c        4 Feb 2019 21:40:52 -0000       1.255
+++ netinet/udp_usrreq.c        2 Aug 2019 15:03:37 -0000
@@ -1208,7 +1208,7 @@ release:
 }

 int
-udp_attach(struct socket *so, int proto)
+udp_attach(struct socket *so, int proto, int wait)
 {
        int error;

@@ -1219,7 +1219,7 @@ udp_attach(struct socket *so, int proto)
                return error;

        NET_ASSERT_LOCKED();
-       if ((error = in_pcballoc(so, &udbtable)))
+       if ((error = in_pcballoc(so, &udbtable, wait)))
                return error;
 #ifdef INET6
        if (sotoinpcb(so)->inp_flags & INP_IPV6)
Index: netinet/udp_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_var.h,v
retrieving revision 1.34
diff -u -p -r1.34 udp_var.h
--- netinet/udp_var.h   2 Nov 2017 14:01:18 -0000       1.34
+++ netinet/udp_var.h   2 Aug 2019 14:20:18 -0000
@@ -149,7 +149,7 @@ int  udp6_output(struct inpcb *, struct
 int     udp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int     udp_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
-int     udp_attach(struct socket *, int);
+int     udp_attach(struct socket *, int, int);
 int     udp_detach(struct socket *);
 #endif /* _KERNEL */
 #endif /* _NETINET_UDP_VAR_H_ */
Index: netinet6/ip6_divert.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_divert.c,v
retrieving revision 1.59
diff -u -p -r1.59 ip6_divert.c
--- netinet6/ip6_divert.c       4 Feb 2019 21:40:52 -0000       1.59
+++ netinet6/ip6_divert.c       2 Aug 2019 15:03:12 -0000
@@ -313,7 +313,7 @@ release:
 }

 int
-divert6_attach(struct socket *so, int proto)
+divert6_attach(struct socket *so, int proto, int wait)
 {
        int error;

@@ -323,7 +323,7 @@ divert6_attach(struct socket *so, int pr
        if ((so->so_state & SS_PRIV) == 0)
                return EACCES;

-       error = in_pcballoc(so, &divb6table);
+       error = in_pcballoc(so, &divb6table, wait);
        if (error)
                return (error);

Index: netinet6/ip6_divert.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_divert.h,v
retrieving revision 1.9
diff -u -p -r1.9 ip6_divert.h
--- netinet6/ip6_divert.h       2 Nov 2017 14:01:18 -0000       1.9
+++ netinet6/ip6_divert.h       2 Aug 2019 15:02:47 -0000
@@ -77,7 +77,7 @@ int    divert6_packet(struct mbuf *, int,
 int     divert6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 int     divert6_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
-int     divert6_attach(struct socket *, int);
+int     divert6_attach(struct socket *, int, int);
 int     divert6_detach(struct socket *);
 #endif /* _KERNEL */

Index: netinet6/ip6_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_var.h,v
retrieving revision 1.84
diff -u -p -r1.84 ip6_var.h
--- netinet6/ip6_var.h  10 Oct 2018 11:46:59 -0000      1.84
+++ netinet6/ip6_var.h  2 Aug 2019 14:20:35 -0000
@@ -346,7 +346,7 @@ int rip6_output(struct mbuf *, struct so
            struct mbuf *);
 int    rip6_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *);
-int    rip6_attach(struct socket *, int);
+int    rip6_attach(struct socket *, int, int);
 int    rip6_detach(struct socket *);
 int    rip6_sysctl(int *, u_int, void *, size_t *, void *, size_t);

Index: netinet6/raw_ip6.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.136
diff -u -p -r1.136 raw_ip6.c
--- netinet6/raw_ip6.c  23 Apr 2019 11:01:54 -0000      1.136
+++ netinet6/raw_ip6.c  2 Aug 2019 15:00:35 -0000
@@ -709,7 +709,7 @@ release:
 }

 int
-rip6_attach(struct socket *so, int proto)
+rip6_attach(struct socket *so, int proto, int wait)
 {
        struct inpcb *in6p;
        int error;
@@ -724,15 +724,15 @@ rip6_attach(struct socket *so, int proto
        if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)))
                return error;
        NET_ASSERT_LOCKED();
-       if ((error = in_pcballoc(so, &rawin6pcbtable)))
+       if ((error = in_pcballoc(so, &rawin6pcbtable, wait)))
                return error;

        in6p = sotoinpcb(so);
        in6p->inp_ipv6.ip6_nxt = proto;
        in6p->inp_cksum6 = -1;

-       in6p->inp_icmp6filt = malloc(sizeof(struct icmp6_filter),
-           M_PCB, M_NOWAIT);
+       in6p->inp_icmp6filt = malloc(sizeof(struct icmp6_filter), M_PCB,
+           wait == M_WAIT ? M_WAITOK : M_NOWAIT);
        if (in6p->inp_icmp6filt == NULL) {
                in_pcbdetach(in6p);
                return ENOMEM;
Index: sys/protosw.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/sys/protosw.h,v
retrieving revision 1.31
diff -u -p -r1.31 protosw.h
--- sys/protosw.h       23 Jan 2018 20:49:58 -0000      1.31
+++ sys/protosw.h       2 Aug 2019 14:16:06 -0000
@@ -81,7 +81,7 @@ struct protosw {
        int     (*pr_usrreq)(struct socket *, int, struct mbuf *,
                    struct mbuf *, struct mbuf *, struct proc *);

-       int     (*pr_attach)(struct socket *, int);
+       int     (*pr_attach)(struct socket *, int, int);
        int     (*pr_detach)(struct socket *);

 /* utility hooks */
Index: sys/unpcb.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/sys/unpcb.h,v
retrieving revision 1.17
diff -u -p -r1.17 unpcb.h
--- sys/unpcb.h 15 Jul 2019 12:28:06 -0000      1.17
+++ sys/unpcb.h 2 Aug 2019 15:09:57 -0000
@@ -93,7 +93,7 @@ struct fdpass {

 int    uipc_usrreq(struct socket *, int , struct mbuf *,
                         struct mbuf *, struct mbuf *, struct proc *);
-int    uipc_attach(struct socket *, int);
+int    uipc_attach(struct socket *, int, int);
 int    uipc_detach(struct socket *);

 void   unp_init(void);

Reply via email to