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);