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

Reply via email to