Hi, The call to in_pcballoc() in user request attach is handled in three different ways. Use the same code in udp_usrreq() and rip_usrreq() and rip6_usrreq(). Also put an splsoftassert() into in_pcballoc() for safety.
If I understand the code correctly, this also fixes a pcb and socket leak in udp_usrreq() in case soreserve() fails. ok? bluhm Index: netinet/in_pcb.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.131 diff -u -p -r1.131 in_pcb.c --- netinet/in_pcb.c 5 Feb 2013 19:09:52 -0000 1.131 +++ netinet/in_pcb.c 27 Mar 2013 16:35:19 -0000 @@ -177,6 +177,8 @@ in_pcballoc(struct socket *so, struct in struct inpcb *inp; int s; + splsoftassert(IPL_SOFTNET); + if (inpcb_pool_initialized == 0) { pool_init(&inpcb_pool, sizeof(struct inpcb), 0, 0, 0, "inpcbpl", NULL); Index: netinet/raw_ip.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/raw_ip.c,v retrieving revision 1.62 diff -u -p -r1.62 raw_ip.c --- netinet/raw_ip.c 21 Oct 2012 13:06:03 -0000 1.62 +++ netinet/raw_ip.c 27 Mar 2013 17:37:29 -0000 @@ -396,8 +396,9 @@ int rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct proc *p) { - int error = 0; struct inpcb *inp = sotoinpcb(so); + int error = 0; + int s; #ifdef MROUTING extern struct socket *ip_mrouter; #endif @@ -419,9 +420,13 @@ rip_usrreq(struct socket *so, int req, s error = EACCES; break; } + s = splsoftnet(); if ((error = soreserve(so, rip_sendspace, rip_recvspace)) || - (error = in_pcballoc(so, &rawcbtable))) + (error = in_pcballoc(so, &rawcbtable))) { + splx(s); break; + } + splx(s); inp = (struct inpcb *)so->so_pcb; inp->inp_ip.ip_p = (long)nam; break; Index: netinet/udp_usrreq.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.154 diff -u -p -r1.154 udp_usrreq.c --- netinet/udp_usrreq.c 14 Mar 2013 11:18:37 -0000 1.154 +++ netinet/udp_usrreq.c 27 Mar 2013 18:17:47 -0000 @@ -1151,13 +1151,12 @@ udp_usrreq(struct socket *so, int req, s break; } s = splsoftnet(); - error = in_pcballoc(so, &udbtable); - splx(s); - if (error) - break; - error = soreserve(so, udp_sendspace, udp_recvspace); - if (error) + if ((error = soreserve(so, udp_sendspace, udp_recvspace)) || + (error = in_pcballoc(so, &udbtable))) { + splx(s); break; + } + splx(s); #ifdef INET6 if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6) ((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim = Index: netinet6/raw_ip6.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.47 diff -u -p -r1.47 raw_ip6.c --- netinet6/raw_ip6.c 14 Mar 2013 11:18:37 -0000 1.47 +++ netinet6/raw_ip6.c 27 Mar 2013 17:37:43 -0000 @@ -595,8 +595,8 @@ rip6_usrreq(struct socket *so, int req, struct mbuf *control, struct proc *p) { struct in6pcb *in6p = sotoin6pcb(so); - int s; int error = 0; + int s; int priv; priv = 0; @@ -616,12 +616,8 @@ rip6_usrreq(struct socket *so, int req, break; } s = splsoftnet(); - if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) != 0) { - splx(s); - break; - } - if ((error = in_pcballoc(so, &rawin6pcbtable)) != 0) - { + if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) || + (error = in_pcballoc(so, &rawin6pcbtable))) { splx(s); break; }